Merge pull request #1505 from balena-io/1492-compose-image-tests

Add more test coverage for compose/images
This commit is contained in:
bulldozer-balena[bot] 2020-11-03 18:55:17 +00:00 committed by GitHub
commit 064d8f1562
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 666 additions and 28 deletions

View File

@ -6,9 +6,6 @@ process.env.DATABASE_PATH_2 = './test/data/database2.sqlite';
process.env.DATABASE_PATH_3 = './test/data/database3.sqlite';
process.env.LED_FILE = './test/data/led_file';
import * as dbus from 'dbus';
import { DBusError, DBusInterface } from 'dbus';
import { stub } from 'sinon';
import * as fs from 'fs';
// Make sure they are no database files left over from
@ -33,31 +30,7 @@ fs.writeFileSync(
fs.readFileSync('./test/data/testconfig.json'),
);
stub(dbus, 'getBus').returns({
getInterface: (
_serviceName: string,
_objectPath: string,
_interfaceName: string,
interfaceCb: (err: null | DBusError, iface: DBusInterface) => void,
) => {
interfaceCb(null, {
Get: (
_unitName: string,
_property: string,
getCb: (err: null | Error, value: unknown) => void,
) => {
getCb(null, 'this is the value');
},
GetUnit: (
_unitName: string,
getUnitCb: (err: null | Error, unitPath: string) => void,
) => {
getUnitCb(null, 'this is the unit path');
},
} as any);
},
} as any);
import './lib/mocked-dbus';
import './lib/mocked-dockerode';
import './lib/mocked-iptables';
import './lib/mocked-event-tracker';

View File

@ -0,0 +1,133 @@
import * as _ from 'lodash';
import { docker } from '../src/lib/docker-utils';
import { expect } from './lib/chai-config';
import * as Images from '../src/compose/images';
import * as mockedDockerode from './lib/mocked-dockerode';
import * as mockedDatabase from './lib/mocked-database';
import * as db from '../src/db';
import * as sampleImageData from './data/compose-image-data.json';
describe('compose/images', () => {
before(() => {
mockedDatabase.create();
});
after(() => {
try {
mockedDatabase.restore();
} catch (e) {
/* noop */
}
});
afterEach(() => {
// Clear Dockerode actions recorded for each test
mockedDockerode.resetHistory();
});
it('Removes a legacy Image', async () => {
const images = sampleImageData['legacy-image'].dockerode;
const IMAGE_TO_REMOVE = sampleImageData['legacy-image'].remove;
const IMAGES_FROM_DB = sampleImageData['legacy-image'].database;
// Stub the database to return images we want
mockedDatabase.setImages(IMAGES_FROM_DB).stub();
// Perform the test with our specially crafted data
await mockedDockerode.testWithData({ images }, async () => {
// Check that our legacy image exists
await expect(docker.getImage(IMAGE_TO_REMOVE.name).inspect()).to
.eventually.not.be.undefined;
await expect(
db.models('image').select().where(IMAGE_TO_REMOVE),
).to.eventually.have.lengthOf(1);
// Check that docker has this Image
await expect(docker.getImage(IMAGE_TO_REMOVE.name).inspect()).to
.eventually.not.be.undefined;
// Now remove this image...
await Images.remove(IMAGE_TO_REMOVE);
// Check if it still exists!
await expect(docker.getImage(IMAGE_TO_REMOVE.name).inspect()).to
.eventually.be.undefined;
await expect(db.models('image').select().where(IMAGE_TO_REMOVE)).to
.eventually.be.empty;
// Check that docker remove was called once
const removeSteps = _(mockedDockerode.actions)
.pickBy({ name: 'remove' })
.map()
.value();
expect(removeSteps).to.have.lengthOf(1);
});
});
it('Removes a single Image', async () => {
const images = sampleImageData['single-image'].dockerode;
const IMAGE_TO_REMOVE = sampleImageData['single-image'].remove;
const IMAGES_FROM_DB = sampleImageData['single-image'].database;
// Stub the database to return images we want
mockedDatabase.setImages(IMAGES_FROM_DB).stub();
// Perform the test with our specially crafted data
await mockedDockerode.testWithData({ images }, async () => {
// Check that a single image is returned when given entire object
expect(
db.models('image').select().where(IMAGE_TO_REMOVE),
).to.eventually.have.lengthOf(1);
// Check that only one image with this dockerImageId exists in the db
expect(
db
.models('image')
.where({ dockerImageId: IMAGE_TO_REMOVE.dockerImageId })
.select(),
).to.eventually.have.lengthOf(1);
// Now remove this image...
await Images.remove(IMAGE_TO_REMOVE);
// Check that docker does not have this image
await expect(docker.getImage(IMAGE_TO_REMOVE.name).inspect()).to
.eventually.be.empty;
// Check that the database longer has this image
await expect(db.models('image').select().where(IMAGE_TO_REMOVE)).to
.eventually.be.empty;
// Check that docker remove was called once
const removeSteps = _(mockedDockerode.actions)
.pickBy({ name: 'remove' })
.map()
.value();
expect(removeSteps).to.have.lengthOf(1);
});
});
it('Removes an Image with digests', async () => {
const images = sampleImageData['image-with-digests'].dockerode;
const IMAGE_TO_REMOVE = sampleImageData['image-with-digests'].remove;
const IMAGES_FROM_DB = sampleImageData['image-with-digests'].database;
// Stub the database to return images we want
mockedDatabase.setImages(IMAGES_FROM_DB).stub();
// Perform the test with our specially crafted data
await mockedDockerode.testWithData({ images }, async () => {
// Check that a single image is returned when given entire object
expect(
db.models('image').select().where(IMAGE_TO_REMOVE),
).to.eventually.have.lengthOf(1);
// Check that multiple images with the same dockerImageId are returned
expect(
db
.models('image')
.where({ dockerImageId: IMAGE_TO_REMOVE.dockerImageId })
.select(),
).to.eventually.have.lengthOf(2);
// Now remove these image...
await Images.remove(IMAGE_TO_REMOVE);
// Check that docker does not have this image
await expect(docker.getImage(IMAGE_TO_REMOVE.name).inspect()).to
.eventually.be.empty;
// Check that the database no longer has this image
await expect(db.models('image').select().where(IMAGE_TO_REMOVE)).to
.eventually.be.empty;
// Check that docker remove was called twice
const removeSteps = _(mockedDockerode.actions)
.pickBy({ name: 'remove' })
.map()
.value();
expect(removeSteps).to.have.lengthOf(2);
});
});
});

View File

@ -0,0 +1,408 @@
{
"legacy-image": {
"remove": {
"id": 246,
"name": "registry2.balena-cloud.com/v2/793f9296017bbfe026334820ab56bb3a@sha256:2c969a1ba1c6bc10df53481f48c6a74dbd562cfb41ba58f81beabd03facf5582",
"appId": 1658654,
"serviceId": 650325,
"serviceName": "app_1",
"imageId": 2693229,
"releaseId": 1524186,
"dependent": 0
},
"database": [
{
"id": 246,
"name": "registry2.balena-cloud.com/v2/793f9296017bbfe026334820ab56bb3a@sha256:2c969a1ba1c6bc10df53481f48c6a74dbd562cfb41ba58f81beabd03facf5582",
"appId": 1658654,
"serviceId": 650325,
"serviceName": "app_1",
"imageId": 2693229,
"releaseId": 1524186,
"dependent": 0
}
],
"dockerode": {
"registry2.balena-cloud.com/v2/793f9296017bbfe026334820ab56bb3a@sha256:2c969a1ba1c6bc10df53481f48c6a74dbd562cfb41ba58f81beabd03facf5582": {
"Containers": -1,
"Created": 1599492712,
"Id": "sha256:f1154d76c731f04711e5856b6e6858730e3023d9113124900ac65c2ccc90e8e7",
"Labels": {
"io.balena.architecture": "aarch64",
"io.balena.device-type": "jetson-tx2",
"io.balena.qemu.version": "4.0.0+balena2-aarch64"
},
"ParentId": "",
"RepoDigests": [
"registry2.balena-cloud.com/v2/793f9296017bbfe026334820ab56bb3a@sha256:72b80cbd3cc12de08d4adc9dec79916bf466031553f55b59c29e397829ea129f"
],
"RepoTags": [
"registry2.balena-cloud.com/v2/793f9296017bbfe026334820ab56bb3a:delta-ada9fbb57d90e61e"
],
"SharedSize": -1,
"Size": 217024648,
"VirtualSize": 217024648
},
"livepush-supervisor:11.12.11": {
"Containers": -1,
"Created": 1599492599,
"Id": "sha256:db5af2c94366275d8e6d7ea3047f2405eab2f04a27f66843634a45958ef59f5a",
"Labels": {
"io.balena.architecture": "aarch64",
"io.balena.livepush-image": "1",
"io.balena.qemu.version": "4.0.0+balena-aarch64"
},
"ParentId": "sha256:4acb1652178e72c0b6143a08225e0df5ef74b338a0c9e2ca4cd261339f4f0431",
"RepoDigests": null,
"RepoTags": [
"livepush-supervisor:11.12.11"
],
"SharedSize": -1,
"Size": 501352885,
"VirtualSize": 501352885
}
}
},
"single-image": {
"remove": {
"id": 246,
"name": "registry2.balena-cloud.com/v2/793f9296017bbfe026334820ab56bb3a@sha256:2c969a1ba1c6bc10df53481f48c6a74dbd562cfb41ba58f81beabd03facf5582",
"appId": 1658654,
"serviceId": 650325,
"serviceName": "app_1",
"imageId": 2693229,
"releaseId": 1524186,
"dependent": 0,
"dockerImageId": "sha256:f1154d76c731f04711e5856b6e6858730e3023d9113124900ac65c2ccc90e8e7"
},
"database": [
{
"id": 246,
"name": "registry2.balena-cloud.com/v2/793f9296017bbfe026334820ab56bb3a@sha256:2c969a1ba1c6bc10df53481f48c6a74dbd562cfb41ba58f81beabd03facf5582",
"appId": 1658654,
"serviceId": 650325,
"serviceName": "app_1",
"imageId": 2693229,
"releaseId": 1524186,
"dependent": 0,
"dockerImageId": "sha256:f1154d76c731f04711e5856b6e6858730e3023d9113124900ac65c2ccc90e8e7"
},
{
"id": 247,
"name": "registry2.balena-cloud.com/v2/902cf44eb0ed51675a0bf95a7bbf0c91@sha256:12345a1ba1c6bc10df53481f48c6a74dbd562cfb41ba58f81beabd03facf5582",
"appId": 1658654,
"serviceId": 650331,
"serviceName": "app_2",
"imageId": 2693230,
"releaseId": 1524186,
"dependent": 0,
"dockerImageId": "sha256:f1154d76c731f04711e5856b6e6858730e3023d9113124900ac65c2ccc901234"
}
],
"dockerode": {
"sha256:acf4069b3cf68d05dc8a2df0e511447927303ebef88f897f05cbad823f240d97": {
"Containers": -1,
"Created": 1599492964,
"Id": "sha256:acf4069b3cf68d05dc8a2df0e511447927303ebef88f897f05cbad823f240d97",
"Labels": {
"io.balena.architecture": "aarch64",
"io.balena.device-type": "jetson-tx2",
"io.balena.qemu.version": "4.0.0+balena2-aarch64"
},
"ParentId": "",
"RepoDigests": [
"registry2.balena-cloud.com/v2/772eca412ce780e860b988da6ea26ee0@sha256:7d5e55d6aac00b8504c5c360a3ee59677fc5a7324360f1f54df19d0bb17c2cfe",
"registry2.balena-cloud.com/v2/7f1290fa85b253936ebf6e0dbbd95875@sha256:107f63eb1bc2e9978f2a4bb5b095bc010dd91dd5a6a0a39a494e27ee8b396232"
],
"RepoTags": [
"registry2.balena-cloud.com/v2/772eca412ce780e860b988da6ea26ee0:delta-ff3f0a82c404830b",
"registry2.balena-cloud.com/v2/7f1290fa85b253936ebf6e0dbbd95875:delta-79acb6d8bf4795f6"
],
"SharedSize": -1,
"Size": 217024666,
"VirtualSize": 217024666
},
"sha256:f1154d76c731f04711e5856b6e6858730e3023d9113124900ac65c2ccc90e8e7": {
"Containers": -1,
"Created": 1599492712,
"Id": "sha256:f1154d76c731f04711e5856b6e6858730e3023d9113124900ac65c2ccc90e8e7",
"Labels": {
"io.balena.architecture": "aarch64",
"io.balena.device-type": "jetson-tx2",
"io.balena.qemu.version": "4.0.0+balena2-aarch64"
},
"ParentId": "",
"RepoDigests": [
"registry2.balena-cloud.com/v2/793f9296017bbfe026334820ab56bb3a@sha256:72b80cbd3cc12de08d4adc9dec79916bf466031553f55b59c29e397829ea129f"
],
"RepoTags": [
"registry2.balena-cloud.com/v2/793f9296017bbfe026334820ab56bb3a:delta-ada9fbb57d90e61e"
],
"SharedSize": -1,
"Size": 217024648,
"VirtualSize": 217024648
},
"sha256:db5af2c94366275d8e6d7ea3047f2405eab2f04a27f66843634a45958ef59f5a": {
"Containers": -1,
"Created": 1599492599,
"Id": "sha256:db5af2c94366275d8e6d7ea3047f2405eab2f04a27f66843634a45958ef59f5a",
"Labels": {
"io.balena.architecture": "aarch64",
"io.balena.livepush-image": "1",
"io.balena.qemu.version": "4.0.0+balena-aarch64"
},
"ParentId": "sha256:4acb1652178e72c0b6143a08225e0df5ef74b338a0c9e2ca4cd261339f4f0431",
"RepoDigests": null,
"RepoTags": [
"livepush-supervisor:11.12.11"
],
"SharedSize": -1,
"Size": 501352885,
"VirtualSize": 501352885
},
"sha256:272c54e27104cf6c2153538165dba3c29b58ae35837b47134fa55b53ddb61154": {
"Containers": -1,
"Created": 1599181227,
"Id": "sha256:272c54e27104cf6c2153538165dba3c29b58ae35837b47134fa55b53ddb61154",
"Labels": {
"io.balena.architecture": "aarch64",
"io.balena.device-type": "jetson-tx2",
"io.balena.qemu.version": "4.0.0+balena2-aarch64"
},
"ParentId": "",
"RepoDigests": [
"registry2.balena-cloud.com/v2/459bffd69101d788cc3e0722a012878a@sha256:3cc9231cf0e117585e53ebfa6bf9f75a9a4eaa371fb82c21ab9bca8fe0d5c3e3",
"registry2.balena-cloud.com/v2/b0cfe2b1e8c5ab3b6da23f0bd92045b4@sha256:ba5f6d1849c63c8d0f11f35fce694464240002d2c3732898935bf0fedf451063"
],
"RepoTags": [
"registry2.balena-cloud.com/v2/459bffd69101d788cc3e0722a012878a:delta-80ed841a1d3fefa9",
"registry2.balena-cloud.com/v2/b0cfe2b1e8c5ab3b6da23f0bd92045b4:delta-532f970c60decb81"
],
"SharedSize": -1,
"Size": 217024558,
"VirtualSize": 217024558
},
"sha256:25d6abae14f08de6b80f9d95003e674598738959a535a2f21be34c03675ebd02": {
"Containers": -1,
"Created": 1599146808,
"Id": "sha256:25d6abae14f08de6b80f9d95003e674598738959a535a2f21be34c03675ebd02",
"Labels": {
"io.balena.qemu.version": "4.0.0+balena-aarch64"
},
"ParentId": "",
"RepoDigests": [
"balena/aarch64-supervisor@sha256:e7e3b166e855f4c113a67bc528b4ef77408d05e280052f35452f3e2cd7b5322b"
],
"RepoTags": [
"balena/aarch64-supervisor:v11.14.0"
],
"SharedSize": -1,
"Size": 72305850,
"VirtualSize": 72305850
},
"sha256:60783b8688d395f9b4ce4b288d941244d1b0a4c43114ba980acd012ccffc6b53": {
"Containers": -1,
"Created": 1585746557,
"Id": "sha256:60783b8688d395f9b4ce4b288d941244d1b0a4c43114ba980acd012ccffc6b53",
"Labels": {
"io.balena.qemu.version": "4.0.0+balena-aarch64"
},
"ParentId": "",
"RepoDigests": [
"balenalib/aarch64-alpine-supervisor-base@sha256:6eb712fc797ff68f258d9032cf292c266cb9bd8be4cbdaaafeb5a8824bb104fd"
],
"RepoTags": [
"balenalib/aarch64-alpine-supervisor-base:3.11"
],
"SharedSize": -1,
"Size": 14503741,
"VirtualSize": 14503741
},
"sha256:a29f45ccde2ac0bde957b1277b1501f471960c8ca49f1588c6c885941640ae60": {
"Containers": -1,
"Created": 1578015959,
"Id": "sha256:a29f45ccde2ac0bde957b1277b1501f471960c8ca49f1588c6c885941640ae60",
"Labels": null,
"ParentId": "",
"RepoDigests": null,
"RepoTags": [
"balena-healthcheck-image:latest"
],
"SharedSize": -1,
"Size": 9136,
"VirtualSize": 9136
}
}
},
"image-with-digests": {
"remove": {
"id": 246,
"name": "registry2.balena-cloud.com/v2/793f9296017bbfe026334820ab56bb3a@sha256:2c969a1ba1c6bc10df53481f48c6a74dbd562cfb41ba58f81beabd03facf5582",
"appId": 1658654,
"serviceId": 650325,
"serviceName": "app_1",
"imageId": 2693229,
"releaseId": 1524186,
"dependent": 0,
"dockerImageId": "sha256:f1154d76c731f04711e5856b6e6858730e3023d9113124900ac65c2ccc90e8e7"
},
"database": [
{
"id": 246,
"name": "registry2.balena-cloud.com/v2/793f9296017bbfe026334820ab56bb3a@sha256:2c969a1ba1c6bc10df53481f48c6a74dbd562cfb41ba58f81beabd03facf5582",
"appId": 1658654,
"serviceId": 650325,
"serviceName": "app_1",
"imageId": 2693229,
"releaseId": 1524186,
"dependent": 0,
"dockerImageId": "sha256:f1154d76c731f04711e5856b6e6858730e3023d9113124900ac65c2ccc90e8e7"
},
{
"id": 247,
"name": "registry2.balena-cloud.com/v2/902cf44eb0ed51675a0bf95a7bbf0c91@sha256:2c969a1ba1c6bc10df53481f48c6a74dbd562cfb41ba58f81beabd03facf5582",
"appId": 1658654,
"serviceId": 650331,
"serviceName": "app_2",
"imageId": 2693230,
"releaseId": 1524186,
"dependent": 0,
"dockerImageId": "sha256:f1154d76c731f04711e5856b6e6858730e3023d9113124900ac65c2ccc90e8e7"
}
],
"dockerode": {
"sha256:acf4069b3cf68d05dc8a2df0e511447927303ebef88f897f05cbad823f240d97": {
"Containers": -1,
"Created": 1599492964,
"Id": "sha256:acf4069b3cf68d05dc8a2df0e511447927303ebef88f897f05cbad823f240d97",
"Labels": {
"io.balena.architecture": "aarch64",
"io.balena.device-type": "jetson-tx2",
"io.balena.qemu.version": "4.0.0+balena2-aarch64"
},
"ParentId": "",
"RepoDigests": [
"registry2.balena-cloud.com/v2/772eca412ce780e860b988da6ea26ee0@sha256:7d5e55d6aac00b8504c5c360a3ee59677fc5a7324360f1f54df19d0bb17c2cfe",
"registry2.balena-cloud.com/v2/7f1290fa85b253936ebf6e0dbbd95875@sha256:107f63eb1bc2e9978f2a4bb5b095bc010dd91dd5a6a0a39a494e27ee8b396232"
],
"RepoTags": [
"registry2.balena-cloud.com/v2/772eca412ce780e860b988da6ea26ee0:delta-ff3f0a82c404830b",
"registry2.balena-cloud.com/v2/7f1290fa85b253936ebf6e0dbbd95875:delta-79acb6d8bf4795f6"
],
"SharedSize": -1,
"Size": 217024666,
"VirtualSize": 217024666
},
"sha256:f1154d76c731f04711e5856b6e6858730e3023d9113124900ac65c2ccc90e8e7": {
"Containers": -1,
"Created": 1599492712,
"Id": "sha256:f1154d76c731f04711e5856b6e6858730e3023d9113124900ac65c2ccc90e8e7",
"Labels": {
"io.balena.architecture": "aarch64",
"io.balena.device-type": "jetson-tx2",
"io.balena.qemu.version": "4.0.0+balena2-aarch64"
},
"ParentId": "",
"RepoDigests": [
"registry2.balena-cloud.com/v2/793f9296017bbfe026334820ab56bb3a@sha256:72b80cbd3cc12de08d4adc9dec79916bf466031553f55b59c29e397829ea129f"
],
"RepoTags": [
"registry2.balena-cloud.com/v2/793f9296017bbfe026334820ab56bb3a:delta-ada9fbb57d90e61e"
],
"SharedSize": -1,
"Size": 217024648,
"VirtualSize": 217024648
},
"sha256:db5af2c94366275d8e6d7ea3047f2405eab2f04a27f66843634a45958ef59f5a": {
"Containers": -1,
"Created": 1599492599,
"Id": "sha256:db5af2c94366275d8e6d7ea3047f2405eab2f04a27f66843634a45958ef59f5a",
"Labels": {
"io.balena.architecture": "aarch64",
"io.balena.livepush-image": "1",
"io.balena.qemu.version": "4.0.0+balena-aarch64"
},
"ParentId": "sha256:4acb1652178e72c0b6143a08225e0df5ef74b338a0c9e2ca4cd261339f4f0431",
"RepoDigests": null,
"RepoTags": [
"livepush-supervisor:11.12.11"
],
"SharedSize": -1,
"Size": 501352885,
"VirtualSize": 501352885
},
"sha256:272c54e27104cf6c2153538165dba3c29b58ae35837b47134fa55b53ddb61154": {
"Containers": -1,
"Created": 1599181227,
"Id": "sha256:272c54e27104cf6c2153538165dba3c29b58ae35837b47134fa55b53ddb61154",
"Labels": {
"io.balena.architecture": "aarch64",
"io.balena.device-type": "jetson-tx2",
"io.balena.qemu.version": "4.0.0+balena2-aarch64"
},
"ParentId": "",
"RepoDigests": [
"registry2.balena-cloud.com/v2/459bffd69101d788cc3e0722a012878a@sha256:3cc9231cf0e117585e53ebfa6bf9f75a9a4eaa371fb82c21ab9bca8fe0d5c3e3",
"registry2.balena-cloud.com/v2/b0cfe2b1e8c5ab3b6da23f0bd92045b4@sha256:ba5f6d1849c63c8d0f11f35fce694464240002d2c3732898935bf0fedf451063"
],
"RepoTags": [
"registry2.balena-cloud.com/v2/459bffd69101d788cc3e0722a012878a:delta-80ed841a1d3fefa9",
"registry2.balena-cloud.com/v2/b0cfe2b1e8c5ab3b6da23f0bd92045b4:delta-532f970c60decb81"
],
"SharedSize": -1,
"Size": 217024558,
"VirtualSize": 217024558
},
"sha256:25d6abae14f08de6b80f9d95003e674598738959a535a2f21be34c03675ebd02": {
"Containers": -1,
"Created": 1599146808,
"Id": "sha256:25d6abae14f08de6b80f9d95003e674598738959a535a2f21be34c03675ebd02",
"Labels": {
"io.balena.qemu.version": "4.0.0+balena-aarch64"
},
"ParentId": "",
"RepoDigests": [
"balena/aarch64-supervisor@sha256:e7e3b166e855f4c113a67bc528b4ef77408d05e280052f35452f3e2cd7b5322b"
],
"RepoTags": [
"balena/aarch64-supervisor:v11.14.0"
],
"SharedSize": -1,
"Size": 72305850,
"VirtualSize": 72305850
},
"sha256:60783b8688d395f9b4ce4b288d941244d1b0a4c43114ba980acd012ccffc6b53": {
"Containers": -1,
"Created": 1585746557,
"Id": "sha256:60783b8688d395f9b4ce4b288d941244d1b0a4c43114ba980acd012ccffc6b53",
"Labels": {
"io.balena.qemu.version": "4.0.0+balena-aarch64"
},
"ParentId": "",
"RepoDigests": [
"balenalib/aarch64-alpine-supervisor-base@sha256:6eb712fc797ff68f258d9032cf292c266cb9bd8be4cbdaaafeb5a8824bb104fd"
],
"RepoTags": [
"balenalib/aarch64-alpine-supervisor-base:3.11"
],
"SharedSize": -1,
"Size": 14503741,
"VirtualSize": 14503741
},
"sha256:a29f45ccde2ac0bde957b1277b1501f471960c8ca49f1588c6c885941640ae60": {
"Containers": -1,
"Created": 1578015959,
"Id": "sha256:a29f45ccde2ac0bde957b1277b1501f471960c8ca49f1588c6c885941640ae60",
"Labels": null,
"ParentId": "",
"RepoDigests": null,
"RepoTags": [
"balena-healthcheck-image:latest"
],
"SharedSize": -1,
"Size": 9136,
"VirtualSize": 9136
}
}
}
}

