--- type: change message: |- refactor how file changes and hashes are handled, and add tests for hashes This involved a few different changes that all worked together: * Making fileChanged public as ChangedFile, and reorganizing how it's created/used a bit. * Renaming the CommitInterface methods to be clearer, and passing in a `[]ChangedFile` into `ExpectedHash` (previously just `Hash`) rather than trees. * Adding tests for the gen*Hash functions. change_hash: AGCdt2k6FARuf1CBao7zxiuDVMOAdeL5vL8Whnr9KjMu credentials: - type: pgp_signature pub_key_id: 95C46FA6A41148AC body: iQIzBAABAgAdFiEEJ6tQKp6olvZKJ0lwlcRvpqQRSKwFAl6bVGIACgkQlcRvpqQRSKwkmhAAqAuUXKIpr1caE7yuM09udiW51G0TtSe0tLItoZ6ROnSe6lsISZ3hkmOWjSyfeeZFggGIAlK3Uipb42pbSO3Usf0fqDWdNekPLRtTd6qpB65Ye9kDgC3Nz6Z0EhFSMDc6sQzNcisWqAAry6CyEy4ucAm3aK1frSTH/6i/x9DQZXY7WVLM5NewegTr/fatf57Fh6kky7o7yiALeOmQR/oAh7x4AADJgmJMs2aBLsO958GwrNOlQI/RhC83TfoXM7YcTkFv+xz2LucIyBZYYxpM327UTmUk2vuOf3p2OFbiISfIZxFeI3KhpUH05TVXyzohQTnrwyWJDKFGKO8iqxaWHRxdH0INUKsAcBTA8dzTGoRyFF5CUKYX0ZnorlT5NV2HeObmFaDpUHNQKHCcQAAAFoSOGVNNqfGS1IqUNwwZkln+Nzr7YrxmCJ98fDopF0C9ZWhNzNF3+oQbOCIOj3+1kqxsQrcqgK3dwefCL46u244qLDGyqF9s8Aqp4rtrVT+4V2hTB7psdR/EDwu5xZDtXEPEktY+6z0RyYwqxUKBkSklOd+dgmqMYw7YrrNKCW433HjHUEf8Qk/x8CjRANkNYMgOAQqND0pegaAHRJJJbD4xMBrMBO8QlAX5+/ocFfoyEXTKlUuNJXVOh/2TDtOWXhmbVhOBsx7TOhTjUhtAGwE= account: mediocregophermain
parent
1f892070bd
commit
84399603cf
@ -0,0 +1,237 @@ |
|||||||
|
package dehub |
||||||
|
|
||||||
|
import ( |
||||||
|
"bytes" |
||||||
|
"encoding/binary" |
||||||
|
"hash" |
||||||
|
"testing" |
||||||
|
|
||||||
|
"gopkg.in/src-d/go-git.v4/plumbing" |
||||||
|
"gopkg.in/src-d/go-git.v4/plumbing/filemode" |
||||||
|
) |
||||||
|
|
||||||
|
type testHash struct { |
||||||
|
bytes.Buffer |
||||||
|
} |
||||||
|
|
||||||
|
var _ hash.Hash = new(testHash) |
||||||
|
|
||||||
|
func (th *testHash) Sum(b []byte) []byte { |
||||||
|
return append(b, th.Buffer.Bytes()...) |
||||||
|
} |
||||||
|
|
||||||
|
func (th *testHash) Size() int { |
||||||
|
return th.Buffer.Len() |
||||||
|
} |
||||||
|
|
||||||
|
func (th *testHash) BlockSize() int { |
||||||
|
return 1 |
||||||
|
} |
||||||
|
|
||||||
|
func (th *testHash) assertContents(t *testing.T, parts [][]byte) { |
||||||
|
b := th.Buffer.Bytes() |
||||||
|
for _, part := range parts { |
||||||
|
if len(part) > len(b) || !bytes.Equal(part, b[:len(part)]) { |
||||||
|
t.Fatalf("expected %q but only found %q", part, b) |
||||||
|
} |
||||||
|
b = b[len(part):] |
||||||
|
} |
||||||
|
if len(b) != 0 { |
||||||
|
t.Fatalf("unexpected extra bytes written to testHash: %q", b) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func uvarint(i uint64) []byte { |
||||||
|
buf := make([]byte, binary.MaxVarintLen64) |
||||||
|
n := binary.PutUvarint(buf, i) |
||||||
|
return buf[:n] |
||||||
|
} |
||||||
|
|
||||||
|
func TestGenCommentHash(t *testing.T) { |
||||||
|
type test struct { |
||||||
|
descr string |
||||||
|
comment string |
||||||
|
exp [][]byte |
||||||
|
} |
||||||
|
|
||||||
|
tests := []test{ |
||||||
|
{ |
||||||
|
descr: "empty comment", |
||||||
|
comment: "", |
||||||
|
exp: [][]byte{uvarint(0)}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
descr: "normal comment", |
||||||
|
comment: "this is a normal comment", |
||||||
|
exp: [][]byte{uvarint(24), []byte("this is a normal comment")}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
descr: "comment with unicode", |
||||||
|
comment: "sick comment ⚡", |
||||||
|
exp: [][]byte{uvarint(16), []byte("sick comment ⚡")}, |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
for _, test := range tests { |
||||||
|
t.Run(test.descr, func(t *testing.T) { |
||||||
|
th := new(testHash) |
||||||
|
genCommentHash(th, test.comment) |
||||||
|
th.assertContents(t, test.exp) |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func TestGenChangeHash(t *testing.T) { |
||||||
|
type test struct { |
||||||
|
descr string |
||||||
|
msg string |
||||||
|
changedFiles []ChangedFile |
||||||
|
exp [][]byte |
||||||
|
} |
||||||
|
|
||||||
|
hash := func(i byte) plumbing.Hash { |
||||||
|
var h plumbing.Hash |
||||||
|
h[0] = i |
||||||
|
return h |
||||||
|
} |
||||||
|
hashB := func(i byte) []byte { |
||||||
|
h := hash(i) |
||||||
|
return h[:] |
||||||
|
} |
||||||
|
|
||||||
|
tests := []test{ |
||||||
|
{ |
||||||
|
descr: "empty", |
||||||
|
msg: "", |
||||||
|
changedFiles: nil, |
||||||
|
exp: [][]byte{uvarint(0), uvarint(0)}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
descr: "empty changes", |
||||||
|
msg: "some msg", |
||||||
|
changedFiles: nil, |
||||||
|
exp: [][]byte{uvarint(8), []byte("some msg"), uvarint(0)}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
descr: "empty msg", |
||||||
|
msg: "", |
||||||
|
changedFiles: []ChangedFile{{ |
||||||
|
Path: "foo", |
||||||
|
ToMode: filemode.Regular, ToHash: hash(1), |
||||||
|
}}, |
||||||
|
exp: [][]byte{uvarint(0), uvarint(1), |
||||||
|
uvarint(3), []byte("foo"), |
||||||
|
filemode.Empty.Bytes(), hashB(0), |
||||||
|
filemode.Regular.Bytes(), hashB(1)}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
descr: "files added", |
||||||
|
msg: "a", |
||||||
|
changedFiles: []ChangedFile{ |
||||||
|
{ |
||||||
|
Path: "foo", |
||||||
|
ToMode: filemode.Regular, ToHash: hash(1), |
||||||
|
}, |
||||||
|
{ |
||||||
|
Path: "somedir/bar", |
||||||
|
ToMode: filemode.Executable, ToHash: hash(2), |
||||||
|
}, |
||||||
|
}, |
||||||
|
exp: [][]byte{uvarint(1), []byte("a"), uvarint(2), |
||||||
|
uvarint(3), []byte("foo"), |
||||||
|
filemode.Empty.Bytes(), hashB(0), |
||||||
|
filemode.Regular.Bytes(), hashB(1), |
||||||
|
uvarint(11), []byte("somedir/bar"), |
||||||
|
filemode.Empty.Bytes(), hashB(0), |
||||||
|
filemode.Executable.Bytes(), hashB(2), |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
descr: "files added (unordered)", |
||||||
|
msg: "a", |
||||||
|
changedFiles: []ChangedFile{ |
||||||
|
{ |
||||||
|
Path: "somedir/bar", |
||||||
|
ToMode: filemode.Executable, ToHash: hash(2), |
||||||
|
}, |
||||||
|
{ |
||||||
|
Path: "foo", |
||||||
|
ToMode: filemode.Regular, ToHash: hash(1), |
||||||
|
}, |
||||||
|
}, |
||||||
|
exp: [][]byte{uvarint(1), []byte("a"), uvarint(2), |
||||||
|
uvarint(3), []byte("foo"), |
||||||
|
filemode.Empty.Bytes(), hashB(0), |
||||||
|
filemode.Regular.Bytes(), hashB(1), |
||||||
|
uvarint(11), []byte("somedir/bar"), |
||||||
|
filemode.Empty.Bytes(), hashB(0), |
||||||
|
filemode.Executable.Bytes(), hashB(2), |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
descr: "file modified", |
||||||
|
msg: "a", |
||||||
|
changedFiles: []ChangedFile{{ |
||||||
|
Path: "foo", |
||||||
|
FromMode: filemode.Regular, FromHash: hash(1), |
||||||
|
ToMode: filemode.Executable, ToHash: hash(2), |
||||||
|
}}, |
||||||
|
exp: [][]byte{uvarint(1), []byte("a"), uvarint(1), |
||||||
|
uvarint(3), []byte("foo"), |
||||||
|
filemode.Regular.Bytes(), hashB(1), |
||||||
|
filemode.Executable.Bytes(), hashB(2), |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
descr: "file removed", |
||||||
|
msg: "a", |
||||||
|
changedFiles: []ChangedFile{{ |
||||||
|
Path: "foo", |
||||||
|
FromMode: filemode.Regular, FromHash: hash(1), |
||||||
|
}}, |
||||||
|
exp: [][]byte{uvarint(1), []byte("a"), uvarint(1), |
||||||
|
uvarint(3), []byte("foo"), |
||||||
|
filemode.Regular.Bytes(), hashB(1), |
||||||
|
filemode.Empty.Bytes(), hashB(0), |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
descr: "files added, modified, and removed", |
||||||
|
msg: "aaa", |
||||||
|
changedFiles: []ChangedFile{ |
||||||
|
{ |
||||||
|
Path: "foo", |
||||||
|
ToMode: filemode.Regular, ToHash: hash(1), |
||||||
|
}, |
||||||
|
{ |
||||||
|
Path: "bar", |
||||||
|
FromMode: filemode.Regular, FromHash: hash(2), |
||||||
|
ToMode: filemode.Regular, ToHash: hash(3), |
||||||
|
}, |
||||||
|
{ |
||||||
|
Path: "baz", |
||||||
|
FromMode: filemode.Executable, FromHash: hash(4), |
||||||
|
}, |
||||||
|
}, |
||||||
|
exp: [][]byte{uvarint(3), []byte("aaa"), uvarint(3), |
||||||
|
uvarint(3), []byte("bar"), |
||||||
|
filemode.Regular.Bytes(), hashB(2), |
||||||
|
filemode.Regular.Bytes(), hashB(3), |
||||||
|
uvarint(3), []byte("baz"), |
||||||
|
filemode.Executable.Bytes(), hashB(4), |
||||||
|
filemode.Empty.Bytes(), hashB(0), |
||||||
|
uvarint(3), []byte("foo"), |
||||||
|
filemode.Empty.Bytes(), hashB(0), |
||||||
|
filemode.Regular.Bytes(), hashB(1), |
||||||
|
}, |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
for _, test := range tests { |
||||||
|
t.Run(test.descr, func(t *testing.T) { |
||||||
|
th := new(testHash) |
||||||
|
genChangeHash(th, test.msg, test.changedFiles) |
||||||
|
th.assertContents(t, test.exp) |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue