Merge lp:~harlowja/cloud-init/stage-base-test into lp:~cloud-init-dev/cloud-init/trunk

Proposed by Joshua Harlow
Status: Merged
Merged at revision: 695
Proposed branch: lp:~harlowja/cloud-init/stage-base-test
Merge into: lp:~cloud-init-dev/cloud-init/trunk
Diff against target: 252 lines (+204/-3)
4 files modified
tests/data/roots/simple_ubuntu/etc/networks/interfaces (+3/-0)
tests/unittests/helpers.py (+103/-0)
tests/unittests/test_filters/test_launch_index.py (+11/-3)
tests/unittests/test_runs/test_simple_run.py (+87/-0)
To merge this branch: bzr merge lp:~harlowja/cloud-init/stage-base-test
Reviewer Review Type Date Requested Status
cloud-init Commiters Pending
Review via email: mp+126572@code.launchpad.net

Description of the change

Adds a new awesome test pattern + test.

To post a comment you must log in.
672. By Joshua Harlow

Adjust comment.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added directory 'tests/data/roots'
=== added directory 'tests/data/roots/simple_ubuntu'
=== added directory 'tests/data/roots/simple_ubuntu/etc'
=== added directory 'tests/data/roots/simple_ubuntu/etc/networks'
=== added file 'tests/data/roots/simple_ubuntu/etc/networks/interfaces'
--- tests/data/roots/simple_ubuntu/etc/networks/interfaces 1970-01-01 00:00:00 +0000
+++ tests/data/roots/simple_ubuntu/etc/networks/interfaces 2012-09-26 23:45:24 +0000
@@ -0,0 +1,3 @@
1auto lo
2iface lo inet loopback
3
04
=== modified file 'tests/unittests/helpers.py'
--- tests/unittests/helpers.py 2012-09-01 01:28:12 +0000
+++ tests/unittests/helpers.py 2012-09-26 23:45:24 +0000
@@ -3,6 +3,37 @@
3from mocker import MockerTestCase3from mocker import MockerTestCase
44
5from cloudinit import helpers as ch5from cloudinit import helpers as ch
6from cloudinit import util
7
8import shutil
9
10# Makes the old path start
11# with new base instead of whatever
12# it previously had
13def rebase_path(old_path, new_base):
14 if old_path.startswith(new_base):
15 # Already handled...
16 return old_path
17 # Retarget the base of that path
18 # to the new base instead of the
19 # old one...
20 path = os.path.join(new_base, old_path.lstrip("/"))
21 path = os.path.abspath(path)
22 return path
23
24
25# Can work on anything that takes a path as arguments
26def retarget_many_wrapper(new_base, am, old_func):
27 def wrapper(*args, **kwds):
28 n_args = list(args)
29 nam = am
30 if am == -1:
31 nam = len(n_args)
32 for i in range(0, nam):
33 path = args[i]
34 n_args[i] = rebase_path(path, new_base)
35 return old_func(*n_args, **kwds)
36 return wrapper
637
738
8class ResourceUsingTestCase(MockerTestCase):39class ResourceUsingTestCase(MockerTestCase):
@@ -40,3 +71,75 @@
40 'templates_dir': self.resourceLocation(),71 'templates_dir': self.resourceLocation(),
41 })72 })
42 return cp73 return cp
74
75
76class FilesystemMockingTestCase(ResourceUsingTestCase):
77 def __init__(self, methodName="runTest"):
78 ResourceUsingTestCase.__init__(self, methodName)
79 self.patched_funcs = []
80
81 def replicateTestRoot(self, example_root, target_root):
82 real_root = self.resourceLocation()
83 real_root = os.path.join(real_root, 'roots', example_root)
84 for (dir_path, _dirnames, filenames) in os.walk(real_root):
85 real_path = dir_path
86 make_path = rebase_path(real_path[len(real_root):], target_root)
87 util.ensure_dir(make_path)
88 for f in filenames:
89 real_path = util.abs_join(real_path, f)
90 make_path = util.abs_join(make_path, f)
91 shutil.copy(real_path, make_path)
92
93 def tearDown(self):
94 self.restore()
95 ResourceUsingTestCase.tearDown(self)
96
97 def restore(self):
98 for (mod, f, func) in self.patched_funcs:
99 setattr(mod, f, func)
100 self.patched_funcs = []
101
102 def patchUtils(self, new_root):
103 patch_funcs = {
104 util: [('write_file', 1),
105 ('load_file', 1),
106 ('ensure_dir', 1),
107 ('chmod', 1),
108 ('delete_dir_contents', 1),
109 ('del_file', 1),
110 ('sym_link', -1)],
111 }
112 for (mod, funcs) in patch_funcs.items():
113 for (f, am) in funcs:
114 func = getattr(mod, f)
115 trap_func = retarget_many_wrapper(new_root, am, func)
116 setattr(mod, f, trap_func)
117 self.patched_funcs.append((mod, f, func))
118
119 # Handle subprocess calls
120 func = getattr(util, 'subp')
121
122 def nsubp(*_args, **_kwargs):
123 return ('', '')
124
125 setattr(util, 'subp', nsubp)
126 self.patched_funcs.append((util, 'subp', func))
127
128 def null_func(*_args, **_kwargs):
129 return None
130
131 for f in ['chownbyid', 'chownbyname']:
132 func = getattr(util, f)
133 setattr(util, f, null_func)
134 self.patched_funcs.append((util, f, func))
135
136 def patchOS(self, new_root):
137 patch_funcs = {
138 os.path: ['isfile', 'exists', 'islink', 'isdir'],
139 }
140 for (mod, funcs) in patch_funcs.items():
141 for f in funcs:
142 func = getattr(mod, f)
143 trap_func = retarget_many_wrapper(new_root, 1, func)
144 setattr(mod, f, trap_func)
145 self.patched_funcs.append((mod, f, func))
43146
=== modified file 'tests/unittests/test_filters/test_launch_index.py'
--- tests/unittests/test_filters/test_launch_index.py 2012-09-02 00:00:34 +0000
+++ tests/unittests/test_filters/test_launch_index.py 2012-09-26 23:45:24 +0000
@@ -1,6 +1,14 @@
1import copy1import copy
22import os
3import helpers as th3import sys
4
5top_dir = os.path.join(os.path.dirname(__file__), os.pardir, "helpers.py")
6top_dir = os.path.abspath(top_dir)
7if os.path.exists(top_dir):
8 sys.path.insert(0, os.path.dirname(top_dir))
9
10
11import helpers
412
5import itertools13import itertools
614
@@ -18,7 +26,7 @@
18 return am26 return am
1927
2028
21class TestLaunchFilter(th.ResourceUsingTestCase):29class TestLaunchFilter(helpers.ResourceUsingTestCase):
2230
23 def assertCounts(self, message, expected_counts):31 def assertCounts(self, message, expected_counts):
24 orig_message = copy.deepcopy(message)32 orig_message = copy.deepcopy(message)
2533
=== added directory 'tests/unittests/test_runs'
=== added file 'tests/unittests/test_runs/test_simple_run.py'
--- tests/unittests/test_runs/test_simple_run.py 1970-01-01 00:00:00 +0000
+++ tests/unittests/test_runs/test_simple_run.py 2012-09-26 23:45:24 +0000
@@ -0,0 +1,87 @@
1import sys
2import os
3
4# Allow running this test individually
5top_dir = os.path.join(os.path.dirname(__file__), os.pardir, "helpers.py")
6top_dir = os.path.abspath(top_dir)
7if os.path.exists(top_dir):
8 sys.path.insert(0, os.path.dirname(top_dir))
9
10
11import helpers
12
13from cloudinit import util
14from cloudinit import stages
15
16from cloudinit.settings import (PER_INSTANCE)
17
18
19class TestSimpleRun(helpers.FilesystemMockingTestCase):
20 def _patchIn(self, root):
21 self.restore()
22 self.patchOS(root)
23 self.patchUtils(root)
24
25 def _pp_root(self, root, repatch=True):
26 self.restore()
27 for (dirpath, dirnames, filenames) in os.walk(root):
28 print(dirpath)
29 for f in filenames:
30 joined = os.path.join(dirpath, f)
31 if os.path.islink(joined):
32 print("f %s - (symlink)" % (f))
33 else:
34 print("f %s" % (f))
35 for d in dirnames:
36 joined = os.path.join(dirpath, d)
37 if os.path.islink(joined):
38 print("d %s - (symlink)" % (d))
39 else:
40 print("d %s" % (d))
41 if repatch:
42 self._patchIn(root)
43
44 def test_none_ds(self):
45 new_root = self.makeDir()
46 self.replicateTestRoot('simple_ubuntu', new_root)
47 cfg = {
48 'datasource_list': ['None'],
49 'write_files': [{
50 'path': '/etc/blah.ini',
51 'content': 'blah',
52 'permissions': 0755,
53 }],
54 'cloud_init_modules': ['write-files'],
55 }
56 cloud_cfg = util.yaml_dumps(cfg)
57 util.ensure_dir(os.path.join(new_root, 'etc', 'cloud'))
58 util.write_file(os.path.join(new_root, 'etc',
59 'cloud', 'cloud.cfg'), cloud_cfg)
60 self._patchIn(new_root)
61
62 # Now start verifying whats created
63 initer = stages.Init()
64 initer.read_cfg()
65 initer.initialize()
66 self.assertTrue(os.path.exists("/var/lib/cloud"))
67 for d in ['scripts', 'seed', 'instances', 'handlers', 'sem', 'data']:
68 self.assertTrue(os.path.isdir(os.path.join("/var/lib/cloud", d)))
69
70 initer.fetch()
71 iid = initer.instancify()
72 self.assertEquals(iid, 'iid-datasource-none')
73 initer.update()
74 self.assertTrue(os.path.islink("var/lib/cloud/instance"))
75
76 initer.cloudify().run('consume_userdata',
77 initer.consume_userdata,
78 args=[PER_INSTANCE],
79 freq=PER_INSTANCE)
80
81 mods = stages.Modules(initer)
82 (which_ran, failures) = mods.run_section('cloud_init_modules')
83 self.assertTrue(len(failures) == 0)
84 self.assertTrue(os.path.exists('/etc/blah.ini'))
85 self.assertIn('write-files', which_ran)
86 contents = util.load_file('/etc/blah.ini')
87 self.assertEquals(contents, 'blah')