View File

@ -0,0 +1,68 @@
import * as _ from 'lodash';
import { SinonStub, stub } from 'sinon';
import { QueryBuilder } from 'knex';
import * as db from '../../src/db';
import { Image } from '../../src/compose/images';
let modelStub: SinonStub | null = null;
// MOCKED MODELS
const MOCKED_MODELS: Dictionary<QueryBuilder> = {};
// MOCKED MODEL TYPES
let MOCKED_IMAGES: Image[] = [];
export function create(): SinonStub {
if (modelStub === null) {
modelStub = stub(db, 'models');
// Stub model requests to return our stubbed models
modelStub.callsFake((model: string) => {
return MOCKED_MODELS[model];
});
}
return modelStub;
}
export function restore(): void {
if (modelStub !== null) {
modelStub.restore();
}
}
export function setImages(images: Image[]) {
MOCKED_IMAGES = images;
return {
stub: stubImages,
};
}
function stubImages() {
// Set the functions for this model (add them as you need for your test cases)
MOCKED_MODELS['image'] = ({
select: () => {
return {
where: async (condition: Partial<Image>) =>
_(MOCKED_IMAGES).pickBy(condition).map().value(),
};
},
where: (condition: Partial<Image>) => {
return {
select: async () => _(MOCKED_IMAGES).pickBy(condition).map().value(),
};
},
del: () => {
return {
where: async (condition: Partial<Image>) => {
return _(MOCKED_IMAGES)
.pickBy(condition)
.map()
.value()
.forEach((val) => {
MOCKED_IMAGES = _.reject(MOCKED_IMAGES, {
id: val.id,
});
});
},
};
},
} as unknown) as QueryBuilder;
}

