github.com/google/osv-scalibr@v0.4.1/extractor/standalone/containers/docker/docker_test.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 docker_test 16 17 import ( 18 "testing" 19 20 "github.com/docker/docker/api/types/container" 21 "github.com/google/go-cmp/cmp" 22 "github.com/google/go-cmp/cmp/cmpopts" 23 "github.com/google/osv-scalibr/extractor" 24 "github.com/google/osv-scalibr/extractor/standalone" 25 plugin "github.com/google/osv-scalibr/extractor/standalone/containers/docker" 26 "github.com/google/osv-scalibr/extractor/standalone/containers/docker/fakeclient" 27 ) 28 29 func TestExtract(t *testing.T) { 30 tests := []struct { 31 name string 32 // ctrs values are extracted using `docker inspect <containerID>` 33 // some fields of `container.Summary` are omitted 34 ctrs []container.Summary 35 wantInventory []*extractor.Package 36 }{ 37 { 38 name: "valid with no container", 39 ctrs: []container.Summary{}, 40 wantInventory: []*extractor.Package{}, 41 }, 42 { 43 name: "valid_with_one_container", 44 ctrs: []container.Summary{ 45 { 46 ID: "3ea6adad2e94daf386e1d6c5960807b41f19da2333e8a6261065c1cb8e85ac81", 47 Names: []string{"redis_server"}, 48 Image: "redis", 49 ImageID: "sha256:a8036f14f15ead9517115576fb4462894a000620c2be556410f6c24afb8a482b", 50 Command: "docker-entrypoint.sh redis-server", 51 Created: 1742382918, 52 Ports: []container.Port{{IP: "127.0.0.1", PrivatePort: 6379, PublicPort: 1112, Type: "tcp"}}, 53 SizeRw: 0, 54 SizeRootFs: 0, 55 Labels: map[string]string{}, 56 State: "running", 57 Status: "Up 4 days", 58 }, 59 }, 60 wantInventory: []*extractor.Package{ 61 { 62 Name: "redis", 63 Version: "sha256:a8036f14f15ead9517115576fb4462894a000620c2be556410f6c24afb8a482b", 64 Metadata: &plugin.Metadata{ 65 ImageName: "redis", 66 ImageDigest: "sha256:a8036f14f15ead9517115576fb4462894a000620c2be556410f6c24afb8a482b", 67 ID: "3ea6adad2e94daf386e1d6c5960807b41f19da2333e8a6261065c1cb8e85ac81", 68 Ports: []container.Port{{IP: "127.0.0.1", PrivatePort: 6379, PublicPort: 1112, Type: "tcp"}}, 69 }, 70 }, 71 }, 72 }, 73 { 74 name: "valid_with_one_container_running", 75 ctrs: []container.Summary{ 76 { 77 ID: "3ea6adad2e94daf386e1d6c5960807b41f19da2333e8a6261065c1cb8e85ac81", 78 Names: []string{"redis_server"}, 79 Image: "redis", 80 ImageID: "sha256:a8036f14f15ead9517115576fb4462894a000620c2be556410f6c24afb8a482b", 81 Command: "docker-entrypoint.sh redis-server", 82 Created: 1742382918, 83 Ports: []container.Port{{IP: "127.0.0.1", PrivatePort: 6379, PublicPort: 1112, Type: "tcp"}}, 84 Labels: map[string]string{}, 85 State: "running", 86 Status: "Up 4 days", 87 }, 88 { 89 ID: "57eaa9ded450bde6c214dfdced8897d6bb67f1611fa6befffc7a768b5d1cbc5a", 90 Names: []string{"postgres_server"}, 91 Image: "postgres", 92 ImageID: "sha256:e92968df83750a723114bf998e3e323dda53e4c5c3ea42b22dd6ad6e3df80ca5", 93 Command: "docker-entrypoint.sh postgres", 94 Created: 1742814002, 95 Ports: []container.Port{}, 96 Labels: map[string]string{}, 97 State: "exited", 98 Status: "Exited (1) 2 minutes ago", 99 }, 100 }, 101 wantInventory: []*extractor.Package{ 102 { 103 Name: "redis", 104 Version: "sha256:a8036f14f15ead9517115576fb4462894a000620c2be556410f6c24afb8a482b", 105 Metadata: &plugin.Metadata{ 106 ImageName: "redis", 107 ImageDigest: "sha256:a8036f14f15ead9517115576fb4462894a000620c2be556410f6c24afb8a482b", 108 ID: "3ea6adad2e94daf386e1d6c5960807b41f19da2333e8a6261065c1cb8e85ac81", 109 Ports: []container.Port{{IP: "127.0.0.1", PrivatePort: 6379, PublicPort: 1112, Type: "tcp"}}, 110 }, 111 }, 112 }, 113 }, 114 { 115 name: "valid_two_containers_running", 116 ctrs: []container.Summary{ 117 { 118 ID: "3ea6adad2e94daf386e1d6c5960807b41f19da2333e8a6261065c1cb8e85ac81", 119 Names: []string{"redis_server"}, 120 Image: "redis", 121 ImageID: "sha256:a8036f14f15ead9517115576fb4462894a000620c2be556410f6c24afb8a482b", 122 Command: "docker-entrypoint.sh redis-server", 123 Created: 1742382918, 124 Ports: []container.Port{{IP: "127.0.0.1", PrivatePort: 6379, PublicPort: 1112, Type: "tcp"}}, 125 Labels: map[string]string{}, 126 State: "running", 127 Status: "Up 4 days", 128 }, 129 { 130 ID: "57eaa9ded450bde6c214dfdced8897d6bb67f1611fa6befffc7a768b5d1cbc5a", 131 Names: []string{"postgres_server"}, 132 Image: "postgres", 133 ImageID: "sha256:e92968df83750a723114bf998e3e323dda53e4c5c3ea42b22dd6ad6e3df80ca5", 134 Command: "docker-entrypoint.sh postgres", 135 Created: 1742814376, 136 Ports: []container.Port{{IP: "", PrivatePort: 5432, PublicPort: 0, Type: "tcp"}}, 137 Labels: map[string]string{}, 138 State: "running", 139 Status: "Up 8 minutes", 140 }, 141 }, 142 wantInventory: []*extractor.Package{ 143 { 144 Name: "redis", 145 Version: "sha256:a8036f14f15ead9517115576fb4462894a000620c2be556410f6c24afb8a482b", 146 Metadata: &plugin.Metadata{ 147 ImageName: "redis", 148 ImageDigest: "sha256:a8036f14f15ead9517115576fb4462894a000620c2be556410f6c24afb8a482b", 149 ID: "3ea6adad2e94daf386e1d6c5960807b41f19da2333e8a6261065c1cb8e85ac81", 150 Ports: []container.Port{{IP: "127.0.0.1", PrivatePort: 6379, PublicPort: 1112, Type: "tcp"}}, 151 }, 152 }, 153 { 154 Name: "postgres", 155 Version: "sha256:e92968df83750a723114bf998e3e323dda53e4c5c3ea42b22dd6ad6e3df80ca5", 156 Metadata: &plugin.Metadata{ 157 ImageName: "postgres", 158 ImageDigest: "sha256:e92968df83750a723114bf998e3e323dda53e4c5c3ea42b22dd6ad6e3df80ca5", 159 ID: "57eaa9ded450bde6c214dfdced8897d6bb67f1611fa6befffc7a768b5d1cbc5a", 160 Ports: []container.Port{{IP: "", PrivatePort: 5432, PublicPort: 0, Type: "tcp"}}, 161 }, 162 }, 163 }, 164 }, 165 } 166 167 for _, tt := range tests { 168 t.Run(tt.name, func(t *testing.T) { 169 var input *standalone.ScanInput 170 171 cli := fakeclient.New(tt.ctrs) 172 e := plugin.NewWithClient(cli) 173 174 got, _ := e.Extract(t.Context(), input) 175 176 ignoreOrder := cmpopts.SortSlices(func(a, b *extractor.Package) bool { 177 return a.Name < b.Name 178 }) 179 if diff := cmp.Diff(tt.wantInventory, got.Packages, ignoreOrder); diff != "" { 180 t.Errorf("Extract(%s) (-want +got):\n%s", tt.name, diff) 181 } 182 }) 183 } 184 }