Skip to content

Commit a0943d9

Browse files
extract base image layers from built image layers
1 parent a540f83 commit a0943d9

File tree

1 file changed

+35
-3
lines changed

1 file changed

+35
-3
lines changed

src/test/cli.build.test.ts

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import * as os from 'os';
1010
import { buildKitOptions, shellExec } from './testUtils';
1111
import { ImageDetails } from '../spec-shutdown/dockerUtils';
1212
import { envListToObj } from '../spec-node/utils';
13-
import * as crypto from 'crypto';
1413

1514
const pkg = require('../../package.json');
1615

@@ -68,6 +67,11 @@ describe('Dev Containers CLI', function () {
6867
it.only('should not use docker cache for features when `--no-cache` flag is passed', async () => {
6968
// Arrange
7069
const testFolder = `${__dirname}/configs/image-with-features`;
70+
const devContainerJson = `${testFolder}/.devcontainer.json`;
71+
72+
const devContainerFileContents = JSON.parse(fs.readFileSync(devContainerJson, 'utf8'));
73+
const baseImage = devContainerFileContents.image;
74+
7175
const originalImageName = 'feature-cache-test-original-image';
7276
const cachedImageName = 'feature-cache-test-rerun-image';
7377
const nonCachedImageName = 'feature-cache-test-no-cache-image';
@@ -77,26 +81,54 @@ describe('Dev Containers CLI', function () {
7781
const cachedBuildCommand = `${commandBase} --image-name ${cachedImageName}`;
7882
const buildWithoutCacheCommand = `${commandBase} --image-name ${nonCachedImageName} --no-cache`;
7983

84+
function arrayStartsWithArray(subject: string[], startsWith: string[]) {
85+
if (subject.length < startsWith.length) {
86+
return false;
87+
}
88+
for (let i = 0; i < startsWith.length; i++) {
89+
if (subject[i] !== startsWith[i]) {
90+
return false;
91+
}
92+
}
93+
return true;
94+
}
95+
96+
function haveCommonEntries(arr1: string[], arr2: string[]) {
97+
return arr1.every(item => arr2.includes(item));
98+
}
99+
80100
// Act
101+
await shellExec(`docker pull ${baseImage}`); // pull base image so we can inspect it later
81102
await shellExec(buildCommand);
82103
await shellExec(cachedBuildCommand);
83104
await shellExec(buildWithoutCacheCommand);
84105

85106
// Assert
107+
const baseImageInspectCommandResult = await shellExec(`docker inspect ${baseImage}`);
86108
const originalImageInspectCommandResult = await shellExec(`docker inspect ${originalImageName}`);
87109
const cachedImageInspectCommandResult = await shellExec(`docker inspect ${cachedImageName}`);
88110
const noCacheImageInspectCommandResult = await shellExec(`docker inspect ${nonCachedImageName}`);
89111

112+
const baseImageDetails = JSON.parse(baseImageInspectCommandResult.stdout);
90113
const originalImageDetails = JSON.parse(originalImageInspectCommandResult.stdout);
91114
const cachedImageDetails = JSON.parse(cachedImageInspectCommandResult.stdout);
92115
const noCacheImageDetails = JSON.parse(noCacheImageInspectCommandResult.stdout);
93116

117+
const baseImageLayers: string[] = baseImageDetails[0].RootFS.Layers;
94118
const originalImageLayers: string[] = originalImageDetails[0].RootFS.Layers;
95119
const cachedImageLayers: string[] = cachedImageDetails[0].RootFS.Layers;
96120
const nonCachedImageLayers: string[] = noCacheImageDetails[0].RootFS.Layers;
97121

98-
assert.deepEqual(originalImageLayers, cachedImageLayers, 'because they were built csequentially and should have used caching');
99-
assert.notDeepEqual(cachedImageLayers, nonCachedImageLayers, 'because we passed the --no-cache argument disabling caching');
122+
assert.equal(arrayStartsWithArray(originalImageLayers, baseImageLayers), true, 'because the image is made up of feature layers on top of the base image');
123+
assert.equal(arrayStartsWithArray(cachedImageLayers, baseImageLayers), true, 'because the image is made up of feature layers on top of the base image');
124+
assert.equal(arrayStartsWithArray(nonCachedImageLayers, baseImageLayers), true, 'because the image is made up of feature layers on top of the base image');
125+
126+
const originalImageWithoutBaseImageLayers = originalImageLayers.slice(baseImageLayers.length);
127+
const cachedImageWithoutBaseImageLayers = cachedImageLayers.slice(baseImageLayers.length);
128+
const nonCachedImageWithoutBaseImageLayers = nonCachedImageLayers.slice(baseImageLayers.length);
129+
130+
assert.deepEqual(originalImageWithoutBaseImageLayers, cachedImageWithoutBaseImageLayers, 'because they are the same image built sequentially therefore the second should have used caching');
131+
assert.equal(haveCommonEntries(cachedImageWithoutBaseImageLayers, nonCachedImageWithoutBaseImageLayers), false, 'because we passed the --no-cache argument which disables the use of the cache, therefore the non-base image layers should have nothin in common');
100132
});
101133

102134
it('should fail with "not found" error when config is not found', async () => {

0 commit comments

Comments
 (0)