Merge lp:~elopio/snappy/15.04-backport-integration into lp:~snappy-dev/snappy/15.04-deprecated

Proposed by Leo Arias
Status: Merged
Approved by: Leo Arias
Approved revision: 469
Merged at revision: 466
Proposed branch: lp:~elopio/snappy/15.04-backport-integration
Merge into: lp:~snappy-dev/snappy/15.04-deprecated
Prerequisite: lp:~elopio/snappy/backport-gocheck
Diff against target: 2812 lines (+2596/-3)
34 files modified
_integration-tests/README.md (+117/-0)
_integration-tests/data/snaps/basic/meta/package.yaml (+4/-0)
_integration-tests/data/snaps/basic/meta/readme.md (+3/-0)
_integration-tests/data/snaps/missing-readme/meta/package.yaml (+4/-0)
_integration-tests/data/snaps/wrong-yaml/meta/package.yaml (+5/-0)
_integration-tests/data/snaps/wrong-yaml/meta/readme.md (+3/-0)
_integration-tests/data/tpl/control (+4/-0)
_integration-tests/main.go (+105/-0)
_integration-tests/reboot-wrapper (+35/-0)
_integration-tests/tests/apt_test.go (+39/-0)
_integration-tests/tests/base_test.go (+29/-0)
_integration-tests/tests/build_test.go (+90/-0)
_integration-tests/tests/failover_rclocal_crash_test.go (+54/-0)
_integration-tests/tests/failover_systemd_loop_test.go (+114/-0)
_integration-tests/tests/failover_test.go (+58/-0)
_integration-tests/tests/failover_zero_size_file_test.go (+258/-0)
_integration-tests/tests/info_test.go (+79/-0)
_integration-tests/tests/installApp_test.go (+128/-0)
_integration-tests/tests/installFramework_test.go (+93/-0)
_integration-tests/tests/list_test.go (+78/-0)
_integration-tests/tests/rollback_test.go (+53/-0)
_integration-tests/tests/search_test.go (+44/-0)
_integration-tests/tests/update_test.go (+51/-0)
_integration-tests/tests/writablePaths_test.go (+106/-0)
_integration-tests/testutils/autopkgtest/autopkgtest.go (+111/-0)
_integration-tests/testutils/autopkgtest/ssh.go (+46/-0)
_integration-tests/testutils/build/build.go (+76/-0)
_integration-tests/testutils/common/common.go (+379/-0)
_integration-tests/testutils/common/common_test.go (+68/-0)
_integration-tests/testutils/config/config.go (+75/-0)
_integration-tests/testutils/config/config_test.go (+121/-0)
_integration-tests/testutils/image/image.go (+86/-0)
_integration-tests/testutils/testutils.go (+61/-0)
run-checks (+19/-3)
To merge this branch: bzr merge lp:~elopio/snappy/15.04-backport-integration
Reviewer Review Type Date Requested Status
Federico Gimenez (community) Approve
Review via email: mp+266664@code.launchpad.net

This proposal supersedes a proposal from 2015-07-27.

Commit message

Backported the integration tests.

Description of the change

Huge branch! But you don't need to check everything, as it's just a copy from trunk. Run the tests and we are good to go.

To post a comment you must log in.
Revision history for this message
Leo Arias (elopio) wrote : Posted in a previous version of this proposal

Work in progress because we want to land this after the current release. But this is working, ready to be tested.

Revision history for this message
Federico Gimenez (fgimenez) wrote : Posted in a previous version of this proposal

Thanks for this Leo, leaving my approval here

review: Approve (tested)
Revision history for this message
Federico Gimenez (fgimenez) wrote : Posted in a previous version of this proposal

There's a problem with the gocheck dependency, the installed package name doesn't match the import name [1]. We should modify also dependencies.tsv.

Thanks!

[1] http://10.55.61.165:8080/job/snappy-integration-tests-canonistack-1504-edge/14/console

Revision history for this message
Leo Arias (elopio) wrote :

@Federico, I backported the gocheck update because we need a newer version than the one that's in launchpad. It's a prerequisite of this branch.

Revision history for this message
Federico Gimenez (fgimenez) wrote :

