--- 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