github.com/ethersphere/bee/v2@v2.2.0/pkg/manifest/simple/manifest_test.go (about) 1 // Copyright 2020 The Swarm Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package simple_test 6 7 import ( 8 "errors" 9 "reflect" 10 "testing" 11 12 "github.com/ethersphere/bee/v2/pkg/manifest/simple" 13 "github.com/ethersphere/bee/v2/pkg/swarm" 14 ) 15 16 func TestNilPath(t *testing.T) { 17 t.Parallel() 18 19 m := simple.NewManifest() 20 n, err := m.Lookup("") 21 if err == nil { 22 t.Fatalf("expected error, got reference %s", n.Reference()) 23 } 24 } 25 26 // struct for manifest entries for test cases 27 type e struct { 28 path string 29 reference swarm.Address 30 metadata map[string]string 31 } 32 33 type testCase struct { 34 name string 35 entries []e // entries to add to manifest 36 } 37 38 func makeTestCases(t *testing.T) []testCase { 39 t.Helper() 40 41 return []testCase{ 42 { 43 name: "empty-manifest", 44 entries: nil, 45 }, 46 { 47 name: "one-entry", 48 entries: []e{ 49 { 50 path: "entry-1", 51 reference: swarm.RandAddress(t), 52 }, 53 }, 54 }, 55 { 56 name: "two-entries", 57 entries: []e{ 58 { 59 path: "entry-1.txt", 60 reference: swarm.RandAddress(t), 61 }, 62 { 63 path: "entry-2.png", 64 reference: swarm.RandAddress(t), 65 }, 66 }, 67 }, 68 { 69 name: "nested-entries", 70 entries: []e{ 71 { 72 path: "text/robots.txt", 73 reference: swarm.RandAddress(t), 74 }, 75 { 76 path: "img/1.png", 77 reference: swarm.RandAddress(t), 78 }, 79 { 80 path: "img/2.jpg", 81 reference: swarm.RandAddress(t), 82 }, 83 { 84 path: "readme.md", 85 reference: swarm.RandAddress(t), 86 }, 87 { 88 path: "/", 89 metadata: map[string]string{ 90 "index-document": "readme.md", 91 "error-document": "404.html", 92 }, 93 }, 94 }, 95 }, 96 } 97 } 98 99 func TestEntries(t *testing.T) { 100 t.Parallel() 101 102 for _, tc := range makeTestCases(t) { 103 tc := tc 104 t.Run(tc.name, func(t *testing.T) { 105 t.Parallel() 106 107 m := simple.NewManifest() 108 109 checkLength(t, m, 0) 110 111 // add entries 112 for i, e := range tc.entries { 113 err := m.Add(e.path, e.reference.String(), e.metadata) 114 if err != nil { 115 t.Fatal(err) 116 } 117 118 checkLength(t, m, i+1) 119 checkEntry(t, m, e.reference.String(), e.path) 120 } 121 122 manifestLen := m.Length() 123 124 if len(tc.entries) != manifestLen { 125 t.Fatalf("expected %d entries, found %d", len(tc.entries), manifestLen) 126 } 127 128 if manifestLen == 0 { 129 // special case for empty manifest 130 return 131 } 132 133 // replace entry 134 lastEntry := tc.entries[len(tc.entries)-1] 135 136 newReference := swarm.RandAddress(t).String() 137 138 err := m.Add(lastEntry.path, newReference, map[string]string{}) 139 if err != nil { 140 t.Fatal(err) 141 } 142 143 checkLength(t, m, manifestLen) // length should not have changed 144 checkEntry(t, m, newReference, lastEntry.path) 145 146 // remove entries 147 err = m.Remove("invalid/path.ext") // try removing inexistent entry 148 if err != nil { 149 t.Fatal(err) 150 } 151 152 checkLength(t, m, manifestLen) // length should not have changed 153 154 for i, e := range tc.entries { 155 err = m.Remove(e.path) 156 if err != nil { 157 t.Fatal(err) 158 } 159 160 entry, err := m.Lookup(e.path) 161 if entry != nil || !errors.Is(err, simple.ErrNotFound) { 162 t.Fatalf("expected path %v not to be present in the manifest, but it was found", e.path) 163 } 164 165 checkLength(t, m, manifestLen-i-1) 166 } 167 168 }) 169 } 170 } 171 172 // checkLength verifies that the given manifest length and integer match. 173 func checkLength(t *testing.T, m simple.Manifest, length int) { 174 t.Helper() 175 176 if m.Length() != length { 177 t.Fatalf("expected length to be %d, but is %d instead", length, m.Length()) 178 } 179 } 180 181 // checkEntry verifies that an entry is equal to the one retrieved from the given manifest and path. 182 func checkEntry(t *testing.T, m simple.Manifest, reference, path string) { 183 t.Helper() 184 185 n, err := m.Lookup(path) 186 if err != nil { 187 t.Fatal(err) 188 } 189 if n.Reference() != reference { 190 t.Fatalf("expected reference %s, got: %s", reference, n.Reference()) 191 } 192 } 193 194 // TestMarshal verifies that created manifests are successfully marshalled and unmarshalled. 195 // This function will add all test case entries to a manifest and marshal it. 196 // After, it will unmarshal the result, and verify that it is equal to the original manifest. 197 func TestMarshal(t *testing.T) { 198 t.Parallel() 199 200 for _, tc := range makeTestCases(t) { 201 tc := tc 202 t.Run(tc.name, func(t *testing.T) { 203 t.Parallel() 204 205 m := simple.NewManifest() 206 207 for _, e := range tc.entries { 208 err := m.Add(e.path, e.reference.String(), e.metadata) 209 if err != nil { 210 t.Fatal(err) 211 } 212 } 213 214 b, err := m.MarshalBinary() 215 if err != nil { 216 t.Fatal(err) 217 } 218 219 um := simple.NewManifest() 220 if err := um.UnmarshalBinary(b); err != nil { 221 t.Fatal(err) 222 } 223 224 if !reflect.DeepEqual(m, um) { 225 t.Fatalf("marshalled and unmarshalled manifests are not equal: %v, %v", m, um) 226 } 227 }) 228 } 229 } 230 231 func TestHasPrefix(t *testing.T) { 232 t.Parallel() 233 234 for _, tc := range []struct { 235 name string 236 toAdd []string 237 testPrefix []string 238 shouldExist []bool 239 }{ 240 { 241 name: "simple", 242 toAdd: []string{ 243 "index.html", 244 "img/1.png", 245 "img/2.png", 246 "robots.txt", 247 }, 248 testPrefix: []string{ 249 "img/", 250 "images/", 251 }, 252 shouldExist: []bool{ 253 true, 254 false, 255 }, 256 }, 257 { 258 name: "nested-single", 259 toAdd: []string{ 260 "some-path/file.ext", 261 }, 262 testPrefix: []string{ 263 "some-path/", 264 "some-path/file", 265 "some-other-path/", 266 }, 267 shouldExist: []bool{ 268 true, 269 true, 270 false, 271 }, 272 }, 273 } { 274 tc := tc 275 t.Run(tc.name, func(t *testing.T) { 276 t.Parallel() 277 278 m := simple.NewManifest() 279 280 for _, e := range tc.toAdd { 281 err := m.Add(e, "", nil) 282 if err != nil { 283 t.Fatalf("expected no error, got %v", err) 284 } 285 } 286 287 for i := 0; i < len(tc.testPrefix); i++ { 288 testPrefix := tc.testPrefix[i] 289 shouldExist := tc.shouldExist[i] 290 291 exists := m.HasPrefix(testPrefix) 292 293 if shouldExist != exists { 294 t.Errorf("expected prefix path %s to be %t, was %t", testPrefix, shouldExist, exists) 295 } 296 } 297 298 }) 299 } 300 }