Ok, tested and working, thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added directory '_integration-tests'
=== added file '_integration-tests/README.md'
--- _integration-tests/README.md 1970-01-01 00:00:00 +0000
+++ _integration-tests/README.md 2015-08-02 12:28:52 +0000
@@ -0,0 +1,117 @@
1# Integration testing for snappy
2
3## Requirements
4
5 * autopkgtest (>= 3.15.1)
6
7 Get the latest autopkgtest deb from
8 https://packages.debian.org/sid/all/autopkgtest/download
9
10 * Internet access in the test bed.
11
12## Setting up the project
13
14First you need to set up the GOPATH, get the snappy sources and the
15dependencies as explained in the `README.md` that is located at the root of the
16branch.
17
18## Testing a virtual machine
19
20You can execute the full integration suite in a local virtual machine with:
21
22 go run _integration-tests/main.go
23
24The test runner will create the snappy images with `ubuntu-device-flash`, so it
25will ask for your password to run this command with `sudo`.
26
27You can also especify more options to customize the image being created, including
28the release, the channel and the revision to use. This parameters will be passed
29to `ubuntu-device-flash`:
30
31 go run _integration-tests/main.go -release 15.04 -channel stable -revision 3
32
33The default values are suited to testing the most recent version, `rolling` for
34release, `edge` for channel and an empty revision, which picks the latest
35available.
36
37## Testing snappy from a branch
38
39With the --snappy-from-branch flag, the snappy CLI command will be compiled
40from the current branch, copied to the test bed and used during the integration
41tests:
42
43 go run _integration-tests/main.go --snappy-from-branch
44
45You can use this flag to test in a remote machine too.
46
47## Filtering the tests to run
48
49With the --filter flag you can select the tests to run. For instance you can
50pass MyTestSuite, MyTestSuite.FirstCustomTest or MyTestSuite.*CustomTest:
51
52 go run _integration-tests/main.go --filter MyTestSuite.FirstCustomTest
53
54## Testing a remote machine
55
56You can execute the integration suite in a remote snappy machine with:
57
58 go run _integration-tests/main.go --ip {testbed-ip} --port {testbed-port} \
59 --arch {testbed-arch}
60
61The test runner will use `ssh-copy-id` to send your identity file to the
62testbed, so it will ask for the password of the ubuntu user in the test bed.
63
64When running in a remote machine, the test runner assumes the test bed is in
65the latest rolling edge version, and it will skip all the tests that
66require a different version. See the following section for instructions for
67setting up a BeagleBone Black as the test bed.
68
69## Testing a BeagleBone Black
70
71First flash the latest 15.04 edge version into the sd card
72(replacing /dev/sdX with the path to your card):
73
74 sudo ubuntu-device-flash core 15.04 --channel edge --oem beagleblack \
75 --developer-mode --enable-ssh -o ubuntu-15.04-edge-armhf-bbb.img
76
77 sudo dd if=ubuntu-15.04-edge-armhf-bbb.img of=/dev/sdX bs=32M
78 sync
79
80Then boot the board with the sd card, make sure that it is connected to the
81same network as the test runner host, and find the {beaglebone-ip}.
82
83Run the tests with:
84
85 go run _integration-tests/main.go --ip {beaglebone-ip} --arch arm
86
87## Testing an update
88
89With the --update flag you can flash an old image, update to the latest and
90then run the whole suite on the updated system. The release, the channel and
91the revision flags specify the image that will be flashed, and the
92target-release and target-channel flags specify the values to be used in the
93update if they are different from the flashed values.
94
95For example, to update from 15.04 edge -1 to the latest and then run the
96integration tests:
97
98 go run _integration-tests/main.go --snappy-from-branch \
99 --release=15.04 --revision=-1 --update
100
101To update from 15.04 alpha to 15.04 edge and then run the integration tests:
102
103 go run _integration-tests/main.go --snappy-from-branch \
104 --release=15.04 --channel=alpha \
105 --update --target-channel=edge
106
107## Testing a rollback
108
109With the --rollback flag you can flash an old image, update to the latest,
110rollback again to the old image and then run the whole suite on the rolled
111back system. You should use the release, channel, revision, target-release and
112target-channel flags as when testing an update.
113
114For example, to test a rollback from latest 15.04 edge to 15.04 edge -1:
115
116 go run _integration-tests/main.go \
117 --release=15.04 --revision=-1 --rollback
0118
=== added directory '_integration-tests/data'
=== added directory '_integration-tests/data/snaps'
=== added directory '_integration-tests/data/snaps/basic'
=== added directory '_integration-tests/data/snaps/basic/meta'
=== added file '_integration-tests/data/snaps/basic/meta/package.yaml'
--- _integration-tests/data/snaps/basic/meta/package.yaml 1970-01-01 00:00:00 +0000
+++ _integration-tests/data/snaps/basic/meta/package.yaml 2015-08-02 12:28:52 +0000
@@ -0,0 +1,4 @@
1name: basic
2version: 1.0
3vendor: Snappy Developers <snappy-devel@lists.ubuntu.com>
4icon: meta/snappy64.png
05
=== added file '_integration-tests/data/snaps/basic/meta/readme.md'
--- _integration-tests/data/snaps/basic/meta/readme.md 1970-01-01 00:00:00 +0000
+++ _integration-tests/data/snaps/basic/meta/readme.md 2015-08-02 12:28:52 +0000
@@ -0,0 +1,3 @@
1Basic snap
2
3A basic buildable snap
04
=== added file '_integration-tests/data/snaps/basic/meta/snappy64.png'
1Binary files _integration-tests/data/snaps/basic/meta/snappy64.png 1970-01-01 00:00:00 +0000 and _integration-tests/data/snaps/basic/meta/snappy64.png 2015-08-02 12:28:52 +0000 differ5Binary files _integration-tests/data/snaps/basic/meta/snappy64.png 1970-01-01 00:00:00 +0000 and _integration-tests/data/snaps/basic/meta/snappy64.png 2015-08-02 12:28:52 +0000 differ
=== added directory '_integration-tests/data/snaps/missing-readme'
=== added directory '_integration-tests/data/snaps/missing-readme/meta'
=== added file '_integration-tests/data/snaps/missing-readme/meta/package.yaml'
--- _integration-tests/data/snaps/missing-readme/meta/package.yaml 1970-01-01 00:00:00 +0000
+++ _integration-tests/data/snaps/missing-readme/meta/package.yaml 2015-08-02 12:28:52 +0000
@@ -0,0 +1,4 @@
1name: missing-readme
2version: 1.0
3vendor: Snappy Developers <snappy-devel@lists.ubuntu.com>
4icon: meta/snappy64.png
05
=== added file '_integration-tests/data/snaps/missing-readme/meta/snappy64.png'
1Binary files _integration-tests/data/snaps/missing-readme/meta/snappy64.png 1970-01-01 00:00:00 +0000 and _integration-tests/data/snaps/missing-readme/meta/snappy64.png 2015-08-02 12:28:52 +0000 differ6Binary files _integration-tests/data/snaps/missing-readme/meta/snappy64.png 1970-01-01 00:00:00 +0000 and _integration-tests/data/snaps/missing-readme/meta/snappy64.png 2015-08-02 12:28:52 +0000 differ
=== added directory '_integration-tests/data/snaps/wrong-yaml'
=== added directory '_integration-tests/data/snaps/wrong-yaml/meta'
=== added file '_integration-tests/data/snaps/wrong-yaml/meta/package.yaml'
--- _integration-tests/data/snaps/wrong-yaml/meta/package.yaml 1970-01-01 00:00:00 +0000
+++ _integration-tests/data/snaps/wrong-yaml/meta/package.yaml 2015-08-02 12:28:52 +0000
@@ -0,0 +1,5 @@
1# This is an invalid yaml, there's a missing colon after the 'name' field
2name wrong-yaml
3version: 1.0
4vendor: Snappy Developers <snappy-devel@lists.ubuntu.com>
5icon: meta/snappy64.png
06
=== added file '_integration-tests/data/snaps/wrong-yaml/meta/readme.md'
--- _integration-tests/data/snaps/wrong-yaml/meta/readme.md 1970-01-01 00:00:00 +0000
+++ _integration-tests/data/snaps/wrong-yaml/meta/readme.md 2015-08-02 12:28:52 +0000
@@ -0,0 +1,3 @@
1Wrong metadata snap
2
3A snap with an invalid meta/package.yaml
04
=== added file '_integration-tests/data/snaps/wrong-yaml/meta/snappy64.png'
1Binary files _integration-tests/data/snaps/wrong-yaml/meta/snappy64.png 1970-01-01 00:00:00 +0000 and _integration-tests/data/snaps/wrong-yaml/meta/snappy64.png 2015-08-02 12:28:52 +0000 differ5Binary files _integration-tests/data/snaps/wrong-yaml/meta/snappy64.png 1970-01-01 00:00:00 +0000 and _integration-tests/data/snaps/wrong-yaml/meta/snappy64.png 2015-08-02 12:28:52 +0000 differ
=== added directory '_integration-tests/data/tpl'
=== added file '_integration-tests/data/tpl/control'
--- _integration-tests/data/tpl/control 1970-01-01 00:00:00 +0000
+++ _integration-tests/data/tpl/control 2015-08-02 12:28:52 +0000
@@ -0,0 +1,4 @@
1{{ $filter := .Filter }}
2{{ $test := .Test }}
3Test-Command: ./_integration-tests/reboot-wrapper {{ $test }} {{ if $filter }}-gocheck.f {{ $filter }}{{ end }}
4Restrictions: allow-stderr
05
=== added file '_integration-tests/main.go'
--- _integration-tests/main.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/main.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,105 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package main
21
22import (
23 "flag"
24 "log"
25 "os"
26 "path/filepath"
27 "strconv"
28
29 "launchpad.net/snappy/_integration-tests/testutils"
30 "launchpad.net/snappy/_integration-tests/testutils/autopkgtest"
31 "launchpad.net/snappy/_integration-tests/testutils/build"
32 "launchpad.net/snappy/_integration-tests/testutils/config"
33 "launchpad.net/snappy/_integration-tests/testutils/image"
34)
35
36const (
37 baseDir = "/tmp/snappy-test"
38 defaultRelease = "rolling"
39 defaultChannel = "edge"
40 defaultSSHPort = 22
41 dataOutputDir = "_integration-tests/data/output/"
42)
43
44var configFileName = filepath.Join(dataOutputDir, "testconfig.json")
45
46func main() {
47 var (
48 useSnappyFromBranch = flag.Bool("snappy-from-branch", false,
49 "If this flag is used, snappy will be compiled from this branch, copied to the testbed and used for the tests. Otherwise, the snappy installed with the image will be used.")
50 arch = flag.String("arch", "",
51 "Architecture of the test bed. Defaults to use the same architecture as the host.")
52 testbedIP = flag.String("ip", "",
53 "IP of the testbed. If no IP is passed, a virtual machine will be created for the test.")
54 testbedPort = flag.Int("port", defaultSSHPort,
55 "SSH port of the testbed. Defaults to use port "+strconv.Itoa(defaultSSHPort))
56 testFilter = flag.String("filter", "",
57 "Suites or tests to run, for instance MyTestSuite, MyTestSuite.FirstCustomTest or MyTestSuite.*CustomTest")
58 imgRelease = flag.String("release", defaultRelease,
59 "Release of the image to be built, defaults to "+defaultRelease)
60 imgChannel = flag.String("channel", defaultChannel,
61 "Channel of the image to be built, defaults to "+defaultChannel)
62 imgRevision = flag.String("revision", "",
63 "Revision of the image to be built (can be relative to the latest available revision in the given release and channel as in -1), defaults to the empty string")
64 update = flag.Bool("update", false,
65 "If this flag is used, the image will be updated before running the tests.")
66 targetRelease = flag.String("target-release", "",
67 "If the update flag is used, the image will be updated to this release before running the tests.")
68 targetChannel = flag.String("target-channel", "",
69 "If the update flag is used, the image will be updated to this channel before running the tests.")
70 rollback = flag.Bool("rollback", false,
71 "If this flag is used, the image will be updated and then rolled back before running the tests.")
72 )
73
74 flag.Parse()
75
76 build.Assets(*useSnappyFromBranch, *arch)
77
78 // TODO: generate the files out of the source tree. --elopio - 2015-07-15
79 testutils.PrepareTargetDir(dataOutputDir)
80 defer os.RemoveAll(dataOutputDir)
81
82 remoteTestbed := *testbedIP != ""
83
84 // TODO: pass the config as arguments to the test binaries.
85 // --elopio - 2015-07-15
86 cfg := config.NewConfig(
87 configFileName, *imgRelease, *imgChannel, *targetRelease, *targetChannel,
88 remoteTestbed, *update, *rollback)
89 cfg.Write()
90
91 rootPath := testutils.RootPath()
92
93 test := autopkgtest.NewAutopkgtest(rootPath, baseDir, *testFilter, build.IntegrationTestName)
94 if !remoteTestbed {
95 img := image.NewImage(*imgRelease, *imgChannel, *imgRevision, baseDir)
96
97 if imagePath, err := img.UdfCreate(); err == nil {
98 test.AdtRunLocal(imagePath)
99 } else {
100 log.Panic(err.Error())
101 }
102 } else {
103 test.AdtRunRemote(*testbedIP, *testbedPort)
104 }
105}
0106
=== added file '_integration-tests/reboot-wrapper'
--- _integration-tests/reboot-wrapper 1970-01-01 00:00:00 +0000
+++ _integration-tests/reboot-wrapper 2015-08-02 12:28:52 +0000
@@ -0,0 +1,35 @@
1#!/bin/sh
2
3# Copyright (C) 2015 Canonical Ltd
4#
5# This program is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License version 3 as
7# published by the Free Software Foundation.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17# This runs the $1 go test binary and reboots if necessary.
18
19set -e
20
21TEST=$1
22NEEDS_REBOOT=/tmp/needs-reboot
23
24export PATH=$(pwd)/_integration-tests/bin:$PATH
25
26# shift to remove the test binary name (first argument) and be able to pass the rest
27# of them to it
28shift
29${TEST} -check.vv -test.outputdir=$ADT_ARTIFACTS-$ADT_REBOOT_MARK "$@"
30
31if [ -e ${NEEDS_REBOOT} ]; then
32 mark=`cat ${NEEDS_REBOOT}`
33 echo "Rebooting..."
34 sudo /tmp/autopkgtest-reboot "$mark"
35fi
036
=== added directory '_integration-tests/tests'
=== added file '_integration-tests/tests/apt_test.go'
--- _integration-tests/tests/apt_test.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/tests/apt_test.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,39 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package tests
21
22import (
23 . "launchpad.net/snappy/_integration-tests/testutils/common"
24
25 check "gopkg.in/check.v1"
26)
27
28var _ = check.Suite(&aptSuite{})
29
30type aptSuite struct {
31 SnappySuite
32}
33
34func (s *aptSuite) TestAptGetMustPrintError(c *check.C) {
35 aptOutput := ExecCommand(c, "apt-get", "update")
36
37 expected := "Ubuntu Core does not use apt-get, see 'snappy --help'!\n"
38 c.Assert(aptOutput, check.Equals, expected)
39}
040
=== added file '_integration-tests/tests/base_test.go'
--- _integration-tests/tests/base_test.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/tests/base_test.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,29 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package tests
21
22import (
23 "testing"
24
25 . "gopkg.in/check.v1"
26)
27
28// Hook up gocheck into the "go test" runner.
29func Test(t *testing.T) { TestingT(t) }
030
=== added file '_integration-tests/tests/build_test.go'
--- _integration-tests/tests/build_test.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/tests/build_test.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,90 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package tests
21
22import (
23 "fmt"
24 "os"
25 "os/exec"
26
27 . "launchpad.net/snappy/_integration-tests/testutils/common"
28
29 . "gopkg.in/check.v1"
30)
31
32const (
33 baseSnapPath = "_integration-tests/data/snaps"
34 basicSnapName = "basic"
35 wrongYamlSnapName = "wrong-yaml"
36 missingReadmeSnapName = "missing-readme"
37)
38
39var _ = Suite(&buildSuite{})
40
41type buildSuite struct {
42 SnappySuite
43}
44
45func buildSnap(c *C, snapPath string) string {
46 return ExecCommand(c, "snappy", "build", snapPath)
47}
48
49func (s *buildSuite) TestBuildBasicSnapOnSnappy(c *C) {
50 // build basic snap and check output
51 snapPath := baseSnapPath + "/" + basicSnapName
52 buildOutput := buildSnap(c, snapPath)
53 snapName := basicSnapName + "_1.0_all.snap"
54 expected := fmt.Sprintf("Generated '%s' snap\n", snapName)
55 c.Check(buildOutput, Equals, expected)
56 defer os.Remove(snapPath + "/" + snapName)
57
58 // install built snap and check output
59 installOutput := InstallSnap(c, snapName)
60 defer RemoveSnap(c, basicSnapName)
61 expected = "(?ms)" +
62 "Installing " + snapName + "\n" +
63 ".*Signature check failed, but installing anyway as requested\n" +
64 "Name +Date +Version +Developer \n" +
65 ".*\n" +
66 basicSnapName + " +.* +.* +sideload \n" +
67 ".*\n"
68
69 c.Check(installOutput, Matches, expected)
70
71 // teardown, remove snap file
72 c.Assert(os.Remove(snapName), IsNil, Commentf("Error removing %s", snapName))
73}
74
75func (s *buildSuite) TestBuildWrongYamlSnapOnSnappy(c *C) {
76 commonWrongTest(c, wrongYamlSnapName, "(?msi).*Can not parse.*yaml: line 2: mapping values are not allowed in this context.*")
77}
78
79func (s *buildSuite) TestBuildMissingReadmeSnapOnSnappy(c *C) {
80 commonWrongTest(c, missingReadmeSnapName, ".*readme.md: no such file or directory\n")
81}
82
83func commonWrongTest(c *C, testName, expected string) {
84 // build wrong snap and check output
85 cmd := exec.Command("snappy", "build", fmt.Sprintf("%s/%s", baseSnapPath, testName))
86 echoOutput, err := cmd.CombinedOutput()
87 c.Assert(err, NotNil, Commentf("%s should not be built", testName))
88
89 c.Assert(string(echoOutput), Matches, expected)
90}
091
=== added file '_integration-tests/tests/failover_rclocal_crash_test.go'
--- _integration-tests/tests/failover_rclocal_crash_test.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/tests/failover_rclocal_crash_test.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,54 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package tests
21
22import (
23 "fmt"
24
25 . "launchpad.net/snappy/_integration-tests/testutils/common"
26
27 check "gopkg.in/check.v1"
28)
29
30type rcLocalCrash struct{}
31
32func (rcLocalCrash) set(c *check.C) {
33 MakeWritable(c, BaseAltPartitionPath)
34 defer MakeReadonly(c, BaseAltPartitionPath)
35 targetFile := fmt.Sprintf("%s/etc/rc.local", BaseAltPartitionPath)
36 ExecCommand(c, "sudo", "chmod", "a+xw", targetFile)
37 ExecCommandToFile(c, targetFile,
38 "sudo", "echo", "#!bin/sh\nprintf c > /proc/sysrq-trigger")
39}
40
41func (rcLocalCrash) unset(c *check.C) {
42 MakeWritable(c, BaseAltPartitionPath)
43 defer MakeReadonly(c, BaseAltPartitionPath)
44 ExecCommand(c, "sudo", "rm", fmt.Sprintf("%s/etc/rc.local", BaseAltPartitionPath))
45}
46
47/*
48TODO: uncomment when bug https://bugs.launchpad.net/snappy/+bug/1476129 is fixed
49(fgimenez 20150728)
50
51func (s *failoverSuite) TestRCLocalCrash(c *check.C) {
52 commonFailoverTest(c, rcLocalCrash{})
53}
54*/
055
=== added file '_integration-tests/tests/failover_systemd_loop_test.go'
--- _integration-tests/tests/failover_systemd_loop_test.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/tests/failover_systemd_loop_test.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,114 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package tests
21
22import (
23 "fmt"
24
25 . "launchpad.net/snappy/_integration-tests/testutils/common"
26
27 check "gopkg.in/check.v1"
28)
29
30const (
31 deadlockService = `[Unit]
32Before=sysinit.target
33DefaultDependencies=no
34
35[Service]
36Type=oneshot
37ExecStartPre=-/bin/sh -c "echo 'DEBUG: $(date): deadlocked system' >/dev/console"
38ExecStartPre=-/bin/sh -c "echo 'DEBUG: $(date): deadlocked system' >/dev/ttyS0"
39ExecStart=/bin/systemctl start deadlock.service
40RemainAfterExit=yes
41
42[Install]
43RequiredBy=sysinit.target
44`
45 rebootService = `[Unit]
46DefaultDependencies=no
47Description=Hack to force reboot if booting did not finish after 20s
48
49[Service]
50Type=oneshot
51ExecStartPre=/bin/sleep 20
52ExecStart=-/bin/sh -c 'if ! systemctl is-active default.target; then wall "EMERGENCY REBOOT"; reboot -f; fi'
53
54[Install]
55RequiredBy=sysinit.target
56`
57 baseSystemdPath = "/lib/systemd/system"
58 systemdTargetRequiresDir = "sysinit.target.requires"
59)
60
61type systemdDependencyLoop struct{}
62
63func (systemdDependencyLoop) set(c *check.C) {
64 installService(c, "deadlock", deadlockService, BaseAltPartitionPath)
65 installService(c, "emerg-reboot", rebootService, BaseAltPartitionPath)
66}
67
68func (systemdDependencyLoop) unset(c *check.C) {
69 unInstallService(c, "deadlock", BaseAltPartitionPath)
70 unInstallService(c, "emerg-reboot", BaseAltPartitionPath)
71}
72
73func installService(c *check.C, serviceName, serviceCfg, basePath string) {
74 MakeWritable(c, basePath)
75 defer MakeReadonly(c, basePath)
76
77 // Create service file
78 serviceFile := fmt.Sprintf("%s%s/%s.service", basePath, baseSystemdPath, serviceName)
79 ExecCommand(c, "sudo", "chmod", "a+w", fmt.Sprintf("%s%s", basePath, baseSystemdPath))
80 ExecCommandToFile(c, serviceFile, "sudo", "echo", serviceCfg)
81
82 // Create requires directory
83 requiresDirPart := fmt.Sprintf("%s/%s", baseSystemdPath, systemdTargetRequiresDir)
84 requiresDir := fmt.Sprintf("%s%s", basePath, requiresDirPart)
85 ExecCommand(c, "sudo", "mkdir", "-p", requiresDir)
86
87 // Symlink from the requires dir to the service file (with chroot for being
88 // usable in the other partition)
89 ExecCommand(c, "sudo", "chroot", basePath, "ln", "-s",
90 fmt.Sprintf("%s/%s.service", baseSystemdPath, serviceName),
91 fmt.Sprintf("%s/%s.service", requiresDirPart, serviceName),
92 )
93}
94
95func unInstallService(c *check.C, serviceName, basePath string) {
96 MakeWritable(c, basePath)
97 defer MakeReadonly(c, basePath)
98
99 // Disable the service
100 ExecCommand(c, "sudo", "chroot", basePath,
101 "systemctl", "disable", fmt.Sprintf("%s.service", serviceName))
102
103 // Remove the service file
104 ExecCommand(c, "sudo", "rm",
105 fmt.Sprintf("%s%s/%s.service", basePath, baseSystemdPath, serviceName))
106
107 // Remove the requires symlink
108 ExecCommand(c, "sudo", "rm",
109 fmt.Sprintf("%s%s/%s/%s.service", basePath, baseSystemdPath, systemdTargetRequiresDir, serviceName))
110}
111
112func (s *failoverSuite) TestSystemdDependencyLoop(c *check.C) {
113 commonFailoverTest(c, systemdDependencyLoop{})
114}
0115
=== added file '_integration-tests/tests/failover_test.go'
--- _integration-tests/tests/failover_test.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/tests/failover_test.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,58 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package tests
21
22import (
23 check "gopkg.in/check.v1"
24
25 . "launchpad.net/snappy/_integration-tests/testutils/common"
26)
27
28var _ = check.Suite(&failoverSuite{})
29
30type failoverSuite struct {
31 SnappySuite
32}
33
34// The types that implement this interface can be used in the test logic
35type failer interface {
36 // Sets the failure conditions
37 set(c *check.C)
38 // Unsets the failure conditions
39 unset(c *check.C)
40}
41
42// This is the logic common to all the failover tests. Each of them has define a
43// type implementing the failer interface and call this function with an instance
44// of it
45func commonFailoverTest(c *check.C, f failer) {
46 currentVersion := GetCurrentUbuntuCoreVersion(c)
47
48 if AfterReboot(c) {
49 RemoveRebootMark(c)
50 f.unset(c)
51 c.Assert(GetSavedVersion(c), check.Equals, currentVersion)
52 } else {
53 SetSavedVersion(c, currentVersion-1)
54 CallFakeUpdate(c)
55 f.set(c)
56 Reboot(c)
57 }
58}
059
=== added file '_integration-tests/tests/failover_zero_size_file_test.go'
--- _integration-tests/tests/failover_zero_size_file_test.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/tests/failover_zero_size_file_test.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,258 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package tests
21
22import (
23 "bufio"
24 "fmt"
25 "os"
26 "path/filepath"
27 "strings"
28
29 . "launchpad.net/snappy/_integration-tests/testutils/common"
30
31 check "gopkg.in/check.v1"
32)
33
34const (
35 origBootFilenamePattern = "boot/%s%s*"
36 origSystemdFilenamePattern = "lib/systemd/%s%s"
37 kernelFilename = "vmlinuz"
38 initrdFilename = "initrd"
39 systemdFilename = "systemd"
40 destFilenamePrefix = "snappy-selftest-"
41 bootBase = "/boot"
42 ubootDir = bootBase + "/uboot"
43 grubDir = bootBase + "/grub"
44 ubootConfigFile = ubootDir + "/snappy-system.txt"
45 grubConfigFile = grubDir + "/grubenv"
46)
47
48type zeroSizeKernel struct{}
49type zeroSizeInitrd struct{}
50type zeroSizeSystemd struct{}
51
52func (zeroSizeKernel) set(c *check.C) {
53 commonSet(c, BaseAltPartitionPath, origBootFilenamePattern, kernelFilename)
54}
55
56func (zeroSizeKernel) unset(c *check.C) {
57 commonUnset(c, BaseAltPartitionPath, origBootFilenamePattern, kernelFilename)
58}
59
60func (zeroSizeInitrd) set(c *check.C) {
61 if classicKernelFiles(c) {
62 commonSet(c, BaseAltPartitionPath, origBootFilenamePattern, initrdFilename)
63 } else {
64 boot := bootSystem(c)
65 dir := bootDirectory(boot)
66 bootFileNamePattern := newKernelFilenamePattern(c, boot, true)
67 commonSet(c, dir, bootFileNamePattern, initrdFilename)
68 }
69}
70
71func (zeroSizeInitrd) unset(c *check.C) {
72 if classicKernelFiles(c) {
73 commonUnset(c, BaseAltPartitionPath, origBootFilenamePattern, initrdFilename)
74 } else {
75 boot := bootSystem(c)
76 dir := bootDirectory(boot)
77 bootFileNamePattern := newKernelFilenamePattern(c, boot, false)
78 commonUnset(c, dir, bootFileNamePattern, initrdFilename)
79 }
80}
81
82func (zeroSizeSystemd) set(c *check.C) {
83 commonSet(c, BaseAltPartitionPath, origSystemdFilenamePattern, systemdFilename)
84}
85
86func (zeroSizeSystemd) unset(c *check.C) {
87 commonUnset(c, BaseAltPartitionPath, origSystemdFilenamePattern, systemdFilename)
88}
89
90func commonSet(c *check.C, baseOtherPath, origPattern, filename string) {
91 filenamePattern := fmt.Sprintf(origPattern, "", filename)
92 completePattern := filepath.Join(
93 baseOtherPath,
94 filenamePattern)
95 oldFilename := getSingleFilename(c, completePattern)
96 filenameSuffix := fmt.Sprintf(
97 strings.Replace(origPattern, "*", "", 1), destFilenamePrefix, filepath.Base(oldFilename))
98 newFilename := fmt.Sprintf(
99 "%s/%s", baseOtherPath, filenameSuffix)
100
101 renameFile(c, baseOtherPath, oldFilename, newFilename, true)
102}
103
104func commonUnset(c *check.C, baseOtherPath, origPattern, filename string) {
105 completePattern := filepath.Join(
106 baseOtherPath,
107 fmt.Sprintf(origPattern, destFilenamePrefix, filename))
108 oldFilename := getSingleFilename(c, completePattern)
109 newFilename := strings.Replace(oldFilename, destFilenamePrefix, "", 1)
110
111 renameFile(c, baseOtherPath, oldFilename, newFilename, false)
112}
113
114func renameFile(c *check.C, basePath, oldFilename, newFilename string, keepOld bool) {
115 // Only need to make writable and revert for BaseAltPartitionPath,
116 // kernel files' boot directory is writable
117 if basePath == BaseAltPartitionPath {
118 MakeWritable(c, basePath)
119 defer MakeReadonly(c, basePath)
120 }
121
122 ExecCommand(c, "sudo", "mv", oldFilename, newFilename)
123
124 if keepOld {
125 ExecCommand(c, "sudo", "touch", oldFilename)
126 mode := getFileMode(c, newFilename)
127 ExecCommand(c, "sudo", "chmod", fmt.Sprintf("%o", mode), oldFilename)
128 }
129}
130
131func getFileMode(c *check.C, filePath string) os.FileMode {
132 info, err := os.Stat(filePath)
133 c.Check(err, check.IsNil, check.Commentf("Error getting Stat of %s", filePath))
134
135 return info.Mode()
136}
137
138func getSingleFilename(c *check.C, pattern string) string {
139 matches, err := filepath.Glob(pattern)
140
141 c.Assert(err, check.IsNil, check.Commentf("Error: %v", err))
142 c.Assert(len(matches), check.Equals, 1,
143 check.Commentf("%d files matching %s, 1 expected", len(matches), pattern))
144
145 return matches[0]
146}
147
148func classicKernelFiles(c *check.C) bool {
149 initrdClassicFilenamePattern := fmt.Sprintf("/boot/%s*-generic", initrdFilename)
150 matches, err := filepath.Glob(initrdClassicFilenamePattern)
151
152 c.Assert(err, check.IsNil, check.Commentf("Error: %v", err))
153
154 return len(matches) == 1
155}
156
157func bootSystem(c *check.C) string {
158 matches, err := filepath.Glob(bootBase + "/grub")
159
160 c.Assert(err, check.IsNil, check.Commentf("Error: %v", err))
161
162 if len(matches) == 1 {
163 return "grub"
164 }
165 return "uboot"
166}
167
168func bootDirectory(bootSystem string) string {
169 if bootSystem == "grub" {
170 return grubDir
171 }
172 return ubootDir
173}
174
175func bootConfigFile(bootSystem string) string {
176 if bootSystem == "grub" {
177 return grubConfigFile
178 }
179 return ubootConfigFile
180}
181
182func currentPartition(c *check.C, bootSystem string) (partition string) {
183 bootConfigFile := bootConfigFile(bootSystem)
184 file, err := os.Open(bootConfigFile)
185
186 c.Assert(err, check.IsNil,
187 check.Commentf("Error reading boot config file %s", bootConfigFile))
188
189 defer file.Close()
190
191 reader := bufio.NewReader(file)
192 scanner := bufio.NewScanner(reader)
193
194 scanner.Split(bufio.ScanLines)
195
196 for scanner.Scan() {
197 if strings.HasPrefix(scanner.Text(), "snappy_ab") {
198 fields := strings.Split(scanner.Text(), "=")
199 if len(fields) > 1 {
200 if bootSystem == "grub" {
201 partition = fields[1]
202 } else {
203 partition = otherPart(fields[1])
204 }
205 }
206 return
207 }
208 }
209 return
210}
211
212func otherPart(current string) string {
213 if current == "a" {
214 return "b"
215 }
216 return "a"
217}
218
219// newKernelFilenamePattern returns the filename pattern to modify files
220// in the partition declared in the boot config file.
221//
222// After the update, the config file is already changed to point to the new partition.
223// If we are on a and update, the config file would point to b
224// and this function would return "b/%s%s*"
225// If we are not in an update process (ie. we are unsetting the failover conditions)
226// we want to change the files in the other partition
227func newKernelFilenamePattern(c *check.C, bootSystem string, afterUpdate bool) string {
228 var actualPartition string
229 partition := currentPartition(c, bootSystem)
230 if afterUpdate {
231 actualPartition = partition
232 } else {
233 actualPartition = otherPart(partition)
234 }
235 return filepath.Join(actualPartition, "%s%s*")
236}
237
238/*
239TODO: uncomment when bug https://bugs.launchpad.net/snappy/+bug/1467553 is fixed
240(fgimenez 20150729)
241
242func (s *failoverSuite) TestZeroSizeKernel(c *check.C) {
243 commonFailoverTest(c, zeroSizeKernel{})
244}
245*/
246
247func (s *failoverSuite) TestZeroSizeInitrd(c *check.C) {
248 // Skip if on uboot due to https://bugs.launchpad.net/snappy/+bug/1480248
249 // (fgimenez 20150731)
250 if bootSystem(c) == "uboot" {
251 c.Skip("Failover for empty initrd not working in uboot")
252 }
253 commonFailoverTest(c, zeroSizeInitrd{})
254}
255
256func (s *failoverSuite) TestZeroSizeSystemd(c *check.C) {
257 commonFailoverTest(c, zeroSizeSystemd{})
258}
0259
=== added file '_integration-tests/tests/info_test.go'
--- _integration-tests/tests/info_test.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/tests/info_test.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,79 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package tests
21
22import (
23 "fmt"
24
25 . "launchpad.net/snappy/_integration-tests/testutils/common"
26
27 check "gopkg.in/check.v1"
28)
29
30var _ = check.Suite(&infoSuite{})
31
32type infoSuite struct {
33 SnappySuite
34}
35
36func (s *infoSuite) TestInfoMustPrintReleaseAndChannel(c *check.C) {
37 // skip test when having a remote testbed (we can't know which the
38 // release and channels are)
39 if Cfg.RemoteTestbed {
40 c.Skip(fmt.Sprintf(
41 "Skipping %s while testing in remote testbed",
42 c.TestName()))
43 }
44
45 infoOutput := ExecCommand(c, "snappy", "info")
46
47 expected := "(?ms)" +
48 fmt.Sprintf("^release: ubuntu-core/%s/%s\n", Cfg.Release, Cfg.Channel) +
49 ".*"
50
51 c.Assert(infoOutput, check.Matches, expected)
52}
53
54func (s *infoSuite) TestInfoMustPrintInstalledApps(c *check.C) {
55 InstallSnap(c, "hello-world")
56 s.AddCleanup(func() {
57 RemoveSnap(c, "hello-world")
58 })
59 infoOutput := ExecCommand(c, "snappy", "info")
60
61 expected := "(?ms)" +
62 ".*" +
63 "^apps: .*hello-world.*\n"
64 c.Assert(infoOutput, check.Matches, expected)
65}
66
67func (s *infoSuite) TestInfoMustPrintInstalledFrameworks(c *check.C) {
68 InstallSnap(c, "hello-dbus-fwk.canonical")
69 s.AddCleanup(func() {
70 RemoveSnap(c, "hello-dbus-fwk.canonical")
71 })
72 infoOutput := ExecCommand(c, "snappy", "info")
73
74 expected := "(?ms)" +
75 ".*" +
76 "^frameworks: .*hello-dbus-fwk.*\n" +
77 ".*"
78 c.Assert(infoOutput, check.Matches, expected)
79}
080
=== added file '_integration-tests/tests/installApp_test.go'
--- _integration-tests/tests/installApp_test.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/tests/installApp_test.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,128 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package tests
21
22import (
23 "fmt"
24 "net/http"
25 "os/exec"
26 "time"
27
28 . "launchpad.net/snappy/_integration-tests/testutils/common"
29
30 check "gopkg.in/check.v1"
31)
32
33var _ = check.Suite(&installAppSuite{})
34
35type installAppSuite struct {
36 SnappySuite
37}
38
39func (s *installAppSuite) TestInstallAppMustPrintPackageInformation(c *check.C) {
40 installOutput := InstallSnap(c, "hello-world")
41 s.AddCleanup(func() {
42 RemoveSnap(c, "hello-world")
43 })
44
45 expected := "(?ms)" +
46 "Installing hello-world\n" +
47 "Name +Date +Version +Developer \n" +
48 ".*" +
49 "^hello-world +.* +.* +canonical \n" +
50 ".*"
51
52 c.Assert(installOutput, check.Matches, expected)
53}
54
55func (s *installAppSuite) TestCallBinaryFromInstalledSnap(c *check.C) {
56 InstallSnap(c, "hello-world")
57 s.AddCleanup(func() {
58 RemoveSnap(c, "hello-world")
59 })
60
61 echoOutput := ExecCommand(c, "hello-world.echo")
62
63 c.Assert(echoOutput, check.Equals, "Hello World!\n")
64}
65
66func (s *installAppSuite) TestCallBinaryWithPermissionDeniedMustPrintError(c *check.C) {
67 InstallSnap(c, "hello-world")
68 s.AddCleanup(func() {
69 RemoveSnap(c, "hello-world")
70 })
71
72 cmd := exec.Command("hello-world.evil")
73 echoOutput, err := cmd.CombinedOutput()
74 c.Assert(err, check.NotNil, check.Commentf("hello-world.evil did not fail"))
75
76 expected := "" +
77 "Hello Evil World!\n" +
78 "This example demonstrates the app confinement\n" +
79 "You should see a permission denied error next\n" +
80 "/apps/hello-world.canonical/.*/bin/evil: \\d+: " +
81 "/apps/hello-world.canonical/.*/bin/evil: " +
82 "cannot create /var/tmp/myevil.txt: Permission denied\n"
83
84 c.Assert(string(echoOutput), check.Matches, expected)
85}
86
87func (s *installAppSuite) TestInfoMustPrintInstalledPackageInformation(c *check.C) {
88 InstallSnap(c, "hello-world")
89 s.AddCleanup(func() {
90 RemoveSnap(c, "hello-world")
91 })
92
93 infoOutput := ExecCommand(c, "snappy", "info")
94
95 expected := "(?ms).*^apps: hello-world\n"
96 c.Assert(infoOutput, check.Matches, expected)
97}
98
99func (s *installAppSuite) TestAppNetworkingServiceMustBeStarted(c *check.C) {
100 baseAppName := "xkcd-webserver"
101 appName := baseAppName + ".canonical"
102 InstallSnap(c, appName)
103 s.AddCleanup(func() {
104 RemoveSnap(c, appName)
105 })
106
107 appVersion := GetCurrentVersion(c, baseAppName)
108 appService := fmt.Sprintf("%s_%s_%s.service", baseAppName, baseAppName, appVersion)
109
110 err := WaitForActiveService(c, appService)
111 c.Assert(err, check.IsNil)
112
113 time.Sleep(1 * time.Second)
114 resp, err := http.Get("http://localhost")
115 c.Assert(err, check.IsNil)
116 c.Check(resp.Status, check.Equals, "200 OK")
117 c.Assert(resp.Proto, check.Equals, "HTTP/1.0")
118}
119
120func (s *installAppSuite) TestInstallUnexistingAppMustPrintError(c *check.C) {
121 cmd := exec.Command("sudo", "snappy", "install", "unexisting.canonical")
122 output, err := cmd.CombinedOutput()
123
124 c.Assert(err, check.NotNil)
125 c.Assert(string(output), check.Equals,
126 "Installing unexisting.canonical\n"+
127 "unexisting.canonical failed to install: snappy package not found\n")
128}
0129
=== added file '_integration-tests/tests/installFramework_test.go'
--- _integration-tests/tests/installFramework_test.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/tests/installFramework_test.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,93 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package tests
21
22import (
23 "fmt"
24 "regexp"
25
26 . "launchpad.net/snappy/_integration-tests/testutils/common"
27
28 check "gopkg.in/check.v1"
29)
30
31var _ = check.Suite(&installFrameworkSuite{})
32
33type installFrameworkSuite struct {
34 SnappySuite
35}
36
37func (s *installFrameworkSuite) TearDownTest(c *check.C) {
38 if !NeedsReboot() && CheckRebootMark("") {
39 RemoveSnap(c, "docker")
40 }
41 // run cleanup last
42 s.SnappySuite.TearDownTest(c)
43}
44
45func isDockerServiceRunning(c *check.C) bool {
46 dockerVersion := GetCurrentVersion(c, "docker")
47 dockerService := fmt.Sprintf("docker_docker-daemon_%s.service", dockerVersion)
48
49 err := WaitForActiveService(c, dockerService)
50 c.Assert(err, check.IsNil)
51
52 statusOutput := ExecCommand(
53 c, "systemctl", "status",
54 dockerService)
55
56 expected := "(?ms)" +
57 ".* docker_docker-daemon_.*\\.service .*\n" +
58 ".*Loaded: loaded .*\n" +
59 ".*Active: active \\(running\\) .*\n" +
60 ".*"
61
62 matched, err := regexp.MatchString(expected, statusOutput)
63 c.Assert(err, check.IsNil)
64 return matched
65}
66
67func (s *installFrameworkSuite) TestInstallFrameworkMustPrintPackageInformation(c *check.C) {
68 installOutput := InstallSnap(c, "docker")
69
70 expected := "(?ms)" +
71 "Installing docker\n" +
72 "Name +Date +Version +Developer \n" +
73 ".*" +
74 "^docker +.* +.* +canonical \n" +
75 ".*"
76
77 c.Assert(installOutput, check.Matches, expected)
78}
79
80func (s *installFrameworkSuite) TestInstalledFrameworkServiceMustBeStarted(c *check.C) {
81 InstallSnap(c, "docker")
82 c.Assert(isDockerServiceRunning(c), check.Equals, true)
83}
84
85func (s *installFrameworkSuite) TestFrameworkServiceMustBeStartedAfterReboot(c *check.C) {
86 if BeforeReboot() {
87 InstallSnap(c, "docker")
88 Reboot(c)
89 } else if AfterReboot(c) {
90 RemoveRebootMark(c)
91 c.Assert(isDockerServiceRunning(c), check.Equals, true)
92 }
93}
094
=== added file '_integration-tests/tests/list_test.go'
--- _integration-tests/tests/list_test.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/tests/list_test.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,78 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package tests
21
22import (
23 "fmt"
24 "os"
25
26 . "launchpad.net/snappy/_integration-tests/testutils/common"
27
28 "github.com/mvo5/goconfigparser"
29 check "gopkg.in/check.v1"
30)
31
32var _ = check.Suite(&listSuite{})
33
34type listSuite struct {
35 SnappySuite
36}
37
38func getVersionFromConfig(c *check.C) string {
39 cfg := goconfigparser.New()
40 f, err := os.Open("/etc/system-image/channel.ini")
41 c.Assert(err, check.IsNil,
42 check.Commentf("Error opening the config file: %v:", err))
43 defer f.Close()
44 err = cfg.Read(f)
45 c.Assert(err, check.IsNil,
46 check.Commentf("Error parsing the config file: %v", err))
47 version, err := cfg.Get("service", "build_number")
48 c.Assert(err, check.IsNil,
49 check.Commentf("Error getting the build number: %v", err))
50 return version
51}
52
53func (s *listSuite) TestListMustPrintCoreVersion(c *check.C) {
54 listOutput := ExecCommand(c, "snappy", "list")
55
56 expected := "(?ms)" +
57 "Name +Date +Version +Developer *\n" +
58 ".*" +
59 fmt.Sprintf("^ubuntu-core +.* +%s +ubuntu *\n", getVersionFromConfig(c)) +
60 ".*"
61 c.Assert(listOutput, check.Matches, expected)
62}
63
64func (s *listSuite) TestListMustPrintAppVersion(c *check.C) {
65 InstallSnap(c, "hello-world")
66 s.AddCleanup(func() {
67 RemoveSnap(c, "hello-world")
68 })
69
70 listOutput := ExecCommand(c, "snappy", "list")
71 expected := "(?ms)" +
72 "Name +Date +Version +Developer *\n" +
73 ".*" +
74 "^hello-world +.* +(\\d+)(\\.\\d+)* +.* +.* *\n" +
75 ".*"
76
77 c.Assert(listOutput, check.Matches, expected)
78}
079
=== added file '_integration-tests/tests/rollback_test.go'
--- _integration-tests/tests/rollback_test.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/tests/rollback_test.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,53 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package tests
21
22import (
23 "strconv"
24
25 . "launchpad.net/snappy/_integration-tests/testutils/common"
26
27 check "gopkg.in/check.v1"
28)
29
30var _ = check.Suite(&rollbackSuite{})
31
32type rollbackSuite struct {
33 SnappySuite
34}
35
36func (s *rollbackSuite) TestRollbackMustRebootToOtherVersion(c *check.C) {
37 if BeforeReboot() {
38 CallFakeUpdate(c)
39 Reboot(c)
40 } else if CheckRebootMark(c.TestName()) {
41 RemoveRebootMark(c)
42 currentVersion := GetCurrentUbuntuCoreVersion(c)
43 c.Assert(currentVersion > GetSavedVersion(c), check.Equals, true)
44 ExecCommand(c, "sudo", "snappy", "rollback", "ubuntu-core",
45 strconv.Itoa(GetSavedVersion(c)))
46 SetSavedVersion(c, currentVersion)
47 RebootWithMark(c, c.TestName()+"-rollback")
48 } else if CheckRebootMark(c.TestName() + "-rollback") {
49 RemoveRebootMark(c)
50 c.Assert(
51 GetCurrentUbuntuCoreVersion(c) < GetSavedVersion(c), check.Equals, true)
52 }
53}
054
=== added file '_integration-tests/tests/search_test.go'
--- _integration-tests/tests/search_test.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/tests/search_test.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,44 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package tests
21
22import (
23 . "launchpad.net/snappy/_integration-tests/testutils/common"
24
25 . "gopkg.in/check.v1"
26)
27
28var _ = Suite(&searchSuite{})
29
30type searchSuite struct {
31 SnappySuite
32}
33
34func (s *searchSuite) TestSearchFrameworkMustPrintMatch(c *C) {
35 searchOutput := ExecCommand(c, "snappy", "search", "hello-dbus-fwk")
36
37 expected := "(?ms)" +
38 "Name +Version +Summary *\n" +
39 ".*" +
40 "^hello-dbus-fwk +.* +hello-dbus-fwk *\n" +
41 ".*"
42
43 c.Assert(searchOutput, Matches, expected)
44}
045
=== added file '_integration-tests/tests/update_test.go'
--- _integration-tests/tests/update_test.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/tests/update_test.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,51 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package tests
21
22import (
23 . "launchpad.net/snappy/_integration-tests/testutils/common"
24
25 check "gopkg.in/check.v1"
26)
27
28var _ = check.Suite(&updateSuite{})
29
30type updateSuite struct {
31 SnappySuite
32}
33
34// Test that the update to the same release and channel must install a newer
35// version. If there is no update available, the channel version will be
36// modified to fake an update. If there is a version available, the image will
37// be up-to-date after running this test.
38func (s *updateSuite) TestUpdateToSameReleaseAndChannel(c *check.C) {
39 if BeforeReboot() {
40 updateOutput := CallFakeUpdate(c)
41 expected := "(?ms)" +
42 ".*" +
43 "^Reboot to use .*ubuntu-core.\n"
44 c.Assert(updateOutput, check.Matches, expected)
45 Reboot(c)
46 } else if AfterReboot(c) {
47 RemoveRebootMark(c)
48 c.Assert(GetCurrentUbuntuCoreVersion(c) > GetSavedVersion(c),
49 check.Equals, true)
50 }
51}
052
=== added file '_integration-tests/tests/writablePaths_test.go'
--- _integration-tests/tests/writablePaths_test.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/tests/writablePaths_test.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,106 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package tests
21
22import (
23 "bufio"
24 "fmt"
25 "os"
26 "os/exec"
27 "path/filepath"
28 "strings"
29
30 . "launchpad.net/snappy/_integration-tests/testutils/common"
31
32 check "gopkg.in/check.v1"
33)
34
35const writablePathsListFile = "/etc/system-image/writable-paths"
36
37var _ = check.Suite(&writablePathsSuite{})
38
39type writablePathsSuite struct {
40 SnappySuite
41}
42
43var IsWritable check.Checker = &isWritable{}
44
45type isWritable struct {
46}
47
48func (is *isWritable) Info() *check.CheckerInfo {
49 return &check.CheckerInfo{Name: "IsWritable", Params: []string{"path"}}
50}
51
52func (is *isWritable) Check(params []interface{}, names []string) (result bool, error string) {
53 if path, ok := params[0].(string); ok {
54 filename := filepath.Join(path, "tmpfile")
55
56 cmd := exec.Command("sudo", "touch", filename)
57 rmCmd := exec.Command("sudo", "rm", filename)
58 defer rmCmd.Run()
59
60 if _, err := cmd.CombinedOutput(); err == nil {
61 result = true
62 } else {
63 error = fmt.Sprintf("Error creating file %s", filename)
64 }
65 } else {
66 error = fmt.Sprintf("First param of checker %v is of type %T and it should be a string", params[0], params[0])
67 }
68 return result, error
69}
70
71func (s *writablePathsSuite) TestWritablePathsAreWritable(c *check.C) {
72 for writablePath := range generateWritablePaths(c) {
73 c.Logf("Checking if %s is writable", writablePath)
74 c.Check(writablePath, IsWritable)
75 }
76}
77
78func generateWritablePaths(c *check.C) chan string {
79 ch := make(chan string)
80
81 go func() {
82 file, err := os.Open(writablePathsListFile)
83
84 c.Assert(err, check.IsNil,
85 check.Commentf("Error reading writable files list %s", writablePathsListFile))
86
87 defer file.Close()
88
89 reader := bufio.NewReader(file)
90 scanner := bufio.NewScanner(reader)
91
92 scanner.Split(bufio.ScanLines)
93
94 for scanner.Scan() {
95 fields := strings.Fields(scanner.Text())
96 if len(fields) > 0 && fields[0] != "#" {
97 if src, err := os.Stat(fields[0]); err == nil && src.IsDir() {
98 ch <- fields[0]
99 }
100 }
101 }
102 close(ch)
103 }()
104
105 return ch
106}
0107
=== added directory '_integration-tests/testutils'
=== added directory '_integration-tests/testutils/autopkgtest'
=== added file '_integration-tests/testutils/autopkgtest/autopkgtest.go'
--- _integration-tests/testutils/autopkgtest/autopkgtest.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/testutils/autopkgtest/autopkgtest.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,111 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package autopkgtest
21
22import (
23 "fmt"
24 "os"
25 "path/filepath"
26 "strconv"
27 "text/template"
28
29 "log"
30
31 "launchpad.net/snappy/_integration-tests/testutils"
32)
33
34const (
35 controlTpl = "_integration-tests/data/tpl/control"
36 dataOutputDir = "_integration-tests/data/output/"
37)
38
39var controlFile = filepath.Join(dataOutputDir, "control")
40
41// Autopkgtest is the type that knows how to call adt-run
42type Autopkgtest struct {
43 sourceCodePath string // location of the source code on the host
44 testArtifactsPath string // location of the test artifacts on the host
45 testFilter string
46 integrationTestName string
47}
48
49// NewAutopkgtest is the Autopkgtest constructor
50func NewAutopkgtest(sourceCodePath, testArtifactsPath, testFilter, integrationTestName string) *Autopkgtest {
51 return &Autopkgtest{
52 sourceCodePath: sourceCodePath,
53 testArtifactsPath: testArtifactsPath,
54 testFilter: testFilter,
55 integrationTestName: integrationTestName}
56}
57
58// AdtRunLocal starts a kvm running the image passed as argument and runs the
59// autopkgtests using it as the testbed.
60func (a *Autopkgtest) AdtRunLocal(imgPath string) {
61 // Run the tests on the latest rolling edge image.
62 a.adtRun(kvmSSHOptions(imgPath))
63}
64
65// AdtRunRemote runs the autopkgtests using a remote machine as the testbed.
66func (a *Autopkgtest) AdtRunRemote(testbedIP string, testbedPort int) {
67 testutils.ExecCommand("ssh-copy-id", "-p", strconv.Itoa(testbedPort),
68 "ubuntu@"+testbedIP)
69 a.adtRun(remoteTestbedSSHOptions(testbedIP, testbedPort))
70}
71
72func (a *Autopkgtest) adtRun(testbedOptions []string) {
73 a.createControlFile()
74
75 fmt.Println("Calling adt-run...")
76 outputDir := filepath.Join(a.testArtifactsPath, "output")
77 testutils.PrepareTargetDir(outputDir)
78
79 cmd := []string{
80 "adt-run", "-B",
81 "--setup-commands", "touch /run/autopkgtest_no_reboot.stamp",
82 "--override-control", controlFile,
83 "--built-tree", a.sourceCodePath,
84 "--output-dir", outputDir}
85
86 testutils.ExecCommand(append(cmd, testbedOptions...)...)
87}
88
89func (a *Autopkgtest) createControlFile() {
90 type controlData struct {
91 Filter string
92 Test string
93 }
94
95 tpl, err := template.ParseFiles(controlTpl)
96 if err != nil {
97 log.Panicf("Error reading adt-run control template %s", controlTpl)
98 }
99
100 outputFile, err := os.Create(controlFile)
101 if err != nil {
102 log.Panicf("Error creating control file %s", controlFile)
103 }
104 defer outputFile.Close()
105
106 err = tpl.Execute(outputFile,
107 controlData{Test: a.integrationTestName, Filter: a.testFilter})
108 if err != nil {
109 log.Panicf("execution: %s", err)
110 }
111}
0112
=== added file '_integration-tests/testutils/autopkgtest/ssh.go'
--- _integration-tests/testutils/autopkgtest/ssh.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/testutils/autopkgtest/ssh.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,46 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package autopkgtest
21
22import (
23 "os"
24 "path/filepath"
25 "strconv"
26)
27
28var commonSSHOptions = []string{"---", "ssh"}
29
30func kvmSSHOptions(imagePath string) []string {
31 return append(
32 commonSSHOptions,
33 []string{
34 "-s", "/usr/share/autopkgtest/ssh-setup/snappy",
35 "--", "-i", imagePath}...)
36}
37
38func remoteTestbedSSHOptions(testbedIP string, testbedPort int) []string {
39 options := []string{
40 "-H", testbedIP,
41 "-p", strconv.Itoa(testbedPort),
42 "-l", "ubuntu",
43 "-i", filepath.Join(os.Getenv("HOME"), ".ssh", "id_rsa"),
44 "--reboot"}
45 return append(commonSSHOptions, options...)
46}
047
=== added directory '_integration-tests/testutils/build'
=== added file '_integration-tests/testutils/build/build.go'
--- _integration-tests/testutils/build/build.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/testutils/build/build.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,76 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package build
21
22import (
23 "fmt"
24 "os"
25
26 "launchpad.net/snappy/_integration-tests/testutils"
27)
28
29const (
30 // IntegrationTestName is the name of the test binary.
31 IntegrationTestName = "integration.test"
32 defaultGoArm = "7"
33 testsBinDir = "_integration-tests/bin/"
34)
35
36// Assets builds the snappy and integration tests binaries for the target
37// architecture.
38func Assets(useSnappyFromBranch bool, arch string) {
39 testutils.PrepareTargetDir(testsBinDir)
40
41 if useSnappyFromBranch {
42 // FIXME We need to build an image that has the snappy from the branch
43 // installed. --elopio - 2015-06-25.
44 buildSnappyCLI(arch)
45 }
46 buildTests(arch)
47}
48
49func buildSnappyCLI(arch string) {
50 fmt.Println("Building snappy CLI...")
51 // On the root of the project we have a directory called snappy, so we
52 // output the binary for the tests in the tests directory.
53 goCall(arch, "build", "-o", testsBinDir+"snappy", "./cmd/snappy")
54}
55
56func buildTests(arch string) {
57 fmt.Println("Building tests...")
58
59 goCall(arch, "test", "-c", "./_integration-tests/tests")
60 // XXX Go test 1.3 does not have the output flag, so we move the
61 // binaries after they are generated.
62 os.Rename("tests.test", testsBinDir+IntegrationTestName)
63}
64
65func goCall(arch string, cmds ...string) {
66 if arch != "" {
67 defer os.Setenv("GOARCH", os.Getenv("GOARCH"))
68 os.Setenv("GOARCH", arch)
69 if arch == "arm" {
70 defer os.Setenv("GOARM", os.Getenv("GOARM"))
71 os.Setenv("GOARM", defaultGoArm)
72 }
73 }
74 goCmd := append([]string{"go"}, cmds...)
75 testutils.ExecCommand(goCmd...)
76}
077
=== added directory '_integration-tests/testutils/common'
=== added file '_integration-tests/testutils/common/common.go'
--- _integration-tests/testutils/common/common.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/testutils/common/common.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,379 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package common
21
22import (
23 "fmt"
24 "io/ioutil"
25 "os"
26 "os/exec"
27 "path/filepath"
28 "regexp"
29 "strconv"
30 "strings"
31 "time"
32
33 check "gopkg.in/check.v1"
34
35 "launchpad.net/snappy/_integration-tests/testutils/config"
36)
37
38const (
39 // BaseAltPartitionPath is the path to the B system partition.
40 BaseAltPartitionPath = "/writable/cache/system"
41 needsRebootFile = "/tmp/needs-reboot"
42 channelCfgFile = "/etc/system-image/channel.ini"
43)
44
45// Cfg is a struct that contains the configuration values passed from the
46// host to the testbed.
47var Cfg *config.Config
48
49// SnappySuite is a structure used as a base test suite for all the snappy
50// integration tests.
51type SnappySuite struct {
52 cleanupHandlers []func()
53}
54
55// SetUpSuite disables the snappy autopilot. It will run before all the
56// integration suites.
57func (s *SnappySuite) SetUpSuite(c *check.C) {
58 ExecCommand(c, "sudo", "systemctl", "stop", "snappy-autopilot.timer")
59 ExecCommand(c, "sudo", "systemctl", "disable", "snappy-autopilot.timer")
60 if !isInRebootProcess() {
61 var err error
62 Cfg, err = config.ReadConfig(
63 "_integration-tests/data/output/testconfig.json")
64 c.Assert(err, check.IsNil, check.Commentf("Error reading config: %v", err))
65 if Cfg.Update || Cfg.Rollback {
66 switchSystemImageConf(c, Cfg.TargetRelease, Cfg.TargetChannel, "0")
67 // Always use the installed snappy because we are updating from an old
68 // image, so we should not use the snappy from the branch.
69 output := ExecCommand(c, "sudo", "/usr/bin/snappy", "update")
70 if output != "" {
71 RebootWithMark(c, "setupsuite-update")
72 }
73 }
74 } else if CheckRebootMark("setupsuite-update") {
75 RemoveRebootMark(c)
76 if Cfg.Rollback {
77 ExecCommand(c, "sudo", "snappy", "rollback", "ubuntu-core")
78 RebootWithMark(c, "setupsuite-rollback")
79 }
80 } else if CheckRebootMark("setupsuite-rollback") {
81 RemoveRebootMark(c)
82 }
83}
84
85// SetUpTest handles reboots and stores version information. It will run before
86// all the integration tests. Before running a test, it will save the
87// ubuntu-core version. If a reboot was requested by a previous test, it
88// will skip all the following tests. If the suite is being called after the
89// test bed was rebooted, it will resume the test that requested the reboot.
90func (s *SnappySuite) SetUpTest(c *check.C) {
91 if NeedsReboot() {
92 contents, err := ioutil.ReadFile(needsRebootFile)
93 c.Assert(err, check.IsNil, check.Commentf("Error reading needs-reboot file %v", err))
94 c.Skip(fmt.Sprintf("****** Skipped %s during reboot caused by %s",
95 c.TestName(), contents))
96 } else {
97 if CheckRebootMark("") {
98 c.Logf("****** Running %s", c.TestName())
99 SetSavedVersion(c, GetCurrentUbuntuCoreVersion(c))
100 } else {
101 if AfterReboot(c) {
102 c.Logf("****** Resuming %s after reboot", c.TestName())
103 } else {
104 c.Skip(fmt.Sprintf("****** Skipped %s after reboot caused by %s",
105 c.TestName(), os.Getenv("ADT_REBOOT_MARK")))
106 }
107 }
108 }
109 // clear slice
110 s.cleanupHandlers = nil
111}
112
113// TearDownTest cleans up the channel.ini files in case they were changed by
114// the test.
115// It also runs the cleanup handlers
116func (s *SnappySuite) TearDownTest(c *check.C) {
117 if !NeedsReboot() && CheckRebootMark("") {
118 // Only restore the channel config files if the reboot has been handled.
119 m := make(map[string]string)
120 m[channelCfgBackupFile()] = "/"
121 m[channelCfgOtherBackupFile()] = BaseAltPartitionPath
122 for backup, target := range m {
123 if _, err := os.Stat(backup); err == nil {
124 MakeWritable(c, target)
125 defer MakeReadonly(c, target)
126 original := filepath.Join(target, channelCfgFile)
127 c.Logf("Restoring %s...", original)
128 ExecCommand(c, "sudo", "mv", backup, original)
129 }
130 }
131 }
132
133 // run cleanup handlers and clear the slice
134 for _, f := range s.cleanupHandlers {
135 f()
136 }
137 s.cleanupHandlers = nil
138}
139
140// AddCleanup adds a new cleanup function to the test
141func (s *SnappySuite) AddCleanup(f func()) {
142 s.cleanupHandlers = append(s.cleanupHandlers, f)
143}
144
145func switchSystemImageConf(c *check.C, release, channel, version string) {
146 targets := []string{"/", BaseAltPartitionPath}
147 for _, target := range targets {
148 file := filepath.Join(target, channelCfgFile)
149 if _, err := os.Stat(file); err == nil {
150 MakeWritable(c, target)
151 defer MakeReadonly(c, target)
152 replaceSystemImageValues(c, file, release, channel, version)
153 }
154 }
155}
156
157func replaceSystemImageValues(c *check.C, file, release, channel, version string) {
158 c.Log("Switching the system image conf...")
159 replaceRegex := map[string]string{
160 release: `s#channel: ubuntu-core/.*/\(.*\)#channel: ubuntu-core/%s/\1#`,
161 channel: `s#channel: ubuntu-core/\(.*\)/.*#channel: ubuntu-core/\1/%s#`,
162 version: `s/build_number: .*/build_number: %s/`,
163 }
164 for value, regex := range replaceRegex {
165 if value != "" {
166 ExecCommand(c,
167 "sudo", "sed", "-i", fmt.Sprintf(regex, value), file)
168 }
169 }
170 // Leave the new file in the test log.
171 ExecCommand(c, "cat", file)
172}
173
174func channelCfgBackupFile() string {
175 return filepath.Join(os.Getenv("ADT_ARTIFACTS"), "channel.ini")
176}
177
178func channelCfgOtherBackupFile() string {
179 return filepath.Join(os.Getenv("ADT_ARTIFACTS"), "channel.ini.other")
180}
181
182// ExecCommand executes a shell command and returns a string with the output
183// of the command. In case of error, it will fail the test.
184func ExecCommand(c *check.C, cmds ...string) string {
185 fmt.Println(strings.Join(cmds, " "))
186 cmd := exec.Command(cmds[0], cmds[1:len(cmds)]...)
187 output, err := cmd.CombinedOutput()
188 stringOutput := string(output)
189 fmt.Print(stringOutput)
190 c.Assert(err, check.IsNil, check.Commentf("Error: %v", stringOutput))
191 return stringOutput
192}
193
194// ExecCommandToFile executes a shell command and saves the output of the
195// command to a file. In case of error, it will fail the test.
196func ExecCommandToFile(c *check.C, filename string, cmds ...string) {
197 cmd := exec.Command(cmds[0], cmds[1:len(cmds)]...)
198 outfile, err := os.Create(filename)
199 c.Assert(err, check.IsNil, check.Commentf("Error creating output file %s", filename))
200
201 defer outfile.Close()
202 cmd.Stdout = outfile
203
204 err = cmd.Run()
205 c.Assert(err, check.IsNil, check.Commentf("Error executing command '%v': %v", cmds, err))
206}
207
208// GetCurrentVersion returns the version of the installed and active package.
209func GetCurrentVersion(c *check.C, packageName string) string {
210 output := ExecCommand(c, "snappy", "list")
211 pattern := "(?mU)^" + packageName + " +(.*)$"
212 re := regexp.MustCompile(pattern)
213 match := re.FindStringSubmatch(string(output))
214 c.Assert(match, check.NotNil, check.Commentf("Version not found in %s", output))
215
216 // match is like "ubuntu-core 2015-06-18 93 ubuntu"
217 items := strings.Fields(match[0])
218 return items[2]
219}
220
221// GetCurrentUbuntuCoreVersion returns the version number of the installed and
222// active ubuntu-core.
223func GetCurrentUbuntuCoreVersion(c *check.C) int {
224 versionString := GetCurrentVersion(c, "ubuntu-core")
225 version, err := strconv.Atoi(versionString)
226 c.Assert(err, check.IsNil, check.Commentf("Error converting version to int %v", version))
227 return version
228}
229
230// CallFakeUpdate calls snappy update after faking the current version
231func CallFakeUpdate(c *check.C) string {
232 c.Log("Preparing fake and calling update.")
233 fakeAvailableUpdate(c)
234 return ExecCommand(c, "sudo", "snappy", "update")
235}
236
237func fakeAvailableUpdate(c *check.C) {
238 c.Log("Faking an available update...")
239 currentVersion := GetCurrentUbuntuCoreVersion(c)
240 switchChannelVersionWithBackup(c, currentVersion-1)
241 SetSavedVersion(c, currentVersion-1)
242}
243
244func switchChannelVersionWithBackup(c *check.C, newVersion int) {
245 m := make(map[string]string)
246 m["/"] = channelCfgBackupFile()
247 m[BaseAltPartitionPath] = channelCfgOtherBackupFile()
248 for target, backup := range m {
249 file := filepath.Join(target, channelCfgFile)
250 if _, err := os.Stat(file); err == nil {
251 MakeWritable(c, target)
252 defer MakeReadonly(c, target)
253 // Back up the file. It will be restored during the test tear down.
254 ExecCommand(c, "cp", file, backup)
255 replaceSystemImageValues(c, file, "", "", strconv.Itoa(newVersion))
256 }
257 }
258}
259
260// MakeWritable remounts a path with read and write permissions.
261func MakeWritable(c *check.C, path string) {
262 ExecCommand(c, "sudo", "mount", "-o", "remount,rw", path)
263}
264
265// MakeReadonly remounts a path with only read permissions.
266func MakeReadonly(c *check.C, path string) {
267 ExecCommand(c, "sudo", "mount", "-o", "remount,ro", path)
268}
269
270// Reboot requests a reboot using the test name as the mark.
271func Reboot(c *check.C) {
272 RebootWithMark(c, c.TestName())
273}
274
275// RebootWithMark requests a reboot using a specified mark.
276func RebootWithMark(c *check.C, mark string) {
277 c.Log("Preparing reboot with mark " + mark)
278 err := ioutil.WriteFile(needsRebootFile, []byte(mark), 0777)
279 c.Assert(err, check.IsNil, check.Commentf("Error writing needs-reboot file: %v", err))
280}
281
282// NeedsReboot returns True if a reboot has been requested by a test.
283func NeedsReboot() bool {
284 _, err := os.Stat(needsRebootFile)
285 return err == nil
286}
287
288// BeforeReboot returns True if the test is running before the test bed has
289// been rebooted, or after the test that requested the reboot handled it.
290func BeforeReboot() bool {
291 return CheckRebootMark("")
292}
293
294// AfterReboot returns True if the test is running after the test bed has been
295// rebooted.
296func AfterReboot(c *check.C) bool {
297 // $ADT_REBOOT_MARK contains the reboot mark, if we have rebooted it'll be the test name
298 return strings.HasPrefix(os.Getenv("ADT_REBOOT_MARK"), c.TestName())
299}
300
301// CheckRebootMark returns True if the reboot mark matches the string passed as
302// argument.
303func CheckRebootMark(mark string) bool {
304 return os.Getenv("ADT_REBOOT_MARK") == mark
305}
306
307func isInRebootProcess() bool {
308 return !CheckRebootMark("") || NeedsReboot()
309}
310
311// RemoveRebootMark removes the reboot mark to signal that the reboot has been
312// handled.
313func RemoveRebootMark(c *check.C) {
314 os.Setenv("ADT_REBOOT_MARK", "")
315}
316
317// SetSavedVersion saves a version number into a file so it can be used on
318// tests after reboots.
319func SetSavedVersion(c *check.C, version int) {
320 versionFile := getVersionFile()
321 err := ioutil.WriteFile(versionFile, []byte(strconv.Itoa(version)), 0777)
322 c.Assert(err, check.IsNil, check.Commentf("Error writing version file %s with %s", versionFile, version))
323}
324
325// GetSavedVersion returns the saved version number.
326func GetSavedVersion(c *check.C) int {
327 versionFile := getVersionFile()
328 contents, err := ioutil.ReadFile(versionFile)
329 c.Assert(err, check.IsNil, check.Commentf("Error reading version file %s", versionFile))
330
331 version, err := strconv.Atoi(string(contents))
332 c.Assert(err, check.IsNil, check.Commentf("Error converting version %v", contents))
333
334 return version
335}
336
337func getVersionFile() string {
338 return filepath.Join(os.Getenv("ADT_ARTIFACTS"), "version")
339}
340
341// InstallSnap executes the required command to install the specified snap
342func InstallSnap(c *check.C, packageName string) string {
343 return ExecCommand(c, "sudo", "snappy", "install", packageName, "--allow-unauthenticated")
344}
345
346// RemoveSnap executes the required command to remove the specified snap
347func RemoveSnap(c *check.C, packageName string) string {
348 return ExecCommand(c, "sudo", "snappy", "remove", packageName)
349}
350
351// WaitForActiveService keeps asking for the active state of the given service until
352// it is active or the maximun waiting time expires, in which case an error is returned
353func WaitForActiveService(c *check.C, serviceName string) error {
354 maxWait := time.Second * 10
355 checkInterval := time.Millisecond * 500
356
357 timer := time.NewTimer(maxWait)
358 timeChan := timer.C
359
360 ticker := time.NewTicker(checkInterval)
361 tickChan := ticker.C
362
363 for {
364 select {
365 case <-timeChan:
366 ticker.Stop()
367 journalctlOutput := ExecCommand(c, "sudo", "journalctl", "-u", serviceName)
368 return fmt.Errorf("Service %s not active after %s, journalctl output: %s",
369 serviceName, maxWait, journalctlOutput)
370 case <-tickChan:
371 statusOutput := ExecCommand(
372 c, "systemctl", "show", "-p", "ActiveState", serviceName)
373 if statusOutput == "ActiveState=active\n" {
374 timer.Stop()
375 return nil
376 }
377 }
378 }
379}
0380
=== added file '_integration-tests/testutils/common/common_test.go'
--- _integration-tests/testutils/common/common_test.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/testutils/common/common_test.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,68 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2014-2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package common
21
22import (
23 "testing"
24
25 . "gopkg.in/check.v1"
26)
27
28// Hook up check.v1 into the "go test" runner
29func Test(t *testing.T) { TestingT(t) }
30
31// testing a testsuite - thats so meta
32type MetaTestSuite struct {
33}
34
35var _ = Suite(&MetaTestSuite{})
36
37// test trivial cleanup
38func (m *MetaTestSuite) TestCleanupSimple(c *C) {
39 canary := "not-called"
40 s := SnappySuite{}
41
42 s.AddCleanup(func() {
43 canary = "was-called"
44 })
45 s.TearDownTest(c)
46
47 c.Assert(canary, Equals, "was-called")
48}
49
50// a mock method that takes a parameter
51func mockCleanupMethodWithParameters(s *string) {
52 *s = "was-called"
53}
54
55// test that whle AddCleanup() does not take any parameters itself,
56// functions that need parameters can be passed by creating an
57// anonymous function as a wrapper
58func (m *MetaTestSuite) TestCleanupWithParameters(c *C) {
59 canary := "not-called"
60 s := SnappySuite{}
61
62 s.AddCleanup(func() {
63 mockCleanupMethodWithParameters(&canary)
64 })
65 s.TearDownTest(c)
66
67 c.Assert(canary, Equals, "was-called")
68}
069
=== added directory '_integration-tests/testutils/config'
=== added file '_integration-tests/testutils/config/config.go'
--- _integration-tests/testutils/config/config.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/testutils/config/config.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,75 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package config
21
22import (
23 "encoding/json"
24 "fmt"
25 "io/ioutil"
26 "log"
27)
28
29// Config contains the values to pass to the test bed from the host.
30type Config struct {
31 FileName string
32 Release string
33 Channel string
34 TargetRelease string
35 TargetChannel string
36 RemoteTestbed bool
37 Update bool
38 Rollback bool
39}
40
41// NewConfig is the Config constructor
42func NewConfig(fileName, release, channel, targetRelease, targetChannel string, remoteTestbed, update, rollback bool) *Config {
43 return &Config{
44 FileName: fileName, Release: release, Channel: channel,
45 TargetRelease: targetRelease, TargetChannel: targetChannel,
46 RemoteTestbed: remoteTestbed, Update: update, Rollback: rollback,
47 }
48}
49
50// Write writes the config to a file that will be copied to the test bed.
51func (cfg Config) Write() {
52 fmt.Println("Writing test config...")
53 fmt.Println(cfg)
54 encoded, err := json.Marshal(cfg)
55 if err != nil {
56 log.Panicf("Error encoding the test config: %v", err)
57 }
58 err = ioutil.WriteFile(cfg.FileName, encoded, 0644)
59 if err != nil {
60 log.Panicf("Error writing the test config: %v", err)
61 }
62}
63
64// ReadConfig the config from a file
65func ReadConfig(fileName string) (*Config, error) {
66 b, err := ioutil.ReadFile(fileName)
67 if err != nil {
68 return nil, err
69 }
70 var decoded Config
71 if err = json.Unmarshal(b, &decoded); err != nil {
72 return nil, err
73 }
74 return &decoded, nil
75}
076
=== added file '_integration-tests/testutils/config/config.test'
1Binary files _integration-tests/testutils/config/config.test 1970-01-01 00:00:00 +0000 and _integration-tests/testutils/config/config.test 2015-08-02 12:28:52 +0000 differ77Binary files _integration-tests/testutils/config/config.test 1970-01-01 00:00:00 +0000 and _integration-tests/testutils/config/config.test 2015-08-02 12:28:52 +0000 differ
=== added file '_integration-tests/testutils/config/config_test.go'
--- _integration-tests/testutils/config/config_test.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/testutils/config/config_test.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,121 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2014-2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package config
21
22import (
23 "fmt"
24 "io/ioutil"
25 "os"
26 "path/filepath"
27 "testing"
28
29 check "gopkg.in/check.v1"
30)
31
32// Hook up check.v1 into the "go test" runner
33func Test(t *testing.T) { check.TestingT(t) }
34
35type ConfigSuite struct{}
36
37var _ = check.Suite(&ConfigSuite{})
38
39func testConfigFileName(c *check.C) string {
40 tmpDir, err := ioutil.TempDir("", "")
41 c.Assert(err, check.IsNil, check.Commentf(
42 "Error creating a temporary directory: %v", err))
43 return filepath.Join(tmpDir, "test.config")
44}
45
46func testConfigStruct(fileName string) *Config {
47 return NewConfig(
48 fileName,
49 "testrelease", "testchannel", "testtargetrelease", "testtargetchannel",
50 true, true, true)
51}
52func testConfigContents(fileName string) string {
53 return `{` +
54 fmt.Sprintf(`"FileName":"%s",`, fileName) +
55 `"Release":"testrelease",` +
56 `"Channel":"testchannel",` +
57 `"TargetRelease":"testtargetrelease",` +
58 `"TargetChannel":"testtargetchannel",` +
59 `"RemoteTestbed":true,` +
60 `"Update":true,` +
61 `"Rollback":true` +
62 `}`
63}
64
65func (s *ConfigSuite) TestWriteConfig(c *check.C) {
66 // Do not print to stdout.
67 devnull, err := os.Open(os.DevNull)
68 c.Assert(err, check.IsNil)
69 oldStdout := os.Stdout
70 os.Stdout = devnull
71 defer func() {
72 os.Stdout = oldStdout
73 }()
74 configFileName := testConfigFileName(c)
75
76 cfg := testConfigStruct(configFileName)
77 cfg.Write()
78
79 writtenConfig, err := ioutil.ReadFile(configFileName)
80 c.Assert(err, check.IsNil, check.Commentf("Error reading config: %v", err))
81 c.Assert(string(writtenConfig), check.Equals, testConfigContents(configFileName))
82}
83
84func (s *ConfigSuite) TestReadConfig(c *check.C) {
85 configFileName := testConfigFileName(c)
86
87 configContents := testConfigContents(configFileName)
88 ioutil.WriteFile(configFileName, []byte(configContents), 0644)
89
90 cfg, err := ReadConfig(configFileName)
91
92 c.Assert(err, check.IsNil, check.Commentf("Error reading config: %v", err))
93 c.Assert(cfg, check.DeepEquals, testConfigStruct(configFileName))
94}
95
96func (s *ConfigSuite) TestReadConfigLocalTestBed(c *check.C) {
97 configFileName := testConfigFileName(c)
98
99 configContents := `{` +
100 fmt.Sprintf(`"FileName":"%s",`, configFileName) +
101 `"Release":"testrelease",` +
102 `"Channel":"testchannel",` +
103 `"TargetRelease":"testtargetrelease",` +
104 `"TargetChannel":"testtargetchannel",` +
105 `"RemoteTestbed":false,` +
106 `"Update":true,` +
107 `"Rollback":true` +
108 `}`
109
110 ioutil.WriteFile(configFileName, []byte(configContents), 0644)
111
112 cfg, err := ReadConfig(configFileName)
113
114 testConfigStruct := NewConfig(
115 configFileName,
116 "testrelease", "testchannel", "testtargetrelease", "testtargetchannel",
117 false, true, true)
118
119 c.Assert(err, check.IsNil, check.Commentf("Error reading config: %v", err))
120 c.Assert(cfg, check.DeepEquals, testConfigStruct)
121}
0122
=== added directory '_integration-tests/testutils/image'
=== added file '_integration-tests/testutils/image/image.go'
--- _integration-tests/testutils/image/image.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/testutils/image/image.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,86 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package image
21
22import (
23 "fmt"
24 "path/filepath"
25 "strings"
26
27 "launchpad.net/snappy/_integration-tests/testutils"
28)
29
30// Image type encapsulates image actions
31type Image struct {
32 release string
33 channel string
34 revision string
35 baseDir string
36}
37
38// NewImage is the Image constructor
39func NewImage(release, channel, revision, baseDir string) *Image {
40 return &Image{release: release, channel: channel, revision: revision, baseDir: baseDir}
41}
42
43// UdfCreate forms and executes the UDF command for creating the image
44func (img Image) UdfCreate() (string, error) {
45 fmt.Println("Creating image...")
46
47 imageDir := filepath.Join(img.baseDir, "image")
48
49 testutils.PrepareTargetDir(imageDir)
50
51 udfCommand := []string{"sudo", "ubuntu-device-flash", "--verbose"}
52
53 if img.revision != "" {
54 udfCommand = append(udfCommand, "--revision", img.revision)
55 }
56
57 imagePath := img.imagePath(imageDir)
58
59 coreOptions := []string{
60 "core", img.release,
61 "--output", imagePath,
62 "--channel", img.channel,
63 "--developer-mode",
64 }
65
66 err := testutils.ExecCommand(append(udfCommand, coreOptions...)...)
67
68 return imagePath, err
69}
70
71func (img Image) imagePath(imageDir string) string {
72 revisionTag := img.revision
73 if revisionTag == "" {
74 revisionTag = "latest"
75 }
76
77 imageName := strings.Join(
78 []string{"snappy", img.release, img.channel, revisionTag}, "-") + ".img"
79
80 return filepath.Join(imageDir, imageName)
81}
82
83// SetRevision is the setter method for revision
84func (img Image) SetRevision(rev string) {
85 img.revision = rev
86}
087
=== added file '_integration-tests/testutils/testutils.go'
--- _integration-tests/testutils/testutils.go 1970-01-01 00:00:00 +0000
+++ _integration-tests/testutils/testutils.go 2015-08-02 12:28:52 +0000
@@ -0,0 +1,61 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package testutils
21
22import (
23 "fmt"
24 "log"
25 "os"
26 "os/exec"
27 "strings"
28)
29
30// PrepareTargetDir creates the given target directory, removing it previously if it didn't exist
31func PrepareTargetDir(targetDir string) {
32 if _, err := os.Stat(targetDir); err == nil {
33 // dir exists, remove it
34 os.RemoveAll(targetDir)
35 }
36 os.MkdirAll(targetDir, 0777)
37}
38
39// RootPath return the test current working directory.
40func RootPath() string {
41 dir, err := os.Getwd()
42 if err != nil {
43 log.Panic(err)
44 }
45 return dir
46}
47
48// ExecCommand executes the given command and pipes the results to os.Stdout and os.Stderr, returning the resulting error
49func ExecCommand(cmds ...string) error {
50 fmt.Println(strings.Join(cmds, " "))
51
52 cmd := exec.Command(cmds[0], cmds[1:]...)
53 cmd.Stdout = os.Stdout
54 cmd.Stderr = os.Stderr
55
56 err := cmd.Run()
57 if err != nil {
58 log.Panicf("Error while running %s: %s\n", cmd.Args, err)
59 }
60 return err
61}
062
=== modified file 'run-checks'
--- run-checks 2015-03-27 18:35:24 +0000
+++ run-checks 2015-08-02 12:28:52 +0000
@@ -13,7 +13,7 @@
1313
14if [ -n "$fmt" ]; then14if [ -n "$fmt" ]; then
15 echo "Formatting wrong in following files"15 echo "Formatting wrong in following files"
16 echo $fmt16 echo "$fmt"
17 exit 117 exit 1
18fi18fi
1919
@@ -42,14 +42,30 @@
42# go vet42# go vet
43echo Running vet43echo Running vet
44go vet ./...44go vet ./...
45go vet ./_integration-tests/tests/...
46go vet ./_integration-tests/testutils/...
4547
46# golint48# golint
47echo Running lint49echo Running lint
48lint=$(golint ./...)50lint=$(golint ./... && golint ./_integration-tests/testutils/... && golint ./_integration-tests/tests/...)
49if [ -n "$lint" ]; then51if [ -n "$lint" ]; then
50 echo "Lint complains:"52 echo "Lint complains:"
51 echo $lint53 echo "$lint"
52 exit 154 exit 1
53fi55fi
5456
57# integration tests
58echo Building the integration tests
59go build _integration-tests/main.go
60
61# the rabbit hole
62echo Running the tests for the integration testutils
63$goctest -v -cover ./_integration-tests/testutils/...
64
65# integration suite in kvm
66if which adt-run >/dev/null 2>&1; then
67 echo "Running integration tests on 15.04 edge"
68 go run _integration-tests/main.go --snappy-from-branch --release=15.04
69fi
70
55echo "All good, what could possibly go wrong"71echo "All good, what could possibly go wrong"

Subscribers

People subscribed via source and target branches

to all changes: