dehub/commit_change_test.go
mediocregopher f3226d6171 Refactor combined commits a bit
---
type: change
message: |-
  Refactor combined commits a bit

  This commit makes the combine method not take in revisions, which simplifies
  some things as well as makes it more consistent with other methods. Additionally
  this commit fixes authorship for combined commits so that they only show the
  authors of the change commits involved, not all commits with credentials.
change_hash: APQFD5UML2F+ulO3awYJ3BHqvn05EZSFqmCg2i7vTfgA
credentials:
- type: pgp_signature
  pub_key_id: 95C46FA6A41148AC
  body: iQIzBAABAgAdFiEEJ6tQKp6olvZKJ0lwlcRvpqQRSKwFAl55PNYACgkQlcRvpqQRSKz51Q//anLA1v9Qqtn0dey24oGngaJnV80fi53CZf57AGulbTj6WWQIlZrH126B/YJgSAFg6EzRZZj8vWW7JTXLXhExVM3vGvGWJWyslW9vadBLXRbK9Uw4RuPxN9hDgnXPYs4TNbIm11q5m8jxrCPAehs4aMebsRB4k//m0ul/17kjWlIOHTJupE/gyg47hjoyD//q2vNi9izkEEtRYDVykxXzy++UtEp7CCt9MO9Tp6H8FRxDH1h5jwWaGbedL/AakLDBAN0DhEZ1tvStpeSwycRiGlbIO3eRpDoLoBgX5yLwwrCqF6acEToJZR+amerKlTa5dNf/cqynS8CzMs35u+ZZx0QKTp7eqn/TEP3LNlAbbzILyrktFVBml47JNjLwS2LVZknJvV3mWI6K9r6yE01m/S+2zbkZz2EoADn0PgA99tKfJoozjFbqRQaTJn/B6/4L38GyVKSW3DXF3BYjz9DrFiEZR95449q9gHmJCVZ7S7wX/KfYvI5K7QMpBhiGUZSsWKc4DX6de2TP1HgXQX/08WJGb5463J6TQoB2LoQbDzOUBli4VblQwpWaREDp0DlPz+BUaFVCAwIXsaYGGrUkKeqFN0MH1OR7Ir5t5uVg8C97RbywAYvdThyOdQLyKQaK4CHwtyHU0BPrKSU13rE6tl66NTqY46MgyBSPEJ4ukvA=
  account: mediocregopher
2020-03-23 16:49:01 -06:00

200 lines
5.4 KiB
Go

