diff --git a/lib/device.js b/lib/device.js index 7fd719b..a814e28 100644 --- a/lib/device.js +++ b/lib/device.js @@ -565,7 +565,11 @@ class DeviceManager { } else { platforms = this._devicePool; } - const devs = platforms.get(platform.id); + let id = platform.id; + if (platform.mixed && Array.from(platforms.keys()).length === 1) { + id = Array.from(platforms.keys())[0]; + } + const devs = platforms.get(id); if (!devs || !devs.length) { throw new Error('No devices available for the target platform'); } @@ -756,6 +760,17 @@ class DeviceManager { dev.setAttached(attached); } } + + getPlatformsForFixtures(fixtures) { + const platforms = []; + for (const f of fixtures) { + const fixture = this._fixtures.get(f.name); + if (fixture) { + platforms.push(... fixture.keys()); + } + } + return Array.from(new Set(platforms)); + } } module.exports = { diff --git a/lib/runner.js b/lib/runner.js index 8a32a84..5103fa8 100644 --- a/lib/runner.js +++ b/lib/runner.js @@ -2,7 +2,7 @@ const { PlatformSuite } = require('./suite'); const { DeviceManager } = require('./device'); const { ApiClient } = require('./api'); const { Builder } = require('./build'); -const { platformsForTag, isKnownPlatformTag, PLATFORMS, PLATFORM_TAGS } = require('./platform'); +const { platformsForTag, isKnownPlatformTag, PLATFORMS, PLATFORM_TAGS, Platform } = require('./platform'); const { RunMode, OutputFormat, config, APP_NAME } = require('./config'); const { findTestName, shortenRight } = require('./util'); const { InternalError, isInternalError } = require('./error'); @@ -185,8 +185,6 @@ class Runner { } async _run() { - this._log.verbose('Generating test matrix'); - this._initTestMatrix(); this._log.verbose('Initializing API client'); this._apiClient = new ApiClient({ log: this._log @@ -198,6 +196,8 @@ class Runner { log: this._log }); await this._devMgr.init(this._enabledPlatforms); + this._log.verbose('Generating test matrix'); + await this._initTestMatrix(); // Initialize the runner's context const ctx = this._mocha.suite.ctx; ctx.particle = { @@ -401,7 +401,7 @@ class Runner { runner.once(MochaRunner.constants.EVENT_RUN_END, runEnd); } - _initTestMatrix() { + async _initTestMatrix() { const suites = []; const rootSuite = this._mocha.suite; for (const srcSuite of rootSuite.suites) { @@ -411,8 +411,26 @@ class Runner { } const file = particle.file; const newSuite = srcSuite.clone(); // Doesn't copy tests and hooks + let platformsByFixture = this._devMgr.getPlatformsForFixtures(particle.fixtures); + let platforms = particle.platforms; + if (platformsByFixture && platformsByFixture.length > 1) { + // Mixed platforms + platformsByFixture = platforms.filter((v) => platformsByFixture.includes(v.id)); + platforms = platformsByFixture; + let fakeId = 0; + const fakeName = platforms.map((v) => v.name).join('/'); + const fakeDisplayName = platforms.map((v) => v.displayName).join(' / '); + const fakeTags = [... platforms.map((v) => v.tags)].flat(1); + for (let i = 0; i < platforms.length; i++) { + fakeId += platforms[i].id * (100 ** (i)); + } + platforms = [new Platform({ id: fakeId, name: fakeName, displayName: fakeDisplayName, tags: fakeTags })]; + // FIXME + platforms[0].mixed = true; + platforms[0].platforms = platformsByFixture; + } // Create a nested suite for each platform - for (const platform of particle.platforms) { + for (const platform of platforms) { const platformSuite = MochaSuite.create(newSuite, platform.name); platformSuite.particle = { platform, diff --git a/lib/suite.js b/lib/suite.js index 7b22626..bc85ccc 100644 --- a/lib/suite.js +++ b/lib/suite.js @@ -161,10 +161,9 @@ class PlatformSuite { this._ctx.addDeviceTests(this._suite, tests); } - async _flashApps() { + async _flashAppForPlatform(platform) { const particle = this._suite.particle; const suiteDir = path.dirname(particle.file); - const platform = particle.platform; const apps = new Map(); // Find precompiled binaries if (this._ctx.binaryDir) { @@ -208,13 +207,15 @@ class PlatformSuite { if (!app) { throw new Error(`Application not found: ${appName}`); } - devApps.push({ dev, app }); + if (dev.platform.id === platform.id) { + devApps.push({ dev, app }); + } } // Build applications for (const devApp of devApps) { const app = devApp.app; if (app.build) { - this._log.verbose(`Building application: ${app.path}`); + this._log.verbose(`Building application for ${platform.name}: ${app.path}`); app.path = await this._ctx.builder.buildApp({ appDir: app.path, platform }); app.build = false; } @@ -248,6 +249,17 @@ class PlatformSuite { } } + async _flashApps() { + const particle = this._suite.particle; + if (!particle.platform.mixed) { + return this._flashAppForPlatform(particle.platform); + } else { + for (const platform of particle.platform.platforms) { + await this._flashAppForPlatform(platform); + } + } + } + async _initDevices() { this._ctx.devices = []; this._ctx.fixtures = new Map();