func TestRemoveContainerReferenceFromImageStateWithNoReference(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() client := NewMockDockerClient(ctrl) imageManager := &dockerImageManager{ client: client, state: dockerstate.NewDockerTaskEngineState(), minimumAgeBeforeDeletion: config.DefaultImageDeletionAge, numImagesToDelete: config.DefaultNumImagesToDeletePerCycle, imageCleanupTimeInterval: config.DefaultImageCleanupTimeInterval, } container := &api.Container{ Name: "testContainer", Image: "testContainerImage", } sourceImage := &image.Image{ ImageID: "sha256:qwerty", } sourceImageState := &image.ImageState{ Image: sourceImage, PulledAt: time.Now(), } imageManager.addImageState(sourceImageState) imageInspected := &docker.Image{ ID: "sha256:qwerty", } client.EXPECT().InspectImage(container.Image).Return(imageInspected, nil).AnyTimes() err := imageManager.RemoveContainerReferenceFromImageState(container) if err == nil { t.Error("Expected error removing non-existing container reference from image state") } }
func TestGetLeastRecentlyUsedImagesLessThanFive(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() client := NewMockDockerClient(ctrl) imageManager := &dockerImageManager{ client: client, state: dockerstate.NewDockerTaskEngineState(), minimumAgeBeforeDeletion: config.DefaultImageDeletionAge, numImagesToDelete: config.DefaultNumImagesToDeletePerCycle, imageCleanupTimeInterval: config.DefaultImageCleanupTimeInterval, } imageStateA := &image.ImageState{ LastUsedAt: time.Now().AddDate(0, -5, 0), } imageStateB := &image.ImageState{ LastUsedAt: time.Now().AddDate(0, -3, 0), } imageStateC := &image.ImageState{ LastUsedAt: time.Now().AddDate(0, -2, 0), } candidateImagesForDeletion := []*image.ImageState{ imageStateA, imageStateB, imageStateC, } expectedLeastRecentlyUsedImages := []*image.ImageState{ imageStateA, imageStateB, imageStateC, } leastRecentlyUsedImage := imageManager.getLeastRecentlyUsedImage(candidateImagesForDeletion) if !reflect.DeepEqual(leastRecentlyUsedImage, expectedLeastRecentlyUsedImages[0]) { t.Error("Incorrect order of least recently used images") } }
func TestDeleteImageOtherRemoveImageErrors(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() client := NewMockDockerClient(ctrl) imageManager := &dockerImageManager{client: client, state: dockerstate.NewDockerTaskEngineState()} imageManager.SetSaver(statemanager.NewNoopStateManager()) container := &api.Container{ Name: "testContainer", Image: "testContainerImage", } imageInspected := &docker.Image{ ID: "sha256:qwerty", } client.EXPECT().InspectImage(container.Image).Return(imageInspected, nil).AnyTimes() err := imageManager.AddContainerReferenceToImageState(container) if err != nil { t.Error("Error in adding container to an existing image state") } imageState, _ := imageManager.getImageState(imageInspected.ID) client.EXPECT().RemoveImage(container.Image, removeImageTimeout).Return(errors.New("container for this image exists")) imageManager.deleteImage(container.Image, imageState) if len(imageState.Image.Names) == 0 { t.Error("Incorrectly removed Image name from image state") } if len(imageManager.getAllImageStates()) == 0 { t.Error("Incorrecting removed image state from image manager before deletion") } }
func TestAddContainerReferenceToImageStateInspectError(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() client := NewMockDockerClient(ctrl) imageManager := &dockerImageManager{ client: client, state: dockerstate.NewDockerTaskEngineState(), minimumAgeBeforeDeletion: config.DefaultImageDeletionAge, numImagesToDelete: config.DefaultNumImagesToDeletePerCycle, imageCleanupTimeInterval: config.DefaultImageCleanupTimeInterval, } container := &api.Container{ Name: "testContainer", Image: "testContainerImage", } sourceImage := &image.Image{ ImageID: "sha256:qwerty", } sourceImageState := &image.ImageState{ Image: sourceImage, PulledAt: time.Now(), } sourceImageState.AddImageName(container.Image) imageManager.addImageState(sourceImageState) client.EXPECT().InspectImage(container.Image).Return(nil, errors.New("error inspecting")).AnyTimes() err := imageManager.AddContainerReferenceToImageState(container) if err == nil { t.Error("Expected error in inspecting image while adding container to image state") } }
func TestAddContainerReferenceToNewImageStateAddedState(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() client := NewMockDockerClient(ctrl) imageManager := &dockerImageManager{client: client, state: dockerstate.NewDockerTaskEngineState()} imageID := "sha256:qwerty" var imageSize int64 imageSize = 18767 container := &api.Container{ Name: "testContainer", Image: "testContainerImage", } sourceImage := &image.Image{ ImageID: imageID, } sourceImageState := &image.ImageState{ Image: sourceImage, } sourceImage1 := &image.Image{ ImageID: "sha256:asdfg", } sourceImageState1 := &image.ImageState{ Image: sourceImage1, } sourceImageState1.AddImageName("testContainerImage") imageManager.addImageState(sourceImageState) imageManager.addImageState(sourceImageState1) imageManager.addContainerReferenceToNewImageState(container, imageID, imageSize) if !reflect.DeepEqual(sourceImageState.Containers[0], container) { t.Error("Incorrect container added to an already existing image state") } if len(sourceImageState1.Image.Names) != 0 { t.Error("Error removing existing image name of different ID") } }
func TestLoadsV1DataCorrectly(t *testing.T) { cfg := &config.Config{DataDir: filepath.Join(".", "testdata", "v1", "1")} taskEngine := engine.NewTaskEngine(&config.Config{}, nil, nil, nil, nil, dockerstate.NewDockerTaskEngineState()) var containerInstanceArn, cluster, savedInstanceID string var sequenceNumber int64 stateManager, err := statemanager.NewStateManager(cfg, statemanager.AddSaveable("TaskEngine", taskEngine), statemanager.AddSaveable("ContainerInstanceArn", &containerInstanceArn), statemanager.AddSaveable("Cluster", &cluster), statemanager.AddSaveable("EC2InstanceID", &savedInstanceID), statemanager.AddSaveable("SeqNum", &sequenceNumber), ) if err != nil { t.Fatal(err) } err = stateManager.Load() if err != nil { t.Fatal("Error loading state", err) } if cluster != "test" { t.Fatal("Wrong cluster: " + cluster) } if sequenceNumber != 0 { t.Fatal("v1 should give a sequence number of 0") } tasks, err := taskEngine.ListTasks() if err != nil { t.Fatal(err) } var deadTask *api.Task for _, task := range tasks { if task.Arn == "arn:aws:ecs:us-west-2:1234567890:task/f44b4fc9-adb0-4f4f-9dff-871512310588" { deadTask = task } } if deadTask == nil { t.Fatal("Could not find task expected to be in state") } if deadTask.SentStatus != api.TaskStopped { t.Fatal("task dead should be stopped now") } if deadTask.Containers[0].SentStatus != api.ContainerStopped { t.Fatal("container Dead should go to stopped") } if deadTask.Containers[0].DesiredStatus != api.ContainerStopped { t.Fatal("container Dead should go to stopped") } if deadTask.Containers[0].KnownStatus != api.ContainerStopped { t.Fatal("container Dead should go to stopped") } expected, _ := time.Parse(time.RFC3339, "2015-04-28T17:29:48.129140193Z") if deadTask.KnownStatusTime != expected { t.Fatal("Time was not correct") } }
func TestDeleteImageIDNull(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() client := NewMockDockerClient(ctrl) imageManager := &dockerImageManager{client: client, state: dockerstate.NewDockerTaskEngineState()} imageManager.SetSaver(statemanager.NewNoopStateManager()) imageManager.deleteImage("", nil) }
func TestRemoveUnusedImagesNoImages(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() client := NewMockDockerClient(ctrl) imageManager := &dockerImageManager{client: client, state: dockerstate.NewDockerTaskEngineState()} imageManager.SetSaver(statemanager.NewNoopStateManager()) imageManager.removeUnusedImages() }
func TestJsonEncoding(t *testing.T) { state := dockerstate.NewDockerTaskEngineState() decodeEqual(t, state) testState := dockerstate.NewDockerTaskEngineState() testTask := createTestTask("test1", 1) testState.AddTask(testTask) for i, cont := range testTask.Containers { testState.AddContainer(&api.DockerContainer{DockerId: "docker" + strconv.Itoa(i), DockerName: "someName", Container: cont}, testTask) } other := decodeEqual(t, testState) _, ok := other.ContainerMapByArn("test1") if !ok { t.Error("Could not retrieve expected task") } }
func TestRemoveLeastRecentlyUsedImageNoImage(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() client := NewMockDockerClient(ctrl) imageManager := &dockerImageManager{client: client, state: dockerstate.NewDockerTaskEngineState()} imageManager.SetSaver(statemanager.NewNoopStateManager()) err := imageManager.removeLeastRecentlyUsedImage() if err == nil { t.Error("Expected Error for no LRU image to remove") } }
func TestGetCandidateImagesForDeletionImageHasMoreContainerReferences(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() client := NewMockDockerClient(ctrl) imageManager := &dockerImageManager{ client: client, state: dockerstate.NewDockerTaskEngineState(), minimumAgeBeforeDeletion: config.DefaultImageDeletionAge, numImagesToDelete: config.DefaultNumImagesToDeletePerCycle, imageCleanupTimeInterval: config.DefaultImageCleanupTimeInterval, } container := &api.Container{ Name: "testContainer", Image: "testContainerImage", } container2 := &api.Container{ Name: "testContainer2", Image: "testContainerImage", } sourceImage := &image.Image{ ImageID: "sha256:qwerty", } sourceImage.Names = append(sourceImage.Names, container.Image) sourceImageState := &image.ImageState{ Image: sourceImage, PulledAt: time.Now().AddDate(0, -2, 0), } imageManager.addImageState(sourceImageState) imageInspected := &docker.Image{ ID: "sha256:qwerty", } client.EXPECT().InspectImage(container.Image).Return(imageInspected, nil).AnyTimes() err := imageManager.AddContainerReferenceToImageState(container) if err != nil { t.Error("Error in adding container to an existing image state") } client.EXPECT().InspectImage(container.Image).Return(imageInspected, nil).AnyTimes() err = imageManager.AddContainerReferenceToImageState(container2) if err != nil { t.Error("Error in adding container2 to an existing image state") } client.EXPECT().InspectImage(container.Image).Return(imageInspected, nil).AnyTimes() err = imageManager.RemoveContainerReferenceFromImageState(container) if err != nil { t.Error("Error removing container reference from image state") } imageStates := imageManager.getCandidateImagesForDeletion() if len(imageStates) > 0 { t.Error("Expected no image state to be returned for deletion") } }
func TestImageCleanupHappyPath(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() client := NewMockDockerClient(ctrl) imageManager := &dockerImageManager{ client: client, state: dockerstate.NewDockerTaskEngineState(), minimumAgeBeforeDeletion: 1 * time.Millisecond, numImagesToDelete: config.DefaultNumImagesToDeletePerCycle, imageCleanupTimeInterval: config.DefaultImageCleanupTimeInterval, } imageManager.SetSaver(statemanager.NewNoopStateManager()) container := &api.Container{ Name: "testContainer", Image: "testContainerImage", } imageInspected := &docker.Image{ ID: "sha256:qwerty", } client.EXPECT().InspectImage(container.Image).Return(imageInspected, nil).AnyTimes() err := imageManager.AddContainerReferenceToImageState(container) if err != nil { t.Error("Error in adding container to an existing image state") } err = imageManager.RemoveContainerReferenceFromImageState(container) if err != nil { t.Error("Error removing container reference from image state") } imageState, _ := imageManager.getImageState(imageInspected.ID) imageState.PulledAt = time.Now().AddDate(0, -2, 0) imageState.LastUsedAt = time.Now().AddDate(0, -2, 0) imageState.AddImageName("anotherImage") client.EXPECT().RemoveImage(container.Image, removeImageTimeout).Return(nil) client.EXPECT().RemoveImage("anotherImage", removeImageTimeout).Return(nil) parent := context.Background() ctx, cancel := context.WithCancel(parent) go imageManager.performPeriodicImageCleanup(ctx, 2*time.Millisecond) time.Sleep(1 * time.Second) cancel() if len(imageState.Image.Names) != 0 { t.Error("Error removing image name from state after the image is removed") } if len(imageManager.imageStates) != 0 { t.Error("Error removing image state after the image is removed") } }
func TestAddContainerReferenceToExistingImageStateNoState(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() client := NewMockDockerClient(ctrl) imageManager := &dockerImageManager{client: client, state: dockerstate.NewDockerTaskEngineState()} imageID := "sha256:qwerty" container := &api.Container{ Name: "testContainer", Image: "testContainerImage", } if imageManager.addContainerReferenceToExistingImageState(container, imageID) { t.Error("Error adding container to an incorrect existing image state") } }
func TestImageCleanupCannotRemoveImage(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() client := NewMockDockerClient(ctrl) imageManager := &dockerImageManager{ client: client, state: dockerstate.NewDockerTaskEngineState(), minimumAgeBeforeDeletion: config.DefaultImageDeletionAge, numImagesToDelete: config.DefaultNumImagesToDeletePerCycle, imageCleanupTimeInterval: config.DefaultImageCleanupTimeInterval, } imageManager.SetSaver(statemanager.NewNoopStateManager()) container := &api.Container{ Name: "testContainer", Image: "testContainerImage", } sourceImage := &image.Image{ ImageID: "sha256:qwerty", } sourceImage.Names = append(sourceImage.Names, container.Image) imageInspected := &docker.Image{ ID: "sha256:qwerty", } client.EXPECT().InspectImage(container.Image).Return(imageInspected, nil).AnyTimes() err := imageManager.AddContainerReferenceToImageState(container) if err != nil { t.Error("Error in adding container to an existing image state") } err = imageManager.RemoveContainerReferenceFromImageState(container) if err != nil { t.Error("Error removing container reference from image state") } imageState, _ := imageManager.getImageState(imageInspected.ID) imageState.PulledAt = time.Now().AddDate(0, -2, 0) imageState.LastUsedAt = time.Now().AddDate(0, -2, 0) client.EXPECT().RemoveImage(container.Image, removeImageTimeout).Return(errors.New("error removing image")).AnyTimes() imageManager.removeUnusedImages() if len(imageState.Image.Names) == 0 { t.Error("Error: image name should not be removed") } if len(imageManager.imageStates) == 0 { t.Error("Error: image state should not be removed") } }
func TestRemoveAlreadyExistingImageNameWithDifferentID(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() client := NewMockDockerClient(ctrl) imageManager := &dockerImageManager{ client: client, state: dockerstate.NewDockerTaskEngineState(), minimumAgeBeforeDeletion: config.DefaultImageDeletionAge, numImagesToDelete: config.DefaultNumImagesToDeletePerCycle, imageCleanupTimeInterval: config.DefaultImageCleanupTimeInterval, } container := &api.Container{ Name: "testContainer", Image: "testContainerImage", } sourceImage := &image.Image{ ImageID: "sha256:qwerty", } sourceImage.Names = append(sourceImage.Names, container.Image) imageInspected := &docker.Image{ ID: "sha256:qwerty", } client.EXPECT().InspectImage(container.Image).Return(imageInspected, nil) err := imageManager.AddContainerReferenceToImageState(container) if err != nil { t.Error("Error in adding container to an existing image state") } container1 := &api.Container{ Name: "testContainer1", Image: "testContainerImage", } imageInspected1 := &docker.Image{ ID: "sha256:asdfg", } client.EXPECT().InspectImage(container.Image).Return(imageInspected1, nil) err = imageManager.AddContainerReferenceToImageState(container1) if err != nil { t.Error("Error in adding container to an existing image state") } imageState, ok := imageManager.getImageState(imageInspected.ID) if !ok { t.Error("Error in retrieving existing Image State for the Container") } if len(imageState.Image.Names) != 0 { t.Error("Error in removing already existing image name with different ID") } }
func TestRemoveInvalidContainerReferenceFromImageState(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() client := NewMockDockerClient(ctrl) imageManager := NewImageManager(defaultTestConfig(), client, dockerstate.NewDockerTaskEngineState()) container := &api.Container{ Image: "", } err := imageManager.RemoveContainerReferenceFromImageState(container) if err == nil { t.Error("Expected error removing container reference with no image name from image state") } }
func TestRemoveContainerReferenceFromImageStateInspectError(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() client := NewMockDockerClient(ctrl) imageManager := NewImageManager(defaultTestConfig(), client, dockerstate.NewDockerTaskEngineState()) container := &api.Container{ Image: "myContainerImage", } client.EXPECT().InspectImage(container.Image).Return(nil, errors.New("error inspecting")).AnyTimes() err := imageManager.RemoveContainerReferenceFromImageState(container) if err == nil { t.Error("Expected error in inspecting image while adding container to image state") } }
// NewDockerTaskEngine returns a created, but uninitialized, DockerTaskEngine. // The distinction between created and initialized is that when created it may // be serialized/deserialized, but it will not communicate with docker until it // is also initialized. func NewDockerTaskEngine(cfg *config.Config) *DockerTaskEngine { dockerTaskEngine := &DockerTaskEngine{ client: nil, saver: statemanager.NewNoopStateManager(), state: dockerstate.NewDockerTaskEngineState(), managedTasks: make(map[string]*managedTask), taskStopGroup: utilsync.NewSequentialWaitGroup(), containerEvents: make(chan api.ContainerStateChange), taskEvents: make(chan api.TaskStateChange), } dockerauth.SetConfig(cfg) return dockerTaskEngine }
func decodeEqual(t *testing.T, state *dockerstate.DockerTaskEngineState) *dockerstate.DockerTaskEngineState { data, err := json.Marshal(&state) if err != nil { t.Error(err) } otherState := dockerstate.NewDockerTaskEngineState() err = json.Unmarshal(data, &otherState) if err != nil { t.Error(err) } if !DockerStatesEqual(state, otherState) { debug.PrintStack() t.Error("States were not equal") } return otherState }
// NewDockerTaskEngine returns a created, but uninitialized, DockerTaskEngine. // The distinction between created and initialized is that when created it may // be serialized/deserialized, but it will not communicate with docker until it // is also initialized. func NewDockerTaskEngine(cfg *config.Config, acceptInsecureCert bool) *DockerTaskEngine { dockerTaskEngine := &DockerTaskEngine{ cfg: cfg, acceptInsecureCert: acceptInsecureCert, client: nil, saver: statemanager.NewNoopStateManager(), state: dockerstate.NewDockerTaskEngineState(), managedTasks: make(map[string]*managedTask), taskStopGroup: utilsync.NewSequentialWaitGroup(), containerEvents: make(chan api.ContainerStateChange), taskEvents: make(chan api.TaskStateChange), } return dockerTaskEngine }
func TestAddAndRemoveContainerToImageStateReferenceHappyPath(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() client := NewMockDockerClient(ctrl) imageManager := NewImageManager(defaultTestConfig(), client, dockerstate.NewDockerTaskEngineState()) container := &api.Container{ Name: "testContainer", Image: "testContainerImage", } sourceImage := &image.Image{ ImageID: "sha256:qwerty", } sourceImageState := &image.ImageState{ Image: sourceImage, PulledAt: time.Now().AddDate(0, -2, 0), } sourceImageState.AddImageName(container.Image) imageManager.(*dockerImageManager).addImageState(sourceImageState) imageInspected := &docker.Image{ ID: "sha256:qwerty", } client.EXPECT().InspectImage(container.Image).Return(imageInspected, nil) err := imageManager.AddContainerReferenceToImageState(container) if err != nil { t.Error("Error in adding container to an existing image state") } imageState, ok := imageManager.(*dockerImageManager).getImageState(imageInspected.ID) if !ok { t.Error("Error in retrieving existing Image State for the Container") } if !reflect.DeepEqual(sourceImageState, imageState) { t.Error("Mismatch between added and retrieved image state") } client.EXPECT().InspectImage(container.Image).Return(imageInspected, nil) err = imageManager.RemoveContainerReferenceFromImageState(container) if err != nil { t.Error("Error removing container reference from image state") } imageState, _ = imageManager.(*dockerImageManager).getImageState(imageInspected.ID) if len(imageState.Containers) != 0 { t.Error("Error removing container reference from image state") } }
func TestAddContainerReferenceToNewImageState(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() client := NewMockDockerClient(ctrl) imageManager := &dockerImageManager{client: client, state: dockerstate.NewDockerTaskEngineState()} imageID := "sha256:qwerty" var imageSize int64 imageSize = 18767 container := &api.Container{ Name: "testContainer", Image: "testContainerImage", } imageManager.addContainerReferenceToNewImageState(container, imageID, imageSize) _, ok := imageManager.getImageState(imageID) if !ok { t.Error("Error adding container reference to new image state") } }
// NewDockerTaskEngine returns a created, but uninitialized, DockerTaskEngine. // The distinction between created and initialized is that when created it may // be serialized/deserialized, but it will not communicate with docker until it // is also initialized. func NewDockerTaskEngine(cfg *config.Config, client DockerClient, credentialsManager credentials.Manager) *DockerTaskEngine { dockerTaskEngine := &DockerTaskEngine{ cfg: cfg, client: client, saver: statemanager.NewNoopStateManager(), state: dockerstate.NewDockerTaskEngineState(), managedTasks: make(map[string]*managedTask), taskStopGroup: utilsync.NewSequentialWaitGroup(), containerEvents: make(chan api.ContainerStateChange), taskEvents: make(chan api.TaskStateChange), credentialsManager: credentialsManager, } return dockerTaskEngine }
func performMockRequest(t *testing.T, path string) *httptest.ResponseRecorder { ctrl := gomock.NewController(t) defer ctrl.Finish() mockStateResolver := mock_handlers.NewMockDockerStateResolver(ctrl) state := dockerstate.NewDockerTaskEngineState() stateSetupHelper(state, testTasks) mockStateResolver.EXPECT().State().Return(state) requestHandler := setupServer(utils.Strptr(testContainerInstanceArn), mockStateResolver, &config.Config{Cluster: testClusterArn}) recorder := httptest.NewRecorder() req, _ := http.NewRequest("GET", path, nil) requestHandler.Handler.ServeHTTP(recorder, req) return recorder }
func TestBackendMismatchMapping(t *testing.T) { // Test that a KnownStatus past a DesiredStatus suppresses the DesiredStatus output ctrl := gomock.NewController(t) defer ctrl.Finish() mockStateResolver := mock_handlers.NewMockDockerStateResolver(ctrl) containers := []*api.Container{ &api.Container{ Name: "c1", }, } testTask := &api.Task{ Arn: "task1", DesiredStatus: api.TaskRunning, KnownStatus: api.TaskStopped, Family: "test", Version: "1", Containers: containers, } state := dockerstate.NewDockerTaskEngineState() stateSetupHelper(state, []*api.Task{testTask}) mockStateResolver.EXPECT().State().Return(state) requestHandler := tasksV1RequestHandlerMaker(mockStateResolver) recorder := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/v1/tasks", nil) requestHandler(recorder, req) var tasksResponse TasksResponse err := json.Unmarshal(recorder.Body.Bytes(), &tasksResponse) if err != nil { t.Fatal(err) } if tasksResponse.Tasks[0].DesiredStatus != "" { t.Error("Expected '', was ", tasksResponse.Tasks[0].DesiredStatus) } if tasksResponse.Tasks[0].KnownStatus != "STOPPED" { t.Error("Expected STOPPED, was ", tasksResponse.Tasks[0].KnownStatus) } }
func TestAddContainerReferenceToImageStateWithNoImageName(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() client := NewMockDockerClient(ctrl) imageManager := &dockerImageManager{ client: client, state: dockerstate.NewDockerTaskEngineState(), minimumAgeBeforeDeletion: config.DefaultImageDeletionAge, numImagesToDelete: config.DefaultNumImagesToDeletePerCycle, imageCleanupTimeInterval: config.DefaultImageCleanupTimeInterval, } container := &api.Container{ Name: "testContainer", Image: "testContainerImage", } sourceImage := &image.Image{ ImageID: "sha256:qwerty", } sourceImageState := &image.ImageState{ Image: sourceImage, PulledAt: time.Now(), } imageManager.addImageState(sourceImageState) imageInspected := &docker.Image{ ID: "sha256:qwerty", } client.EXPECT().InspectImage(container.Image).Return(imageInspected, nil).AnyTimes() err := imageManager.AddContainerReferenceToImageState(container) if err != nil { t.Error("Error in adding container to an existing image state") } imageState, ok := imageManager.getImageState(imageInspected.ID) if !ok { t.Error("Error in retrieving existing Image State for the Container") } for _, imageName := range imageState.Image.Names { if imageName != container.Image { t.Error("Error while adding image name to image state") } } }
func TestRemoveContainerReferenceFromInvalidImageState(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() client := NewMockDockerClient(ctrl) imageManager := NewImageManager(defaultTestConfig(), client, dockerstate.NewDockerTaskEngineState()) container := &api.Container{ Image: "myContainerImage", } imageInspected := &docker.Image{ ID: "sha256:qwerty", } client.EXPECT().InspectImage(container.Image).Return(imageInspected, nil).AnyTimes() err := imageManager.RemoveContainerReferenceFromImageState(container) if err == nil { t.Error("Expected error while adding container to an invalid image state") } }
func TestGetCandidateImagesForDeletionImageNoImageState(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() client := NewMockDockerClient(ctrl) imageManager := &dockerImageManager{ client: client, state: dockerstate.NewDockerTaskEngineState(), minimumAgeBeforeDeletion: config.DefaultImageDeletionAge, numImagesToDelete: config.DefaultNumImagesToDeletePerCycle, imageCleanupTimeInterval: config.DefaultImageCleanupTimeInterval, } imageStates := imageManager.getCandidateImagesForDeletion() if imageStates != nil { t.Error("Expected no image state to be returned for deletion") } }
func TestGetImageStateFromImageNameNoImageState(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() client := NewMockDockerClient(ctrl) imageManager := &dockerImageManager{client: client, state: dockerstate.NewDockerTaskEngineState()} imageManager.SetSaver(statemanager.NewNoopStateManager()) container := &api.Container{ Name: "testContainer", Image: "testContainerImage", } imageInspected := &docker.Image{ ID: "sha256:qwerty", } client.EXPECT().InspectImage(container.Image).Return(imageInspected, nil).AnyTimes() err := imageManager.AddContainerReferenceToImageState(container) if err != nil { t.Error("Error in adding container to an existing image state") } imageState := imageManager.GetImageStateFromImageName("noSuchImage") if imageState != nil { t.Error("Incorrect image state retrieved by image name") } }
func TestGetLeastRecentlyUsedImages(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() client := NewMockDockerClient(ctrl) imageManager := NewImageManager(defaultTestConfig(), client, dockerstate.NewDockerTaskEngineState()) imageStateA := &image.ImageState{ LastUsedAt: time.Now().AddDate(0, -5, 0), } imageStateB := &image.ImageState{ LastUsedAt: time.Now().AddDate(0, -3, 0), } imageStateC := &image.ImageState{ LastUsedAt: time.Now().AddDate(0, -2, 0), } imageStateD := &image.ImageState{ LastUsedAt: time.Now().AddDate(0, -6, 0), } imageStateE := &image.ImageState{ LastUsedAt: time.Now().AddDate(0, -4, 0), } imageStateF := &image.ImageState{ LastUsedAt: time.Now().AddDate(0, -1, 0), } candidateImagesForDeletion := []*image.ImageState{ imageStateA, imageStateB, imageStateC, imageStateD, imageStateE, imageStateF, } expectedLeastRecentlyUsedImages := []*image.ImageState{ imageStateD, imageStateA, imageStateE, imageStateB, imageStateC, } leastRecentlyUsedImage := imageManager.(*dockerImageManager).getLeastRecentlyUsedImage(candidateImagesForDeletion) if !reflect.DeepEqual(leastRecentlyUsedImage, expectedLeastRecentlyUsedImages[0]) { t.Error("Incorrect order of least recently used images") } }