b01fe1524a
--- type: change description: |- Completely refactor naming of everything, in light of new SPEC Writing the SPEC shed some light on just how weakly a lot of concepts, like "commit", had been defined, and prompted the delineation of a lot of things along specific lines (commit vs payload, repo vs project). This commit makes the code reflect the SPEC much better in quite a few ways: * Repo is now Project * Commit is now Payload * GitCommit is now just Commit * Hash is now Fingerprint * A lot of minor fields got renamed * All the XXXInterface types are now just XXX, and their old XXX type is now XXXUnion. More than likely there's still some comments and variable names that have slipped passed, but overall I feel like I got most of the changes. fingerprint: AKkDC5BKhKbfXzZQ/F4KquHeMgVvcNxgLmkZFz/nP/tY credentials: - type: pgp_signature pub_key_id: 95C46FA6A41148AC body: iQIzBAABAgAdFiEEJ6tQKp6olvZKJ0lwlcRvpqQRSKwFAl6l7aYACgkQlcRvpqQRSKxFrA//VQ+f8B6pwGS3ORB4VVBnHvvJTGZvAYTvB0fHuHJx2EreR4FwjhaNakk5ClkwbO7WFMq++2OV4xIkvzwswLdbXZF0IHx3wScQM59v4vIkR4V9Lj5p1aGGhQna52uIKugF2gTqKdU4tqYzmBjDND/c2XDwCN5CwTwwnAHXUSSsHxviiPUYPWV5wzFP7uyRW0ZeK8Isv7QECKRXlsDjcSJa+g+jc091FG/jG9Dkai8fbDbW8YXj7W3ALaXgXWEBJMrgQxZcJJRjgCvLY72FIIrUBquu3FepiyzMtZ0yaIvi4NmGCsYqIv00NcMvMtD7iwhOCZn10Sku4wvaKJ8YBMRduhqC99fnr/ZDW0/HvTNcL7GKx11GjwtmzkJgwsHFPy3zX+kMdF4m3WgtoeI0GwEsBXXZE2C49yAk3Mb/3puegl3a1PPMvOabTzo7Xm6xpWkI6gISChI7My71H3EuKZWhkb+IubPmMvJJXIdVxHnsHPz2dl/BZXLgpfVdEgQa2qWeXtYI4NNm37pLl3gv92V4kka+Kr4gfdoq8mJ7aqvc9was35baJbHg4+fEVJG2Wj+2AQU+ncx3nAFzgYyMxwo9K8VuC4QdfRF4ImyxTnWkuokEn9H6JRrbkBDKIELj6vzdPmsjOUEQ4nsYX66/zSibFD7UvhQmdXFs8Gp8/Qq6g4M= account: mediocregopher
184 lines
5.1 KiB
Go
184 lines
5.1 KiB
Go
package dehub
|
|
|
|
import (
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/davecgh/go-spew/spew"
|
|
"gopkg.in/src-d/go-git.v4/plumbing"
|
|
)
|
|
|
|
func TestPayloadChangeVerify(t *testing.T) {
|
|
type step struct {
|
|
descr string
|
|
msgHead string // defaults to msg
|
|
tree map[string]string
|
|
}
|
|
testCases := []struct {
|
|
descr string
|
|
steps []step
|
|
}{
|
|
{
|
|
descr: "single commit",
|
|
steps: []step{
|
|
{
|
|
descr: "first commit",
|
|
tree: map[string]string{"a": "0", "b": "1"},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
descr: "multiple commits",
|
|
steps: []step{
|
|
{
|
|
descr: "first commit",
|
|
tree: map[string]string{"a": "0", "b": "1"},
|
|
},
|
|
{
|
|
descr: "second commit, changing a",
|
|
tree: map[string]string{"a": "1"},
|
|
},
|
|
{
|
|
descr: "third commit, empty",
|
|
},
|
|
{
|
|
descr: "fourth commit, adding c, removing b",
|
|
tree: map[string]string{"b": "", "c": "2"},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
descr: "big body commits",
|
|
steps: []step{
|
|
{
|
|
descr: "first commit, single line but with newline\n",
|
|
},
|
|
{
|
|
descr: "second commit, single line but with two newlines\n\n",
|
|
msgHead: "second commit, single line but with two newlines\n\n",
|
|
},
|
|
{
|
|
descr: "third commit, multi-line with one newline\nanother line!",
|
|
msgHead: "third commit, multi-line with one newline\n\n",
|
|
},
|
|
{
|
|
descr: "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)
|
|
rootSig := h.stageNewAccount("root", false)
|
|
|
|
for _, step := range test.steps {
|
|
h.stage(step.tree)
|
|
|
|
commit := h.assertCommitChange(verifyShouldSucceed, step.descr, rootSig)
|
|
if step.msgHead == "" {
|
|
step.msgHead = strings.TrimSpace(step.descr) + "\n\n"
|
|
}
|
|
|
|
if !strings.HasPrefix(commit.Object.Message, step.msgHead) {
|
|
t.Fatalf("commit message %q does not start with expected head %q",
|
|
commit.Object.Message, step.msgHead)
|
|
}
|
|
|
|
var payUn PayloadUnion
|
|
if err := payUn.UnmarshalText([]byte(commit.Object.Message)); err != nil {
|
|
t.Fatalf("error unmarshaling commit message: %v", err)
|
|
} else if !reflect.DeepEqual(payUn, commit.Payload) {
|
|
t.Fatalf("returned change payload:\n%s\ndoes not match actual one:\n%s",
|
|
spew.Sdump(commit.Payload), spew.Sdump(payUn))
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCombinePayloadChanges(t *testing.T) {
|
|
h := newHarness(t)
|
|
|
|
// commit initial config, so the root user can modify it in the next commit
|
|
rootSig := h.stageNewAccount("root", false)
|
|
h.assertCommitChange(verifyShouldSucceed, "initial commit", rootSig)
|
|
|
|
// add a toot user and modify the access controls such that both accounts
|
|
// are required for the main branch
|
|
tootSig := h.stageNewAccount("toot", false)
|
|
h.stageAccessControls(`
|
|
- action: allow
|
|
filters:
|
|
- type: branch
|
|
pattern: main
|
|
- type: payload_type
|
|
payload_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
|
|
`)
|
|
tootCommit := h.assertCommitChange(verifyShouldSucceed, "add toot", rootSig)
|
|
|
|
// 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.assertCommitChange(verifyShouldSucceed, "add foo file", rootSig)
|
|
|
|
// now adding a credential commit from toot should work
|
|
credCommitPayUn, err := h.proj.NewPayloadCredential(fooCommit.Payload.Common.Fingerprint)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
credCommit := h.tryCommit(verifyShouldSucceed, credCommitPayUn, tootSig)
|
|
|
|
allCommits, err := h.proj.GetCommitRange(tootCommit.Hash, credCommit.Hash)
|
|
if err != nil {
|
|
t.Fatalf("getting commits: %v", err)
|
|
}
|
|
|
|
combinedCommit, err := h.proj.CombinePayloadChanges(allCommits, MainRefName)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// that new commit should have both credentials
|
|
creds := combinedCommit.Payload.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.proj.GetHeadCommit()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
} else if mainHead.Hash != combinedCommit.Hash {
|
|
t.Fatalf("mainHead's should be pointed at %s but is pointed at %s",
|
|
combinedCommit.Hash, mainHead.Hash)
|
|
} else if err = h.proj.VerifyCommits(MainRefName, []Commit{combinedCommit}); err != nil {
|
|
t.Fatalf("unable to verify combined commit: %v", err)
|
|
} else if author := combinedCommit.Object.Author.Name; author != "root" {
|
|
t.Fatalf("unexpected author value %q", author)
|
|
}
|
|
}
|