github.com/google/osv-scalibr@v0.4.1/artifact/image/layerscanning/testing/fakechainlayer/fake_chain_layer.go (about)

     1  // Copyright 2025 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package fakechainlayer provides a fake implementation of the image.ChainLayer and scalibrfs.FS
    16  // interface for testing purposes.
    17  package fakechainlayer
    18  
    19  import (
    20  	"errors"
    21  	"io/fs"
    22  	"os"
    23  	"path"
    24  	"path/filepath"
    25  
    26  	"github.com/google/osv-scalibr/artifact/image"
    27  	scalibrfs "github.com/google/osv-scalibr/fs"
    28  	"github.com/opencontainers/go-digest"
    29  )
    30  
    31  // FakeChainLayer is a fake implementation of the image.ChainLayer and scalibrfs.FS interface for
    32  // testing purposes.
    33  type FakeChainLayer struct {
    34  	index   int
    35  	command string
    36  	testDir string
    37  	diffID  digest.Digest
    38  	chainID digest.Digest
    39  	layer   image.Layer
    40  	files   map[string]string
    41  }
    42  
    43  // Config is the configuration for creating a FakeChainLayer.
    44  type Config struct {
    45  	TestDir           string
    46  	Index             int
    47  	DiffID            digest.Digest
    48  	ChainID           digest.Digest
    49  	Command           string
    50  	Layer             image.Layer
    51  	Files             map[string]string
    52  	FilesAlreadyExist bool
    53  }
    54  
    55  // New creates a new FakeChainLayer.
    56  func New(cfg *Config) (*FakeChainLayer, error) {
    57  	if cfg == nil {
    58  		return nil, errors.New("config is nil")
    59  	}
    60  
    61  	if !cfg.FilesAlreadyExist {
    62  		for name, contents := range cfg.Files {
    63  			filename := filepath.Join(cfg.TestDir, name)
    64  			if err := os.MkdirAll(filepath.Dir(filename), 0700); err != nil {
    65  				return nil, err
    66  			}
    67  
    68  			if err := os.WriteFile(filename, []byte(contents), 0600); err != nil {
    69  				return nil, err
    70  			}
    71  		}
    72  	}
    73  	return &FakeChainLayer{
    74  		index:   cfg.Index,
    75  		diffID:  cfg.DiffID,
    76  		chainID: cfg.ChainID,
    77  		command: cfg.Command,
    78  		layer:   cfg.Layer,
    79  		testDir: cfg.TestDir,
    80  		files:   cfg.Files,
    81  	}, nil
    82  }
    83  
    84  // -------------------------------------------------------------------------------------------------
    85  // image.ChainLayer implementation
    86  // -------------------------------------------------------------------------------------------------
    87  
    88  // Index returns the index of the chain layer.
    89  func (fakeChainLayer *FakeChainLayer) Index() int {
    90  	return fakeChainLayer.index
    91  }
    92  
    93  // ChainID returns the chain ID of the chain layer.
    94  func (fakeChainLayer *FakeChainLayer) ChainID() digest.Digest {
    95  	return fakeChainLayer.chainID
    96  }
    97  
    98  // Layer returns the underlying layer of the chain layer.
    99  func (fakeChainLayer *FakeChainLayer) Layer() image.Layer {
   100  	return fakeChainLayer.layer
   101  }
   102  
   103  // FS returns a scalibrfs.FS that can be used to scan for inventory. fakeChainLayer is a
   104  // scalibrfs.FS, thus this method returns itself.
   105  func (fakeChainLayer *FakeChainLayer) FS() scalibrfs.FS {
   106  	return fakeChainLayer
   107  }
   108  
   109  // -------------------------------------------------------------------------------------------------
   110  // scalibrfs.FS implementation
   111  // -------------------------------------------------------------------------------------------------
   112  
   113  // Open returns a file if it exists in the files map.
   114  func (fakeChainLayer *FakeChainLayer) Open(name string) (fs.File, error) {
   115  	return os.Open(filepath.Join(fakeChainLayer.testDir, name))
   116  }
   117  
   118  // Stat returns the file info of a file if it exists in the files map.
   119  func (fakeChainLayer *FakeChainLayer) Stat(name string) (fs.FileInfo, error) {
   120  	return os.Stat(path.Join(fakeChainLayer.testDir, name))
   121  }
   122  
   123  // ReadDir is not used in the trace package since individual files are opened instead of
   124  // directories.
   125  func (fakeChainLayer *FakeChainLayer) ReadDir(name string) ([]fs.DirEntry, error) {
   126  	return nil, errors.New("not implemented")
   127  }