[gnome-ostree] Support installed tests, add integrationtest task
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-ostree] Support installed tests, add integrationtest task
- Date: Thu, 25 Apr 2013 21:40:10 +0000 (UTC)
commit c81e11a94af247268c1bfa0096a6c3f23f649b1e
Author: Colin Walters <walters verbum org>
Date: Fri Apr 19 02:52:27 2013 -0400
Support installed tests, add integrationtest task
This allows us to fully automate running test suites.
Makefile-ostbuild.am | 1 +
manifest.json | 7 +-
src/js/tasks/task-build.js | 242 +++++++++++++++++++++++-----------
src/js/tasks/task-integrationtest.js | 69 ++++++++++
src/js/tasks/task-smoketest.js | 6 +-
src/js/tasks/testbase.js | 43 +++++-
6 files changed, 282 insertions(+), 86 deletions(-)
---
diff --git a/Makefile-ostbuild.am b/Makefile-ostbuild.am
index a0bcc08..c6810c1 100644
--- a/Makefile-ostbuild.am
+++ b/Makefile-ostbuild.am
@@ -75,6 +75,7 @@ jsosttasks_DATA= \
src/js/tasks/task-bdiff.js \
src/js/tasks/task-builddisks.js \
src/js/tasks/task-smoketest.js \
+ src/js/tasks/task-integrationtest.js \
src/js/tasks/task-zdisks.js \
src/js/tasks/testbase.js \
$(NULL)
diff --git a/manifest.json b/manifest.json
index ba8c55b..2aacfaf 100644
--- a/manifest.json
+++ b/manifest.json
@@ -849,9 +849,14 @@
{"src": "gnome:nautilus"},
- {"src": "gnome:gnome-software"}
+ {"src": "gnome:gnome-software"},
+
+ {"src": "gnome:gnome-desktop-testing",
+ "component": "testing"}
],
+ "installed-tests-components": ["gjs"],
+
"initramfs-build-epoch": {"version": 0},
"build-epoch": {"version": 8,
diff --git a/src/js/tasks/task-build.js b/src/js/tasks/task-build.js
index a771698..01ce841 100644
--- a/src/js/tasks/task-build.js
+++ b/src/js/tasks/task-build.js
@@ -24,6 +24,7 @@ const GSystem = imports.gi.GSystem;
const Builtin = imports.builtin;
const Task = imports.task;
+const Params = imports.params;
const JsonDB = imports.jsondb;
const FileUtil = imports.fileutil;
const ProcUtil = imports.procutil;
@@ -72,46 +73,20 @@ const TaskBuild = new Lang.Class({
}
},
- _composeBuildroot: function(workdir, componentName, architecture, cancellable) {
+ _composeBuildrootCore: function(workdir, componentName, architecture, rootContents, cancellable) {
let starttime = GLib.DateTime.new_now_utc();
let buildname = Format.vprintf('%s/%s/%s', [this.osname, componentName, architecture]);
let buildrootCachedir = this.cachedir.resolve_relative_path('roots/' + buildname);
GSystem.file_ensure_directory(buildrootCachedir, true, cancellable);
- let components = this._snapshot.data['components']
- let component = null;
- let buildDependencies = [];
- for (let i = 0; i < components.length; i++) {
- let component = components[i];
- if (component['name'] == componentName)
- break;
- buildDependencies.push(component);
- }
-
- let refToRev = {};
-
- let archBuildrootName = Format.vprintf('%s/bases/%s/%s-devel', [this.osname,
-
this._snapshot.data['base']['name'],
- architecture]);
-
- print("Computing buildroot contents");
-
- let archBuildrootRev = ProcUtil.runSyncGetOutputUTF8Stripped(['ostree', '--repo=' +
this.repo.get_path(), 'rev-parse',
- archBuildrootName], cancellable);
-
- refToRev[archBuildrootName] = archBuildrootRev;
- let checkoutTrees = [[archBuildrootName, '/']];
- let refsToResolve = [];
- for (let i = 0; i < buildDependencies.length; i++) {
- let dependency = buildDependencies[i];
- let buildname = Format.vprintf('%s/components/%s/%s', [this.osname, dependency['name'],
architecture]);
- refsToResolve.push(buildname);
- checkoutTrees.push([buildname, '/runtime']);
- checkoutTrees.push([buildname, '/devel']);
+ let refsToResolve = []
+ for (let i = 0; i < rootContents.length; i++) {
+ refsToResolve.push(rootContents[i][0]);
}
let resolvedRefs = this._resolveRefs(refsToResolve);
+ let refToRev = {};
for (let i = 0; i < refsToResolve.length; i++) {
refToRev[refsToResolve[i]] = resolvedRefs[i];
}
@@ -129,8 +104,8 @@ const TaskBuild = new Lang.Class({
let [tmpPath, stream] = Gio.File.new_tmp("ostbuild-buildroot-XXXXXX.txt");
let dataOut = Gio.DataOutputStream.new(stream.get_output_stream());
- for (let i = 0; i < checkoutTrees.length; i++) {
- let [branch, subpath] = checkoutTrees[i];
+ for (let i = 0; i < rootContents.length; i++) {
+ let [branch, subpath] = rootContents[i];
let rev = refToRev[branch];
toChecksumData += refToRev[branch];
dataOut.put_string(refToRev[branch], cancellable);
@@ -150,9 +125,9 @@ const TaskBuild = new Lang.Class({
return cachedRoot;
}
- if (checkoutTrees.length > 0) {
- print(Format.vprintf("composing buildroot from %d parents (last: %s)", [checkoutTrees.length,
-
checkoutTrees[checkoutTrees.length-1][0]]));
+ if (rootContents.length > 0) {
+ print(Format.vprintf("composing buildroot from %d parents (last: %s)", [rootContents.length,
+
rootContents[rootContents.length-1][0]]));
}
let cachedRootTmp = cachedRoot.get_parent().get_child(cachedRoot.get_basename() + '.tmp');
@@ -176,6 +151,38 @@ const TaskBuild = new Lang.Class({
let endtime = GLib.DateTime.new_now_utc();
print(Format.vprintf("Composed buildroot; %d seconds elapsed", [endtime.difference(starttime) /
GLib.USEC_PER_SEC]));
return cachedRoot;
+
+ },
+
+ _composeBuildroot: function(workdir, componentName, architecture, cancellable) {
+ let components = this._snapshot.data['components']
+ let component = null;
+ let buildDependencies = [];
+ for (let i = 0; i < components.length; i++) {
+ let component = components[i];
+ if (component['name'] == componentName)
+ break;
+ buildDependencies.push(component);
+ }
+
+ let archBuildrootName = Format.vprintf('%s/bases/%s/%s-devel', [this.osname,
+ this._snapshot.data['base']['name'],
+ architecture]);
+
+ print("Computing buildroot contents");
+
+ let archBuildrootRev = ProcUtil.runSyncGetOutputUTF8Stripped(['ostree', '--repo=' +
this.repo.get_path(), 'rev-parse',
+ archBuildrootName], cancellable);
+
+ let rootContents = [[archBuildrootName, '/']];
+ for (let i = 0; i < buildDependencies.length; i++) {
+ let dependency = buildDependencies[i];
+ let buildname = Format.vprintf('%s/components/%s/%s', [this.osname, dependency['name'],
architecture]);
+ rootContents.push([buildname, '/runtime']);
+ rootContents.push([buildname, '/devel']);
+ }
+
+ return this._composeBuildrootCore(workdir, componentName, architecture, rootContents, cancellable);
},
_analyzeBuildFailure: function(t, architecture, component, componentSrcdir,
@@ -457,20 +464,27 @@ const TaskBuild = new Lang.Class({
loop.quit();
},
- _componentBuildRef: function(component, architecture) {
- let archBuildname = Format.vprintf('%s/%s', [component['name'], architecture]);
+ _componentBuildRefFromName: function(componentName, architecture) {
+ let archBuildname = Format.vprintf('%s/%s', [componentName, architecture]);
return this.osname + '/components/' + archBuildname;
},
- _buildOneComponent: function(component, architecture, cancellable) {
+ _componentBuildRef: function(component, architecture) {
+ return this._componentBuildRefFromName(component['name'], architecture);
+ },
+
+ _buildOneComponent: function(component, architecture, cancellable, params) {
+ params = Params.parse(params, { installedTests: false });
let basename = component['name'];
- let archBuildname = Format.vprintf('%s/%s', [component['name'], architecture]);
+ if (params.installedTests)
+ basename = basename + '-installed-tests';
+ let archBuildname = Format.vprintf('%s/%s', [basename, architecture]);
let unixBuildname = archBuildname.replace(/\//g, '_');
let buildRef = this._componentBuildRef(component, architecture);
let currentVcsVersion = component['revision'];
- let expandedComponent = this._snapshot.getExpanded(basename);
+ let expandedComponent = this._snapshot.getExpanded(component['name']);
let previousMetadata = this._componentBuildCache[buildRef];
let previousBuildVersion = null;
let previousVcsVersion = null;
@@ -549,7 +563,12 @@ const TaskBuild = new Lang.Class({
let componentResultdir = buildWorkdir.get_child('results');
GSystem.file_ensure_directory(componentResultdir, true, cancellable);
- let rootdir = this._composeBuildroot(buildWorkdir, basename, architecture, cancellable);
+ let rootdir;
+ if (params.installedTests)
+ rootdir = this._composeBuildrootCore(buildWorkdir, basename, architecture,
+ [[this._installedTestsBuildrootRev, '/']], cancellable);
+ else
+ rootdir = this._composeBuildroot(buildWorkdir, basename, architecture, cancellable);
let tmpdir=buildWorkdir.get_child('tmp');
GSystem.file_ensure_directory(tmpdir, true, cancellable);
@@ -559,8 +578,20 @@ const TaskBuild = new Lang.Class({
srcCompileOnePath.copy(destCompileOnePath, Gio.FileCopyFlags.OVERWRITE,
cancellable, null);
GSystem.file_chmod(destCompileOnePath, 493, cancellable);
-
+
let chrootSourcedir = Gio.File.new_for_path('/ostbuild/source/' + basename);
+ let chrootChdir = chrootSourcedir;
+
+ let installedTestsSrcdir = componentSrc.get_child('installed-tests');
+ if (params.installedTests) {
+ // We're just building the tests, set our source directory
+ let metaName = '_ostbuild-meta.json';
+ GSystem.file_rename(componentSrc.get_child(metaName), installedTestsSrcdir.get_child(metaName),
cancellable);
+ chrootChdir = chrootSourcedir.get_child('installed-tests');
+ if (!componentSrc.query_exists(null)) {
+ throw new Error("Component " + basename + " specified with installed tests, but no
subdirectory found");
+ }
+ }
childArgs = ['setarch', architecture];
childArgs.push.apply(childArgs, BuildUtil.getBaseUserChrootArgs());
@@ -571,7 +602,7 @@ const TaskBuild = new Lang.Class({
'--mount-bind', tmpdir.get_path(), '/tmp',
'--mount-bind', componentSrc.get_path(), chrootSourcedir.get_path(),
'--mount-bind', componentResultdir.get_path(), '/ostbuild/results',
- '--chdir', chrootSourcedir.get_path(),
+ '--chdir', chrootChdir.get_path(),
rootdir.get_path(), '/ostree-build-compile-one',
'--ostbuild-resultdir=/ostbuild/results',
'--ostbuild-meta=_ostbuild-meta.json']);
@@ -628,6 +659,36 @@ const TaskBuild = new Lang.Class({
return ostreeRevision;
},
+
+ _checkoutOneTreeCore: function(name, composeContents, cancellable) {
+ let composeRootdir = this.subworkdir.get_child(name);
+ GSystem.shutil_rm_rf(composeRootdir, cancellable);
+ GSystem.file_ensure_directory(composeRootdir, true, cancellable);
+
+ let [contentsTmpPath, stream] = Gio.File.new_tmp("ostbuild-compose-XXXXXX.txt");
+ let dataOut = Gio.DataOutputStream.new(stream.get_output_stream());
+ for (let i = 0; i < composeContents.length; i++) {
+ let [branch, subpath] = composeContents[i];
+ dataOut.put_string(branch, cancellable);
+ dataOut.put_byte(0, cancellable);
+ dataOut.put_string(subpath, cancellable);
+ dataOut.put_byte(0, cancellable);
+ }
+ dataOut.close(cancellable);
+
+ ProcUtil.runSync(['ostree', '--repo=' + this.repo.get_path(),
+ 'checkout', '--user-mode', '--union',
+ '--from-file=' + contentsTmpPath.get_path(), composeRootdir.get_path()],
+ cancellable,
+ {logInitiation: true});
+ GSystem.file_unlink(contentsTmpPath, cancellable);
+
+ let contentsPath = composeRootdir.resolve_relative_path('usr/share/contents.json');
+ GSystem.file_ensure_directory(contentsPath.get_parent(), true, cancellable);
+ JsonUtil.writeJsonFileAtomic(contentsPath, this._snapshot.data, cancellable);
+
+ return composeRootdir;
+ },
_checkoutOneTree: function(target, componentBuildRevs, cancellable) {
let base = target['base'];
@@ -635,10 +696,6 @@ const TaskBuild = new Lang.Class({
let runtimeName = this.osname +'/bases/' + base['runtime'];
let develName = this.osname + '/bases/' + base['devel'];
- let composeRootdir = this.subworkdir.get_child(target['name']);
- GSystem.shutil_rm_rf(composeRootdir, cancellable);
- GSystem.file_ensure_directory(composeRootdir, true, cancellable);
-
let relatedRefs = {};
let baseRevision = ProcUtil.runSyncGetOutputUTF8Stripped(['ostree', '--repo=' + this.repo.get_path(),
'rev-parse', baseName], cancellable);
@@ -679,26 +736,7 @@ const TaskBuild = new Lang.Class({
}
}
- let [contentsTmpPath, stream] = Gio.File.new_tmp("ostbuild-compose-XXXXXX.txt");
- let dataOut = Gio.DataOutputStream.new(stream.get_output_stream());
- for (let i = 0; i < composeContents.length; i++) {
- let [branch, subpath] = composeContents[i];
- dataOut.put_string(branch, cancellable);
- dataOut.put_byte(0, cancellable);
- dataOut.put_string(subpath, cancellable);
- dataOut.put_byte(0, cancellable);
- }
- dataOut.close(cancellable);
-
- ProcUtil.runSync(['ostree', '--repo=' + this.repo.get_path(),
- 'checkout', '--user-mode', '--union',
- '--from-file=' + contentsTmpPath.get_path(), composeRootdir.get_path()],
- cancellable,
- {logInitiation: true});
- GSystem.file_unlink(contentsTmpPath, cancellable);
-
- let contentsPath = composeRootdir.resolve_relative_path('usr/share/contents.json');
- JsonUtil.writeJsonFileAtomic(contentsPath, this._snapshot.data, cancellable);
+ let composeRootdir = this._checkoutOneTreeCore(target['name'], composeContents, cancellable);
let shareOstree = composeRootdir.resolve_relative_path('usr/share/ostree');
GSystem.file_ensure_directory(shareOstree, true, cancellable);
@@ -710,14 +748,17 @@ const TaskBuild = new Lang.Class({
_commitComposedTree: function(targetName, composeRootdir, relatedTmpPath, cancellable) {
let treename = this.osname + '/' + targetName;
- let ostreeRevision = ProcUtil.runSyncGetOutputUTF8Stripped(['ostree', '--repo=' +
this.repo.get_path(),
- 'commit', '-b', treename, '-s', 'Compose',
- '--owner-uid=0', '--owner-gid=0',
'--no-xattrs',
- '--related-objects-file=' +
relatedTmpPath.get_path(),
- '--skip-if-unchanged'], cancellable,
+ let args = ['ostree', '--repo=' + this.repo.get_path(),
+ 'commit', '-b', treename, '-s', 'Compose',
+ '--owner-uid=0', '--owner-gid=0', '--no-xattrs',
+ '--skip-if-unchanged'];
+ if (relatedTmpPath !== null)
+ args.push('--related-objects-file=' + relatedTmpPath.get_path());
+ let ostreeRevision = ProcUtil.runSyncGetOutputUTF8Stripped(args, cancellable,
{cwd: composeRootdir.get_path(),
logInitiation: true});
- GSystem.file_unlink(relatedTmpPath, cancellable);
+ if (relatedTmpPath !== null)
+ GSystem.file_unlink(relatedTmpPath, cancellable);
GSystem.shutil_rm_rf(composeRootdir, cancellable);
return [treename, ostreeRevision];
},
@@ -964,17 +1005,22 @@ const TaskBuild = new Lang.Class({
let runtimeComponents = [];
let develComponents = [];
+ let testingComponents = [];
for (let i = 0; i < components.length; i++) {
let component = components[i];
let name = component['name']
let isRuntime = (component['component'] || 'runtime') == 'runtime';
+ let isTesting = (component['component'] || 'runtime') == 'testing';
if (isRuntime) {
runtimeComponents.push(component);
}
- develComponents.push(component);
+ if (isTesting)
+ testingComponents.push(component);
+ else
+ develComponents.push(component);
let isNoarch = component['noarch'] || false;
let componentArches;
@@ -1091,9 +1137,11 @@ const TaskBuild = new Lang.Class({
}
let targetRevisions = {};
+ let finalInstalledTestRevisions = {};
let buildData = { snapshotName: this._snapshot.path.get_basename(),
snapshot: this._snapshot.data,
targets: targetRevisions };
+ buildData['installed-tests'] = finalInstalledTestRevisions;
// First loop over the -devel trees per architecture, and
// generate an initramfs.
@@ -1123,6 +1171,9 @@ const TaskBuild = new Lang.Class({
GSystem.file_linkcopy(initramfsPath, targetInitramfsPath, Gio.FileCopyFlags.ALL_METADATA,
cancellable);
let [treename, ostreeRev] = this._commitComposedTree(develTargetName, composeRootdir,
relatedTmpPath, cancellable);
targetRevisions[treename] = ostreeRev;
+ // Also note the revision of this, since it will be used
+ // as the buildroot for installed tests
+ this._installedTestsBuildrootRev = ostreeRev;
}
// Now loop over the other targets per architecture, reusing
@@ -1143,6 +1194,47 @@ const TaskBuild = new Lang.Class({
targetRevisions[treename] = ostreeRev;
}
}
+
+ let installedTestComponentNames = this._snapshot.data['installed-tests-components'] || [];
+ print("Using installed test components: " + installedTestComponentNames.join(', '));
+ let installedTestRevs = {};
+ for (let i = 0; i < architectures.length; i++) {
+ installedTestRevs[architectures[i]] = [];
+ }
+ for (let i = 0; i < testingComponents.length; i++) {
+ let component = testingComponents[i];
+ let name = component['name'];
+ for (let j = 0; j < architectures.length; j++) {
+ let architecture = architectures[j];
+ let archname = component['name'] + '/' + architecture;
+ let rev = componentBuildRevs[archname];
+ if (!rev)
+ throw new Error("no build for " + buildRef);
+ installedTestRevs[architecture].push(rev);
+ }
+ }
+ for (let i = 0; i < installedTestComponentNames.length; i++) {
+ let componentName = installedTestComponentNames[i];
+ for (let j = 0; j < architectures.length; j++) {
+ let architecture = architectures[j];
+ let archname = componentName + '-installed-tests' + '/' + architecture;
+ let component = this._snapshot.getComponent(componentName);
+ let buildRev = this._buildOneComponent(component, architecture, cancellable, {
installedTests: true });
+ installedTestRevs[architecture].push(buildRev);
+ }
+ }
+ for (let architecture in installedTestRevs) {
+ let rootName = 'buildmaster/' + architecture + '-installed-tests';
+ let composeContents = [];
+ let revs = installedTestRevs[architecture];
+ for (let j = 0; j < revs.length; j++) {
+ composeContents.push([revs[j], '/runtime']);
+ }
+ let composeRootdir = this._checkoutOneTreeCore(rootName, composeContents, cancellable);
+ let [treename, rev] = this._commitComposedTree(rootName, composeRootdir, null, cancellable);
+ finalInstalledTestRevisions[treename] = rev;
+ }
+
let [path, modified] = builddb.store(buildData, cancellable);
print("Build complete: " + path.get_path());
}
diff --git a/src/js/tasks/task-integrationtest.js b/src/js/tasks/task-integrationtest.js
new file mode 100644
index 0000000..c090ff0
--- /dev/null
+++ b/src/js/tasks/task-integrationtest.js
@@ -0,0 +1,69 @@
+// -*- indent-tabs-mode: nil; tab-width: 2; -*-
+// Copyright (C) 2013 Colin Walters <walters verbum org>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+const GLib = imports.gi.GLib;
+const Gio = imports.gi.Gio;
+const Lang = imports.lang;
+const Format = imports.format;
+
+const GSystem = imports.gi.GSystem;
+
+const Builtin = imports.builtin;
+const ArgParse = imports.argparse;
+const ProcUtil = imports.procutil;
+const Task = imports.task;
+const TestBase = imports.tasks.testbase;
+const LibQA = imports.libqa;
+const JSUtil = imports.jsutil;
+const JSONUtil = imports.jsonutil;
+
+const TaskIntegrationTest = new Lang.Class({
+ Name: 'TaskIntegrationTest',
+ Extends: TestBase.TestBase,
+
+ TaskName: "integrationtest",
+ TaskAfter: ['smoketest'],
+
+ RequiredMessageIDs: ["4d013788dd704743b826436c951e551d" // Tests succeeded
+ ],
+
+ FailedMessageIDs: ["10dd2dc188b54a5e98970f56499d1f73", // gnome-session required component failed
+ "0eee66bf98514369bef9868327a43cf1" // Tests failed
+ ],
+
+ CompletedTag: 'integrated',
+
+ _prepareDisk: function(mntdir, arch, cancellable) {
+ let osname = this._buildData['snapshot']['osname'];
+ let [deployDir, deployEtcDir] = LibQA.getDeployDirs(mntdir, osname);
+ let installedTestsName = osname + '/buildmaster/' +arch + '-installed-tests';
+ let installedTestsRev = this._buildData['installed-tests'][installedTestsName];
+ if (!installedTestsRev)
+ throw new Error("No installed tests rev for " + installedTestsName);
+ ProcUtil.runSync(['ostree', '--repo=' + this.repo.get_path(),
+ 'checkout', '--no-triggers', '--user-mode', '--union', installedTestsRev,
deployDir.get_path()], cancellable,
+ { logInitiation: true });
+ // A bit of a hack; we need to sync the data in /etc/ from the tree to the real /etc.
+ // Probably this should have a real ostree command ("ostree admin overlay"?)
+ let relpath = 'xdg/autostart/gnome-desktop-testing.desktop';
+ let src = deployDir.resolve_relative_path('etc/' + relpath);
+ let dest = deployEtcDir.resolve_relative_path(relpath);
+ GSystem.file_linkcopy(src, dest, Gio.FileCopyFlags.OVERWRITE,
+ cancellable);
+ }
+});
diff --git a/src/js/tasks/task-smoketest.js b/src/js/tasks/task-smoketest.js
index d82aff3..2b5f80f 100644
--- a/src/js/tasks/task-smoketest.js
+++ b/src/js/tasks/task-smoketest.js
@@ -34,7 +34,7 @@ const JSONUtil = imports.jsonutil;
const TaskSmoketest = new Lang.Class({
Name: 'TaskSmoketest',
- Extends: TestBase.TaskTestBase,
+ Extends: TestBase.TestBase,
TaskName: "smoketest",
TaskAfter: ['builddisks'],
@@ -43,5 +43,7 @@ const TaskSmoketest = new Lang.Class({
],
FailedMessageIDs: ["10dd2dc188b54a5e98970f56499d1f73" // gnome-session required component failed
- ]
+ ],
+
+ CompletedTag: 'smoketested'
});
diff --git a/src/js/tasks/testbase.js b/src/js/tasks/testbase.js
index 33a31c6..06c5030 100644
--- a/src/js/tasks/testbase.js
+++ b/src/js/tasks/testbase.js
@@ -29,6 +29,7 @@ const ProcUtil = imports.procutil;
const Task = imports.task;
const LibQA = imports.libqa;
const JSUtil = imports.jsutil;
+const JSONUtil = imports.jsonutil;
const TIMEOUT_SECONDS = 10 * 60;
const COMPLETE_IDLE_WAIT_SECONDS = 10;
@@ -36,7 +37,8 @@ const COMPLETE_IDLE_WAIT_SECONDS = 10;
const TestOneDisk = new Lang.Class({
Name: 'TestOneDisk',
- _init: function(testRequiredMessageIds, testFailedMessageIds) {
+ _init: function(parentTask, testRequiredMessageIds, testFailedMessageIds) {
+ this._parentTask = parentTask;
this._testRequiredMessageIds = testRequiredMessageIds;
this._testFailedMessageIds = testFailedMessageIds;
},
@@ -214,8 +216,10 @@ const TestOneDisk = new Lang.Class({
this._loop.quit();
},
- execute: function(subworkdir, diskPath, cancellable) {
+ execute: function(subworkdir, buildData, repo, diskPath, cancellable) {
print("Testing disk " + diskPath.get_path());
+ this._buildData = buildData;
+ this._repo = repo;
this._subworkdir = subworkdir;
this._loop = GLib.MainLoop.new(null, true);
this._foundAllMessageIds = false;
@@ -240,6 +244,12 @@ const TestOneDisk = new Lang.Class({
}
this._cancellable = cancellable;
+ // HACK
+ if (diskPath.get_basename().indexOf('x86_64') >= 0)
+ this._diskArch = 'x86_64';
+ else
+ this._diskArch = 'i686';
+
let qemuArgs = [LibQA.getQemuPath()];
qemuArgs.push.apply(qemuArgs, LibQA.DEFAULT_QEMU_OPTS);
@@ -256,6 +266,8 @@ const TestOneDisk = new Lang.Class({
LibQA.injectExportJournal(currentDir, currentEtcDir, cancellable);
LibQA.injectTestUserCreation(currentDir, currentEtcDir, 'testuser', {}, cancellable);
LibQA.enableAutologin(currentDir, currentEtcDir, 'testuser', cancellable);
+
+ this._parentTask._prepareDisk(mntdir, this._diskArch, cancellable);
} finally {
gfmnt.umount(cancellable);
}
@@ -305,7 +317,7 @@ const TestOneDisk = new Lang.Class({
}
});
-const TaskTestBase = new Lang.Class({
+const TestBase = new Lang.Class({
Name: 'TestBase',
Extends: Task.TaskDef,
@@ -322,6 +334,12 @@ const TaskTestBase = new Lang.Class({
RequiredMessageIDs: [],
FailedMessageIDs: [],
+ CompletedTag: null,
+
+ _prepareDisk: function(mntdir, cancellable) {
+ // Nothing, intended for subclasses
+ },
+
execute: function(cancellable) {
let imageDir = this.workdir.get_child('images');
let currentImages = imageDir.get_child('current');
@@ -330,6 +348,7 @@ const TaskTestBase = new Lang.Class({
cancellable);
let info;
let buildJson;
+ let disksToTest = [];
while ((info = e.next_file(cancellable)) != null) {
let name = info.get_name();
if (name.indexOf('build-') == 0 && JSUtil.stringEndswith(name, '.json')) {
@@ -338,21 +357,29 @@ const TaskTestBase = new Lang.Class({
}
if (!JSUtil.stringEndswith(name, '.qcow2'))
continue;
+ disksToTest.push(name);
+ }
+ e.close(null);
+ this._buildData = null;
+ if (buildJson != null)
+ this._buildData = JSONUtil.loadJson(buildJson, cancellable);
+ for (let i = 0; i < disksToTest.length; i++) {
+ let name = disksToTest[i];
let workdirName = 'work-' + name.replace(/\.qcow2$/, '');
let subworkdir = Gio.File.new_for_path(workdirName);
GSystem.file_ensure_directory(subworkdir, true, cancellable);
- let test = new TestOneDisk(this.BaseRequiredMessageIDs.concat(this.RequiredMessageIDs),
+ let test = new TestOneDisk(this, this.BaseRequiredMessageIDs.concat(this.RequiredMessageIDs),
this.BaseFailedMessageIDs.concat(this.FailedMessageIDs));
- test.execute(subworkdir, currentImages.get_child(name), cancellable);
+ test.execute(subworkdir, this._buildData, this.repo, currentImages.get_child(name), cancellable);
}
- if (buildJson != null) {
- let buildData = JSONUtil.loadJson(buildJson, cancellable);
+ let buildData = this._buildData;
+ if (buildJson != null && this.CompletedTag !== null) {
let refData = '';
let snapshot = buildData['snapshot'];
for (let targetName in buildData['targets']) {
let targetRev = buildData['targets'][targetName];
let lastSlash = targetName.lastIndexOf('/');
- let smoketestedRef = snapshot['osname'] + '/smoketested' + targetName.substr(lastSlash);
+ let smoketestedRef = snapshot['osname'] + '/' + this.CompletedTag +
targetName.substr(lastSlash);
refData += smoketestedRef + ' ' + targetRev + '\n';
}
ProcUtil.runProcWithInputSyncGetLines(['ostree', '--repo=' + this.repo.get_path(),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]