0
|
1 |
#
|
|
2 |
# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
|
3 |
# All rights reserved.
|
|
4 |
# This component and the accompanying materials are made available
|
|
5 |
# under the terms of "Eclipse Public License v1.0"
|
|
6 |
# which accompanies this distribution, and is available
|
|
7 |
# at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
|
8 |
#
|
|
9 |
# Initial Contributors:
|
|
10 |
# Nokia Corporation - initial contribution.
|
|
11 |
#
|
|
12 |
# Contributors:
|
|
13 |
#
|
|
14 |
# Description:
|
|
15 |
#
|
|
16 |
|
|
17 |
"""
|
|
18 |
Test the configuration
|
|
19 |
"""
|
|
20 |
import unittest
|
|
21 |
import os
|
|
22 |
import shutil
|
|
23 |
import zipfile
|
|
24 |
import __init__
|
|
25 |
from testautomation.base_testcase import BaseTestCase
|
|
26 |
from testautomation import unzip_file
|
|
27 |
from scripttest_common import get_cmd
|
|
28 |
|
|
29 |
try:
|
|
30 |
from cElementTree import ElementTree
|
|
31 |
except ImportError:
|
|
32 |
try:
|
|
33 |
from elementtree import ElementTree
|
|
34 |
except ImportError:
|
|
35 |
try:
|
|
36 |
from xml.etree import cElementTree as ElementTree
|
|
37 |
except ImportError:
|
|
38 |
from xml.etree import ElementTree
|
|
39 |
|
|
40 |
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
|
|
41 |
TESTDATA_DIR = os.path.join(ROOT_PATH, 'testdata/merge')
|
|
42 |
TEMP_DIR = os.path.join(ROOT_PATH, 'temp/merge')
|
|
43 |
TEST_PROJECT_CPF = os.path.join(ROOT_PATH, 'test_project.cpf')
|
|
44 |
TEST_VARIANT_CPF = os.path.join(ROOT_PATH, 'test_variant.cpf')
|
|
45 |
|
|
46 |
TEST_VARIANT_CPF_V1 = os.path.join(TESTDATA_DIR, 'test_variant_v1.cpf')
|
|
47 |
TEST_VARIANT_CPF_V2 = os.path.join(TESTDATA_DIR, 'test_variant_v2.cpf')
|
|
48 |
|
|
49 |
|
|
50 |
class TestMerge(BaseTestCase):
|
|
51 |
|
|
52 |
def _prepare_workdir_with_project(self, workdir, expected_zip=None):
|
|
53 |
"""
|
|
54 |
Prepare a working directory for running a test.
|
|
55 |
@param workdir: Sub-directory of the workdir.
|
|
56 |
@param expected_zip: Zip file containing expected data that should
|
|
57 |
be extracted under the workdir, can be None. The path should be
|
|
58 |
relative to testdata/merge.
|
|
59 |
@return: Tuple (test_project_abs, expected_dir_abs). expected_dir_abs
|
|
60 |
will be None if expected_zip was None.
|
|
61 |
"""
|
|
62 |
workdir = os.path.join(TEMP_DIR, workdir)
|
|
63 |
self.recreate_dir(workdir)
|
|
64 |
|
|
65 |
# Unzip the test project
|
|
66 |
test_project_dir = os.path.join(workdir, 'test_project')
|
|
67 |
unzip_file.unzip_file(TEST_PROJECT_CPF, test_project_dir, delete_if_exists=True)
|
|
68 |
|
|
69 |
# Check that it was unzipped correctly
|
|
70 |
paths = [
|
|
71 |
"Layer1/", "Layer2/","Layer3/", "Layer4/", "Layer5/",
|
|
72 |
"root1.confml", "root2.confml", "root3.confml", "root4.confml", "root5.confml"
|
|
73 |
]
|
|
74 |
for path in paths:
|
|
75 |
self.assert_exists_and_contains_something(os.path.join(test_project_dir, path))
|
|
76 |
|
|
77 |
expected_dir = None
|
|
78 |
# Unzip the expected data
|
|
79 |
if expected_zip:
|
|
80 |
expected_zip = os.path.join(TESTDATA_DIR, expected_zip)
|
|
81 |
expected_dir = os.path.join(workdir, 'expected')
|
|
82 |
unzip_file.unzip_file(expected_zip, expected_dir)
|
|
83 |
|
|
84 |
return test_project_dir, expected_dir
|
|
85 |
|
|
86 |
def test_get_help(self):
|
|
87 |
cmd = '%s -h' % get_cmd('merge')
|
|
88 |
out = self.run_command(cmd)
|
|
89 |
lines = out.split('\r\n')
|
|
90 |
self.assertTrue('Options:' in lines)
|
|
91 |
self.assertTrue(' Merge options:' in lines)
|
|
92 |
|
|
93 |
def test_merge_cpf_last_layer_to_project(self):
|
|
94 |
project_dir, expected_dir = self._prepare_workdir_with_project('last_layer_from_cpf', 'last_layer_expected.zip')
|
|
95 |
|
|
96 |
self.set_modification_reference_time(project_dir)
|
|
97 |
self.set_modification_reference_time(TEST_VARIANT_CPF)
|
|
98 |
cmd = '%s -p "%s" -r "%s" -c root5.confml -l -1 -v 5' % (get_cmd('merge'), project_dir, TEST_VARIANT_CPF)
|
|
99 |
self.run_command(cmd)
|
|
100 |
|
|
101 |
self.assert_modified(project_dir)
|
|
102 |
self.assert_not_modified(TEST_VARIANT_CPF)
|
|
103 |
self.assert_dir_contents_equal(expected_dir, project_dir)
|
|
104 |
|
|
105 |
def test_merge_cpf_last_layer_to_project_with_rename(self):
|
|
106 |
project_dir, expected_dir = self._prepare_workdir_with_project('last_layer_from_cpf_rename', 'last_layer_rename_expected.zip')
|
|
107 |
|
|
108 |
self.set_modification_reference_time(project_dir)
|
|
109 |
self.set_modification_reference_time(TEST_VARIANT_CPF)
|
|
110 |
cmd = '%s -p "%s" -r "%s" -c root5.confml -l -1 -v 5 --rename' % (get_cmd('merge'), project_dir, TEST_VARIANT_CPF)
|
|
111 |
self.run_command(cmd)
|
|
112 |
|
|
113 |
self.assert_modified(project_dir)
|
|
114 |
self.assert_not_modified(TEST_VARIANT_CPF)
|
|
115 |
self.assert_dir_contents_equal(expected_dir, project_dir)
|
|
116 |
|
|
117 |
def test_merge_cpf_multiple_last_layers_to_project(self):
|
|
118 |
project_dir, expected_dir = self._prepare_workdir_with_project('multiple_last_layers_from_cpf', 'multiple_last_layers_expected.zip')
|
|
119 |
|
|
120 |
self.set_modification_reference_time(project_dir)
|
|
121 |
self.set_modification_reference_time(TEST_VARIANT_CPF)
|
|
122 |
# Pass the merged layers in random order to check that it doesn't affect
|
|
123 |
# the output
|
|
124 |
cmd = '%s -p "%s" -r "%s" -c root5.confml -l -3 -l -1 -l -2 -v 5' % (get_cmd('merge'), project_dir, TEST_VARIANT_CPF)
|
|
125 |
self.run_command(cmd)
|
|
126 |
|
|
127 |
self.assert_modified(project_dir)
|
|
128 |
self.assert_not_modified(TEST_VARIANT_CPF)
|
|
129 |
self.assert_dir_contents_equal(expected_dir, project_dir)
|
|
130 |
|
|
131 |
def test_merge_cpf_multiple_mixed_layers_to_project(self):
|
|
132 |
project_dir, expected_dir = self._prepare_workdir_with_project('mixed_multiple_last_layers_from_cpf', 'multiple_last_layers_expected.zip')
|
|
133 |
|
|
134 |
self.set_modification_reference_time(project_dir)
|
|
135 |
self.set_modification_reference_time(TEST_VARIANT_CPF)
|
|
136 |
cmd = '%s -p "%s" -r "%s" -c root5.confml -l -3 -l -1 -l 4 -l 5 -v 5' % (get_cmd('merge'), project_dir, TEST_VARIANT_CPF)
|
|
137 |
self.run_command(cmd)
|
|
138 |
|
|
139 |
self.assert_modified(project_dir)
|
|
140 |
self.assert_not_modified(TEST_VARIANT_CPF)
|
|
141 |
self.assert_dir_contents_equal(expected_dir, project_dir)
|
|
142 |
|
|
143 |
def test_merge_layer_to_cpf(self):
|
|
144 |
project_cpf = os.path.join(ROOT_PATH, "temp/merge/layer_to_cpf/project.cpf")
|
|
145 |
self.create_dir_for_file_path(project_cpf)
|
|
146 |
shutil.copy2(TEST_PROJECT_CPF, project_cpf)
|
|
147 |
|
|
148 |
self.set_modification_reference_time(project_cpf)
|
|
149 |
self.set_modification_reference_time(TEST_VARIANT_CPF)
|
|
150 |
|
|
151 |
cmd = '%s -p "%s" -r "%s" -c root5.confml -l -1 -v 5' % (get_cmd('merge'), project_cpf, TEST_VARIANT_CPF)
|
|
152 |
self.run_command(cmd)
|
|
153 |
|
|
154 |
def check(entry):
|
|
155 |
zf = zipfile.ZipFile(project_cpf, "r")
|
|
156 |
try: self.assertTrue(entry in zf.namelist(), "Entry '%s' not in zip file '%s'" % (entry, project_cpf))
|
|
157 |
finally: zf.close()
|
|
158 |
check('variant/root.confml')
|
|
159 |
check('variant/confml/data.confml')
|
|
160 |
check('variant/content/empty/')
|
|
161 |
|
|
162 |
self.assertEquals(
|
|
163 |
self.get_xinclude_list(self.read_data_from_zip_file(project_cpf, "root5.confml")),
|
|
164 |
["Layer1/root.confml",
|
|
165 |
"Layer2/root.confml",
|
|
166 |
"Layer3/root.confml",
|
|
167 |
"Layer4/root.confml",
|
|
168 |
"Layer5/root.confml",
|
|
169 |
"variant/root.confml"])
|
|
170 |
|
|
171 |
self.assert_modified(project_cpf)
|
|
172 |
self.assert_not_modified(TEST_VARIANT_CPF)
|
|
173 |
|
|
174 |
def test_merge_cpf_last_layer_two_versions(self):
|
|
175 |
project_dir, expected_dir = self._prepare_workdir_with_project('last_layer_two_versions', 'last_layer_variant_v1_v2_expected.zip')
|
|
176 |
cmd = '%s -p "%s" -r "%s" -c root5.confml -l -1' % (get_cmd('merge'), project_dir, TEST_VARIANT_CPF_V1)
|
|
177 |
self.run_command(cmd)
|
|
178 |
cmd = '%s -p "%s" -r "%s" -c root5.confml -l -1' % (get_cmd('merge'), project_dir, TEST_VARIANT_CPF_V2)
|
|
179 |
self.run_command(cmd)
|
|
180 |
self.assert_dir_contents_equal(expected_dir, project_dir)
|
|
181 |
|
|
182 |
def test_merge_cpf_last_layer_two_versions_overwrite_layer(self):
|
|
183 |
project_dir, expected_dir = self._prepare_workdir_with_project('last_layer_two_versions_overwrite', 'last_layer_variant_v2_expected.zip')
|
|
184 |
cmd = '%s -p "%s" -r "%s" -c root5.confml -l -1 --merge-policy overwrite-layer' % (get_cmd('merge'), project_dir, TEST_VARIANT_CPF_V1)
|
|
185 |
self.run_command(cmd)
|
|
186 |
cmd = '%s -p "%s" -r "%s" -c root5.confml -l -1 --merge-policy overwrite-layer' % (get_cmd('merge'), project_dir, TEST_VARIANT_CPF_V2)
|
|
187 |
self.run_command(cmd)
|
|
188 |
self.assert_dir_contents_equal(expected_dir, project_dir)
|
|
189 |
|
|
190 |
def get_xinclude_list(self, confml_file_data):
|
|
191 |
"""
|
|
192 |
Read the XInlude element list from a ConfML file and assert that.
|
|
193 |
@param confml_file_data: The raw binary data of the ConfML file.
|
|
194 |
"""
|
|
195 |
root_elem = ElementTree.fromstring(confml_file_data)
|
|
196 |
|
|
197 |
# Make sure that we have a ConfML file
|
|
198 |
self.assertTrue(
|
|
199 |
root_elem.tag in ("{http://www.s60.com/xml/confml/1}configuration", "{http://www.s60.com/xml/confml/2}configuration"),
|
|
200 |
"The root element is not a ConfML configuration element (tag is '%s')" % root_elem.tag)
|
|
201 |
|
|
202 |
# Read the xi:include list
|
|
203 |
result = []
|
|
204 |
for elem in root_elem.findall("{http://www.w3.org/2001/XInclude}include"):
|
|
205 |
result.append(elem.get("href"))
|
|
206 |
|
|
207 |
return result
|
|
208 |
|
|
209 |
# =============================================================================
|
|
210 |
|
|
211 |
def run_in_workdir(workdir):
|
|
212 |
"""
|
|
213 |
Decorator for running asset merge tests in a specific working directory.
|
|
214 |
"""
|
|
215 |
workdir_abs = os.path.join(ROOT_PATH, 'temp/merge/assetmerge', workdir)
|
|
216 |
|
|
217 |
def decorate(testmethod):
|
|
218 |
def run_test(self):
|
|
219 |
assert isinstance(self, TestAssetMerge)
|
|
220 |
|
|
221 |
# Prepare the working directory
|
|
222 |
workdir = self.prepare_workdir(workdir_abs)
|
|
223 |
|
|
224 |
# Go into the working directory to run the test
|
|
225 |
orig_workdir = os.getcwd()
|
|
226 |
os.chdir(workdir)
|
|
227 |
try:
|
|
228 |
# Run the test
|
|
229 |
testmethod(self)
|
|
230 |
finally:
|
|
231 |
# Revert back to the original working directory
|
|
232 |
os.chdir(orig_workdir)
|
|
233 |
return run_test
|
|
234 |
|
|
235 |
return decorate
|
|
236 |
|
|
237 |
class TestAssetMerge(BaseTestCase):
|
|
238 |
"""
|
|
239 |
Tests for merging an asset (basically a single configuration layer) into
|
|
240 |
a specific layer in an existing project.
|
|
241 |
"""
|
|
242 |
TESTDATA_ZIP = os.path.join(ROOT_PATH, 'testdata/merge/assetmerge/data.zip')
|
|
243 |
EXPECTED_ZIP = os.path.join(ROOT_PATH, 'testdata/merge/assetmerge/expected.zip')
|
|
244 |
|
|
245 |
def prepare_workdir(self, workdir):
|
|
246 |
"""
|
|
247 |
Prepare a working directory with all needed test data into
|
|
248 |
the given sub-dir under the temporary directory.
|
|
249 |
@param workdir: Absolute path to the working directory.
|
|
250 |
"""
|
|
251 |
assert os.path.isabs(workdir)
|
|
252 |
|
|
253 |
# Remove the working directory
|
|
254 |
self.remove_if_exists(workdir)
|
|
255 |
|
|
256 |
# Extract asset merge test data into the working dir
|
|
257 |
unzip_file.unzip_file(self.TESTDATA_ZIP, workdir)
|
|
258 |
|
|
259 |
# Extract expected data
|
|
260 |
unzip_file.unzip_file(self.EXPECTED_ZIP, os.path.join(workdir, 'expected'))
|
|
261 |
|
|
262 |
return workdir
|
|
263 |
|
|
264 |
def assert_is_expected(self, subdir):
|
|
265 |
"""
|
|
266 |
Assert that the current main_project is equal to the expected data.
|
|
267 |
"""
|
|
268 |
current_dir = os.path.abspath('main_project')
|
|
269 |
expected_dir = os.path.abspath(os.path.join('expected', subdir))
|
|
270 |
self.assert_exists_and_contains_something(expected_dir)
|
|
271 |
self.assert_dir_contents_equal(current_dir, expected_dir, ['.svn', '.metadata'])
|
|
272 |
|
|
273 |
@run_in_workdir('merge_asset1')
|
|
274 |
def test_merge_asset1(self):
|
|
275 |
self.run_command('%s -p main_project --targetlayer assets/test/root.confml -r asset1_v1 --sourcelayer root.confml' % get_cmd('merge'))
|
|
276 |
self.assert_is_expected('asset1_merged')
|
|
277 |
|
|
278 |
@run_in_workdir('merge_and_update_asset1')
|
|
279 |
def test_merge_and_update_asset1(self):
|
|
280 |
self.run_command('%s -p main_project --targetlayer assets/test/root.confml -r asset1_v1 --sourcelayer root.confml' % get_cmd('merge'))
|
|
281 |
self.assert_is_expected('asset1_merged')
|
|
282 |
self.run_command('%s -p main_project --targetlayer assets/test/root.confml -r asset1_v2 --sourcelayer root.confml' % get_cmd('merge'))
|
|
283 |
self.assert_is_expected('asset1_merged_and_updated')
|
|
284 |
|
|
285 |
@run_in_workdir('merge_both')
|
|
286 |
def test_merge_both(self):
|
|
287 |
self.run_command('%s -p main_project --targetlayer assets/test/root.confml -r asset1_v1 --sourcelayer root.confml' % get_cmd('merge'))
|
|
288 |
self.run_command('%s -p main_project --targetlayer assets/test/root.confml -r asset2_v1 --sourcelayer root.confml' % get_cmd('merge'))
|
|
289 |
self.assert_is_expected('both_merged')
|
|
290 |
|
|
291 |
@run_in_workdir('merge_both_and_update')
|
|
292 |
def test_merge_both_and_update(self):
|
|
293 |
|
|
294 |
self.run_command('%s -p main_project --targetlayer assets/test/root.confml -r asset1_v1 --sourcelayer root.confml' % get_cmd('merge'))
|
|
295 |
self.run_command('%s -p main_project --targetlayer assets/test/root.confml -r asset2_v1 --sourcelayer root.confml' % get_cmd('merge'))
|
|
296 |
self.assert_is_expected('both_merged')
|
|
297 |
|
|
298 |
self.run_command('%s -p main_project --targetlayer assets/test/root.confml -r asset1_v2 --sourcelayer root.confml' % get_cmd('merge'))
|
|
299 |
self.run_command('%s -p main_project --targetlayer assets/test/root.confml -r asset2_v2 --sourcelayer root.confml' % get_cmd('merge'))
|
|
300 |
self.assert_is_expected('both_merged_and_updated')
|
|
301 |
|
|
302 |
class TestMergeInvalidParameters(BaseTestCase):
|
|
303 |
|
|
304 |
def _run_test(self, args, expected_msg):
|
|
305 |
if not isinstance(args, basestring):
|
|
306 |
args = ' '.join(args)
|
|
307 |
|
|
308 |
cmd = get_cmd('merge') + ' ' + args
|
|
309 |
# Note: The following run_command() should really expect the
|
|
310 |
# return code 2, but for some reason when running from the
|
|
311 |
# standalone test set, the return value is 0 for some cases
|
|
312 |
# (specifically, the ones that don't use parser.error() to
|
|
313 |
# exit the program)
|
|
314 |
out = self.run_command(cmd, expected_return_code = None)
|
|
315 |
|
|
316 |
self.assertTrue(expected_msg in out,
|
|
317 |
"Expected message '%s' not in output ('%s')" % (expected_msg, out))
|
|
318 |
|
|
319 |
def test_no_remote(self):
|
|
320 |
self._run_test('', "Remote project must be given")
|
|
321 |
|
|
322 |
def test_source_root_and_target_layer(self):
|
|
323 |
self._run_test(
|
|
324 |
"-p x --targetlayer t.confml -r y --sourceconfiguration s.confml",
|
|
325 |
"Cannot merge a configuration into a layer!")
|
|
326 |
|
|
327 |
def test_source_layer_and_target_root(self):
|
|
328 |
self._run_test(
|
|
329 |
"-p x --configuration t.confml -r y --sourcelayer s.confml",
|
|
330 |
"Merging a layer into a configuration is not supported at the moment!")
|
|
331 |
|
|
332 |
def test_source_layer_and_layer_indices(self):
|
|
333 |
self._run_test(
|
|
334 |
["-p x --configuration t.confml",
|
|
335 |
"-r y --sourcelayer s.confml",
|
|
336 |
"--layer -1 --layer -2"],
|
|
337 |
"Specifying layer indices using --layer is not supported when using --sourcelayer or --targetlayer!")
|
|
338 |
|
|
339 |
def test_target_layer_and_layer_indices(self):
|
|
340 |
self._run_test(
|
|
341 |
["-p x --targetlayer t.confml",
|
|
342 |
"-r y --sourceconfiguration s.confml",
|
|
343 |
"--layer -1 --layer -2"],
|
|
344 |
"Specifying layer indices using --layer is not supported when using --sourcelayer or --targetlayer!")
|
|
345 |
|
|
346 |
def test_invalid_source_layer(self):
|
|
347 |
source_dir = os.path.join(TEMP_DIR, 'invalid_source_layer/source_proj')
|
|
348 |
target_dir = os.path.join(TEMP_DIR, 'invalid_source_layer/target_proj')
|
|
349 |
self.recreate_dir(source_dir)
|
|
350 |
self.recreate_dir(target_dir)
|
|
351 |
self._run_test('-p "%s" --targetlayer foo/root.confml -r "%s" --sourcelayer foo/bar/root.confml' % (source_dir, target_dir),
|
|
352 |
"Could not merge: Layer root 'foo/bar/root.confml' not found in source project")
|
|
353 |
|
|
354 |
def test_invalid_source_config(self):
|
|
355 |
source_dir = os.path.join(TEMP_DIR, 'invalid_source_root/source_proj')
|
|
356 |
target_dir = os.path.join(TEMP_DIR, 'invalid_source_root/target_proj')
|
|
357 |
self.recreate_dir(source_dir)
|
|
358 |
self.recreate_dir(target_dir)
|
|
359 |
self._run_test('-p "%s" -c foo_root.confml -r "%s" --sourceconfiguration foobar_root.confml' % (source_dir, target_dir),
|
|
360 |
"Could not merge: Configuration root 'foobar_root.confml' not found in source project")
|
|
361 |
|
|
362 |
def test_invalid_merge_policy(self):
|
|
363 |
self._run_test('-p x -r y --merge-policy foopolicy',
|
|
364 |
"Invalid merge policy: foopolicy")
|
|
365 |
|
|
366 |
def test_invalid_source_layer_root(self):
|
|
367 |
self._run_test('-p x -r y --sourcelayer foobar --targetlayer test/foo.confml',
|
|
368 |
"Source layer root should be a .confml file")
|
|
369 |
|
|
370 |
def test_invalid_target_layer_root(self):
|
|
371 |
self._run_test('-p x -r y --sourcelayer test/foo.confml --targetlayer foobar',
|
|
372 |
"Target layer root should be a .confml file")
|
|
373 |
|
|
374 |
if __name__ == '__main__':
|
|
375 |
unittest.main()
|