diff --git a/internal/ldcache/empty.go b/internal/ldcache/empty.go new file mode 100644 index 00000000..30d3f4c8 --- /dev/null +++ b/internal/ldcache/empty.go @@ -0,0 +1,37 @@ +/** +# Copyright (c) NVIDIA CORPORATION. All rights reserved. +# +# 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 ldcache + +import "github.com/NVIDIA/nvidia-container-toolkit/internal/logger" + +type empty struct { + logger logger.Interface + path string +} + +var _ LDCache = (*empty)(nil) + +// List always returns nil for an empty ldcache +func (e *empty) List() ([]string, []string) { + return nil, nil +} + +// Lookup logs a debug message and returns nil for an empty ldcache +func (e *empty) Lookup(prefixes ...string) ([]string, []string) { + e.logger.Debugf("Calling Lookup(%v) on empty ldcache: %v", prefixes, e.path) + return nil, nil +} diff --git a/internal/ldcache/ldcache.go b/internal/ldcache/ldcache.go index 5ea263c1..2f6de2fe 100644 --- a/internal/ldcache/ldcache.go +++ b/internal/ldcache/ldcache.go @@ -81,6 +81,8 @@ type entry2 struct { } // LDCache represents the interface for performing lookups into the LDCache +// +//go:generate moq -out ldcache_mock.go . LDCache type LDCache interface { List() ([]string, []string) Lookup(...string) ([]string, []string) @@ -103,7 +105,14 @@ func New(logger logger.Interface, root string) (LDCache, error) { logger.Debugf("Opening ld.conf at %v", path) f, err := os.Open(path) - if err != nil { + if os.IsNotExist(err) { + logger.Warningf("Could not find ld.so.cache at %v; creating empty cache", path) + e := &empty{ + logger: logger, + path: path, + } + return e, nil + } else if err != nil { return nil, err } defer f.Close() diff --git a/internal/ldcache/ldcache_mock.go b/internal/ldcache/ldcache_mock.go new file mode 100644 index 00000000..092a3766 --- /dev/null +++ b/internal/ldcache/ldcache_mock.go @@ -0,0 +1,111 @@ +// Code generated by moq; DO NOT EDIT. +// github.com/matryer/moq + +package ldcache + +import ( + "sync" +) + +// Ensure, that LDCacheMock does implement LDCache. +// If this is not the case, regenerate this file with moq. +var _ LDCache = &LDCacheMock{} + +// LDCacheMock is a mock implementation of LDCache. +// +// func TestSomethingThatUsesLDCache(t *testing.T) { +// +// // make and configure a mocked LDCache +// mockedLDCache := &LDCacheMock{ +// ListFunc: func() ([]string, []string) { +// panic("mock out the List method") +// }, +// LookupFunc: func(strings ...string) ([]string, []string) { +// panic("mock out the Lookup method") +// }, +// } +// +// // use mockedLDCache in code that requires LDCache +// // and then make assertions. +// +// } +type LDCacheMock struct { + // ListFunc mocks the List method. + ListFunc func() ([]string, []string) + + // LookupFunc mocks the Lookup method. + LookupFunc func(strings ...string) ([]string, []string) + + // calls tracks calls to the methods. + calls struct { + // List holds details about calls to the List method. + List []struct { + } + // Lookup holds details about calls to the Lookup method. + Lookup []struct { + // Strings is the strings argument value. + Strings []string + } + } + lockList sync.RWMutex + lockLookup sync.RWMutex +} + +// List calls ListFunc. +func (mock *LDCacheMock) List() ([]string, []string) { + if mock.ListFunc == nil { + panic("LDCacheMock.ListFunc: method is nil but LDCache.List was just called") + } + callInfo := struct { + }{} + mock.lockList.Lock() + mock.calls.List = append(mock.calls.List, callInfo) + mock.lockList.Unlock() + return mock.ListFunc() +} + +// ListCalls gets all the calls that were made to List. +// Check the length with: +// +// len(mockedLDCache.ListCalls()) +func (mock *LDCacheMock) ListCalls() []struct { +} { + var calls []struct { + } + mock.lockList.RLock() + calls = mock.calls.List + mock.lockList.RUnlock() + return calls +} + +// Lookup calls LookupFunc. +func (mock *LDCacheMock) Lookup(strings ...string) ([]string, []string) { + if mock.LookupFunc == nil { + panic("LDCacheMock.LookupFunc: method is nil but LDCache.Lookup was just called") + } + callInfo := struct { + Strings []string + }{ + Strings: strings, + } + mock.lockLookup.Lock() + mock.calls.Lookup = append(mock.calls.Lookup, callInfo) + mock.lockLookup.Unlock() + return mock.LookupFunc(strings...) +} + +// LookupCalls gets all the calls that were made to Lookup. +// Check the length with: +// +// len(mockedLDCache.LookupCalls()) +func (mock *LDCacheMock) LookupCalls() []struct { + Strings []string +} { + var calls []struct { + Strings []string + } + mock.lockLookup.RLock() + calls = mock.calls.Lookup + mock.lockLookup.RUnlock() + return calls +}