28
test/lib/mocked-dbus.ts Normal file
View File

@ -0,0 +1,28 @@
import * as dbus from 'dbus';
import { DBusError, DBusInterface } from 'dbus';
import { stub } from 'sinon';
stub(dbus, 'getBus').returns({
getInterface: (
_serviceName: string,
_objectPath: string,
_interfaceName: string,
interfaceCb: (err: null | DBusError, iface: DBusInterface) => void,
) => {
interfaceCb(null, {
Get: (
_unitName: string,
_property: string,
getCb: (err: null | Error, value: unknown) => void,
) => {
getCb(null, 'this is the value');
},
GetUnit: (
_unitName: string,
getUnitCb: (err: null | Error, unitPath: string) => void,
) => {
getUnitCb(null, 'this is the unit path');
},
} as any);
},
} as any);

View File

@ -15,6 +15,24 @@ export class NotFoundError extends TypedError {
const overrides: Dictionary<(...args: any[]) => Resolvable<any>> = {};
interface Action {
name: string;
parameters: Dictionary<any>;
}
export let actions: Action[] = [];
export function resetHistory() {
actions = [];
}
function addAction(name: string, parameters: Dictionary<any>) {
actions.push({
name,
parameters,
});
}
type DockerodeFunction = keyof dockerode;
for (const fn of Object.getOwnPropertyNames(dockerode.prototype)) {
if (
@ -62,18 +80,28 @@ export interface TestData {
function createMockedDockerode(data: TestData) {
const mockedDockerode = dockerode.prototype;
mockedDockerode.getNetwork = (id: string) => {
addAction('getNetwork', { id });
return {
inspect: async () => {
addAction('inspect', {});
return data.networks[id];
},
} as dockerode.Network;
};
mockedDockerode.getImage = (name: string) => {
addAction('getImage', { name });
return {
inspect: async () => {
addAction('inspect', {});
return data.images[name];
},
remove: async () => {
addAction('remove', {});
data.images = _.reject(data.images, {
name,
});
},
} as dockerode.Image;
};