1 package util
2
3 import (
4 "bytes"
5 "crypto/sha256"
6 "crypto/sha512"
7 "encoding/hex"
8 "hash"
9 "testing"
10
11 "github.com/theupdateframework/go-tuf/data"
12 . "gopkg.in/check.v1"
13 )
14
15
16 func Test(t *testing.T) { TestingT(t) }
17
18 type UtilSuite struct{}
19
20 var _ = Suite(&UtilSuite{})
21
22 func (UtilSuite) TestGenerateTargetFileMetaDefault(c *C) {
23
24 r := bytes.NewReader([]byte("foo"))
25 meta, err := GenerateTargetFileMeta(r)
26 c.Assert(err, IsNil)
27 c.Assert(meta.Length, Equals, int64(3))
28 hashes := meta.Hashes
29 c.Assert(hashes, HasLen, 1)
30 hash, ok := hashes["sha512"]
31 if !ok {
32 c.Fatal("missing sha512 hash")
33 }
34 c.Assert(hash.String(), DeepEquals, "f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7")
35 }
36
37 func (UtilSuite) TestGenerateTargetFileMetaExplicit(c *C) {
38 r := bytes.NewReader([]byte("foo"))
39 meta, err := GenerateTargetFileMeta(r, "sha256", "sha512")
40 c.Assert(err, IsNil)
41 c.Assert(meta.Length, Equals, int64(3))
42 hashes := meta.Hashes
43 c.Assert(hashes, HasLen, 2)
44 for name, val := range map[string]string{
45 "sha256": "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae",
46 "sha512": "f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7",
47 } {
48 hash, ok := hashes[name]
49 if !ok {
50 c.Fatalf("missing %s hash", name)
51 }
52 c.Assert(hash.String(), DeepEquals, val)
53 }
54 }
55
56 func makeHashes(c *C, hashes map[string]string) data.Hashes {
57 h := make(map[string]data.HexBytes, len(hashes))
58 for typ, hash := range hashes {
59 v, err := hex.DecodeString(hash)
60 c.Assert(err, IsNil)
61 h[typ] = v
62 }
63 return h
64 }
65
66 type testMetaFile struct {
67 name string
68 actual data.FileMeta
69 expected data.FileMeta
70 err func(testMetaFile) error
71 }
72
73 func testMetaFileCases(c *C) []testMetaFile {
74 fileMeta := func(c *C, length int64, hashes map[string]string) data.FileMeta {
75 return data.FileMeta{
76 Length: length,
77 Hashes: makeHashes(c, hashes),
78 }
79 }
80
81 return []testMetaFile{
82 {
83 name: "wrong length",
84 actual: data.FileMeta{Length: 1},
85 expected: data.FileMeta{Length: 2},
86 err: func(testMetaFile) error { return ErrWrongLength{Actual: 1, Expected: 2} },
87 },
88 {
89 name: "wrong sha512 hash",
90 actual: fileMeta(c, 10, map[string]string{"sha512": "111111"}),
91 expected: fileMeta(c, 10, map[string]string{"sha512": "222222"}),
92 err: func(t testMetaFile) error {
93 return ErrWrongHash{"sha512", t.expected.Hashes["sha512"], t.actual.Hashes["sha512"]}
94 },
95 },
96 {
97 name: "intersecting hashes",
98 actual: fileMeta(c, 10, map[string]string{"sha512": "111111", "md5": "222222"}),
99 expected: fileMeta(c, 10, map[string]string{"sha512": "111111", "sha256": "333333"}),
100 err: func(testMetaFile) error { return nil },
101 },
102 {
103 name: "no common hashes",
104 actual: fileMeta(c, 10, map[string]string{"sha512": "111111"}),
105 expected: fileMeta(c, 10, map[string]string{"sha256": "222222", "md5": "333333"}),
106 err: func(t testMetaFile) error { return ErrNoCommonHash{t.expected.Hashes, t.actual.Hashes} },
107 },
108 }
109 }
110
111 func (UtilSuite) TestSnapshotFileMetaEqual(c *C) {
112 type test struct {
113 name string
114 actual data.SnapshotFileMeta
115 expected data.SnapshotFileMeta
116 err func(test) error
117 }
118
119 fileMeta := func(version int64, length int64, hashes map[string]string) data.SnapshotFileMeta {
120 return data.SnapshotFileMeta{
121 Length: length,
122 Hashes: makeHashes(c, hashes),
123 Version: version,
124 }
125 }
126
127 tests := []test{
128 {
129 name: "same version",
130 actual: fileMeta(1, 10, map[string]string{"sha512": "111111"}),
131 expected: fileMeta(1, 10, map[string]string{"sha512": "111111"}),
132 err: func(test) error { return nil },
133 },
134 {
135 name: "wrong version",
136 actual: fileMeta(0, 10, map[string]string{"sha512": "111111"}),
137 expected: fileMeta(1, 10, map[string]string{"sha512": "111111"}),
138 err: func(test) error { return ErrWrongVersion{Expected: 1, Actual: 0} },
139 },
140 {
141 name: "wrong version",
142 actual: fileMeta(1, 10, map[string]string{"sha512": "111111"}),
143 expected: fileMeta(0, 10, map[string]string{"sha512": "111111"}),
144 err: func(test) error { return ErrWrongVersion{Expected: 0, Actual: 1} },
145 },
146 {
147 name: "wrong version",
148 actual: fileMeta(1, 10, map[string]string{"sha512": "111111"}),
149 expected: fileMeta(2, 10, map[string]string{"sha512": "111111"}),
150 err: func(test) error { return ErrWrongVersion{Expected: 2, Actual: 1} },
151 },
152 }
153
154 for _, t := range tests {
155 c.Assert(SnapshotFileMetaEqual(t.actual, t.expected), DeepEquals, t.err(t), Commentf("name = %s", t.name))
156 }
157
158 for _, t := range testMetaFileCases(c) {
159 actual := data.SnapshotFileMeta{Length: t.actual.Length, Hashes: t.actual.Hashes}
160 expected := data.SnapshotFileMeta{Length: t.expected.Length, Hashes: t.expected.Hashes}
161 c.Assert(SnapshotFileMetaEqual(actual, expected), DeepEquals, t.err(t), Commentf("name = %s %d %d", t.name, t.actual.Length, t.expected.Length))
162 c.Assert(FileMetaEqual(t.actual, t.expected), DeepEquals, t.err(t), Commentf("name = %s", t.name))
163 }
164 }
165
166 func (UtilSuite) TestNormalizeTarget(c *C) {
167 for before, after := range map[string]string{
168 "": "",
169 "foo.txt": "foo.txt",
170 "/bar.txt": "bar.txt",
171 "foo//bar.txt": "foo/bar.txt",
172 "/with/./a/dot": "with/a/dot",
173 "/with/double/../dot": "with/dot",
174 } {
175 c.Assert(NormalizeTarget(before), Equals, after)
176 }
177 }
178
179 func (UtilSuite) TestHashedPaths(c *C) {
180 hexBytes := func(s string) data.HexBytes {
181 v, err := hex.DecodeString(s)
182 c.Assert(err, IsNil)
183 return v
184 }
185 hashes := data.Hashes{
186 "sha512": hexBytes("abc123"),
187 "sha256": hexBytes("def456"),
188 }
189 paths := HashedPaths("foo/bar.txt", hashes)
190
191 c.Assert(paths, HasLen, 2)
192 expected := map[string]struct{}{"foo/abc123.bar.txt": {}, "foo/def456.bar.txt": {}}
193 for _, path := range paths {
194 if _, ok := expected[path]; !ok {
195 c.Fatalf("unexpected path: %s", path)
196 }
197 delete(expected, path)
198 }
199 }
200
201 func (UtilSuite) TestVersionEqual(c *C) {
202 c.Assert(VersionEqual(1, 1), IsNil)
203 c.Assert(VersionEqual(1, 3), Equals, ErrWrongVersion{3, 1})
204 }
205
206 func makeHash(b []byte, alg string) []byte {
207 var h hash.Hash
208
209 switch alg {
210 case "sha256":
211 h = sha256.New()
212 case "sha512":
213 h = sha512.New()
214 }
215 h.Write(b)
216 return h.Sum(nil)
217 }
218
219 func (UtilSuite) TestBytesMatchLenAndHashes(c *C) {
220 type test struct {
221 name string
222 bytes []byte
223 length int64
224 hashes data.Hashes
225 err func(test) error
226 }
227
228 b := []byte{82, 253, 252, 7, 33, 130, 101, 79, 22, 63, 95, 15, 154, 98, 29, 114}
229 bhashes := data.Hashes{
230 "sha512": makeHash(b, "sha512"),
231 "sha256": makeHash(b, "sha256"),
232 }
233
234 tests := []test{
235 {
236 name: "correct len and hashes",
237 bytes: b,
238 length: 16,
239 hashes: bhashes,
240 err: func(test) error { return nil },
241 },
242 {
243 name: "incorrect len",
244 bytes: b,
245 length: 32,
246 hashes: bhashes,
247 err: func(test) error { return ErrWrongLength{32, 16} },
248 },
249 {
250 name: "incorrect hashes sha512",
251 bytes: b,
252 length: 16,
253 hashes: data.Hashes{
254 "sha512": makeHash(b, "sha256"),
255 },
256 err: func(test) error { return ErrWrongHash{"sha512", bhashes["sha256"], bhashes["sha512"]} },
257 },
258 {
259 name: "incorrect hashes sha256",
260 bytes: b,
261 length: 16,
262 hashes: data.Hashes{
263 "sha256": makeHash(b, "sha512"),
264 },
265 err: func(test) error { return ErrWrongHash{"sha256", bhashes["sha512"], bhashes["sha256"]} },
266 },
267 {
268 name: "incorrect len and hashes",
269 bytes: b,
270 length: 32,
271 hashes: data.Hashes{
272 "sha512": makeHash(b, "sha256"),
273 "sha256": makeHash(b, "sha512"),
274 },
275 err: func(test) error { return ErrWrongLength{32, 16} },
276 },
277 }
278
279 for _, t := range tests {
280 c.Assert(BytesMatchLenAndHashes(t.bytes, t.length, t.hashes), DeepEquals, t.err(t), Commentf("name = %s", t.name))
281 }
282 }
283
View as plain text