 d8b68e3ccc
			
		
	
	d8b68e3ccc
	
	
	
		
			
			From golangci-lint: > SA1019: rand.Read has been deprecated since Go 1.20 because it >shouldn't be used: For almost all use cases, crypto/rand.Read is more >appropriate. (staticcheck) > SA1019: rand.Seed has been deprecated since Go 1.20 and an alternative >has been available since Go 1.0: Programs that call Seed and then expect >a specific sequence of results from the global random source (using >functions such as Int) can be broken when a dependency changes how >much it consumes from the global random source. To avoid such breakages, >programs that need a specific result sequence should use >NewRand(NewSource(seed)) to obtain a random generator that other >packages cannot access. (staticcheck) See also: - https://pkg.go.dev/math/rand@go1.20#Read - https://pkg.go.dev/math/rand@go1.20#Seed Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
		
			
				
	
	
		
			169 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| /*
 | |
|    Copyright The containerd Authors.
 | |
| 
 | |
|    Licensed under the Apache License, Version 2.0 (the "License");
 | |
|    you may not use this file except in compliance with the License.
 | |
|    You may obtain a copy of the License at
 | |
| 
 | |
|        http://www.apache.org/licenses/LICENSE-2.0
 | |
| 
 | |
|    Unless required by applicable law or agreed to in writing, software
 | |
|    distributed under the License is distributed on an "AS IS" BASIS,
 | |
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
|    See the License for the specific language governing permissions and
 | |
|    limitations under the License.
 | |
| */
 | |
| 
 | |
| package testsuite
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 	"os"
 | |
| 
 | |
| 	"github.com/containerd/containerd/mount"
 | |
| 	"github.com/containerd/containerd/pkg/randutil"
 | |
| 	"github.com/containerd/containerd/snapshots"
 | |
| 	"github.com/containerd/continuity/fs/fstest"
 | |
| )
 | |
| 
 | |
| func applyToMounts(m []mount.Mount, work string, a fstest.Applier) (err error) {
 | |
| 	td, err := os.MkdirTemp(work, "prepare")
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("failed to create temp dir: %w", err)
 | |
| 	}
 | |
| 	defer os.RemoveAll(td)
 | |
| 
 | |
| 	if err := mount.All(m, td); err != nil {
 | |
| 		return fmt.Errorf("failed to mount: %w", err)
 | |
| 	}
 | |
| 	defer func() {
 | |
| 		if err1 := mount.UnmountAll(td, umountflags); err1 != nil && err == nil {
 | |
| 			err = fmt.Errorf("failed to unmount: %w", err1)
 | |
| 		}
 | |
| 	}()
 | |
| 
 | |
| 	return a.Apply(td)
 | |
| }
 | |
| 
 | |
| // createSnapshot creates a new snapshot in the snapshotter
 | |
| // given an applier to run on top of the given parent.
 | |
