storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/metacache-stream_test.go (about)

     1  /*
     2   * MinIO Cloud Storage, (C) 2020 MinIO, Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package cmd
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"io"
    23  	"io/ioutil"
    24  	"reflect"
    25  	"sync"
    26  	"testing"
    27  )
    28  
    29  var loadMetacacheSampleNames = []string{"src/compress/bzip2/", "src/compress/bzip2/bit_reader.go", "src/compress/bzip2/bzip2.go", "src/compress/bzip2/bzip2_test.go", "src/compress/bzip2/huffman.go", "src/compress/bzip2/move_to_front.go", "src/compress/bzip2/testdata/", "src/compress/bzip2/testdata/Isaac.Newton-Opticks.txt.bz2", "src/compress/bzip2/testdata/e.txt.bz2", "src/compress/bzip2/testdata/fail-issue5747.bz2", "src/compress/bzip2/testdata/pass-random1.bin", "src/compress/bzip2/testdata/pass-random1.bz2", "src/compress/bzip2/testdata/pass-random2.bin", "src/compress/bzip2/testdata/pass-random2.bz2", "src/compress/bzip2/testdata/pass-sawtooth.bz2", "src/compress/bzip2/testdata/random.data.bz2", "src/compress/flate/", "src/compress/flate/deflate.go", "src/compress/flate/deflate_test.go", "src/compress/flate/deflatefast.go", "src/compress/flate/dict_decoder.go", "src/compress/flate/dict_decoder_test.go", "src/compress/flate/example_test.go", "src/compress/flate/flate_test.go", "src/compress/flate/huffman_bit_writer.go", "src/compress/flate/huffman_bit_writer_test.go", "src/compress/flate/huffman_code.go", "src/compress/flate/inflate.go", "src/compress/flate/inflate_test.go", "src/compress/flate/reader_test.go", "src/compress/flate/testdata/", "src/compress/flate/testdata/huffman-null-max.dyn.expect", "src/compress/flate/testdata/huffman-null-max.dyn.expect-noinput", "src/compress/flate/testdata/huffman-null-max.golden", "src/compress/flate/testdata/huffman-null-max.in", "src/compress/flate/testdata/huffman-null-max.wb.expect", "src/compress/flate/testdata/huffman-null-max.wb.expect-noinput", "src/compress/flate/testdata/huffman-pi.dyn.expect", "src/compress/flate/testdata/huffman-pi.dyn.expect-noinput", "src/compress/flate/testdata/huffman-pi.golden", "src/compress/flate/testdata/huffman-pi.in", "src/compress/flate/testdata/huffman-pi.wb.expect", "src/compress/flate/testdata/huffman-pi.wb.expect-noinput", "src/compress/flate/testdata/huffman-rand-1k.dyn.expect", "src/compress/flate/testdata/huffman-rand-1k.dyn.expect-noinput", "src/compress/flate/testdata/huffman-rand-1k.golden", "src/compress/flate/testdata/huffman-rand-1k.in", "src/compress/flate/testdata/huffman-rand-1k.wb.expect", "src/compress/flate/testdata/huffman-rand-1k.wb.expect-noinput", "src/compress/flate/testdata/huffman-rand-limit.dyn.expect", "src/compress/flate/testdata/huffman-rand-limit.dyn.expect-noinput", "src/compress/flate/testdata/huffman-rand-limit.golden", "src/compress/flate/testdata/huffman-rand-limit.in", "src/compress/flate/testdata/huffman-rand-limit.wb.expect", "src/compress/flate/testdata/huffman-rand-limit.wb.expect-noinput", "src/compress/flate/testdata/huffman-rand-max.golden", "src/compress/flate/testdata/huffman-rand-max.in", "src/compress/flate/testdata/huffman-shifts.dyn.expect", "src/compress/flate/testdata/huffman-shifts.dyn.expect-noinput", "src/compress/flate/testdata/huffman-shifts.golden", "src/compress/flate/testdata/huffman-shifts.in", "src/compress/flate/testdata/huffman-shifts.wb.expect", "src/compress/flate/testdata/huffman-shifts.wb.expect-noinput", "src/compress/flate/testdata/huffman-text-shift.dyn.expect", "src/compress/flate/testdata/huffman-text-shift.dyn.expect-noinput", "src/compress/flate/testdata/huffman-text-shift.golden", "src/compress/flate/testdata/huffman-text-shift.in", "src/compress/flate/testdata/huffman-text-shift.wb.expect", "src/compress/flate/testdata/huffman-text-shift.wb.expect-noinput", "src/compress/flate/testdata/huffman-text.dyn.expect", "src/compress/flate/testdata/huffman-text.dyn.expect-noinput", "src/compress/flate/testdata/huffman-text.golden", "src/compress/flate/testdata/huffman-text.in", "src/compress/flate/testdata/huffman-text.wb.expect", "src/compress/flate/testdata/huffman-text.wb.expect-noinput", "src/compress/flate/testdata/huffman-zero.dyn.expect", "src/compress/flate/testdata/huffman-zero.dyn.expect-noinput", "src/compress/flate/testdata/huffman-zero.golden", "src/compress/flate/testdata/huffman-zero.in", "src/compress/flate/testdata/huffman-zero.wb.expect", "src/compress/flate/testdata/huffman-zero.wb.expect-noinput", "src/compress/flate/testdata/null-long-match.dyn.expect-noinput", "src/compress/flate/testdata/null-long-match.wb.expect-noinput", "src/compress/flate/token.go", "src/compress/flate/writer_test.go", "src/compress/gzip/", "src/compress/gzip/example_test.go", "src/compress/gzip/gunzip.go", "src/compress/gzip/gunzip_test.go", "src/compress/gzip/gzip.go", "src/compress/gzip/gzip_test.go", "src/compress/gzip/issue14937_test.go", "src/compress/gzip/testdata/", "src/compress/gzip/testdata/issue6550.gz.base64", "src/compress/lzw/", "src/compress/lzw/reader.go", "src/compress/lzw/reader_test.go", "src/compress/lzw/writer.go", "src/compress/lzw/writer_test.go", "src/compress/testdata/", "src/compress/testdata/e.txt", "src/compress/testdata/gettysburg.txt", "src/compress/testdata/pi.txt", "src/compress/zlib/", "src/compress/zlib/example_test.go", "src/compress/zlib/reader.go", "src/compress/zlib/reader_test.go", "src/compress/zlib/writer.go", "src/compress/zlib/writer_test.go"}
    30  
    31  func loadMetacacheSample(t testing.TB) *metacacheReader {
    32  	b, err := ioutil.ReadFile("testdata/metacache.s2")
    33  	if err != nil {
    34  		t.Fatal(err)
    35  	}
    36  	r, err := newMetacacheReader(bytes.NewReader(b))
    37  	if err != nil {
    38  		t.Fatal(err)
    39  	}
    40  	return r
    41  }
    42  
    43  func loadMetacacheSampleEntries(t testing.TB) metaCacheEntriesSorted {
    44  	r := loadMetacacheSample(t)
    45  	defer r.Close()
    46  	entries, err := r.readN(-1, false, true, "")
    47  	if err != io.EOF {
    48  		t.Fatal(err)
    49  	}
    50  
    51  	return entries
    52  }
    53  
    54  func Test_metacacheReader_readNames(t *testing.T) {
    55  	r := loadMetacacheSample(t)
    56  	defer r.Close()
    57  	names, err := r.readNames(-1)
    58  	if err != io.EOF {
    59  		t.Fatal(err)
    60  	}
    61  	want := loadMetacacheSampleNames
    62  	if !reflect.DeepEqual(names, want) {
    63  		t.Errorf("got unexpected result: %#v", names)
    64  	}
    65  }
    66  
    67  func Test_metacacheReader_readN(t *testing.T) {
    68  	r := loadMetacacheSample(t)
    69  	defer r.Close()
    70  	entries, err := r.readN(-1, false, true, "")
    71  	if err != io.EOF {
    72  		t.Fatal(err, entries.len())
    73  	}
    74  	want := loadMetacacheSampleNames
    75  	for i, entry := range entries.entries() {
    76  		if entry.name != want[i] {
    77  			t.Errorf("entry %d, want %q, got %q", i, want[i], entry.name)
    78  		}
    79  	}
    80  	if entries.len() != len(want) {
    81  		t.Fatal("unexpected length:", entries.len(), "want:", len(want))
    82  	}
    83  
    84  	want = want[:0]
    85  	entries, err = r.readN(0, false, true, "")
    86  	if err != nil {
    87  		t.Fatal(err, entries.len())
    88  	}
    89  	if entries.len() != len(want) {
    90  		t.Fatal("unexpected length:", entries.len(), "want:", len(want))
    91  	}
    92  
    93  	// Reload.
    94  	r = loadMetacacheSample(t)
    95  	defer r.Close()
    96  	entries, err = r.readN(0, false, true, "")
    97  	if err != nil {
    98  		t.Fatal(err, entries.len())
    99  	}
   100  	if entries.len() != len(want) {
   101  		t.Fatal("unexpected length:", entries.len(), "want:", len(want))
   102  	}
   103  
   104  	entries, err = r.readN(5, false, true, "")
   105  	if err != nil {
   106  		t.Fatal(err, entries.len())
   107  	}
   108  	want = loadMetacacheSampleNames[:5]
   109  	if entries.len() != len(want) {
   110  		t.Fatal("unexpected length:", entries.len(), "want:", len(want))
   111  	}
   112  
   113  	for i, entry := range entries.entries() {
   114  		if entry.name != want[i] {
   115  			t.Errorf("entry %d, want %q, got %q", i, want[i], entry.name)
   116  		}
   117  	}
   118  }
   119  
   120  func Test_metacacheReader_readNDirs(t *testing.T) {
   121  	r := loadMetacacheSample(t)
   122  	defer r.Close()
   123  	entries, err := r.readN(-1, false, true, "")
   124  	if err != io.EOF {
   125  		t.Fatal(err, entries.len())
   126  	}
   127  	want := loadMetacacheSampleNames
   128  	var noDirs []string
   129  	for i, entry := range entries.entries() {
   130  		if entry.name != want[i] {
   131  			t.Errorf("entry %d, want %q, got %q", i, want[i], entry.name)
   132  		}
   133  		if !entry.isDir() {
   134  			noDirs = append(noDirs, entry.name)
   135  		}
   136  	}
   137  	if entries.len() != len(want) {
   138  		t.Fatal("unexpected length:", entries.len(), "want:", len(want))
   139  	}
   140  
   141  	want = noDirs
   142  	r = loadMetacacheSample(t)
   143  	defer r.Close()
   144  	entries, err = r.readN(-1, false, false, "")
   145  	if err != io.EOF {
   146  		t.Fatal(err, entries.len())
   147  	}
   148  	for i, entry := range entries.entries() {
   149  		if entry.name != want[i] {
   150  			t.Errorf("entry %d, want %q, got %q", i, want[i], entry.name)
   151  		}
   152  	}
   153  	if entries.len() != len(want) {
   154  		t.Fatal("unexpected length:", entries.len(), "want:", len(want))
   155  	}
   156  
   157  	want = want[:0]
   158  	entries, err = r.readN(0, false, false, "")
   159  	if err != nil {
   160  		t.Fatal(err, entries.len())
   161  	}
   162  	if entries.len() != len(want) {
   163  		t.Fatal("unexpected length:", entries.len(), "want:", len(want))
   164  	}
   165  
   166  	// Reload.
   167  	r = loadMetacacheSample(t)
   168  	defer r.Close()
   169  	entries, err = r.readN(0, false, false, "")
   170  	if err != nil {
   171  		t.Fatal(err, entries.len())
   172  	}
   173  	if entries.len() != len(want) {
   174  		t.Fatal("unexpected length:", entries.len(), "want:", len(want))
   175  	}
   176  
   177  	entries, err = r.readN(5, false, false, "")
   178  	if err != nil {
   179  		t.Fatal(err, entries.len())
   180  	}
   181  	want = noDirs[:5]
   182  	if entries.len() != len(want) {
   183  		t.Fatal("unexpected length:", entries.len(), "want:", len(want))
   184  	}
   185  
   186  	for i, entry := range entries.entries() {
   187  		if entry.name != want[i] {
   188  			t.Errorf("entry %d, want %q, got %q", i, want[i], entry.name)
   189  		}
   190  	}
   191  }
   192  
   193  func Test_metacacheReader_readNPrefix(t *testing.T) {
   194  	r := loadMetacacheSample(t)
   195  	defer r.Close()
   196  	entries, err := r.readN(-1, false, true, "src/compress/bzip2/")
   197  	if err != io.EOF {
   198  		t.Fatal(err, entries.len())
   199  	}
   200  	want := loadMetacacheSampleNames[:16]
   201  	for i, entry := range entries.entries() {
   202  		if entry.name != want[i] {
   203  			t.Errorf("entry %d, want %q, got %q", i, want[i], entry.name)
   204  		}
   205  	}
   206  	if entries.len() != len(want) {
   207  		t.Fatal("unexpected length:", entries.len(), "want:", len(want))
   208  	}
   209  
   210  	r = loadMetacacheSample(t)
   211  	defer r.Close()
   212  	entries, err = r.readN(-1, false, true, "src/nonexist")
   213  	if err != io.EOF {
   214  		t.Fatal(err, entries.len())
   215  	}
   216  	want = loadMetacacheSampleNames[:0]
   217  	if entries.len() != len(want) {
   218  		t.Fatal("unexpected length:", entries.len(), "want:", len(want))
   219  	}
   220  	for i, entry := range entries.entries() {
   221  		if entry.name != want[i] {
   222  			t.Errorf("entry %d, want %q, got %q", i, want[i], entry.name)
   223  		}
   224  	}
   225  
   226  	r = loadMetacacheSample(t)
   227  	defer r.Close()
   228  	entries, err = r.readN(-1, false, true, "src/a")
   229  	if err != io.EOF {
   230  		t.Fatal(err, entries.len())
   231  	}
   232  	want = loadMetacacheSampleNames[:0]
   233  	if entries.len() != len(want) {
   234  		t.Fatal("unexpected length:", entries.len(), "want:", len(want))
   235  	}
   236  	for i, entry := range entries.entries() {
   237  		if entry.name != want[i] {
   238  			t.Errorf("entry %d, want %q, got %q", i, want[i], entry.name)
   239  		}
   240  	}
   241  
   242  	r = loadMetacacheSample(t)
   243  	defer r.Close()
   244  	entries, err = r.readN(-1, false, true, "src/compress/zlib/e")
   245  	if err != io.EOF {
   246  		t.Fatal(err, entries.len())
   247  	}
   248  	want = []string{"src/compress/zlib/example_test.go"}
   249  	if entries.len() != len(want) {
   250  		t.Fatal("unexpected length:", entries.len(), "want:", len(want))
   251  	}
   252  	for i, entry := range entries.entries() {
   253  		if entry.name != want[i] {
   254  			t.Errorf("entry %d, want %q, got %q", i, want[i], entry.name)
   255  		}
   256  	}
   257  }
   258  
   259  func Test_metacacheReader_readFn(t *testing.T) {
   260  	r := loadMetacacheSample(t)
   261  	defer r.Close()
   262  	i := 0
   263  	err := r.readFn(func(entry metaCacheEntry) bool {
   264  		want := loadMetacacheSampleNames[i]
   265  		if entry.name != want {
   266  			t.Errorf("entry %d, want %q, got %q", i, want, entry.name)
   267  		}
   268  		i++
   269  		return true
   270  	})
   271  	if err != io.EOF {
   272  		t.Fatal(err)
   273  	}
   274  }
   275  
   276  func Test_metacacheReader_readAll(t *testing.T) {
   277  	r := loadMetacacheSample(t)
   278  	defer r.Close()
   279  	var readErr error
   280  	objs := make(chan metaCacheEntry, 1)
   281  	var wg sync.WaitGroup
   282  	wg.Add(1)
   283  	go func() {
   284  		readErr = r.readAll(context.Background(), objs)
   285  		wg.Done()
   286  	}()
   287  	want := loadMetacacheSampleNames
   288  	i := 0
   289  	for entry := range objs {
   290  		if entry.name != want[i] {
   291  			t.Errorf("entry %d, want %q, got %q", i, want[i], entry.name)
   292  		}
   293  		i++
   294  	}
   295  	wg.Wait()
   296  	if readErr != nil {
   297  		t.Fatal(readErr)
   298  	}
   299  }
   300  
   301  func Test_metacacheReader_forwardTo(t *testing.T) {
   302  	r := loadMetacacheSample(t)
   303  	defer r.Close()
   304  	err := r.forwardTo("src/compress/zlib/reader_test.go")
   305  	if err != nil {
   306  		t.Fatal(err)
   307  	}
   308  	names, err := r.readNames(-1)
   309  	if err != io.EOF {
   310  		t.Fatal(err)
   311  	}
   312  	want := []string{"src/compress/zlib/reader_test.go", "src/compress/zlib/writer.go", "src/compress/zlib/writer_test.go"}
   313  	if !reflect.DeepEqual(names, want) {
   314  		t.Errorf("got unexpected result: %#v", names)
   315  	}
   316  
   317  	// Try with prefix
   318  	r = loadMetacacheSample(t)
   319  	err = r.forwardTo("src/compress/zlib/reader_t")
   320  	if err != nil {
   321  		t.Fatal(err)
   322  	}
   323  	names, err = r.readNames(-1)
   324  	if err != io.EOF {
   325  		t.Fatal(err)
   326  	}
   327  	if !reflect.DeepEqual(names, want) {
   328  		t.Errorf("got unexpected result: %#v", names)
   329  	}
   330  }
   331  
   332  func Test_metacacheReader_next(t *testing.T) {
   333  	r := loadMetacacheSample(t)
   334  	defer r.Close()
   335  	for i, want := range loadMetacacheSampleNames {
   336  		gotObj, err := r.next()
   337  		if err != nil {
   338  			t.Fatal(err)
   339  		}
   340  		if gotObj.name != want {
   341  			t.Errorf("entry %d, want %q, got %q", i, want, gotObj.name)
   342  		}
   343  	}
   344  }
   345  func Test_metacacheReader_peek(t *testing.T) {
   346  	r := loadMetacacheSample(t)
   347  	defer r.Close()
   348  	for i, want := range loadMetacacheSampleNames {
   349  		got, err := r.peek()
   350  		if err == io.EOF {
   351  			break
   352  		}
   353  		if err != nil {
   354  			t.Fatal(err)
   355  		}
   356  		if got.name != want {
   357  			t.Errorf("entry %d, want %q, got %q", i, want, got.name)
   358  		}
   359  		gotObj, err := r.next()
   360  		if err != nil {
   361  			t.Fatal(err)
   362  		}
   363  		if gotObj.name != want {
   364  			t.Errorf("entry %d, want %q, got %q", i, want, gotObj.name)
   365  		}
   366  	}
   367  }
   368  
   369  func Test_newMetacacheStream(t *testing.T) {
   370  	r := loadMetacacheSample(t)
   371  	var buf bytes.Buffer
   372  	w := newMetacacheWriter(&buf, 1<<20)
   373  	defer w.Close()
   374  	err := r.readFn(func(object metaCacheEntry) bool {
   375  		err := w.write(object)
   376  		if err != nil {
   377  			t.Fatal(err)
   378  		}
   379  		return true
   380  	})
   381  	r.Close()
   382  	if err != io.EOF {
   383  		t.Fatal(err)
   384  	}
   385  	err = w.Close()
   386  	if err != nil {
   387  		t.Fatal(err)
   388  	}
   389  
   390  	r, err = newMetacacheReader(&buf)
   391  	if err != nil {
   392  		t.Fatal(err)
   393  	}
   394  	defer r.Close()
   395  	names, err := r.readNames(-1)
   396  	if err != io.EOF {
   397  		t.Fatal(err)
   398  	}
   399  	want := loadMetacacheSampleNames
   400  	if !reflect.DeepEqual(names, want) {
   401  		t.Errorf("got unexpected result: %#v", names)
   402  	}
   403  }
   404  
   405  func Test_metacacheReader_skip(t *testing.T) {
   406  	r := loadMetacacheSample(t)
   407  	defer r.Close()
   408  	names, err := r.readNames(5)
   409  	if err != nil {
   410  		t.Fatal(err)
   411  	}
   412  	want := loadMetacacheSampleNames[:5]
   413  	if !reflect.DeepEqual(names, want) {
   414  		t.Errorf("got unexpected result: %#v", names)
   415  	}
   416  	err = r.skip(5)
   417  	if err != nil {
   418  		t.Fatal(err)
   419  	}
   420  	names, err = r.readNames(5)
   421  	if err != nil {
   422  		t.Fatal(err)
   423  	}
   424  	want = loadMetacacheSampleNames[10:15]
   425  	if !reflect.DeepEqual(names, want) {
   426  		t.Errorf("got unexpected result: %#v", names)
   427  	}
   428  
   429  	err = r.skip(len(loadMetacacheSampleNames))
   430  	if err != io.EOF {
   431  		t.Fatal(err)
   432  	}
   433  }