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 }