| func createSnapshot(ctx context.Context, sn snapshots.Snapshotter, parent, work string, a fstest.Applier) (string, error) {
 | |
| 	n := fmt.Sprintf("%p-%d", a, randutil.Int())
 | |
| 	prepare := fmt.Sprintf("%s-prepare", n)
 | |
| 
 | |
| 	m, err := sn.Prepare(ctx, prepare, parent, opt)
 | |
| 	if err != nil {
 | |
| 		return "", fmt.Errorf("failed to prepare snapshot: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	if err := applyToMounts(m, work, a); err != nil {
 | |
| 		return "", fmt.Errorf("failed to apply: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	if err := sn.Commit(ctx, n, prepare, opt); err != nil {
 | |
| 		return "", fmt.Errorf("failed to commit: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	return n, nil
 | |
| }
 | |
| 
 | |
| func checkSnapshot(ctx context.Context, sn snapshots.Snapshotter, work, name, check string) (err error) {
 | |
| 	td, err := os.MkdirTemp(work, "check")
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("failed to create temp dir: %w", err)
 | |
| 	}
 | |
| 	defer func() {
 | |
| 		if err1 := os.RemoveAll(td); err1 != nil && err == nil {
 | |
| 			err = fmt.Errorf("failed to remove temporary directory %s: %w", td, err1)
 | |
| 		}
 | |
| 	}()
 | |
| 
 | |
| 	view := fmt.Sprintf("%s-view", name)
 | |
| 	m, err := sn.View(ctx, view, name, opt)
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("failed to create view: %w", err)
 | |
| 	}
 | |
| 	defer func() {
 | |
| 		if err1 := sn.Remove(ctx, view); err1 != nil && err == nil {
 | |
| 			err = fmt.Errorf("failed to remove view: %w", err1)
 | |
| 		}
 | |
| 	}()
 | |
| 
 | |
| 	if err := mount.All(m, td); err != nil {
 | |
| 		return fmt.Errorf("failed to mount: %w", err)
 | |
| 	}
 | |
| 	defer func() {
 | |
| 		if err1 := mount.UnmountAll(td, umountflags); err1 != nil && err == nil {
 | |
| 			err = fmt.Errorf("failed to unmount view: %w", err1)
 | |
| 		}
 | |
| 	}()
 | |
| 
 | |
| 	if err := fstest.CheckDirectoryEqual(check, td); err != nil {
 | |
| 		return fmt.Errorf("check directory failed: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // checkSnapshots creates a new chain of snapshots in the given snapshotter
 | |
| // using the provided appliers, checking each snapshot created in a view
 | |
| // against the changes applied to a single directory.
 | |
| func checkSnapshots(ctx context.Context, sn snapshots.Snapshotter, work string, as ...fstest.Applier) error {
 | |
| 	td, err := os.MkdirTemp(work, "flat")
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("failed to create temp dir: %w", err)
 | |
| 	}
 | |
| 	defer os.RemoveAll(td)
 | |
| 
 | |
| 	var parentID string
 | |
| 	for i, a := range as {
 | |
| 		s, err := createSnapshot(ctx, sn, parentID, work, a)
 | |
| 		if err != nil {
 | |
| 			return fmt.Errorf("failed to create snapshot %d: %w", i+1, err)
 | |
| 		}
 | |
| 
 | |
| 		if err := a.Apply(td); err != nil {
 | |
| 			return fmt.Errorf("failed to apply to check directory on %d: %w", i+1, err)
 | |
| 		}
 | |
| 
 | |
| 		if err := checkSnapshot(ctx, sn, work, s, td); err != nil {
 | |
| 			return fmt.Errorf("snapshot check failed on snapshot %d: %w", i+1, err)
 | |
| 		}
 | |
| 
 | |
| 		parentID = s
 | |
| 	}
 | |
| 	return nil
 | |
| 
 | |
| }
 | |
| 
 | |
| // checkInfo checks that the infos are the same
 | |
| func checkInfo(si1, si2 snapshots.Info) error {
 | |
| 	if si1.Kind != si2.Kind {
 | |
| 		return fmt.Errorf("expected kind %v, got %v", si1.Kind, si2.Kind)
 | |
| 	}
 | |
| 	if si1.Name != si2.Name {
 | |
| 		return fmt.Errorf("expected name %v, got %v", si1.Name, si2.Name)
 | |
| 	}
 | |
| 	if si1.Parent != si2.Parent {
 | |
| 		return fmt.Errorf("expected Parent %v, got %v", si1.Parent, si2.Parent)
 | |
| 	}
 | |
| 	if len(si1.Labels) != len(si2.Labels) {
 | |
| 		return fmt.Errorf("expected %d labels, got %d", len(si1.Labels), len(si2.Labels))
 | |
| 	}
 | |
| 	for k, l1 := range si1.Labels {
 | |
| 		l2 := si2.Labels[k]
 | |
| 		if l1 != l2 {
 | |
| 			return fmt.Errorf("expected label %v, got %v", l1, l2)
 | |
| 		}
 | |
| 	}
 | |
| 	if si1.Created != si2.Created {
 | |
| 		return fmt.Errorf("expected Created %v, got %v", si1.Created, si2.Created)
 | |
| 	}
 | |
| 	if si1.Updated != si2.Updated {
 | |
| 		return fmt.Errorf("expected Updated %v, got %v", si1.Updated, si2.Updated)
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 |