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  }