Skip to content

Latest commit

 

History

History
191 lines (119 loc) · 5.13 KB

Covert.md

File metadata and controls

191 lines (119 loc) · 5.13 KB

Covert Guide

The Usage is documented in Covert's README.md file.

Architecture

The Covert Project is a standalone Testrunner that runs in node.js version 12+ and uses ECMAScript imports without transpilation to guarantee identical behaviour when it comes to API tests or Integration tests.

  • A Review is a set of tests, including preparation and cleanup helpers.
  • Each Implementation in /source/*.mjs has a single Review located in /review/*.mjs.

Covert is able to watch for filesystem changes (see Usage of watch) and can re-execute Review(s) when the Implementation has changed.

Execution Process

The covert.sh script builds the reference socks proxy via make and starts it in the background before the given set of Reviews are executed.

As Covert also includes peer-to-peer tests for end-to-end network services, it requires the host machine to be reachable under at least two different IPs.

If the host machine has no internet connection, some network-related tests will fail, such as /stealth/connection/DNS, /stealth/connection/HTTPS, /stealth/connection/HTTP, or /stealth/client/Host.

As the only failsafe way to do this (without requiring two network cards or WAN/LAN connections), there's the requirement to reach the local machine via the IPs 127.0.0.1, 127.0.0.2 and 127.0.0.3.

MacOS

On MacOS it is necessary to create an alias for the loopback interface before Covert itself can be run. The covert.sh automatically creates an alias for above mentioned additional IPs on MacOS and will ask for your sudo password in order to do so.

Currently there's no way to simulate slower network connections as there's no netem nor tc available on Darwin-based systems, so the --network should not be used.

Reviews

Multiple Example Reviews are available in these folders:

Codestyle Rules (Assumptions) of a Review:

  • All Reviews (in /review/*) have to use ES Modules syntax.
  • All Source codes (in /source/*) have to use ES Modules syntax.
  • Reviews can have a single before() entry for preparation.
  • Reviews can have a single after() entry for cleanup.
  • Reviews can have multiple stateless describe() entries.
  • Reviews need to export default via finish('library/namespace/Identifier') to ensure ES Modules compatibility.
  • assert() calls have to be in a separate line.
  • assert() calls have to be branch-less, surrounding if/elseif/else conditions are not allowed.

Exports of the Review Folder (/review/index.mjs):

The index.mjs of any review folder has to export the following properties as a default export:

  • (Array) reviews[] that contains all imported reviews.
  • (Object) sources{} that contains a source-to-review map that allows overriding which review have to reflect what implementation.
// Example index.mjs file

// imports of /review/*.mjs
import Foo from './Foo.mjs';
import Bar from './Bar.mjs';
import Doo from './network/Doo.mjs';


// Review ids are consistent with paths.
// Foo.id = 'my-project/Foo'
// Bar.id = 'my-project/Bar'
// Doo.id = 'my-project/network/Doo'


export default {

	reviews: [

		Foo,
		Bar,
		Doo

	],

	sources: {

		// The Bar review has two implementations,
		// one for node and one for the browser

		'browser/Bar': 'Bar',
		'node/Bar':    'Bar',

		// The Bar review should test the following ES Module
		// that is located at my-project/source/node/Bar.mjs
		// (Note that polyfills can be tested this way)

		'Bar':         'node/Bar',

		// Qux does not need to be tested

		'Qux': null

	}

};

Example Review:

import { before, after, describe, finish } from '../../../covert/index.mjs';
import { Example                         } from '../../../project/source/namespace/Example.mjs';



before('prepare stuff', function(assert) {

	this.example = new Example();

	assert(this.example !== null);

	this.example.on('event', () => {
		assert(true);
	});

});

describe('simple test', function(assert) {

	assert(this.example !== null);
	assert(this.example.method(), true);

	this.example.async((response) => {
		assert(response, { foo: 'bar' });
	});

	assert(this.example.url, 'https://example.com/index.html');

});

describe('debug test', function(assert, console) {

	// This can be used with covert scan <Example> --debug=true

	console.info('This is an info');
	console.warn(this.example);
	console.error('console is integrated');
	console.blink('console is also sandboxed');

});

after('cleanup stuff', function(assert) {

	this.example.on('destroy', () => {
		assert(true);
	});

	this.example.destroy();
	this.example = null;

});


// /project/source/namespace/Example.mjs is the Source Code (ES Module) implementation
// /project/review/namespace/Example.mjs is this Review

export default finish('my-project/namespace/Example');