mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-02-20 17:52:51 +00:00
Simplify and move lib/contract.spec.ts to tests/unit
Improve contract tests to remove dependence on stubs and unnecessary system calls. Change-type: patch
This commit is contained in:
parent
eec4d06909
commit
a884a58b4c
@ -1,20 +1,16 @@
|
||||
import { expect } from 'chai';
|
||||
import { SinonStub, stub } from 'sinon';
|
||||
import * as semver from 'semver';
|
||||
import { SinonStub, stub } from 'sinon';
|
||||
|
||||
import * as constants from '~/lib/constants';
|
||||
import {
|
||||
containerContractsFulfilled,
|
||||
initializeContractRequirements,
|
||||
validateContract,
|
||||
} from '~/lib/contracts';
|
||||
import * as osRelease from '~/lib/os-release';
|
||||
import supervisorVersion = require('~/lib/supervisor-version');
|
||||
import * as fsUtils from '~/lib/fs-utils';
|
||||
|
||||
describe('lib/contracts', () => {
|
||||
type Contracts = typeof import('~/src/lib/contracts');
|
||||
const contracts = require('~/src/lib/contracts') as Contracts;
|
||||
before(() => {
|
||||
initializeContractRequirements({
|
||||
contracts.initializeContractRequirements({
|
||||
supervisorVersion,
|
||||
deviceType: 'intel-nuc',
|
||||
l4tVersion: '32.2',
|
||||
@ -24,14 +20,14 @@ describe('lib/contracts', () => {
|
||||
describe('Contract validation', () => {
|
||||
it('should correctly validate a contract with no requirements', () =>
|
||||
expect(() =>
|
||||
validateContract({
|
||||
contracts.validateContract({
|
||||
slug: 'user-container',
|
||||
}),
|
||||
).to.be.not.throw());
|
||||
|
||||
it('should correctly validate a contract with extra fields', () =>
|
||||
expect(() =>
|
||||
validateContract({
|
||||
contracts.validateContract({
|
||||
slug: 'user-container',
|
||||
name: 'user-container',
|
||||
version: '3.0.0',
|
||||
@ -40,15 +36,15 @@ describe('lib/contracts', () => {
|
||||
|
||||
it('should not validate a contract without the minimum required fields', () => {
|
||||
return Promise.all([
|
||||
expect(() => validateContract({})).to.throw(),
|
||||
expect(() => validateContract({ name: 'test' })).to.throw(),
|
||||
expect(() => validateContract({ requires: [] })).to.throw(),
|
||||
expect(() => contracts.validateContract({})).to.throw(),
|
||||
expect(() => contracts.validateContract({ name: 'test' })).to.throw(),
|
||||
expect(() => contracts.validateContract({ requires: [] })).to.throw(),
|
||||
]);
|
||||
});
|
||||
|
||||
it('should correctly validate a contract with requirements', () =>
|
||||
expect(() =>
|
||||
validateContract({
|
||||
contracts.validateContract({
|
||||
slug: 'user-container',
|
||||
requires: [
|
||||
{
|
||||
@ -64,7 +60,7 @@ describe('lib/contracts', () => {
|
||||
|
||||
it('should not validate a contract with requirements without the minimum required fields', () => {
|
||||
return expect(() =>
|
||||
validateContract({
|
||||
contracts.validateContract({
|
||||
slug: 'user-container',
|
||||
requires: [
|
||||
{
|
||||
@ -92,16 +88,16 @@ describe('lib/contracts', () => {
|
||||
// We ensure that the versions we're using for testing
|
||||
// are the same as the time of implementation, otherwise
|
||||
// these tests could fail or succeed when they shouldn't
|
||||
expect(await osRelease.getOSSemver(constants.hostOSVersionPath)).to.equal(
|
||||
'2.0.6',
|
||||
);
|
||||
// expect(await osRelease.getOSSemver(constants.hostOSVersionPath)).to.equal(
|
||||
// '2.0.6',
|
||||
// );
|
||||
expect(semver.gt(supervisorVersionGreater, supervisorVersion)).to.be.true;
|
||||
expect(semver.lt(supervisorVersionLesser, supervisorVersion)).to.be.true;
|
||||
});
|
||||
|
||||
it('Should correctly run containers with no requirements', async () => {
|
||||
expect(
|
||||
containerContractsFulfilled({
|
||||
contracts.containerContractsFulfilled({
|
||||
service: {
|
||||
contract: {
|
||||
type: 'sw.container',
|
||||
@ -114,7 +110,7 @@ describe('lib/contracts', () => {
|
||||
.to.have.property('valid')
|
||||
.that.equals(true);
|
||||
expect(
|
||||
containerContractsFulfilled({
|
||||
contracts.containerContractsFulfilled({
|
||||
service: {
|
||||
contract: {
|
||||
type: 'sw.container',
|
||||
@ -137,7 +133,7 @@ describe('lib/contracts', () => {
|
||||
|
||||
it('should correctly run containers whose requirements are satisfied', async () => {
|
||||
expect(
|
||||
containerContractsFulfilled({
|
||||
contracts.containerContractsFulfilled({
|
||||
service: {
|
||||
contract: {
|
||||
type: 'sw.container',
|
||||
@ -158,7 +154,7 @@ describe('lib/contracts', () => {
|
||||
.that.equals(true);
|
||||
|
||||
expect(
|
||||
containerContractsFulfilled({
|
||||
contracts.containerContractsFulfilled({
|
||||
service: {
|
||||
contract: {
|
||||
type: 'sw.container',
|
||||
@ -179,7 +175,7 @@ describe('lib/contracts', () => {
|
||||
.that.equals(true);
|
||||
|
||||
expect(
|
||||
containerContractsFulfilled({
|
||||
contracts.containerContractsFulfilled({
|
||||
service: {
|
||||
contract: {
|
||||
type: 'sw.container',
|
||||
@ -200,7 +196,7 @@ describe('lib/contracts', () => {
|
||||
.that.equals(true);
|
||||
|
||||
expect(
|
||||
containerContractsFulfilled({
|
||||
contracts.containerContractsFulfilled({
|
||||
service: {
|
||||
contract: {
|
||||
type: 'sw.container',
|
||||
@ -225,7 +221,7 @@ describe('lib/contracts', () => {
|
||||
.that.equals(true);
|
||||
|
||||
expect(
|
||||
containerContractsFulfilled({
|
||||
contracts.containerContractsFulfilled({
|
||||
service: {
|
||||
contract: {
|
||||
type: 'sw.container',
|
||||
@ -261,7 +257,7 @@ describe('lib/contracts', () => {
|
||||
});
|
||||
|
||||
it('Should refuse to run containers whose requirements are not satisfied', async () => {
|
||||
let fulfilled = containerContractsFulfilled({
|
||||
let fulfilled = contracts.containerContractsFulfilled({
|
||||
service: {
|
||||
contract: {
|
||||
type: 'sw.container',
|
||||
@ -282,7 +278,7 @@ describe('lib/contracts', () => {
|
||||
.to.have.property('unmetServices')
|
||||
.that.deep.equals(['service']);
|
||||
|
||||
fulfilled = containerContractsFulfilled({
|
||||
fulfilled = contracts.containerContractsFulfilled({
|
||||
service2: {
|
||||
contract: {
|
||||
type: 'sw.container',
|
||||
@ -303,7 +299,7 @@ describe('lib/contracts', () => {
|
||||
.to.have.property('unmetServices')
|
||||
.that.deep.equals(['service2']);
|
||||
|
||||
fulfilled = containerContractsFulfilled({
|
||||
fulfilled = contracts.containerContractsFulfilled({
|
||||
service: {
|
||||
contract: {
|
||||
type: 'sw.container',
|
||||
@ -342,7 +338,7 @@ describe('lib/contracts', () => {
|
||||
describe('Optional containers', () => {
|
||||
it('should correctly run passing optional containers', async () => {
|
||||
const { valid, unmetServices, fulfilledServices } =
|
||||
containerContractsFulfilled({
|
||||
contracts.containerContractsFulfilled({
|
||||
service1: {
|
||||
contract: {
|
||||
type: 'sw.container',
|
||||
@ -364,7 +360,7 @@ describe('lib/contracts', () => {
|
||||
|
||||
it('should corrrectly omit failing optional containers', async () => {
|
||||
const { valid, unmetServices, fulfilledServices } =
|
||||
containerContractsFulfilled({
|
||||
contracts.containerContractsFulfilled({
|
||||
service1: {
|
||||
contract: {
|
||||
type: 'sw.container',
|
||||
@ -392,143 +388,144 @@ describe('lib/contracts', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('L4T version detection', () => {
|
||||
let execStub: SinonStub;
|
||||
describe('L4T version detection', () => {
|
||||
let execStub: SinonStub;
|
||||
|
||||
const seedExec = (version: string) => {
|
||||
execStub = stub(fsUtils, 'exec').resolves({
|
||||
stdout: Buffer.from(version),
|
||||
stderr: Buffer.from(''),
|
||||
});
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
execStub.restore();
|
||||
});
|
||||
|
||||
it('should correctly parse L4T version strings', async () => {
|
||||
seedExec('4.9.140-l4t-r32.2+g3dcbed5');
|
||||
expect(await osRelease.getL4tVersion()).to.equal('32.2.0');
|
||||
expect(execStub.callCount).to.equal(1);
|
||||
execStub.restore();
|
||||
|
||||
seedExec('4.4.38-l4t-r28.2+g174510d');
|
||||
expect(await osRelease.getL4tVersion()).to.equal('28.2.0');
|
||||
expect(execStub.callCount).to.equal(1);
|
||||
});
|
||||
|
||||
it('should correctly handle l4t versions which contain three numbers', async () => {
|
||||
seedExec('4.4.38-l4t-r32.3.1+g174510d');
|
||||
expect(await osRelease.getL4tVersion()).to.equal('32.3.1');
|
||||
expect(execStub.callCount).to.equal(1);
|
||||
});
|
||||
|
||||
it('should return undefined when there is no l4t string in uname', async () => {
|
||||
seedExec('4.18.14-yocto-standard');
|
||||
expect(await osRelease.getL4tVersion()).to.be.undefined;
|
||||
});
|
||||
|
||||
describe('L4T comparison', () => {
|
||||
const seedEngine = async (version: string) => {
|
||||
if (execStub != null) {
|
||||
execStub.restore();
|
||||
}
|
||||
seedExec(version);
|
||||
initializeContractRequirements({
|
||||
supervisorVersion,
|
||||
deviceType: 'intel-nuc',
|
||||
l4tVersion: await osRelease.getL4tVersion(),
|
||||
const seedExec = (version: string) => {
|
||||
execStub = stub(fsUtils, 'exec').resolves({
|
||||
stdout: Buffer.from(version),
|
||||
stderr: Buffer.from(''),
|
||||
});
|
||||
};
|
||||
|
||||
it('should allow semver matching even when l4t does not fulfill semver', async () => {
|
||||
await seedEngine('4.4.38-l4t-r31.0');
|
||||
|
||||
expect(
|
||||
containerContractsFulfilled({
|
||||
service: {
|
||||
contract: {
|
||||
type: 'sw.container',
|
||||
slug: 'user-container',
|
||||
requires: [
|
||||
{
|
||||
type: 'sw.l4t',
|
||||
version: '>=31.0.0',
|
||||
},
|
||||
],
|
||||
},
|
||||
optional: false,
|
||||
},
|
||||
}),
|
||||
)
|
||||
.to.have.property('valid')
|
||||
.that.equals(true);
|
||||
|
||||
expect(
|
||||
containerContractsFulfilled({
|
||||
service: {
|
||||
contract: {
|
||||
type: 'sw.container',
|
||||
slug: 'user-container',
|
||||
requires: [
|
||||
{
|
||||
type: 'sw.l4t',
|
||||
version: '<31.0.0',
|
||||
},
|
||||
],
|
||||
},
|
||||
optional: false,
|
||||
},
|
||||
}),
|
||||
)
|
||||
.to.have.property('valid')
|
||||
.that.equals(false);
|
||||
afterEach(() => {
|
||||
execStub.restore();
|
||||
});
|
||||
|
||||
it('should allow semver matching when l4t does fulfill semver', async () => {
|
||||
await seedEngine('4.4.38-l4t-r31.0.1');
|
||||
it('should correctly parse L4T version strings', async () => {
|
||||
seedExec('4.9.140-l4t-r32.2+g3dcbed5');
|
||||
expect(await osRelease.getL4tVersion()).to.equal('32.2.0');
|
||||
expect(execStub.callCount).to.equal(1);
|
||||
execStub.restore();
|
||||
|
||||
expect(
|
||||
containerContractsFulfilled({
|
||||
service: {
|
||||
contract: {
|
||||
type: 'sw.container',
|
||||
slug: 'user-container',
|
||||
requires: [
|
||||
{
|
||||
type: 'sw.l4t',
|
||||
version: '>=31.0.0',
|
||||
},
|
||||
],
|
||||
},
|
||||
optional: false,
|
||||
},
|
||||
}),
|
||||
)
|
||||
.to.have.property('valid')
|
||||
.that.equals(true);
|
||||
seedExec('4.4.38-l4t-r28.2+g174510d');
|
||||
expect(await osRelease.getL4tVersion()).to.equal('28.2.0');
|
||||
expect(execStub.callCount).to.equal(1);
|
||||
});
|
||||
|
||||
expect(
|
||||
containerContractsFulfilled({
|
||||
service: {
|
||||
contract: {
|
||||
type: 'sw.container',
|
||||
slug: 'user-container',
|
||||
requires: [
|
||||
{
|
||||
type: 'sw.l4t',
|
||||
version: '<31.0.0',
|
||||
},
|
||||
],
|
||||
it('should correctly handle l4t versions which contain three numbers', async () => {
|
||||
seedExec('4.4.38-l4t-r32.3.1+g174510d');
|
||||
expect(await osRelease.getL4tVersion()).to.equal('32.3.1');
|
||||
expect(execStub.callCount).to.equal(1);
|
||||
});
|
||||
|
||||
it('should return undefined when there is no l4t string in uname', async () => {
|
||||
seedExec('4.18.14-yocto-standard');
|
||||
expect(await osRelease.getL4tVersion()).to.be.undefined;
|
||||
});
|
||||
|
||||
describe('L4T comparison', () => {
|
||||
const seedEngine = async (version: string) => {
|
||||
const engine = require('~/src/lib/contracts') as Contracts;
|
||||
|
||||
seedExec(version);
|
||||
engine.initializeContractRequirements({
|
||||
supervisorVersion,
|
||||
deviceType: 'intel-nuc',
|
||||
l4tVersion: await osRelease.getL4tVersion(),
|
||||
});
|
||||
|
||||
return engine;
|
||||
};
|
||||
|
||||
it('should allow semver matching even when l4t does not fulfill semver', async () => {
|
||||
const engine = await seedEngine('4.4.38-l4t-r31.0');
|
||||
|
||||
expect(
|
||||
engine.containerContractsFulfilled({
|
||||
service: {
|
||||
contract: {
|
||||
type: 'sw.container',
|
||||
slug: 'user-container',
|
||||
requires: [
|
||||
{
|
||||
type: 'sw.l4t',
|
||||
version: '>=31.0.0',
|
||||
},
|
||||
],
|
||||
},
|
||||
optional: false,
|
||||
},
|
||||
optional: false,
|
||||
},
|
||||
}),
|
||||
)
|
||||
.to.have.property('valid')
|
||||
.that.equals(false);
|
||||
}),
|
||||
)
|
||||
.to.have.property('valid')
|
||||
.that.equals(true);
|
||||
|
||||
expect(
|
||||
engine.containerContractsFulfilled({
|
||||
service: {
|
||||
contract: {
|
||||
type: 'sw.container',
|
||||
slug: 'user-container',
|
||||
requires: [
|
||||
{
|
||||
type: 'sw.l4t',
|
||||
version: '<31.0.0',
|
||||
},
|
||||
],
|
||||
},
|
||||
optional: false,
|
||||
},
|
||||
}),
|
||||
)
|
||||
.to.have.property('valid')
|
||||
.that.equals(false);
|
||||
});
|
||||
|
||||
it('should allow semver matching when l4t does fulfill semver', async () => {
|
||||
const engine = await seedEngine('4.4.38-l4t-r31.0.1');
|
||||
|
||||
expect(
|
||||
engine.containerContractsFulfilled({
|
||||
service: {
|
||||
contract: {
|
||||
type: 'sw.container',
|
||||
slug: 'user-container',
|
||||
requires: [
|
||||
{
|
||||
type: 'sw.l4t',
|
||||
version: '>=31.0.0',
|
||||
},
|
||||
],
|
||||
},
|
||||
optional: false,
|
||||
},
|
||||
}),
|
||||
)
|
||||
.to.have.property('valid')
|
||||
.that.equals(true);
|
||||
|
||||
expect(
|
||||
engine.containerContractsFulfilled({
|
||||
service: {
|
||||
contract: {
|
||||
type: 'sw.container',
|
||||
slug: 'user-container',
|
||||
requires: [
|
||||
{
|
||||
type: 'sw.l4t',
|
||||
version: '<31.0.0',
|
||||
},
|
||||
],
|
||||
},
|
||||
optional: false,
|
||||
},
|
||||
}),
|
||||
)
|
||||
.to.have.property('valid')
|
||||
.that.equals(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user