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  }