package dehub
import (
"dehub/sigcred"
"reflect"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
"gopkg.in/src-d/go-git.v4/plumbing"
yaml "gopkg.in/yaml.v2"
)
func TestChangeCommitVerify(t *testing.T) {
type step struct {
msg string
msgHead string // defaults to msg
tree map[string]string
}
testCases := []struct {
descr string
steps []step
}{
{
descr: "single commit",
steps: []step{
{
msg: "first commit",
tree: map[string]string{"a": "0", "b": "1"},
},
},
},
{
descr: "multiple commits",
steps: []step{
{
msg: "first commit",
tree: map[string]string{"a": "0", "b": "1"},
},
{
msg: "second commit, changing a",
tree: map[string]string{"a": "1"},
},
{
msg: "third commit, empty",
},
{
msg: "fourth commit, adding c, removing b",
tree: map[string]string{"b": "", "c": "2"},
},
},
},
{
descr: "big body commits",
steps: []step{
{
msg: "first commit, single line but with newline\n",
},
{
msg: "second commit, single line but with two newlines\n\n",
msgHead: "second commit, single line but with two newlines\n\n",
},
{
msg: "third commit, multi-line with one newline\nanother line!",
msgHead: "third commit, multi-line with one newline\n\n",
},
{
msg: "fourth commit, multi-line with two newlines\n\nanother line!",
msgHead: "fourth commit, multi-line with two newlines\n\n",
},
},
},
}
for _, test := range testCases {
t.Run(test.descr, func(t *testing.T) {
h := newHarness(t)
for _, step := range test.steps {
h.stage(step.tree)
account := h.cfg.Accounts[0]
gitCommit := h.changeCommit(step.msg, account.ID, h.sig)
if step.msgHead == "" {
step.msgHead = strings.TrimSpace(step.msg) + "\n\n"
}
if !strings.HasPrefix(gitCommit.GitCommit.Message, step.msgHead) {
t.Fatalf("commit message %q does not start with expected head %q",
gitCommit.GitCommit.Message, step.msgHead)
}
var actualCommit Commit
if err := actualCommit.UnmarshalText([]byte(gitCommit.GitCommit.Message)); err != nil {
t.Fatalf("error unmarshaling commit body: %v", err)
} else if !reflect.DeepEqual(actualCommit, gitCommit.Commit) {
t.Fatalf("returned change commit:\n%s\ndoes not match actual one:\n%s",
spew.Sdump(gitCommit.Commit), spew.Sdump(actualCommit))
}
}
})
}
}
func TestCombineCommitChanges(t *testing.T) {
h := newHarness(t)
// commit initial config, so the root user can modify it in the next commit
h.changeCommit("initial commit", h.cfg.Accounts[0].ID, h.sig)
// add a toot user and modify the access controls such that both accounts
// are required for the main branch
tootSig, tootPubKeyBody := sigcred.SignifierPGPTmp("toot", h.rand)
h.cfg.Accounts = append(h.cfg.Accounts, Account{
ID: "toot",
Signifiers: []sigcred.Signifier{{PGPPublicKey: &sigcred.SignifierPGP{
Body: string(tootPubKeyBody),
}}},
})
err := yaml.Unmarshal([]byte(`
- action: allow
filters:
- type: branch
pattern: main
- type: commit_type
commit_type: change
- type: signature
any_account: true
count: 2
- action: allow
filters:
- type: not
filter:
type: branch
pattern: main
- type: signature
any_account: true
count: 1
- action: deny
`), &h.cfg.AccessControls)
if err != nil {
t.Fatal(err)
}
h.stageCfg()
tootCommit := h.changeCommit("add toot", h.cfg.Accounts[0].ID, h.sig)
// make a single change commit in another branch using root. Then add a
// credential using toot, and combine them onto main.
otherBranch := plumbing.NewBranchReferenceName("other")
h.checkout(otherBranch)
h.stage(map[string]string{"foo": "bar"})
fooCommit := h.changeCommit("add foo file", h.cfg.Accounts[0].ID, h.sig)
// now adding a credential commit from toot should work
credCommitObj, err := h.repo.NewCommitCredential(fooCommit.Interface.GetHash())
if err != nil {
t.Fatal(err)
}
credCommit := h.tryCommit(true, credCommitObj, h.cfg.Accounts[1].ID, tootSig)
allCommits, err := h.repo.GetGitCommitRange(
tootCommit.GitCommit.Hash,
credCommit.GitCommit.Hash,
)
if err != nil {
t.Fatalf("error getting commits: %v", err)
}
combinedCommit, err := h.repo.CombineCommitChanges(allCommits, MainRefName)
if err != nil {
t.Fatal(err)
}
// that new commit should have both credentials
creds := combinedCommit.Commit.Common.Credentials
if len(creds) != 2 {
t.Fatalf("combined commit has %d credentials, not 2", len(creds))
} else if creds[0].AccountID != "root" {
t.Fatalf("combined commit first credential should be from root, is from %q", creds[0].AccountID)
} else if creds[1].AccountID != "toot" {
t.Fatalf("combined commit second credential should be from toot, is from %q", creds[1].AccountID)
}
// double check that the HEAD commit of main got properly set
h.checkout(MainRefName)
mainHead, err := h.repo.GetGitHead()
if err != nil {
t.Fatal(err)
} else if mainHead.GitCommit.Hash != combinedCommit.GitCommit.Hash {
t.Fatalf("mainHead's should be pointed at %s but is pointed at %s",
combinedCommit.GitCommit.Hash, mainHead.GitCommit.Hash)
} else if err = h.repo.VerifyCommits(MainRefName, []GitCommit{combinedCommit}); err != nil {
t.Fatalf("unable to verify combined commit: %v", err)
} else if author := combinedCommit.GitCommit.Author.Name; author != "root" {
t.Fatalf("unexpected author value %q", author)
}
}