github.com/opencontainers/umoci@v0.4.8-0.20240508124516-656e4836fb0d/pkg/mtreefilter/mask_test.go (about)

     1  /*
     2   * umoci: Umoci Modifies Open Containers' Images
     3   * Copyright (C) 2016-2020 SUSE LLC
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *    http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  
    18  package mtreefilter
    19  
    20  import (
    21  	"io/ioutil"
    22  	"os"
    23  	"path/filepath"
    24  	"testing"
    25  
    26  	"github.com/vbatts/go-mtree"
    27  )
    28  
    29  func isParent(a, b string) bool {
    30  	a = filepath.Clean(a)
    31  	b = filepath.Clean(b)
    32  
    33  	for a != b && b != filepath.Dir(b) {
    34  		b = filepath.Dir(b)
    35  	}
    36  	return a == b
    37  }
    38  
    39  func TestMaskDeltas(t *testing.T) {
    40  	dir, err := ioutil.TempDir("", "TestMaskDeltas-")
    41  	if err != nil {
    42  		t.Fatal(err)
    43  	}
    44  	defer os.RemoveAll(dir)
    45  
    46  	mtreeKeywords := append(mtree.DefaultKeywords, "sha256digest")
    47  
    48  	// Create some files.
    49  	if err != ioutil.WriteFile(filepath.Join(dir, "file1"), []byte("contents"), 0644) {
    50  		t.Fatal(err)
    51  	}
    52  	if err != ioutil.WriteFile(filepath.Join(dir, "file2"), []byte("another content"), 0644) {
    53  		t.Fatal(err)
    54  	}
    55  	if err != os.MkdirAll(filepath.Join(dir, "dir", "child"), 0755) {
    56  		t.Fatal(err)
    57  	}
    58  	if err != os.MkdirAll(filepath.Join(dir, "dir", "child2"), 0755) {
    59  		t.Fatal(err)
    60  	}
    61  	if err != ioutil.WriteFile(filepath.Join(dir, "dir", "file 3"), []byte("more content"), 0644) {
    62  		t.Fatal(err)
    63  	}
    64  	if err != ioutil.WriteFile(filepath.Join(dir, "dir", "child2", "4 files"), []byte("very content"), 0644) {
    65  		t.Fatal(err)
    66  	}
    67  
    68  	// Generate a diff.
    69  	originalDh, err := mtree.Walk(dir, nil, mtreeKeywords, nil)
    70  	if err != nil {
    71  		t.Fatal(err)
    72  	}
    73  
    74  	// Modify the root.
    75  	if err := os.RemoveAll(filepath.Join(dir, "file2")); err != nil {
    76  		t.Fatal(err)
    77  	}
    78  	if err := ioutil.WriteFile(filepath.Join(dir, "dir", "new"), []byte("more content"), 0755); err != nil {
    79  		t.Fatal(err)
    80  	}
    81  	if err := ioutil.WriteFile(filepath.Join(dir, "file1"), []byte("different contents"), 0666); err != nil {
    82  		t.Fatal(err)
    83  	}
    84  
    85  	// Generate the set of diffs.
    86  	newDh, err := mtree.Walk(dir, nil, mtreeKeywords, nil)
    87  	if err != nil {
    88  		t.Fatal(err)
    89  	}
    90  	diff, err := mtree.Compare(originalDh, newDh, mtreeKeywords)
    91  	if err != nil {
    92  		t.Fatal(err)
    93  	}
    94  
    95  	for _, test := range []struct {
    96  		paths []string
    97  	}{
    98  		{nil},
    99  		{[]string{"/"}},
   100  		{[]string{"dir"}},
   101  		{[]string{filepath.Join("dir", "child2")}},
   102  		{[]string{"file2"}},
   103  		{[]string{"/", "file2"}},
   104  		{[]string{"file2", filepath.Join("dir", "child2")}},
   105  	} {
   106  		simpleDiff := FilterDeltas(diff, MaskFilter(test.paths))
   107  		for _, delta := range simpleDiff {
   108  			if len(test.paths) == 0 {
   109  				if len(simpleDiff) != len(diff) {
   110  					t.Errorf("expected diff={} to give %d got %d", len(diff), len(simpleDiff))
   111  				}
   112  			} else {
   113  				found := false
   114  				for _, path := range test.paths {
   115  					if !isParent(path, delta.Path()) {
   116  						found = true
   117  					}
   118  				}
   119  				if !found {
   120  					t.Errorf("expected one of %v to not be a parent of %q", test.paths, delta.Path())
   121  				}
   122  			}
   123  		}
   124  	}
   125  }
   126  
   127  func TestSimplifyFilter(t *testing.T) {
   128  	dir, err := ioutil.TempDir("", "TestSimplifyFilter-")
   129  	if err != nil {
   130  		t.Fatal(err)
   131  	}
   132  	defer os.RemoveAll(dir)
   133  
   134  	mtreeKeywords := append(mtree.DefaultKeywords, "sha256digest")
   135  
   136  	// Create some nested directories we can remove.
   137  	if err != os.MkdirAll(filepath.Join(dir, "some", "path", "to", "remove"), 0755) {
   138  		t.Fatal(err)
   139  	}
   140  	if err != ioutil.WriteFile(filepath.Join(dir, "some", "path", "to", "remove", "child"), []byte("very content"), 0644) {
   141  		t.Fatal(err)
   142  	}
   143  
   144  	// Generate a diff.
   145  	originalDh, err := mtree.Walk(dir, nil, mtreeKeywords, nil)
   146  	if err != nil {
   147  		t.Fatal(err)
   148  	}
   149  
   150  	// Modify the root.
   151  	if err := os.RemoveAll(filepath.Join(dir, "some")); err != nil {
   152  		t.Fatal(err)
   153  	}
   154  
   155  	// Generate the set of diffs.
   156  	newDh, err := mtree.Walk(dir, nil, mtreeKeywords, nil)
   157  	if err != nil {
   158  		t.Fatal(err)
   159  	}
   160  	diff, err := mtree.Compare(originalDh, newDh, mtreeKeywords)
   161  	if err != nil {
   162  		t.Fatal(err)
   163  	}
   164  
   165  	// We expect to see a deletion for each entry.
   166  	var sawDeletions int
   167  	for _, delta := range diff {
   168  		if delta.Type() == mtree.Missing {
   169  			sawDeletions++
   170  		}
   171  	}
   172  	if sawDeletions != 5 {
   173  		t.Errorf("expected to see 5 deletions with stock Compare, saw %v", sawDeletions)
   174  	}
   175  
   176  	// Simplify the diffs.
   177  	simpleDiff := FilterDeltas(diff, SimplifyFilter(diff))
   178  	if len(simpleDiff) >= len(diff) {
   179  		t.Errorf("expected simplified diff to be shorter (%v >= %v)", len(simpleDiff), len(diff))
   180  	}
   181  	var sawSimpleDeletions int
   182  	for _, delta := range simpleDiff {
   183  		if delta.Type() == mtree.Missing {
   184  			sawSimpleDeletions++
   185  		}
   186  	}
   187  	if sawSimpleDeletions != 1 {
   188  		t.Errorf("expected to see 1 deletion with simplified filter, saw %v", sawSimpleDeletions)
   189  	}
   190  }