1737 lines
93 KiB
JavaScript
1737 lines
93 KiB
JavaScript
'use strict';
|
|
|
|
let assert = require('assert');
|
|
|
|
require('../tools/js/v3-models.js');
|
|
const BrowserPrivilegedAPI = require('../public/v3/privileged-api.js').PrivilegedAPI;
|
|
|
|
const MockRemoteAPI = require('./resources/mock-remote-api.js').MockRemoteAPI;
|
|
const MockModels = require('./resources/mock-v3-models.js').MockModels;
|
|
|
|
const BuildbotBuildEntry = require('../tools/js/buildbot-syncer.js').BuildbotBuildEntry;
|
|
const BuildbotSyncer = require('../tools/js/buildbot-syncer.js').BuildbotSyncer;
|
|
|
|
function sampleiOSConfig()
|
|
{
|
|
return {
|
|
'workerArgument': 'workername',
|
|
'buildRequestArgument': 'build_request_id',
|
|
'repositoryGroups': {
|
|
'ios-svn-webkit': {
|
|
'repositories': {'WebKit': {}, 'iOS': {}},
|
|
'testProperties': {
|
|
'desired_image': {'revision': 'iOS'},
|
|
'opensource': {'revision': 'WebKit'},
|
|
}
|
|
}
|
|
},
|
|
'types': {
|
|
'speedometer': {
|
|
'test': ['Speedometer'],
|
|
'properties': {'test_name': 'speedometer'}
|
|
},
|
|
'jetstream': {
|
|
'test': ['JetStream'],
|
|
'properties': {'test_name': 'jetstream'}
|
|
},
|
|
'dromaeo-dom': {
|
|
'test': ['Dromaeo', 'DOM Core Tests'],
|
|
'properties': {'tests': 'dromaeo-dom'}
|
|
},
|
|
},
|
|
'builders': {
|
|
'iPhone-bench': {
|
|
'builder': 'ABTest-iPhone-RunBenchmark-Tests',
|
|
'properties': {'forcescheduler': 'ABTest-iPhone-RunBenchmark-Tests-ForceScheduler'},
|
|
'workerList': ['ABTest-iPhone-0'],
|
|
},
|
|
'iPad-bench': {
|
|
'builder': 'ABTest-iPad-RunBenchmark-Tests',
|
|
'properties': {'forcescheduler': 'ABTest-iPad-RunBenchmark-Tests-ForceScheduler'},
|
|
'workerList': ['ABTest-iPad-0', 'ABTest-iPad-1'],
|
|
},
|
|
'iOS-builder': {
|
|
'builder': 'ABTest-iOS-Builder',
|
|
'properties': {'forcescheduler': 'ABTest-Builder-ForceScheduler'},
|
|
},
|
|
},
|
|
'buildConfigurations': [
|
|
{'builders': ['iOS-builder'], 'platforms': ['iPhone', 'iPad']},
|
|
],
|
|
'testConfigurations': [
|
|
{'builders': ['iPhone-bench'], 'types': ['speedometer', 'jetstream', 'dromaeo-dom'], 'platforms': ['iPhone']},
|
|
{'builders': ['iPad-bench'], 'types': ['speedometer', 'jetstream'], 'platforms': ['iPad']},
|
|
]
|
|
};
|
|
}
|
|
|
|
function sampleiOSConfigWithExpansions()
|
|
{
|
|
return {
|
|
"triggerableName": "build-webkit-ios",
|
|
"buildRequestArgument": "build-request-id",
|
|
"repositoryGroups": { },
|
|
"types": {
|
|
"iphone-plt": {
|
|
"test": ["PLT-iPhone"],
|
|
"properties": {"test_name": "plt"}
|
|
},
|
|
"ipad-plt": {
|
|
"test": ["PLT-iPad"],
|
|
"properties": {"test_name": "plt"}
|
|
},
|
|
"speedometer": {
|
|
"test": ["Speedometer"],
|
|
"properties": {"tests": "speedometer"}
|
|
},
|
|
},
|
|
"builders": {
|
|
"iphone": {
|
|
"builder": "iPhone AB Tests",
|
|
"properties": {"forcescheduler": "force-iphone-ab-tests"},
|
|
},
|
|
"iphone-2": {
|
|
"builder": "iPhone 2 AB Tests",
|
|
"properties": {"forcescheduler": "force-iphone-2-ab-tests"},
|
|
},
|
|
"ipad": {
|
|
"builder": "iPad AB Tests",
|
|
"properties": {"forcescheduler": "force-ipad-ab-tests"},
|
|
},
|
|
},
|
|
"testConfigurations": [
|
|
{
|
|
"builders": ["iphone", "iphone-2"],
|
|
"platforms": ["iPhone", "iOS 10 iPhone"],
|
|
"types": ["iphone-plt", "speedometer"],
|
|
},
|
|
{
|
|
"builders": ["ipad"],
|
|
"platforms": ["iPad"],
|
|
"types": ["ipad-plt", "speedometer"],
|
|
},
|
|
]
|
|
}
|
|
}
|
|
|
|
function smallConfiguration()
|
|
{
|
|
return {
|
|
'buildRequestArgument': 'id',
|
|
'repositoryGroups': {
|
|
'ios-svn-webkit': {
|
|
'repositories': {'iOS': {}, 'WebKit': {}},
|
|
'testProperties': {
|
|
'os': {'revision': 'iOS'},
|
|
'wk': {'revision': 'WebKit'}
|
|
}
|
|
}
|
|
},
|
|
'types': {
|
|
'some-test': {
|
|
'test': ['Some test'],
|
|
}
|
|
},
|
|
'builders': {
|
|
'some-builder': {
|
|
'builder': 'some builder',
|
|
'properties': {'forcescheduler': 'some-builder-ForceScheduler'}
|
|
}
|
|
},
|
|
'testConfigurations': [{
|
|
'builders': ['some-builder'],
|
|
'platforms': ['Some platform'],
|
|
'types': ['some-test'],
|
|
}]
|
|
};
|
|
}
|
|
|
|
function builderNameToIDMap()
|
|
{
|
|
return {
|
|
'some builder' : '100',
|
|
'ABTest-iPhone-RunBenchmark-Tests': '101',
|
|
'ABTest-iPad-RunBenchmark-Tests': '102',
|
|
'ABTest-iOS-Builder': '103',
|
|
'iPhone AB Tests' : '104',
|
|
'iPhone 2 AB Tests': '105',
|
|
'iPad AB Tests': '106'
|
|
};
|
|
}
|
|
|
|
function smallPendingBuild()
|
|
{
|
|
return samplePendingBuildRequests(null, null, null, "some builder");
|
|
}
|
|
|
|
function smallInProgressBuild()
|
|
{
|
|
return sampleInProgressBuild();
|
|
}
|
|
|
|
function smallFinishedBuild()
|
|
{
|
|
return sampleFinishedBuild(null, null, "some builder");
|
|
}
|
|
|
|
function createSampleBuildRequest(platform, test)
|
|
{
|
|
assert(platform instanceof Platform);
|
|
assert(test instanceof Test);
|
|
|
|
const webkit197463 = CommitLog.ensureSingleton('111127', {'id': '111127', 'time': 1456955807334, 'repository': MockModels.webkit, 'revision': '197463'});
|
|
const shared111237 = CommitLog.ensureSingleton('111237', {'id': '111237', 'time': 1456931874000, 'repository': MockModels.sharedRepository, 'revision': '80229'});
|
|
const ios13A452 = CommitLog.ensureSingleton('88930', {'id': '88930', 'time': 0, 'repository': MockModels.ios, 'revision': '13A452'});
|
|
|
|
const commitSet = CommitSet.ensureSingleton('4197', {customRoots: [], revisionItems: [{commit: webkit197463}, {commit: shared111237}, {commit: ios13A452}]});
|
|
|
|
return BuildRequest.ensureSingleton('16733-' + platform.id(), {'triggerable': MockModels.triggerable,
|
|
repositoryGroup: MockModels.svnRepositoryGroup,
|
|
'commitSet': commitSet, 'status': 'pending', 'platform': platform, 'test': test, order: 0});
|
|
}
|
|
|
|
function createSampleBuildRequestWithPatch(platform, test, order)
|
|
{
|
|
assert(platform instanceof Platform);
|
|
assert(!test || test instanceof Test);
|
|
|
|
const webkit197463 = CommitLog.ensureSingleton('111127', {'id': '111127', 'time': 1456955807334, 'repository': MockModels.webkit, 'revision': '197463'});
|
|
const shared111237 = CommitLog.ensureSingleton('111237', {'id': '111237', 'time': 1456931874000, 'repository': MockModels.sharedRepository, 'revision': '80229'});
|
|
const ios13A452 = CommitLog.ensureSingleton('88930', {'id': '88930', 'time': 0, 'repository': MockModels.ios, 'revision': '13A452'});
|
|
|
|
const patch = new UploadedFile(453, {'createdAt': new Date('2017-05-01T19:16:53Z'), 'filename': 'patch.dat', 'extension': '.dat', 'author': 'some user',
|
|
size: 534637, sha256: '169463c8125e07c577110fe144ecd63942eb9472d438fc0014f474245e5df8a1'});
|
|
|
|
const root = new UploadedFile(456, {'createdAt': new Date('2017-05-01T21:03:27Z'), 'filename': 'root.dat', 'extension': '.dat', 'author': 'some user',
|
|
size: 16452234, sha256: '03eed7a8494ab8794c44b7d4308e55448fc56f4d6c175809ba968f78f656d58d'});
|
|
|
|
const commitSet = CommitSet.ensureSingleton('53246456', {customRoots: [root], revisionItems: [{commit: webkit197463, patch, requiresBuild: true}, {commit: shared111237}, {commit: ios13A452}]});
|
|
|
|
return BuildRequest.ensureSingleton(`6345645376-${order}`, {'triggerable': MockModels.triggerable,
|
|
repositoryGroup: MockModels.svnRepositoryGroup,
|
|
'commitSet': commitSet, 'status': 'pending', 'platform': platform, 'test': test, 'order': order});
|
|
}
|
|
|
|
function createSampleBuildRequestWithOwnedCommit(platform, test, order)
|
|
{
|
|
assert(platform instanceof Platform);
|
|
assert(!test || test instanceof Test);
|
|
|
|
const webkit197463 = CommitLog.ensureSingleton('111127', {'id': '111127', 'time': 1456955807334, 'repository': MockModels.webkit, 'revision': '197463'});
|
|
const owner111289 = CommitLog.ensureSingleton('111289', {'id': '111289', 'time': 1456931874000, 'repository': MockModels.ownerRepository, 'revision': 'owner-001'});
|
|
const owned111222 = CommitLog.ensureSingleton('111222', {'id': '111222', 'time': 1456932774000, 'repository': MockModels.ownedRepository, 'revision': 'owned-002'});
|
|
const ios13A452 = CommitLog.ensureSingleton('88930', {'id': '88930', 'time': 0, 'repository': MockModels.ios, 'revision': '13A452'});
|
|
|
|
const root = new UploadedFile(456, {'createdAt': new Date('2017-05-01T21:03:27Z'), 'filename': 'root.dat', 'extension': '.dat', 'author': 'some user',
|
|
size: 16452234, sha256: '03eed7a8494ab8794c44b7d4308e55448fc56f4d6c175809ba968f78f656d58d'});
|
|
|
|
const commitSet = CommitSet.ensureSingleton('53246486', {customRoots: [root], revisionItems: [{commit: webkit197463}, {commit: owner111289}, {commit: owned111222, commitOwner: owner111289, requiresBuild: true}, {commit: ios13A452}]});
|
|
|
|
return BuildRequest.ensureSingleton(`6345645370-${order}`, {'triggerable': MockModels.triggerable,
|
|
repositoryGroup: MockModels.svnRepositoryWithOwnedRepositoryGroup,
|
|
'commitSet': commitSet, 'status': 'pending', 'platform': platform, 'test': test, 'order': order});
|
|
}
|
|
|
|
function createSampleBuildRequestWithOwnedCommitAndPatch(platform, test, order)
|
|
{
|
|
assert(platform instanceof Platform);
|
|
assert(!test || test instanceof Test);
|
|
|
|
const webkit197463 = CommitLog.ensureSingleton('111127', {'id': '111127', 'time': 1456955807334, 'repository': MockModels.webkit, 'revision': '197463'});
|
|
const owner111289 = CommitLog.ensureSingleton('111289', {'id': '111289', 'time': 1456931874000, 'repository': MockModels.ownerRepository, 'revision': 'owner-001'});
|
|
const owned111222 = CommitLog.ensureSingleton('111222', {'id': '111222', 'time': 1456932774000, 'repository': MockModels.ownedRepository, 'revision': 'owned-002'});
|
|
const ios13A452 = CommitLog.ensureSingleton('88930', {'id': '88930', 'time': 0, 'repository': MockModels.ios, 'revision': '13A452'});
|
|
|
|
const patch = new UploadedFile(453, {'createdAt': new Date('2017-05-01T19:16:53Z'), 'filename': 'patch.dat', 'extension': '.dat', 'author': 'some user',
|
|
size: 534637, sha256: '169463c8125e07c577110fe144ecd63942eb9472d438fc0014f474245e5df8a1'});
|
|
|
|
const commitSet = CommitSet.ensureSingleton('53246486', {customRoots: [], revisionItems: [{commit: webkit197463, patch, requiresBuild: true}, {commit: owner111289}, {commit: owned111222, commitOwner: owner111289, requiresBuild: true}, {commit: ios13A452}]});
|
|
|
|
return BuildRequest.ensureSingleton(`6345645370-${order}`, {'triggerable': MockModels.triggerable,
|
|
repositoryGroup: MockModels.svnRepositoryWithOwnedRepositoryGroup,
|
|
'commitSet': commitSet, 'status': 'pending', 'platform': platform, 'test': test, 'order': order});
|
|
}
|
|
|
|
function samplePendingBuildRequestData(buildRequestId, buildTime, workerName, builderId)
|
|
{
|
|
return {
|
|
"builderid": builderId || 102,
|
|
"buildrequestid": 17,
|
|
"buildsetid": 894720,
|
|
"claimed": false,
|
|
"claimed_at": null,
|
|
"claimed_by_masterid": null,
|
|
"complete": false,
|
|
"complete_at": null,
|
|
"priority": 0,
|
|
"results": -1,
|
|
"submitted_at": buildTime || 1458704983,
|
|
"waited_for": false,
|
|
"properties": {
|
|
"build_request_id": [buildRequestId || 16733, "Force Build Form"],
|
|
"scheduler": ["ABTest-iPad-RunBenchmark-Tests-ForceScheduler", "Scheduler"],
|
|
"workername": [workerName, "Worker (deprecated)"],
|
|
"workername": [workerName, "Worker"]
|
|
}
|
|
};
|
|
}
|
|
|
|
function samplePendingBuildRequests(buildRequestId, buildTime, workerName, builderName)
|
|
{
|
|
return {
|
|
"buildrequests" : [samplePendingBuildRequestData(buildRequestId, buildTime, workerName, builderNameToIDMap()[builderName])]
|
|
};
|
|
}
|
|
|
|
function sampleBuildData(workerName, isComplete, buildRequestId, buildTag, builderId, state_string)
|
|
{
|
|
return {
|
|
"builderid": builderId || 102,
|
|
"number": buildTag || 614,
|
|
"buildrequestid": 17,
|
|
"complete": isComplete,
|
|
"complete_at": null,
|
|
"buildid": 418744,
|
|
"masterid": 1,
|
|
"results": null,
|
|
"started_at": 1513725109,
|
|
state_string,
|
|
"workerid": 41,
|
|
"properties": {
|
|
"build_request_id": [buildRequestId || 16733, "Force Build Form"],
|
|
"platform": ["mac", "Unknown"],
|
|
"scheduler": ["ABTest-iPad-RunBenchmark-Tests-ForceScheduler", "Scheduler"],
|
|
"workername": [workerName || "ABTest-iPad-0", "Worker (deprecated)"],
|
|
"workername": [workerName || "ABTest-iPad-0", "Worker"],
|
|
}
|
|
};
|
|
}
|
|
|
|
function sampleInProgressBuildData(workerName)
|
|
{
|
|
return sampleBuildData(workerName, false, null, null, null, 'building');
|
|
}
|
|
|
|
function sampleInProgressBuild(workerName)
|
|
{
|
|
return {
|
|
"builds": [sampleInProgressBuildData(workerName)]
|
|
};
|
|
}
|
|
|
|
function sampleFinishedBuildData(buildRequestId, workerName, builderName)
|
|
{
|
|
return sampleBuildData(workerName, true, buildRequestId || 18935, 1755, builderNameToIDMap()[builderName]);
|
|
}
|
|
|
|
function sampleFinishedBuild(buildRequestId, workerName, builderName)
|
|
{
|
|
return {
|
|
"builds": [sampleFinishedBuildData(buildRequestId, workerName, builderName)]
|
|
};
|
|
}
|
|
|
|
describe('BuildbotSyncer', () => {
|
|
MockModels.inject();
|
|
const requests = MockRemoteAPI.inject('http://build.webkit.org', BrowserPrivilegedAPI);
|
|
|
|
describe('_loadConfig', () => {
|
|
|
|
it('should create BuildbotSyncer objects for a configuration that specify all required options', () => {
|
|
assert.equal(BuildbotSyncer._loadConfig(MockRemoteAPI, smallConfiguration(), builderNameToIDMap()).length, 1);
|
|
});
|
|
|
|
it('should throw when some required options are missing', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
delete config.builders;
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /"some-builder" is not a valid builder in the configuration/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
delete config.types;
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /"some-test" is not a valid type in the configuration/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
delete config.testConfigurations[0].builders;
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /The test configuration 1 does not specify "builders" as an array/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
delete config.testConfigurations[0].platforms;
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /The test configuration 1 does not specify "platforms" as an array/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
delete config.testConfigurations[0].types;
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /The test configuration 0 does not specify "types" as an array/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
delete config.buildRequestArgument;
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /buildRequestArgument must specify the name of the property used to store the build request ID/);
|
|
});
|
|
|
|
it('should throw when a test name is not an array of strings', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.testConfigurations[0].types = 'some test';
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /The test configuration 0 does not specify "types" as an array/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.testConfigurations[0].types = [1];
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /"1" is not a valid type in the configuration/);
|
|
});
|
|
|
|
it('should throw when properties is not an object', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.builders[Object.keys(config.builders)[0]].properties = 'hello';
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Build properties should be a dictionary/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.types[Object.keys(config.types)[0]].properties = 'hello';
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Build properties should be a dictionary/);
|
|
});
|
|
|
|
it('should throw when testProperties is specifed in a type or a builder', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
const firstType = Object.keys(config.types)[0];
|
|
config.types[firstType].testProperties = {};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Unrecognized parameter "testProperties"/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
const firstBuilder = Object.keys(config.builders)[0];
|
|
config.builders[firstBuilder].testProperties = {};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Unrecognized parameter "testProperties"/);
|
|
});
|
|
|
|
it('should throw when buildProperties is specifed in a type or a builder', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
const firstType = Object.keys(config.types)[0];
|
|
config.types[firstType].buildProperties = {};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Unrecognized parameter "buildProperties"/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
const firstBuilder = Object.keys(config.builders)[0];
|
|
config.builders[firstBuilder].buildProperties = {};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Unrecognized parameter "buildProperties"/);
|
|
});
|
|
|
|
it('should throw when properties for a type is malformed', () => {
|
|
const firstType = Object.keys(smallConfiguration().types)[0];
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.types[firstType].properties = 'hello';
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Build properties should be a dictionary/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.types[firstType].properties = {'some': {'otherKey': 'some root'}};
|
|
BuildbotSyncer._loadConfig(RemoteAPI, config, builderNameToIDMap());
|
|
}, /Build properties "some" specifies a non-string value of type "object"/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.types[firstType].properties = {'some': {'otherKey': 'some root'}};
|
|
BuildbotSyncer._loadConfig(RemoteAPI, config, builderNameToIDMap());
|
|
}, /Build properties "some" specifies a non-string value of type "object"/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.types[firstType].properties = {'some': {'revision': 'WebKit'}};
|
|
BuildbotSyncer._loadConfig(RemoteAPI, config, builderNameToIDMap());
|
|
}, /Build properties "some" specifies a non-string value of type "object"/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.types[firstType].properties = {'some': 1};
|
|
BuildbotSyncer._loadConfig(RemoteAPI, config, builderNameToIDMap());
|
|
}, / Build properties "some" specifies a non-string value of type "object"/);
|
|
});
|
|
|
|
it('should throw when properties for a builder is malformed', () => {
|
|
const firstBuilder = Object.keys(smallConfiguration().builders)[0];
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.builders[firstBuilder].properties = 'hello';
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Build properties should be a dictionary/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.builders[firstBuilder].properties = {'some': {'otherKey': 'some root'}};
|
|
BuildbotSyncer._loadConfig(RemoteAPI, config, builderNameToIDMap());
|
|
}, /Build properties "some" specifies a non-string value of type "object"/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.builders[firstBuilder].properties = {'some': {'otherKey': 'some root'}};
|
|
BuildbotSyncer._loadConfig(RemoteAPI, config, builderNameToIDMap());
|
|
}, /Build properties "some" specifies a non-string value of type "object"/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.builders[firstBuilder].properties = {'some': {'revision': 'WebKit'}};
|
|
BuildbotSyncer._loadConfig(RemoteAPI, config, builderNameToIDMap());
|
|
}, /Build properties "some" specifies a non-string value of type "object"/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.builders[firstBuilder].properties = {'some': 1};
|
|
BuildbotSyncer._loadConfig(RemoteAPI, config, builderNameToIDMap());
|
|
}, /Build properties "some" specifies a non-string value of type "object"/);
|
|
});
|
|
|
|
it('should create BuildbotSyncer objects for valid configurations', () => {
|
|
let syncers = BuildbotSyncer._loadConfig(RemoteAPI, sampleiOSConfig(), builderNameToIDMap());
|
|
assert.equal(syncers.length, 3);
|
|
assert.ok(syncers[0] instanceof BuildbotSyncer);
|
|
assert.ok(syncers[1] instanceof BuildbotSyncer);
|
|
assert.ok(syncers[2] instanceof BuildbotSyncer);
|
|
});
|
|
|
|
it('should parse builder names correctly', () => {
|
|
let syncers = BuildbotSyncer._loadConfig(RemoteAPI, sampleiOSConfig(), builderNameToIDMap());
|
|
assert.equal(syncers[0].builderName(), 'ABTest-iPhone-RunBenchmark-Tests');
|
|
assert.equal(syncers[1].builderName(), 'ABTest-iPad-RunBenchmark-Tests');
|
|
assert.equal(syncers[2].builderName(), 'ABTest-iOS-Builder');
|
|
});
|
|
|
|
it('should parse test configurations with build configurations correctly', () => {
|
|
let syncers = BuildbotSyncer._loadConfig(RemoteAPI, sampleiOSConfig(), builderNameToIDMap());
|
|
|
|
let configurations = syncers[0].testConfigurations();
|
|
assert(syncers[0].isTester());
|
|
assert.equal(configurations.length, 3);
|
|
assert.equal(configurations[0].platform, MockModels.iphone);
|
|
assert.equal(configurations[0].test, MockModels.speedometer);
|
|
assert.equal(configurations[1].platform, MockModels.iphone);
|
|
assert.equal(configurations[1].test, MockModels.jetstream);
|
|
assert.equal(configurations[2].platform, MockModels.iphone);
|
|
assert.equal(configurations[2].test, MockModels.domcore);
|
|
assert.deepEqual(syncers[0].buildConfigurations(), []);
|
|
|
|
configurations = syncers[1].testConfigurations();
|
|
assert(syncers[1].isTester());
|
|
assert.equal(configurations.length, 2);
|
|
assert.equal(configurations[0].platform, MockModels.ipad);
|
|
assert.equal(configurations[0].test, MockModels.speedometer);
|
|
assert.equal(configurations[1].platform, MockModels.ipad);
|
|
assert.equal(configurations[1].test, MockModels.jetstream);
|
|
assert.deepEqual(syncers[1].buildConfigurations(), []);
|
|
|
|
assert(!syncers[2].isTester());
|
|
assert.deepEqual(syncers[2].testConfigurations(), []);
|
|
configurations = syncers[2].buildConfigurations();
|
|
assert.equal(configurations.length, 2);
|
|
assert.equal(configurations[0].platform, MockModels.iphone);
|
|
assert.equal(configurations[0].test, null);
|
|
assert.equal(configurations[1].platform, MockModels.ipad);
|
|
assert.equal(configurations[1].test, null);
|
|
});
|
|
|
|
it('should throw when a build configuration use the same builder as a test configuration', () => {
|
|
assert.throws(() => {
|
|
const config = sampleiOSConfig();
|
|
config.buildConfigurations[0].builders = config.testConfigurations[0].builders;
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
});
|
|
});
|
|
|
|
it('should parse test configurations with types and platforms expansions correctly', () => {
|
|
const syncers = BuildbotSyncer._loadConfig(RemoteAPI, sampleiOSConfigWithExpansions(), builderNameToIDMap());
|
|
|
|
assert.equal(syncers.length, 3);
|
|
|
|
let configurations = syncers[0].testConfigurations();
|
|
assert.equal(configurations.length, 4);
|
|
assert.equal(configurations[0].platform, MockModels.iphone);
|
|
assert.equal(configurations[0].test, MockModels.iPhonePLT);
|
|
assert.equal(configurations[1].platform, MockModels.iphone);
|
|
assert.equal(configurations[1].test, MockModels.speedometer);
|
|
assert.equal(configurations[2].platform, MockModels.iOS10iPhone);
|
|
assert.equal(configurations[2].test, MockModels.iPhonePLT);
|
|
assert.equal(configurations[3].platform, MockModels.iOS10iPhone);
|
|
assert.equal(configurations[3].test, MockModels.speedometer);
|
|
assert.deepEqual(syncers[0].buildConfigurations(), []);
|
|
|
|
configurations = syncers[1].testConfigurations();
|
|
assert.equal(configurations.length, 4);
|
|
assert.equal(configurations[0].platform, MockModels.iphone);
|
|
assert.equal(configurations[0].test, MockModels.iPhonePLT);
|
|
assert.equal(configurations[1].platform, MockModels.iphone);
|
|
assert.equal(configurations[1].test, MockModels.speedometer);
|
|
assert.equal(configurations[2].platform, MockModels.iOS10iPhone);
|
|
assert.equal(configurations[2].test, MockModels.iPhonePLT);
|
|
assert.equal(configurations[3].platform, MockModels.iOS10iPhone);
|
|
assert.equal(configurations[3].test, MockModels.speedometer);
|
|
assert.deepEqual(syncers[1].buildConfigurations(), []);
|
|
|
|
configurations = syncers[2].testConfigurations();
|
|
assert.equal(configurations.length, 2);
|
|
assert.equal(configurations[0].platform, MockModels.ipad);
|
|
assert.equal(configurations[0].test, MockModels.iPadPLT);
|
|
assert.equal(configurations[1].platform, MockModels.ipad);
|
|
assert.equal(configurations[1].test, MockModels.speedometer);
|
|
assert.deepEqual(syncers[2].buildConfigurations(), []);
|
|
});
|
|
|
|
it('should throw when repositoryGroups is not an object', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = 1;
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /repositoryGroups must specify a dictionary from the name to its definition/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = 'hello';
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /repositoryGroups must specify a dictionary from the name to its definition/);
|
|
});
|
|
|
|
it('should throw when a repository group does not specify a dictionary of repositories', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {testProperties: {}}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Repository group "some-group" does not specify a dictionary of repositories/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {repositories: 1}, testProperties: {}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Repository group "some-group" does not specify a dictionary of repositories/);
|
|
});
|
|
|
|
it('should throw when a repository group specifies an empty dictionary', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {repositories: {}, testProperties: {}}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Repository group "some-group" does not specify any repository/);
|
|
});
|
|
|
|
it('should throw when a repository group specifies an invalid repository name', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {repositories: {'InvalidRepositoryName': {}}}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /"InvalidRepositoryName" is not a valid repository name/);
|
|
});
|
|
|
|
it('should throw when a repository group specifies a repository with a non-dictionary value', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {repositories: {'WebKit': 1}}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /"WebKit" specifies a non-dictionary value/);
|
|
});
|
|
|
|
it('should throw when the description of a repository group is not a string', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {repositories: {'WebKit': {}}, description: 1}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Repository group "some-group" have an invalid description/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {repositories: {'WebKit': {}}, description: [1, 2]}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Repository group "some-group" have an invalid description/);
|
|
});
|
|
|
|
it('should throw when a repository group does not specify a dictionary of properties', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {repositories: {'WebKit': {}}, testProperties: 1}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Repository group "some-group" specifies the test configurations with an invalid type/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {repositories: {'WebKit': {}}, testProperties: 'hello'}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Repository group "some-group" specifies the test configurations with an invalid type/);
|
|
});
|
|
|
|
it('should throw when a repository group refers to a non-existent repository in the properties dictionary', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {repositories: {'WebKit': {}}, testProperties: {'wk': {revision: 'InvalidRepository'}}}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Repository group "some-group" an invalid repository "InvalidRepository"/);
|
|
});
|
|
|
|
it('should throw when a repository group refers to a repository which is not listed in the list of repositories', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {repositories: {'WebKit': {}}, testProperties: {'os': {revision: 'iOS'}}}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Repository group "some-group" an invalid repository "iOS"/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {
|
|
repositories: {'WebKit': {acceptsPatch: true}},
|
|
testProperties: {'wk': {revision: 'WebKit'}, 'install-roots': {'roots': {}}},
|
|
buildProperties: {'os': {revision: 'iOS'}},
|
|
acceptsRoots: true}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Repository group "some-group" an invalid repository "iOS"/);
|
|
});
|
|
|
|
it('should throw when a repository group refers to a repository in building a patch which does not accept a patch', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {
|
|
repositories: {'WebKit': {acceptsPatch: true}, 'iOS': {}},
|
|
testProperties: {'wk': {revision: 'WebKit'}, 'ios': {revision: 'iOS'}, 'install-roots': {'roots': {}}},
|
|
buildProperties: {'wk': {revision: 'WebKit'}, 'ios': {revision: 'iOS'}, 'wk-patch': {patch: 'iOS'}},
|
|
acceptsRoots: true}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Repository group "some-group" specifies a patch for "iOS" but it does not accept a patch/);
|
|
});
|
|
|
|
it('should throw when a repository group specifies a patch without specifying a revision', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {
|
|
repositories: {'WebKit': {acceptsPatch: true}},
|
|
testProperties: {'wk': {revision: 'WebKit'}, 'install-roots': {'roots': {}}},
|
|
buildProperties: {'wk-patch': {patch: 'WebKit'}},
|
|
acceptsRoots: true}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Repository group "some-group" specifies a patch for "WebKit" but does not specify a revision/);
|
|
});
|
|
|
|
it('should throw when a repository group does not use a listed repository', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {'repositories': {'WebKit': {}}, testProperties: {}}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Repository group "some-group" does not use some of the repositories listed in testing/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {
|
|
repositories: {'WebKit': {acceptsPatch: true}},
|
|
testProperties: {'wk': {revision: 'WebKit'}, 'install-roots': {'roots': {}}},
|
|
buildProperties: {},
|
|
acceptsRoots: true}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Repository group "some-group" does not use some of the repositories listed in building a patch/);
|
|
});
|
|
|
|
it('should throw when a repository group specifies non-boolean value to acceptsRoots', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {'repositories': {'WebKit': {}}, 'testProperties': {'webkit': {'revision': 'WebKit'}}, acceptsRoots: 1}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Repository group "some-group" contains invalid acceptsRoots value:/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {'repositories': {'WebKit': {}}, 'testProperties': {'webkit': {'revision': 'WebKit'}}, acceptsRoots: []}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Repository group "some-group" contains invalid acceptsRoots value:/);
|
|
});
|
|
|
|
it('should throw when a repository group specifies non-boolean value to acceptsPatch', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {'repositories': {'WebKit': {acceptsPatch: 1}}, 'testProperties': {'webkit': {'revision': 'WebKit'}}}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /"WebKit" contains invalid acceptsPatch value:/);
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {'repositories': {'WebKit': {acceptsPatch: []}}, 'testProperties': {'webkit': {'revision': 'WebKit'}}}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /"WebKit" contains invalid acceptsPatch value:/);
|
|
});
|
|
|
|
it('should throw when a repository group specifies a patch in testProperties', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {'repositories': {'WebKit': {acceptsPatch: true}},
|
|
'testProperties': {'webkit': {'revision': 'WebKit'}, 'webkit-patch': {'patch': 'WebKit'}}}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Repository group "some-group" specifies a patch for "WebKit" in the properties for testing/);
|
|
});
|
|
|
|
it('should throw when a repository group specifies roots in buildProperties', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {
|
|
repositories: {'WebKit': {acceptsPatch: true}},
|
|
testProperties: {'webkit': {revision: 'WebKit'}, 'install-roots': {'roots': {}}},
|
|
buildProperties: {'webkit': {revision: 'WebKit'}, 'patch': {patch: 'WebKit'}, 'install-roots': {roots: {}}},
|
|
acceptsRoots: true}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Repository group "some-group" specifies roots in the properties for building/);
|
|
});
|
|
|
|
it('should throw when a repository group that does not accept roots specifies roots in testProperties', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {
|
|
repositories: {'WebKit': {}},
|
|
testProperties: {'webkit': {'revision': 'WebKit'}, 'install-roots': {'roots': {}}}}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Repository group "some-group" specifies roots in a property but it does not accept roots/);
|
|
});
|
|
|
|
it('should throw when a repository group specifies buildProperties but does not accept roots', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {
|
|
repositories: {'WebKit': {acceptsPatch: true}},
|
|
testProperties: {'webkit': {revision: 'WebKit'}},
|
|
buildProperties: {'webkit': {revision: 'WebKit'}, 'webkit-patch': {patch: 'WebKit'}}}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Repository group "some-group" specifies the properties for building but does not accept roots in testing/);
|
|
});
|
|
|
|
it('should throw when a repository group specifies buildProperties but does not accept any patch', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {
|
|
repositories: {'WebKit': {}},
|
|
testProperties: {'webkit': {'revision': 'WebKit'}, 'install-roots': {'roots': {}}},
|
|
buildProperties: {'webkit': {'revision': 'WebKit'}},
|
|
acceptsRoots: true}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Repository group "some-group" specifies the properties for building but does not accept any patches/);
|
|
});
|
|
|
|
it('should throw when a repository group accepts roots but does not specify roots in testProperties', () => {
|
|
assert.throws(() => {
|
|
const config = smallConfiguration();
|
|
config.repositoryGroups = {'some-group': {
|
|
repositories: {'WebKit': {acceptsPatch: true}},
|
|
testProperties: {'webkit': {revision: 'WebKit'}},
|
|
buildProperties: {'webkit': {revision: 'WebKit'}, 'webkit-patch': {patch: 'WebKit'}},
|
|
acceptsRoots: true}};
|
|
BuildbotSyncer._loadConfig(MockRemoteAPI, config, builderNameToIDMap());
|
|
}, /Repository group "some-group" accepts roots but does not specify roots in testProperties/);
|
|
});
|
|
});
|
|
|
|
describe('_propertiesForBuildRequest', () => {
|
|
it('should include all properties specified in a given configuration', () => {
|
|
const syncers = BuildbotSyncer._loadConfig(RemoteAPI, sampleiOSConfig(), builderNameToIDMap());
|
|
const request = createSampleBuildRequest(MockModels.iphone, MockModels.speedometer);
|
|
const properties = syncers[0]._propertiesForBuildRequest(request, [request]);
|
|
assert.deepEqual(Object.keys(properties).sort(), ['build_request_id', 'desired_image', 'forcescheduler', 'opensource', 'test_name']);
|
|
});
|
|
|
|
it('should preserve non-parametric property values', () => {
|
|
const syncers = BuildbotSyncer._loadConfig(RemoteAPI, sampleiOSConfig(), builderNameToIDMap());
|
|
let request = createSampleBuildRequest(MockModels.iphone, MockModels.speedometer);
|
|
let properties = syncers[0]._propertiesForBuildRequest(request, [request]);
|
|
assert.equal(properties['test_name'], 'speedometer');
|
|
assert.equal(properties['forcescheduler'], 'ABTest-iPhone-RunBenchmark-Tests-ForceScheduler');
|
|
|
|
request = createSampleBuildRequest(MockModels.ipad, MockModels.jetstream);
|
|
properties = syncers[1]._propertiesForBuildRequest(request, [request]);
|
|
assert.equal(properties['test_name'], 'jetstream');
|
|
assert.equal(properties['forcescheduler'], 'ABTest-iPad-RunBenchmark-Tests-ForceScheduler');
|
|
});
|
|
|
|
it('should resolve "root"', () => {
|
|
const syncers = BuildbotSyncer._loadConfig(RemoteAPI, sampleiOSConfig(), builderNameToIDMap());
|
|
const request = createSampleBuildRequest(MockModels.iphone, MockModels.speedometer);
|
|
const properties = syncers[0]._propertiesForBuildRequest(request, [request]);
|
|
assert.equal(properties['desired_image'], '13A452');
|
|
});
|
|
|
|
it('should resolve "revision"', () => {
|
|
const syncers = BuildbotSyncer._loadConfig(RemoteAPI, sampleiOSConfig(), builderNameToIDMap());
|
|
const request = createSampleBuildRequest(MockModels.iphone, MockModels.speedometer);
|
|
const properties = syncers[0]._propertiesForBuildRequest(request, [request]);
|
|
assert.equal(properties['opensource'], '197463');
|
|
});
|
|
|
|
it('should resolve "patch"', () => {
|
|
const config = sampleiOSConfig();
|
|
config.repositoryGroups['ios-svn-webkit'] = {
|
|
'repositories': {'WebKit': {'acceptsPatch': true}, 'Shared': {}, 'iOS': {}},
|
|
'testProperties': {
|
|
'os': {'revision': 'iOS'},
|
|
'webkit': {'revision': 'WebKit'},
|
|
'shared': {'revision': 'Shared'},
|
|
'roots': {'roots': {}},
|
|
},
|
|
'buildProperties': {
|
|
'webkit': {'revision': 'WebKit'},
|
|
'webkit-patch': {'patch': 'WebKit'},
|
|
'checkbox': {'ifRepositorySet': ['WebKit'], 'value': 'build-webkit'},
|
|
'build-webkit': {'ifRepositorySet': ['WebKit'], 'value': true},
|
|
'shared': {'revision': 'Shared'},
|
|
},
|
|
'acceptsRoots': true,
|
|
};
|
|
const syncers = BuildbotSyncer._loadConfig(RemoteAPI, config, builderNameToIDMap());
|
|
const request = createSampleBuildRequestWithPatch(MockModels.iphone, null, -1);
|
|
const properties = syncers[2]._propertiesForBuildRequest(request, [request]);
|
|
assert.equal(properties['webkit'], '197463');
|
|
assert.equal(properties['webkit-patch'], 'http://build.webkit.org/api/uploaded-file/453.dat');
|
|
assert.equal(properties['checkbox'], 'build-webkit');
|
|
assert.equal(properties['build-webkit'], true);
|
|
});
|
|
|
|
it('should resolve "ifBuilt"', () => {
|
|
const config = sampleiOSConfig();
|
|
config.repositoryGroups['ios-svn-webkit'] = {
|
|
'repositories': {'WebKit': {}, 'Shared': {}, 'iOS': {}},
|
|
'testProperties': {
|
|
'os': {'revision': 'iOS'},
|
|
'webkit': {'revision': 'WebKit'},
|
|
'shared': {'revision': 'Shared'},
|
|
'roots': {'roots': {}},
|
|
'test-custom-build': {'ifBuilt': [], 'value': ''},
|
|
'has-built-patch': {'ifBuilt': [], 'value': 'true'},
|
|
},
|
|
'acceptsRoots': true,
|
|
};
|
|
const syncers = BuildbotSyncer._loadConfig(RemoteAPI, config, builderNameToIDMap());
|
|
const requestToBuild = createSampleBuildRequestWithPatch(MockModels.iphone, null, -1);
|
|
const requestToTest = createSampleBuildRequestWithPatch(MockModels.iphone, MockModels.speedometer, 0);
|
|
const otherRequestToTest = createSampleBuildRequest(MockModels.iphone, MockModels.speedometer);
|
|
|
|
let properties = syncers[0]._propertiesForBuildRequest(requestToTest, [requestToTest]);
|
|
assert.equal(properties['webkit'], '197463');
|
|
assert.equal(properties['roots'], '[{"url":"http://build.webkit.org/api/uploaded-file/456.dat"}]');
|
|
assert.equal(properties['test-custom-build'], undefined);
|
|
assert.equal(properties['has-built-patch'], undefined);
|
|
|
|
properties = syncers[0]._propertiesForBuildRequest(requestToTest, [requestToBuild, requestToTest]);
|
|
assert.equal(properties['webkit'], '197463');
|
|
assert.equal(properties['roots'], '[{"url":"http://build.webkit.org/api/uploaded-file/456.dat"}]');
|
|
assert.equal(properties['test-custom-build'], '');
|
|
assert.equal(properties['has-built-patch'], 'true');
|
|
|
|
properties = syncers[0]._propertiesForBuildRequest(otherRequestToTest, [requestToBuild, otherRequestToTest, requestToTest]);
|
|
assert.equal(properties['webkit'], '197463');
|
|
assert.equal(properties['roots'], undefined);
|
|
assert.equal(properties['test-custom-build'], undefined);
|
|
assert.equal(properties['has-built-patch'], undefined);
|
|
|
|
});
|
|
|
|
it('should set the value for "ifBuilt" if the repository in the list appears', () => {
|
|
const config = sampleiOSConfig();
|
|
config.repositoryGroups['ios-svn-webkit'] = {
|
|
'repositories': {'WebKit': {'acceptsPatch': true}, 'Shared': {}, 'iOS': {}},
|
|
'testProperties': {
|
|
'os': {'revision': 'iOS'},
|
|
'webkit': {'revision': 'WebKit'},
|
|
'shared': {'revision': 'Shared'},
|
|
'roots': {'roots': {}},
|
|
'checkbox': {'ifBuilt': ['WebKit'], 'value': 'test-webkit'},
|
|
'test-webkit': {'ifBuilt': ['WebKit'], 'value': true}
|
|
},
|
|
'buildProperties': {
|
|
'webkit': {'revision': 'WebKit'},
|
|
'webkit-patch': {'patch': 'WebKit'},
|
|
'checkbox': {'ifRepositorySet': ['WebKit'], 'value': 'build-webkit'},
|
|
'build-webkit': {'ifRepositorySet': ['WebKit'], 'value': true},
|
|
'shared': {'revision': 'Shared'},
|
|
},
|
|
'acceptsRoots': true,
|
|
};
|
|
const syncers = BuildbotSyncer._loadConfig(RemoteAPI, config, builderNameToIDMap());
|
|
const requestToBuild = createSampleBuildRequestWithPatch(MockModels.iphone, null, -1);
|
|
const requestToTest = createSampleBuildRequestWithPatch(MockModels.iphone, MockModels.speedometer, 0);
|
|
const properties = syncers[0]._propertiesForBuildRequest(requestToTest, [requestToBuild, requestToTest]);
|
|
assert.equal(properties['webkit'], '197463');
|
|
assert.equal(properties['roots'], '[{"url":"http://build.webkit.org/api/uploaded-file/456.dat"}]');
|
|
assert.equal(properties['checkbox'], 'test-webkit');
|
|
assert.equal(properties['test-webkit'], true);
|
|
});
|
|
|
|
it('should not set the value for "ifBuilt" if no build for the repository in the list appears', () => {
|
|
const config = sampleiOSConfig();
|
|
config.repositoryGroups['ios-svn-webkit-with-owned-commit'] = {
|
|
'repositories': {'WebKit': {'acceptsPatch': true}, 'Owner Repository': {}, 'iOS': {}},
|
|
'testProperties': {
|
|
'os': {'revision': 'iOS'},
|
|
'webkit': {'revision': 'WebKit'},
|
|
'owner-repo': {'revision': 'Owner Repository'},
|
|
'roots': {'roots': {}},
|
|
'checkbox': {'ifBuilt': ['WebKit'], 'value': 'test-webkit'},
|
|
'test-webkit': {'ifBuilt': ['WebKit'], 'value': true}
|
|
},
|
|
'buildProperties': {
|
|
'webkit': {'revision': 'WebKit'},
|
|
'webkit-patch': {'patch': 'WebKit'},
|
|
'owner-repo': {'revision': 'Owner Repository'},
|
|
'checkbox': {'ifRepositorySet': ['WebKit'], 'value': 'build-webkit'},
|
|
'build-webkit': {'ifRepositorySet': ['WebKit'], 'value': true},
|
|
'owned-commits': {'ownedRevisions': 'Owner Repository'}
|
|
},
|
|
'acceptsRoots': true,
|
|
};
|
|
const syncers = BuildbotSyncer._loadConfig(RemoteAPI, config, builderNameToIDMap());
|
|
const requestToBuild = createSampleBuildRequestWithOwnedCommit(MockModels.iphone, null, -1);
|
|
const requestToTest = createSampleBuildRequestWithOwnedCommit(MockModels.iphone, MockModels.speedometer, 0);
|
|
const properties = syncers[0]._propertiesForBuildRequest(requestToTest, [requestToBuild, requestToTest]);
|
|
|
|
assert.equal(properties['webkit'], '197463');
|
|
assert.equal(properties['roots'], '[{"url":"http://build.webkit.org/api/uploaded-file/456.dat"}]');
|
|
assert.equal(properties['checkbox'], undefined);
|
|
assert.equal(properties['test-webkit'], undefined);
|
|
});
|
|
|
|
it('should resolve "ifRepositorySet" and "requiresBuild"', () => {
|
|
const config = sampleiOSConfig();
|
|
config.repositoryGroups['ios-svn-webkit-with-owned-commit'] = {
|
|
'repositories': {'WebKit': {'acceptsPatch': true}, 'Owner Repository': {}, 'iOS': {}},
|
|
'testProperties': {
|
|
'os': {'revision': 'iOS'},
|
|
'webkit': {'revision': 'WebKit'},
|
|
'owner-repo': {'revision': 'Owner Repository'},
|
|
'roots': {'roots': {}},
|
|
},
|
|
'buildProperties': {
|
|
'webkit': {'revision': 'WebKit'},
|
|
'webkit-patch': {'patch': 'WebKit'},
|
|
'owner-repo': {'revision': 'Owner Repository'},
|
|
'checkbox': {'ifRepositorySet': ['WebKit'], 'value': 'build-webkit'},
|
|
'build-webkit': {'ifRepositorySet': ['WebKit'], 'value': true},
|
|
'owned-commits': {'ownedRevisions': 'Owner Repository'}
|
|
},
|
|
'acceptsRoots': true,
|
|
};
|
|
const syncers = BuildbotSyncer._loadConfig(RemoteAPI, config, builderNameToIDMap());
|
|
const request = createSampleBuildRequestWithOwnedCommit(MockModels.iphone, null, -1);
|
|
const properties = syncers[2]._propertiesForBuildRequest(request, [request]);
|
|
assert.equal(properties['webkit'], '197463');
|
|
assert.equal(properties['owner-repo'], 'owner-001');
|
|
assert.equal(properties['checkbox'], undefined);
|
|
assert.equal(properties['build-webkit'], undefined);
|
|
assert.deepEqual(JSON.parse(properties['owned-commits']), {'Owner Repository': [{revision: 'owned-002', repository: 'Owned Repository', ownerRevision: 'owner-001'}]});
|
|
});
|
|
|
|
it('should resolve "patch", "ifRepositorySet" and "requiresBuild"', () => {
|
|
|
|
const config = sampleiOSConfig();
|
|
config.repositoryGroups['ios-svn-webkit-with-owned-commit'] = {
|
|
'repositories': {'WebKit': {'acceptsPatch': true}, 'Owner Repository': {}, 'iOS': {}},
|
|
'testProperties': {
|
|
'os': {'revision': 'iOS'},
|
|
'webkit': {'revision': 'WebKit'},
|
|
'owner-repo': {'revision': 'Owner Repository'},
|
|
'roots': {'roots': {}},
|
|
},
|
|
'buildProperties': {
|
|
'webkit': {'revision': 'WebKit'},
|
|
'webkit-patch': {'patch': 'WebKit'},
|
|
'owner-repo': {'revision': 'Owner Repository'},
|
|
'checkbox': {'ifRepositorySet': ['WebKit'], 'value': 'build-webkit'},
|
|
'build-webkit': {'ifRepositorySet': ['WebKit'], 'value': true},
|
|
'owned-commits': {'ownedRevisions': 'Owner Repository'}
|
|
},
|
|
'acceptsRoots': true,
|
|
};
|
|
const syncers = BuildbotSyncer._loadConfig(RemoteAPI, config, builderNameToIDMap());
|
|
const request = createSampleBuildRequestWithOwnedCommitAndPatch(MockModels.iphone, null, -1);
|
|
const properties = syncers[2]._propertiesForBuildRequest(request, [request]);
|
|
assert.equal(properties['webkit'], '197463');
|
|
assert.equal(properties['owner-repo'], 'owner-001');
|
|
assert.equal(properties['checkbox'], 'build-webkit');
|
|
assert.equal(properties['build-webkit'], true);
|
|
assert.equal(properties['webkit-patch'], 'http://build.webkit.org/api/uploaded-file/453.dat');
|
|
assert.deepEqual(JSON.parse(properties['owned-commits']), {'Owner Repository': [{revision: 'owned-002', repository: 'Owned Repository', ownerRevision: 'owner-001'}]});
|
|
});
|
|
|
|
it('should allow to build with an owned component even if no repository accepts a patch in the triggerable repository group', () => {
|
|
const config = sampleiOSConfig();
|
|
config.repositoryGroups['owner-repository'] = {
|
|
'repositories': {'Owner Repository': {}},
|
|
'testProperties': {
|
|
'owner-repo': {'revision': 'Owner Repository'},
|
|
'roots': {'roots': {}},
|
|
},
|
|
'buildProperties': {
|
|
'owned-commits': {'ownedRevisions': 'Owner Repository'}
|
|
},
|
|
'acceptsRoots': true,
|
|
};
|
|
const syncers = BuildbotSyncer._loadConfig(RemoteAPI, config, builderNameToIDMap());
|
|
const owner111289 = CommitLog.ensureSingleton('111289', {'id': '111289', 'time': 1456931874000, 'repository': MockModels.ownerRepository, 'revision': 'owner-001'});
|
|
const owned111222 = CommitLog.ensureSingleton('111222', {'id': '111222', 'time': 1456932774000, 'repository': MockModels.ownedRepository, 'revision': 'owned-002'});
|
|
const commitSet = CommitSet.ensureSingleton('53246486', {customRoots: [], revisionItems: [{commit: owner111289}, {commit: owned111222, commitOwner: owner111289, requiresBuild: true}]});
|
|
const request = BuildRequest.ensureSingleton(`123123`, {'triggerable': MockModels.triggerable,
|
|
repositoryGroup: MockModels.ownerRepositoryGroup,
|
|
'commitSet': commitSet, 'status': 'pending', 'platform': MockModels.iphone, 'test': null, 'order': -1});
|
|
|
|
const properties = syncers[2]._propertiesForBuildRequest(request, [request]);
|
|
assert.deepEqual(JSON.parse(properties['owned-commits']), {'Owner Repository': [{revision: 'owned-002', repository: 'Owned Repository', ownerRevision: 'owner-001'}]});
|
|
});
|
|
|
|
it('should fail if build type build request does not have any build repository group template', () => {
|
|
const config = sampleiOSConfig();
|
|
config.repositoryGroups['owner-repository'] = {
|
|
'repositories': {'Owner Repository': {}},
|
|
'testProperties': {
|
|
'owner-repo': {'revision': 'Owner Repository'},
|
|
'roots': {'roots': {}},
|
|
},
|
|
'acceptsRoots': true,
|
|
};
|
|
const syncers = BuildbotSyncer._loadConfig(RemoteAPI, config, builderNameToIDMap());
|
|
const owner1 = CommitLog.ensureSingleton('111289', {'id': '111289', 'time': 1456931874000, 'repository': MockModels.ownerRepository, 'revision': 'owner-001'});
|
|
const owned2 = CommitLog.ensureSingleton('111222', {'id': '111222', 'time': 1456932774000, 'repository': MockModels.ownedRepository, 'revision': 'owned-002'});
|
|
const commitSet = CommitSet.ensureSingleton('53246486', {customRoots: [], revisionItems: [{commit: owner1}, {commit: owned2, commitOwner: owner1, requiresBuild: true}]});
|
|
const request = BuildRequest.ensureSingleton(`123123`, {'triggerable': MockModels.triggerable,
|
|
repositoryGroup: MockModels.ownerRepositoryGroup,
|
|
'commitSet': commitSet, 'status': 'pending', 'platform': MockModels.iphone, 'test': null, 'order': -1});
|
|
|
|
assert.throws(() => syncers[2]._propertiesForBuildRequest(request, [request]),
|
|
(error) => error.code === 'ERR_ASSERTION');
|
|
});
|
|
|
|
it('should set the property for the build request id', () => {
|
|
const syncers = BuildbotSyncer._loadConfig(RemoteAPI, sampleiOSConfig(), builderNameToIDMap());
|
|
const request = createSampleBuildRequest(MockModels.iphone, MockModels.speedometer);
|
|
const properties = syncers[0]._propertiesForBuildRequest(request, [request]);
|
|
assert.equal(properties['build_request_id'], request.id());
|
|
});
|
|
});
|
|
|
|
|
|
describe('BuildbotBuildEntry', () => {
|
|
it('should create BuildbotBuildEntry for pending build', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
const buildbotData = samplePendingBuildRequests();
|
|
const pendingEntries = buildbotData.buildrequests.map((entry) => new BuildbotBuildEntry(syncer, entry));
|
|
|
|
assert.equal(pendingEntries.length, 1);
|
|
const entry = pendingEntries[0];
|
|
assert.ok(entry instanceof BuildbotBuildEntry);
|
|
assert.ok(!entry.buildTag());
|
|
assert.ok(!entry.workerName());
|
|
assert.equal(entry.buildRequestId(), 16733);
|
|
assert.ok(entry.isPending());
|
|
assert.ok(!entry.isInProgress());
|
|
assert.ok(!entry.hasFinished());
|
|
assert.equal(entry.url(), 'http://build.webkit.org/#/buildrequests/17');
|
|
assert.equal(entry.statusDescription(), null);
|
|
});
|
|
|
|
it('should create BuildbotBuildEntry for in-progress build', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
const buildbotData = sampleInProgressBuild();
|
|
const entries = buildbotData.builds.map((entry) => new BuildbotBuildEntry(syncer, entry));
|
|
|
|
assert.equal(entries.length, 1);
|
|
const entry = entries[0];
|
|
assert.ok(entry instanceof BuildbotBuildEntry);
|
|
assert.equal(entry.buildTag(), 614);
|
|
assert.equal(entry.workerName(), 'ABTest-iPad-0');
|
|
assert.equal(entry.buildRequestId(), 16733);
|
|
assert.ok(!entry.isPending());
|
|
assert.ok(entry.isInProgress());
|
|
assert.ok(!entry.hasFinished());
|
|
assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/614');
|
|
assert.equal(entry.statusDescription(), 'building');
|
|
});
|
|
|
|
it('should create BuildbotBuildEntry for finished build', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
const buildbotData = sampleFinishedBuild();
|
|
const entries = buildbotData.builds.map((entry) => new BuildbotBuildEntry(syncer, entry));
|
|
|
|
assert.deepEqual(entries.length, 1);
|
|
const entry = entries[0];
|
|
assert.ok(entry instanceof BuildbotBuildEntry);
|
|
assert.equal(entry.buildTag(), 1755);
|
|
assert.equal(entry.workerName(), 'ABTest-iPad-0');
|
|
assert.equal(entry.buildRequestId(), 18935);
|
|
assert.ok(!entry.isPending());
|
|
assert.ok(!entry.isInProgress());
|
|
assert.ok(entry.hasFinished());
|
|
assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/1755');
|
|
assert.equal(entry.statusDescription(), null);
|
|
});
|
|
|
|
it('should create BuildbotBuildEntry for mix of in-progress and finished builds', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
const buildbotData = {'builds': [sampleInProgressBuildData(), sampleFinishedBuildData()]};
|
|
const entries = buildbotData.builds.map((entry) => new BuildbotBuildEntry(syncer, entry));
|
|
|
|
assert.deepEqual(entries.length, 2);
|
|
|
|
let entry = entries[0];
|
|
assert.ok(entry instanceof BuildbotBuildEntry);
|
|
assert.equal(entry.buildTag(), 614);
|
|
assert.equal(entry.workerName(), 'ABTest-iPad-0');
|
|
assert.equal(entry.buildRequestId(), 16733);
|
|
assert.ok(!entry.isPending());
|
|
assert.ok(entry.isInProgress());
|
|
assert.ok(!entry.hasFinished());
|
|
assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/614');
|
|
assert.equal(entry.statusDescription(), 'building');
|
|
|
|
entry = entries[1];
|
|
assert.ok(entry instanceof BuildbotBuildEntry);
|
|
assert.equal(entry.buildTag(), 1755);
|
|
assert.equal(entry.workerName(), 'ABTest-iPad-0');
|
|
assert.equal(entry.buildRequestId(), 18935);
|
|
assert.ok(!entry.isPending());
|
|
assert.ok(!entry.isInProgress());
|
|
assert.ok(entry.hasFinished());
|
|
assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/1755');
|
|
assert.equal(entry.statusDescription(), null);
|
|
});
|
|
});
|
|
|
|
describe('_pullRecentBuilds()', () => {
|
|
it('should not fetch recent builds when count is zero', async () => {
|
|
const syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
const promise = syncer._pullRecentBuilds(0);
|
|
assert.equal(requests.length, 0);
|
|
const content = await promise;
|
|
assert.deepEqual(content, []);
|
|
});
|
|
|
|
it('should pull the right number of recent builds', () => {
|
|
const syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
syncer._pullRecentBuilds(12);
|
|
assert.equal(requests.length, 1);
|
|
assert.equal(requests[0].url, '/api/v2/builders/102/builds?limit=12&order=-number&property=*');
|
|
});
|
|
|
|
it('should handle unexpected error while fetching recent builds', async () => {
|
|
const syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
const promise = syncer._pullRecentBuilds(2);
|
|
assert.equal(requests.length, 1);
|
|
assert.equal(requests[0].url, '/api/v2/builders/102/builds?limit=2&order=-number&property=*');
|
|
requests[0].resolve({'error': 'Unexpected error'});
|
|
const content = await promise;
|
|
assert.deepEqual(content, []);
|
|
});
|
|
|
|
it('should create BuildbotBuildEntry after fetching recent builds', async () => {
|
|
const syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
const promise = syncer._pullRecentBuilds(2);
|
|
assert.equal(requests.length, 1);
|
|
assert.equal(requests[0].url, '/api/v2/builders/102/builds?limit=2&order=-number&property=*');
|
|
requests[0].resolve({'builds': [sampleFinishedBuildData(), sampleInProgressBuildData()]});
|
|
|
|
const entries = await promise;
|
|
assert.deepEqual(entries.length, 2);
|
|
|
|
let entry = entries[0];
|
|
assert.ok(entry instanceof BuildbotBuildEntry);
|
|
assert.equal(entry.buildTag(), 1755);
|
|
assert.equal(entry.workerName(), 'ABTest-iPad-0');
|
|
assert.equal(entry.buildRequestId(), 18935);
|
|
assert.ok(!entry.isPending());
|
|
assert.ok(!entry.isInProgress());
|
|
assert.ok(entry.hasFinished());
|
|
assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/1755');
|
|
|
|
entry = entries[1];
|
|
assert.ok(entry instanceof BuildbotBuildEntry);
|
|
assert.equal(entry.buildTag(), 614);
|
|
assert.equal(entry.workerName(), 'ABTest-iPad-0');
|
|
assert.equal(entry.buildRequestId(), 16733);
|
|
assert.ok(!entry.isPending());
|
|
assert.ok(entry.isInProgress());
|
|
assert.ok(!entry.hasFinished());
|
|
assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/614');
|
|
});
|
|
});
|
|
|
|
describe('pullBuildbot', () => {
|
|
it('should fetch pending builds from the right URL', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
assert.equal(syncer.builderName(), 'ABTest-iPad-RunBenchmark-Tests');
|
|
let expectedURL = '/api/v2/builders/102/buildrequests?complete=false&claimed=false&property=*';
|
|
assert.equal(syncer.pathForPendingBuilds(), expectedURL);
|
|
syncer.pullBuildbot();
|
|
assert.equal(requests.length, 1);
|
|
assert.equal(requests[0].url, expectedURL);
|
|
});
|
|
|
|
it('should fetch recent builds once pending builds have been fetched', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
assert.equal(syncer.builderName(), 'ABTest-iPad-RunBenchmark-Tests');
|
|
|
|
syncer.pullBuildbot(1);
|
|
assert.equal(requests.length, 1);
|
|
assert.equal(requests[0].url, '/api/v2/builders/102/buildrequests?complete=false&claimed=false&property=*');
|
|
requests[0].resolve([]);
|
|
return MockRemoteAPI.waitForRequest().then(() => {
|
|
assert.equal(requests.length, 2);
|
|
assert.equal(requests[1].url, '/api/v2/builders/102/builds?limit=1&order=-number&property=*');
|
|
});
|
|
});
|
|
|
|
it('should fetch the right number of recent builds', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
|
|
syncer.pullBuildbot(3);
|
|
assert.equal(requests.length, 1);
|
|
assert.equal(requests[0].url, '/api/v2/builders/102/buildrequests?complete=false&claimed=false&property=*');
|
|
requests[0].resolve([]);
|
|
return MockRemoteAPI.waitForRequest().then(() => {
|
|
assert.equal(requests.length, 2);
|
|
assert.equal(requests[1].url, '/api/v2/builders/102/builds?limit=3&order=-number&property=*');
|
|
});
|
|
});
|
|
|
|
it('should create BuildbotBuildEntry for pending builds', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
let promise = syncer.pullBuildbot();
|
|
requests[0].resolve(samplePendingBuildRequests());
|
|
return promise.then((entries) => {
|
|
assert.equal(entries.length, 1);
|
|
let entry = entries[0];
|
|
assert.ok(entry instanceof BuildbotBuildEntry);
|
|
assert.ok(!entry.buildTag());
|
|
assert.ok(!entry.workerName());
|
|
assert.equal(entry.buildRequestId(), 16733);
|
|
assert.ok(entry.isPending());
|
|
assert.ok(!entry.isInProgress());
|
|
assert.ok(!entry.hasFinished());
|
|
assert.equal(entry.url(), 'http://build.webkit.org/#/buildrequests/17');
|
|
});
|
|
});
|
|
|
|
it('should create BuildbotBuildEntry for in-progress builds', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
|
|
let promise = syncer.pullBuildbot(1);
|
|
assert.equal(requests.length, 1);
|
|
requests[0].resolve([]);
|
|
return MockRemoteAPI.waitForRequest().then(() => {
|
|
assert.equal(requests.length, 2);
|
|
requests[1].resolve(sampleInProgressBuild());
|
|
return promise;
|
|
}).then((entries) => {
|
|
assert.equal(entries.length, 1);
|
|
let entry = entries[0];
|
|
assert.ok(entry instanceof BuildbotBuildEntry);
|
|
assert.equal(entry.buildTag(), 614);
|
|
assert.equal(entry.workerName(), 'ABTest-iPad-0');
|
|
assert.equal(entry.buildRequestId(), 16733);
|
|
assert.ok(!entry.isPending());
|
|
assert.ok(entry.isInProgress());
|
|
assert.ok(!entry.hasFinished());
|
|
assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/614');
|
|
});
|
|
});
|
|
|
|
it('should create BuildbotBuildEntry for finished builds', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
|
|
let promise = syncer.pullBuildbot(1);
|
|
assert.equal(requests.length, 1);
|
|
requests[0].resolve([]);
|
|
return MockRemoteAPI.waitForRequest().then(() => {
|
|
assert.equal(requests.length, 2);
|
|
requests[1].resolve(sampleFinishedBuild());
|
|
return promise;
|
|
}).then((entries) => {
|
|
assert.deepEqual(entries.length, 1);
|
|
let entry = entries[0];
|
|
assert.ok(entry instanceof BuildbotBuildEntry);
|
|
assert.equal(entry.buildTag(), 1755);
|
|
assert.equal(entry.workerName(), 'ABTest-iPad-0');
|
|
assert.equal(entry.buildRequestId(), 18935);
|
|
assert.ok(!entry.isPending());
|
|
assert.ok(!entry.isInProgress());
|
|
assert.ok(entry.hasFinished());
|
|
assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/1755');
|
|
});
|
|
});
|
|
|
|
it('should create BuildbotBuildEntry for mixed pending, in-progress, finished, and missing builds', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
|
|
let promise = syncer.pullBuildbot(5);
|
|
assert.equal(requests.length, 1);
|
|
|
|
requests[0].resolve(samplePendingBuildRequests(123));
|
|
|
|
return MockRemoteAPI.waitForRequest().then(() => {
|
|
assert.equal(requests.length, 2);
|
|
requests[1].resolve({'builds': [sampleFinishedBuildData(), sampleInProgressBuildData()]});
|
|
return promise;
|
|
}).then((entries) => {
|
|
assert.deepEqual(entries.length, 3);
|
|
|
|
let entry = entries[0];
|
|
assert.ok(entry instanceof BuildbotBuildEntry);
|
|
assert.equal(entry.buildTag(), null);
|
|
assert.equal(entry.workerName(), null);
|
|
assert.equal(entry.buildRequestId(), 123);
|
|
assert.ok(entry.isPending());
|
|
assert.ok(!entry.isInProgress());
|
|
assert.ok(!entry.hasFinished());
|
|
assert.equal(entry.url(), 'http://build.webkit.org/#/buildrequests/17');
|
|
|
|
entry = entries[1];
|
|
assert.ok(entry instanceof BuildbotBuildEntry);
|
|
assert.equal(entry.buildTag(), 614);
|
|
assert.equal(entry.workerName(), 'ABTest-iPad-0');
|
|
assert.equal(entry.buildRequestId(), 16733);
|
|
assert.ok(!entry.isPending());
|
|
assert.ok(entry.isInProgress());
|
|
assert.ok(!entry.hasFinished());
|
|
assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/614');
|
|
|
|
entry = entries[2];
|
|
assert.ok(entry instanceof BuildbotBuildEntry);
|
|
assert.equal(entry.buildTag(), 1755);
|
|
assert.equal(entry.workerName(), 'ABTest-iPad-0');
|
|
assert.equal(entry.buildRequestId(), 18935);
|
|
assert.ok(!entry.isPending());
|
|
assert.ok(!entry.isInProgress());
|
|
assert.ok(entry.hasFinished());
|
|
assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/1755');
|
|
});
|
|
});
|
|
|
|
it('should sort BuildbotBuildEntry by order', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
|
|
let promise = syncer.pullBuildbot(5);
|
|
assert.equal(requests.length, 1);
|
|
|
|
requests[0].resolve({"buildrequests": [samplePendingBuildRequestData(456, 2), samplePendingBuildRequestData(123, 1)]});
|
|
|
|
return MockRemoteAPI.waitForRequest().then(() => {
|
|
assert.equal(requests.length, 2);
|
|
requests[1].resolve({'builds': [sampleFinishedBuildData(), sampleInProgressBuildData()]});
|
|
return promise;
|
|
}).then((entries) => {
|
|
assert.deepEqual(entries.length, 4);
|
|
|
|
let entry = entries[0];
|
|
assert.ok(entry instanceof BuildbotBuildEntry);
|
|
assert.equal(entry.buildTag(), null);
|
|
assert.equal(entry.workerName(), null);
|
|
assert.equal(entry.buildRequestId(), 123);
|
|
assert.ok(entry.isPending());
|
|
assert.ok(!entry.isInProgress());
|
|
assert.ok(!entry.hasFinished());
|
|
assert.equal(entry.url(), 'http://build.webkit.org/#/buildrequests/17');
|
|
|
|
entry = entries[1];
|
|
assert.ok(entry instanceof BuildbotBuildEntry);
|
|
assert.equal(entry.buildTag(), null);
|
|
assert.equal(entry.workerName(), null);
|
|
assert.equal(entry.buildRequestId(), 456);
|
|
assert.ok(entry.isPending());
|
|
assert.ok(!entry.isInProgress());
|
|
assert.ok(!entry.hasFinished());
|
|
assert.equal(entry.url(), 'http://build.webkit.org/#/buildrequests/17');
|
|
|
|
entry = entries[2];
|
|
assert.ok(entry instanceof BuildbotBuildEntry);
|
|
assert.equal(entry.buildTag(), 614);
|
|
assert.equal(entry.workerName(), 'ABTest-iPad-0');
|
|
assert.equal(entry.buildRequestId(), 16733);
|
|
assert.ok(!entry.isPending());
|
|
assert.ok(entry.isInProgress());
|
|
assert.ok(!entry.hasFinished());
|
|
assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/614');
|
|
|
|
entry = entries[3];
|
|
assert.ok(entry instanceof BuildbotBuildEntry);
|
|
assert.equal(entry.buildTag(), 1755);
|
|
assert.equal(entry.workerName(), 'ABTest-iPad-0');
|
|
assert.equal(entry.buildRequestId(), 18935);
|
|
assert.ok(!entry.isPending());
|
|
assert.ok(!entry.isInProgress());
|
|
assert.ok(entry.hasFinished());
|
|
assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/1755');
|
|
});
|
|
});
|
|
|
|
it('should override BuildbotBuildEntry for pending builds by in-progress builds', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
|
|
let promise = syncer.pullBuildbot(5);
|
|
assert.equal(requests.length, 1);
|
|
|
|
requests[0].resolve(samplePendingBuildRequests());
|
|
|
|
return MockRemoteAPI.waitForRequest().then(() => {
|
|
assert.equal(requests.length, 2);
|
|
requests[1].resolve(sampleInProgressBuild());
|
|
return promise;
|
|
}).then((entries) => {
|
|
assert.equal(entries.length, 1);
|
|
|
|
let entry = entries[0];
|
|
assert.ok(entry instanceof BuildbotBuildEntry);
|
|
assert.equal(entry.buildTag(), 614);
|
|
assert.equal(entry.workerName(), 'ABTest-iPad-0');
|
|
assert.equal(entry.buildRequestId(), 16733);
|
|
assert.ok(!entry.isPending());
|
|
assert.ok(entry.isInProgress());
|
|
assert.ok(!entry.hasFinished());
|
|
assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/614');
|
|
});
|
|
});
|
|
|
|
it('should override BuildbotBuildEntry for pending builds by finished builds', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
|
|
let promise = syncer.pullBuildbot(5);
|
|
assert.equal(requests.length, 1);
|
|
|
|
requests[0].resolve(samplePendingBuildRequests());
|
|
|
|
return MockRemoteAPI.waitForRequest().then(() => {
|
|
assert.equal(requests.length, 2);
|
|
requests[1].resolve(sampleFinishedBuild(16733));
|
|
return promise;
|
|
}).then((entries) => {
|
|
assert.equal(entries.length, 1);
|
|
|
|
let entry = entries[0];
|
|
assert.ok(entry instanceof BuildbotBuildEntry);
|
|
assert.equal(entry.buildTag(), 1755);
|
|
assert.equal(entry.workerName(), 'ABTest-iPad-0');
|
|
assert.equal(entry.buildRequestId(), 16733);
|
|
assert.ok(!entry.isPending());
|
|
assert.ok(!entry.isInProgress());
|
|
assert.ok(entry.hasFinished());
|
|
assert.equal(entry.url(), 'http://build.webkit.org/#/builders/102/builds/1755');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('scheduleBuildOnBuildbot', () => {
|
|
it('should schedule a build request on Buildbot', async () => {
|
|
const syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[0];
|
|
const request = createSampleBuildRequest(MockModels.iphone, MockModels.speedometer);
|
|
const properties = syncer._propertiesForBuildRequest(request, [request]);
|
|
const promise = syncer.scheduleBuildOnBuildbot(properties);
|
|
|
|
assert.equal(requests.length, 1);
|
|
assert.equal(requests[0].method, 'POST');
|
|
assert.equal(requests[0].url, '/api/v2/forceschedulers/ABTest-iPhone-RunBenchmark-Tests-ForceScheduler');
|
|
requests[0].resolve();
|
|
await promise;
|
|
assert.deepEqual(requests[0].data, {
|
|
'id': '16733-' + MockModels.iphone.id(),
|
|
'jsonrpc': '2.0',
|
|
'method': 'force',
|
|
'params': {
|
|
'build_request_id': '16733-' + MockModels.iphone.id(),
|
|
'desired_image': '13A452',
|
|
'opensource': '197463',
|
|
'forcescheduler': 'ABTest-iPhone-RunBenchmark-Tests-ForceScheduler',
|
|
'test_name': 'speedometer'
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('scheduleRequest', () => {
|
|
it('should schedule a build request on a specified worker', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[0];
|
|
|
|
const waitForRequest = MockRemoteAPI.waitForRequest();
|
|
const request = createSampleBuildRequest(MockModels.iphone, MockModels.speedometer);
|
|
syncer.scheduleRequest(request, [request], 'some-worker');
|
|
return waitForRequest.then(() => {
|
|
assert.equal(requests.length, 1);
|
|
assert.equal(requests[0].url, '/api/v2/forceschedulers/ABTest-iPhone-RunBenchmark-Tests-ForceScheduler');
|
|
assert.equal(requests[0].method, 'POST');
|
|
assert.deepEqual(requests[0].data, {
|
|
'id': '16733-' + MockModels.iphone.id(),
|
|
'jsonrpc': '2.0',
|
|
'method': 'force',
|
|
'params': {
|
|
'build_request_id': '16733-' + MockModels.iphone.id(),
|
|
'desired_image': '13A452',
|
|
'opensource': '197463',
|
|
'forcescheduler': 'ABTest-iPhone-RunBenchmark-Tests-ForceScheduler',
|
|
'workername': 'some-worker',
|
|
'test_name': 'speedometer'
|
|
}
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('scheduleRequestInGroupIfAvailable', () => {
|
|
|
|
function pullBuildbotWithAssertion(syncer, pendingBuilds, inProgressAndFinishedBuilds)
|
|
{
|
|
const promise = syncer.pullBuildbot(5);
|
|
assert.equal(requests.length, 1);
|
|
requests[0].resolve(pendingBuilds);
|
|
return MockRemoteAPI.waitForRequest().then(() => {
|
|
assert.equal(requests.length, 2);
|
|
requests[1].resolve(inProgressAndFinishedBuilds);
|
|
requests.length = 0;
|
|
return promise;
|
|
});
|
|
}
|
|
|
|
it('should schedule a build if builder has no builds if workerList is not specified', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, smallConfiguration(), builderNameToIDMap())[0];
|
|
|
|
return pullBuildbotWithAssertion(syncer, {}, {}).then(() => {
|
|
const request = createSampleBuildRequest(MockModels.somePlatform, MockModels.someTest);
|
|
syncer.scheduleRequestInGroupIfAvailable(request, [request]);
|
|
assert.equal(requests.length, 1);
|
|
assert.equal(requests[0].url, '/api/v2/forceschedulers/some-builder-ForceScheduler');
|
|
assert.equal(requests[0].method, 'POST');
|
|
assert.deepEqual(requests[0].data, {id: '16733-' + MockModels.somePlatform.id(), 'jsonrpc': '2.0', 'method': 'force',
|
|
'params': {id: '16733-' + MockModels.somePlatform.id(), 'forcescheduler': 'some-builder-ForceScheduler', 'os': '13A452', 'wk': '197463'}});
|
|
});
|
|
});
|
|
|
|
it('should schedule a build if builder only has finished builds if workerList is not specified', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, smallConfiguration(), builderNameToIDMap())[0];
|
|
|
|
return pullBuildbotWithAssertion(syncer, {}, smallFinishedBuild()).then(() => {
|
|
const request = createSampleBuildRequest(MockModels.somePlatform, MockModels.someTest);
|
|
syncer.scheduleRequestInGroupIfAvailable(request, [request]);
|
|
assert.equal(requests.length, 1);
|
|
assert.equal(requests[0].url, '/api/v2/forceschedulers/some-builder-ForceScheduler');
|
|
assert.equal(requests[0].method, 'POST');
|
|
assert.deepEqual(requests[0].data, {id: '16733-' + MockModels.somePlatform.id(), 'jsonrpc': '2.0', 'method': 'force',
|
|
'params': {id: '16733-' + MockModels.somePlatform.id(), 'forcescheduler': 'some-builder-ForceScheduler', 'os': '13A452', 'wk': '197463'}});
|
|
});
|
|
});
|
|
|
|
it('should not schedule a build if builder has a pending build if workerList is not specified', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, smallConfiguration(), builderNameToIDMap())[0];
|
|
|
|
return pullBuildbotWithAssertion(syncer, smallPendingBuild(), {}).then(() => {
|
|
syncer.scheduleRequestInGroupIfAvailable(createSampleBuildRequest(MockModels.somePlatform, MockModels.someTest));
|
|
assert.equal(requests.length, 0);
|
|
});
|
|
});
|
|
|
|
it('should schedule a build if builder does not have pending or completed builds on the matching worker', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[0];
|
|
|
|
return pullBuildbotWithAssertion(syncer, {}, {}).then(() => {
|
|
const request = createSampleBuildRequest(MockModels.iphone, MockModels.speedometer);
|
|
syncer.scheduleRequestInGroupIfAvailable(request, [request], null);
|
|
assert.equal(requests.length, 1);
|
|
assert.equal(requests[0].url, '/api/v2/forceschedulers/ABTest-iPhone-RunBenchmark-Tests-ForceScheduler');
|
|
assert.equal(requests[0].method, 'POST');
|
|
});
|
|
});
|
|
|
|
it('should schedule a build if builder only has finished builds on the matching worker', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
|
|
pullBuildbotWithAssertion(syncer, {}, sampleFinishedBuild()).then(() => {
|
|
const request = createSampleBuildRequest(MockModels.ipad, MockModels.speedometer);
|
|
syncer.scheduleRequestInGroupIfAvailable(request, [request], null);
|
|
assert.equal(requests.length, 1);
|
|
assert.equal(requests[0].url, '/api/v2/forceschedulers/ABTest-iPad-RunBenchmark-Tests-ForceScheduler');
|
|
assert.equal(requests[0].method, 'POST');
|
|
});
|
|
});
|
|
|
|
it('should not schedule a build if builder has a pending build on the maching worker', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
|
|
pullBuildbotWithAssertion(syncer, samplePendingBuildRequests(), {}).then(() => {
|
|
const request = createSampleBuildRequest(MockModels.ipad, MockModels.speedometer);
|
|
syncer.scheduleRequestInGroupIfAvailable(request, [request], null);
|
|
assert.equal(requests.length, 0);
|
|
});
|
|
});
|
|
|
|
it('should schedule a build if builder only has a pending build on a non-maching worker', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
|
|
return pullBuildbotWithAssertion(syncer, samplePendingBuildRequests(1, 1, 'another-worker'), {}).then(() => {
|
|
const request = createSampleBuildRequest(MockModels.ipad, MockModels.speedometer);
|
|
syncer.scheduleRequestInGroupIfAvailable(request, [request], null);
|
|
assert.equal(requests.length, 1);
|
|
});
|
|
});
|
|
|
|
it('should schedule a build if builder only has an in-progress build on the matching worker', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
|
|
return pullBuildbotWithAssertion(syncer, {}, sampleInProgressBuild()).then(() => {
|
|
const request = createSampleBuildRequest(MockModels.ipad, MockModels.speedometer);
|
|
syncer.scheduleRequestInGroupIfAvailable(request, [request], null);
|
|
assert.equal(requests.length, 1);
|
|
});
|
|
});
|
|
|
|
it('should schedule a build if builder has an in-progress build on another worker', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
|
|
return pullBuildbotWithAssertion(syncer, {}, sampleInProgressBuild('other-worker')).then(() => {
|
|
const request = createSampleBuildRequest(MockModels.ipad, MockModels.speedometer);
|
|
syncer.scheduleRequestInGroupIfAvailable(request, [request], null);
|
|
assert.equal(requests.length, 1);
|
|
});
|
|
});
|
|
|
|
it('should not schedule a build if the request does not match any configuration', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[0];
|
|
|
|
return pullBuildbotWithAssertion(syncer, {}, {}).then(() => {
|
|
const request = createSampleBuildRequest(MockModels.ipad, MockModels.speedometer);
|
|
syncer.scheduleRequestInGroupIfAvailable(request, [request], null);
|
|
assert.equal(requests.length, 0);
|
|
});
|
|
});
|
|
|
|
it('should not schedule a build if a new request had been submitted to the same worker', (done) => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
|
|
pullBuildbotWithAssertion(syncer, {}, {}).then(() => {
|
|
let request = createSampleBuildRequest(MockModels.ipad, MockModels.speedometer);
|
|
syncer.scheduleRequest(request, [request], 'ABTest-iPad-0');
|
|
request = createSampleBuildRequest(MockModels.ipad, MockModels.speedometer);
|
|
syncer.scheduleRequest(request, [request], 'ABTest-iPad-1');
|
|
}).then(() => {
|
|
assert.equal(requests.length, 2);
|
|
const request = createSampleBuildRequest(MockModels.ipad, MockModels.speedometer);
|
|
syncer.scheduleRequestInGroupIfAvailable(request, [request], null);
|
|
}).then(() => {
|
|
assert.equal(requests.length, 2);
|
|
done();
|
|
}).catch(done);
|
|
});
|
|
|
|
it('should schedule a build if a new request had been submitted to another worker', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, sampleiOSConfig(), builderNameToIDMap())[1];
|
|
|
|
return pullBuildbotWithAssertion(syncer, {}, {}).then(() => {
|
|
let request = createSampleBuildRequest(MockModels.ipad, MockModels.speedometer);
|
|
syncer.scheduleRequest(request, [request], 'ABTest-iPad-0');
|
|
assert.equal(requests.length, 1);
|
|
request = createSampleBuildRequest(MockModels.ipad, MockModels.speedometer)
|
|
syncer.scheduleRequestInGroupIfAvailable(request, [request], 'ABTest-iPad-1');
|
|
assert.equal(requests.length, 2);
|
|
});
|
|
});
|
|
|
|
it('should not schedule a build if a new request had been submitted to the same builder without workerList', () => {
|
|
let syncer = BuildbotSyncer._loadConfig(MockRemoteAPI, smallConfiguration(), builderNameToIDMap())[0];
|
|
|
|
return pullBuildbotWithAssertion(syncer, {}, {}).then(() => {
|
|
let request = createSampleBuildRequest(MockModels.somePlatform, MockModels.someTest);
|
|
syncer.scheduleRequest(request, [request], null);
|
|
assert.equal(requests.length, 1);
|
|
request = createSampleBuildRequest(MockModels.somePlatform, MockModels.someTest);
|
|
syncer.scheduleRequestInGroupIfAvailable(request, [request], null);
|
|
assert.equal(requests.length, 1);
|
|
});
|
|
});
|
|
});
|
|
});
|