summaryrefslogtreecommitdiffstats
path: root/meta/lib/oeqa
diff options
context:
space:
mode:
authorMariano Lopez <mariano.lopez@linux.intel.com>2017-02-21 14:33:07 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2017-05-27 00:21:04 +0100
commit48a8c893ade7bb2dd1319b9c00095a86fa100ca4 (patch)
tree8663597865706d661fde1142456b0079f4e4439e /meta/lib/oeqa
parent078915fbf5180ebb76891737c73cdc3b20a2bfca (diff)
downloadpoky-48a8c893ade7bb2dd1319b9c00095a86fa100ca4.tar.gz
selftest: Avoid sstate corruption by calling cleansstate
Currently selftest doesn't use sstates because some tests clean sstate cache; using sstates would give a performance boost instead of building everything from scratch. With this sstates are not corrupted using different methods depending on tests: devtool: These tests needed to delete the cache so SSTATE_DIR as SSTATE_MIRRORS and set a temporal SSTATE_DIR. sstatetests: This module already used a temporal SSTATE_DIR, so just set up the SSTATE_MIRRORS. Rest: Removed cleansstate, some of them required to force a certain task, others were just removed or changed for another task. [YOCTO #10929] (From OE-Core rev: 62c61087a10cc3b26fbff32c9e2efd1704a39724) (From OE-Core rev: 44ca8b1c23e4b2cf470e9be42705e3cca23b7f85) Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com> Signed-off-by: Ross Burton <ross.burton@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/lib/oeqa')
-rw-r--r--meta/lib/oeqa/selftest/bbtests.py6
-rw-r--r--meta/lib/oeqa/selftest/buildoptions.py18
-rw-r--r--meta/lib/oeqa/selftest/devtool.py18
-rw-r--r--meta/lib/oeqa/selftest/oescripts.py8
-rw-r--r--meta/lib/oeqa/selftest/prservice.py3
-rw-r--r--meta/lib/oeqa/selftest/recipetool.py5
-rw-r--r--meta/lib/oeqa/selftest/signing.py8
-rw-r--r--meta/lib/oeqa/selftest/sstatetests.py6
8 files changed, 36 insertions, 36 deletions
diff --git a/meta/lib/oeqa/selftest/bbtests.py b/meta/lib/oeqa/selftest/bbtests.py
index c9802a416b..4ce935fc1d 100644
--- a/meta/lib/oeqa/selftest/bbtests.py
+++ b/meta/lib/oeqa/selftest/bbtests.py
@@ -37,7 +37,6 @@ class BitbakeTests(oeSelfTest):
37 37
38 @testcase(103) 38 @testcase(103)
39 def test_local_sstate(self): 39 def test_local_sstate(self):
40 bitbake('m4-native -ccleansstate')
41 bitbake('m4-native') 40 bitbake('m4-native')
42 bitbake('m4-native -cclean') 41 bitbake('m4-native -cclean')
43 result = bitbake('m4-native') 42 result = bitbake('m4-native')
@@ -83,8 +82,8 @@ class BitbakeTests(oeSelfTest):
83 pkgsplit_dir = get_bb_var('PKGDEST', test_recipe) 82 pkgsplit_dir = get_bb_var('PKGDEST', test_recipe)
84 man_dir = get_bb_var('mandir', test_recipe) 83 man_dir = get_bb_var('mandir', test_recipe)
85 84
86 bitbake('-c cleansstate %s' % test_recipe) 85 bitbake('-c clean %s' % test_recipe)
87 bitbake(test_recipe) 86 bitbake('-c package -f %s' % test_recipe)
88 self.add_command_to_tearDown('bitbake -c clean %s' % test_recipe) 87 self.add_command_to_tearDown('bitbake -c clean %s' % test_recipe)
89 88
90 man_file = os.path.join(image_dir + man_dir, 'man3/zlib.3') 89 man_file = os.path.join(image_dir + man_dir, 'man3/zlib.3')
@@ -103,7 +102,6 @@ class BitbakeTests(oeSelfTest):
103 # test 2 from bug 5875 102 # test 2 from bug 5875
104 test_recipe = 'zlib' 103 test_recipe = 'zlib'
105 104
106 bitbake('-c cleansstate %s' % test_recipe)
107 bitbake(test_recipe) 105 bitbake(test_recipe)
108 self.add_command_to_tearDown('bitbake -c clean %s' % test_recipe) 106 self.add_command_to_tearDown('bitbake -c clean %s' % test_recipe)
109 107
diff --git a/meta/lib/oeqa/selftest/buildoptions.py b/meta/lib/oeqa/selftest/buildoptions.py
index 09657ec189..47549550c7 100644
--- a/meta/lib/oeqa/selftest/buildoptions.py
+++ b/meta/lib/oeqa/selftest/buildoptions.py
@@ -35,9 +35,8 @@ class ImageOptionsTests(oeSelfTest):
35 bitbake("ccache-native") 35 bitbake("ccache-native")
36 self.assertTrue(os.path.isfile(os.path.join(get_bb_var('STAGING_BINDIR_NATIVE', 'ccache-native'), "ccache")), msg = "No ccache found under %s" % str(get_bb_var('STAGING_BINDIR_NATIVE', 'ccache-native'))) 36 self.assertTrue(os.path.isfile(os.path.join(get_bb_var('STAGING_BINDIR_NATIVE', 'ccache-native'), "ccache")), msg = "No ccache found under %s" % str(get_bb_var('STAGING_BINDIR_NATIVE', 'ccache-native')))
37 self.write_config('INHERIT += "ccache"') 37 self.write_config('INHERIT += "ccache"')
38 bitbake("m4 -c cleansstate") 38 self.add_command_to_tearDown('bitbake -c clean m4')
39 bitbake("m4 -c compile") 39 bitbake("m4 -f -c compile")
40 self.addCleanup(bitbake, 'ccache-native -ccleansstate')
41 res = runCmd("grep ccache %s" % (os.path.join(get_bb_var("WORKDIR","m4"),"temp/log.do_compile")), ignore_status=True) 40 res = runCmd("grep ccache %s" % (os.path.join(get_bb_var("WORKDIR","m4"),"temp/log.do_compile")), ignore_status=True)
42 self.assertEqual(0, res.status, msg="No match for ccache in m4 log.do_compile. For further details: %s" % os.path.join(get_bb_var("WORKDIR","m4"),"temp/log.do_compile")) 41 self.assertEqual(0, res.status, msg="No match for ccache in m4 log.do_compile. For further details: %s" % os.path.join(get_bb_var("WORKDIR","m4"),"temp/log.do_compile"))
43 42
@@ -71,14 +70,14 @@ class SanityOptionsTest(oeSelfTest):
71 70
72 @testcase(927) 71 @testcase(927)
73 def test_options_warnqa_errorqa_switch(self): 72 def test_options_warnqa_errorqa_switch(self):
74 bitbake("xcursor-transparent-theme -ccleansstate")
75 73
76 self.write_config("INHERIT_remove = \"report-error\"") 74 self.write_config("INHERIT_remove = \"report-error\"")
77 if "packages-list" not in get_bb_var("ERROR_QA"): 75 if "packages-list" not in get_bb_var("ERROR_QA"):
78 self.append_config("ERROR_QA_append = \" packages-list\"") 76 self.append_config("ERROR_QA_append = \" packages-list\"")
79 77
80 self.write_recipeinc('xcursor-transparent-theme', 'PACKAGES += \"${PN}-dbg\"') 78 self.write_recipeinc('xcursor-transparent-theme', 'PACKAGES += \"${PN}-dbg\"')
81 res = bitbake("xcursor-transparent-theme", ignore_status=True) 79 self.add_command_to_tearDown('bitbake -c clean xcursor-transparent-theme')
80 res = bitbake("xcursor-transparent-theme -f -c package", ignore_status=True)
82 self.delete_recipeinc('xcursor-transparent-theme') 81 self.delete_recipeinc('xcursor-transparent-theme')
83 line = self.getline(res, "QA Issue: xcursor-transparent-theme-dbg is listed in PACKAGES multiple times, this leads to packaging errors.") 82 line = self.getline(res, "QA Issue: xcursor-transparent-theme-dbg is listed in PACKAGES multiple times, this leads to packaging errors.")
84 self.assertTrue(line and line.startswith("ERROR:"), msg=res.output) 83 self.assertTrue(line and line.startswith("ERROR:"), msg=res.output)
@@ -86,8 +85,7 @@ class SanityOptionsTest(oeSelfTest):
86 self.write_recipeinc('xcursor-transparent-theme', 'PACKAGES += \"${PN}-dbg\"') 85 self.write_recipeinc('xcursor-transparent-theme', 'PACKAGES += \"${PN}-dbg\"')
87 self.append_config('ERROR_QA_remove = "packages-list"') 86 self.append_config('ERROR_QA_remove = "packages-list"')
88 self.append_config('WARN_QA_append = " packages-list"') 87 self.append_config('WARN_QA_append = " packages-list"')
89 bitbake("xcursor-transparent-theme -ccleansstate") 88 res = bitbake("xcursor-transparent-theme -f -c package")
90 res = bitbake("xcursor-transparent-theme")
91 self.delete_recipeinc('xcursor-transparent-theme') 89 self.delete_recipeinc('xcursor-transparent-theme')
92 line = self.getline(res, "QA Issue: xcursor-transparent-theme-dbg is listed in PACKAGES multiple times, this leads to packaging errors.") 90 line = self.getline(res, "QA Issue: xcursor-transparent-theme-dbg is listed in PACKAGES multiple times, this leads to packaging errors.")
93 self.assertTrue(line and line.startswith("WARNING:"), msg=res.output) 91 self.assertTrue(line and line.startswith("WARNING:"), msg=res.output)
@@ -96,8 +94,8 @@ class SanityOptionsTest(oeSelfTest):
96 def test_sanity_unsafe_script_references(self): 94 def test_sanity_unsafe_script_references(self):
97 self.write_config('WARN_QA_append = " unsafe-references-in-scripts"') 95 self.write_config('WARN_QA_append = " unsafe-references-in-scripts"')
98 96
99 bitbake("-ccleansstate gzip") 97 self.add_command_to_tearDown('bitbake -c clean gzip')
100 res = bitbake("gzip") 98 res = bitbake("gzip -f -c package_qa")
101 line = self.getline(res, "QA Issue: gzip") 99 line = self.getline(res, "QA Issue: gzip")
102 self.assertFalse(line, "WARNING: QA Issue: gzip message is present in bitbake's output and shouldn't be: %s" % res.output) 100 self.assertFalse(line, "WARNING: QA Issue: gzip message is present in bitbake's output and shouldn't be: %s" % res.output)
103 101
@@ -106,7 +104,7 @@ do_install_append_pn-gzip () {
106 echo "\n${bindir}/test" >> ${D}${bindir}/zcat 104 echo "\n${bindir}/test" >> ${D}${bindir}/zcat
107} 105}
108""") 106""")
109 res = bitbake("gzip") 107 res = bitbake("gzip -f -c package_qa")
110 line = self.getline(res, "QA Issue: gzip") 108 line = self.getline(res, "QA Issue: gzip")
111 self.assertTrue(line and line.startswith("WARNING:"), "WARNING: QA Issue: gzip message is not present in bitbake's output: %s" % res.output) 109 self.assertTrue(line and line.startswith("WARNING:"), "WARNING: QA Issue: gzip message is not present in bitbake's output: %s" % res.output)
112 110
diff --git a/meta/lib/oeqa/selftest/devtool.py b/meta/lib/oeqa/selftest/devtool.py
index e992dcf771..302ec5d42e 100644
--- a/meta/lib/oeqa/selftest/devtool.py
+++ b/meta/lib/oeqa/selftest/devtool.py
@@ -9,7 +9,8 @@ import fnmatch
9 9
10import oeqa.utils.ftools as ftools 10import oeqa.utils.ftools as ftools
11from oeqa.selftest.base import oeSelfTest 11from oeqa.selftest.base import oeSelfTest
12from oeqa.utils.commands import runCmd, bitbake, get_bb_var, create_temp_layer, runqemu, get_test_layer 12from oeqa.utils.commands import runCmd, bitbake, get_bb_var, create_temp_layer
13from oeqa.utils.commands import get_bb_vars, runqemu, get_test_layer
13from oeqa.utils.decorators import testcase 14from oeqa.utils.decorators import testcase
14 15
15class DevtoolBase(oeSelfTest): 16class DevtoolBase(oeSelfTest):
@@ -114,6 +115,20 @@ class DevtoolBase(oeSelfTest):
114 115
115class DevtoolTests(DevtoolBase): 116class DevtoolTests(DevtoolBase):
116 117
118 @classmethod
119 def setUpClass(cls):
120 bb_vars = get_bb_vars(['TOPDIR', 'SSTATE_DIR'])
121 cls.original_sstate = bb_vars['SSTATE_DIR']
122 cls.devtool_sstate = os.path.join(bb_vars['TOPDIR'], 'sstate_devtool')
123 cls.sstate_conf = 'SSTATE_DIR = "%s"\n' % cls.devtool_sstate
124 cls.sstate_conf += ('SSTATE_MIRRORS += "file://.* file:///%s/PATH"\n'
125 % cls.original_sstate)
126
127 @classmethod
128 def tearDownClass(cls):
129 cls.log.debug('Deleting devtool sstate cache on %s' % cls.devtool_sstate)
130 runCmd('rm -rf %s' % cls.devtool_sstate)
131
117 def setUp(self): 132 def setUp(self):
118 """Test case setup function""" 133 """Test case setup function"""
119 super(DevtoolTests, self).setUp() 134 super(DevtoolTests, self).setUp()
@@ -121,6 +136,7 @@ class DevtoolTests(DevtoolBase):
121 self.assertTrue(not os.path.exists(self.workspacedir), 136 self.assertTrue(not os.path.exists(self.workspacedir),
122 'This test cannot be run with a workspace directory ' 137 'This test cannot be run with a workspace directory '
123 'under the build directory') 138 'under the build directory')
139 self.append_config(self.sstate_conf)
124 140
125 def _check_src_repo(self, repo_dir): 141 def _check_src_repo(self, repo_dir):
126 """Check srctree git repository""" 142 """Check srctree git repository"""
diff --git a/meta/lib/oeqa/selftest/oescripts.py b/meta/lib/oeqa/selftest/oescripts.py
index 31cd50809c..28345dc6a2 100644
--- a/meta/lib/oeqa/selftest/oescripts.py
+++ b/meta/lib/oeqa/selftest/oescripts.py
@@ -17,12 +17,8 @@ class TestScripts(oeSelfTest):
17 path = os.path.dirname(get_bb_var('WORKDIR', 'gzip')) 17 path = os.path.dirname(get_bb_var('WORKDIR', 'gzip'))
18 old_version_recipe = os.path.join(get_bb_var('COREBASE'), 'meta/recipes-extended/gzip/gzip_1.3.12.bb') 18 old_version_recipe = os.path.join(get_bb_var('COREBASE'), 'meta/recipes-extended/gzip/gzip_1.3.12.bb')
19 old_version = '1.3.12' 19 old_version = '1.3.12'
20 bitbake("-ccleansstate gzip") 20 bitbake("-c clean gzip")
21 bitbake("-ccleansstate -b %s" % old_version_recipe) 21 bitbake("-c clean -b %s" % old_version_recipe)
22 if os.path.exists(get_bb_var('WORKDIR', "-b %s" % old_version_recipe)):
23 shutil.rmtree(get_bb_var('WORKDIR', "-b %s" % old_version_recipe))
24 if os.path.exists(get_bb_var('WORKDIR', 'gzip')):
25 shutil.rmtree(get_bb_var('WORKDIR', 'gzip'))
26 22
27 if os.path.exists(path): 23 if os.path.exists(path):
28 initial_contents = os.listdir(path) 24 initial_contents = os.listdir(path)
diff --git a/meta/lib/oeqa/selftest/prservice.py b/meta/lib/oeqa/selftest/prservice.py
index 1b9a510fd4..0b2dfe6494 100644
--- a/meta/lib/oeqa/selftest/prservice.py
+++ b/meta/lib/oeqa/selftest/prservice.py
@@ -37,7 +37,6 @@ class BitbakePrTests(oeSelfTest):
37 def increment_package_pr(self, package_name): 37 def increment_package_pr(self, package_name):
38 inc_data = "do_package_append() {\n bb.build.exec_func('do_test_prserv', d)\n}\ndo_test_prserv() {\necho \"The current date is: %s\"\n}" % datetime.datetime.now() 38 inc_data = "do_package_append() {\n bb.build.exec_func('do_test_prserv', d)\n}\ndo_test_prserv() {\necho \"The current date is: %s\"\n}" % datetime.datetime.now()
39 self.write_recipeinc(package_name, inc_data) 39 self.write_recipeinc(package_name, inc_data)
40 bitbake("-ccleansstate %s" % package_name)
41 res = bitbake(package_name, ignore_status=True) 40 res = bitbake(package_name, ignore_status=True)
42 self.delete_recipeinc(package_name) 41 self.delete_recipeinc(package_name)
43 self.assertEqual(res.status, 0, msg=res.output) 42 self.assertEqual(res.status, 0, msg=res.output)
@@ -60,7 +59,6 @@ class BitbakePrTests(oeSelfTest):
60 pr_2 = self.get_pr_version(package_name) 59 pr_2 = self.get_pr_version(package_name)
61 stamp_2 = self.get_task_stamp(package_name, track_task) 60 stamp_2 = self.get_task_stamp(package_name, track_task)
62 61
63 bitbake("-ccleansstate %s" % package_name)
64 self.assertTrue(pr_2 - pr_1 == 1, "Step between same pkg. revision is greater than 1") 62 self.assertTrue(pr_2 - pr_1 == 1, "Step between same pkg. revision is greater than 1")
65 self.assertTrue(stamp_1 != stamp_2, "Different pkg rev. but same stamp: %s" % stamp_1) 63 self.assertTrue(stamp_1 != stamp_2, "Different pkg rev. but same stamp: %s" % stamp_1)
66 64
@@ -86,7 +84,6 @@ class BitbakePrTests(oeSelfTest):
86 self.increment_package_pr(package_name) 84 self.increment_package_pr(package_name)
87 pr_2 = self.get_pr_version(package_name) 85 pr_2 = self.get_pr_version(package_name)
88 86
89 bitbake("-ccleansstate %s" % package_name)
90 self.assertTrue(pr_2 - pr_1 == 1, "Step between same pkg. revision is greater than 1") 87 self.assertTrue(pr_2 - pr_1 == 1, "Step between same pkg. revision is greater than 1")
91 88
92 @testcase(930) 89 @testcase(930)
diff --git a/meta/lib/oeqa/selftest/recipetool.py b/meta/lib/oeqa/selftest/recipetool.py
index db1f8deeb0..93e75a588e 100644
--- a/meta/lib/oeqa/selftest/recipetool.py
+++ b/meta/lib/oeqa/selftest/recipetool.py
@@ -71,11 +71,6 @@ class RecipetoolTests(RecipetoolBase):
71 logger.info('Running bitbake to generate pkgdata') 71 logger.info('Running bitbake to generate pkgdata')
72 bitbake('-c packagedata base-files coreutils busybox selftest-recipetool-appendfile') 72 bitbake('-c packagedata base-files coreutils busybox selftest-recipetool-appendfile')
73 73
74 @classmethod
75 def tearDownClass(cls):
76 # Shouldn't leave any traces of this artificial recipe behind
77 bitbake('-c cleansstate selftest-recipetool-appendfile')
78
79 def _try_recipetool_appendfile(self, testrecipe, destfile, newfile, options, expectedlines, expectedfiles): 74 def _try_recipetool_appendfile(self, testrecipe, destfile, newfile, options, expectedlines, expectedfiles):
80 cmd = 'recipetool appendfile %s %s %s %s' % (self.templayerdir, destfile, newfile, options) 75 cmd = 'recipetool appendfile %s %s %s %s' % (self.templayerdir, destfile, newfile, options)
81 return self._try_recipetool_appendcmd(cmd, testrecipe, expectedfiles, expectedlines) 76 return self._try_recipetool_appendcmd(cmd, testrecipe, expectedfiles, expectedlines)
diff --git a/meta/lib/oeqa/selftest/signing.py b/meta/lib/oeqa/selftest/signing.py
index bd0879d8d0..606bfd3e99 100644
--- a/meta/lib/oeqa/selftest/signing.py
+++ b/meta/lib/oeqa/selftest/signing.py
@@ -54,8 +54,9 @@ class Signing(oeSelfTest):
54 54
55 self.write_config(feature) 55 self.write_config(feature)
56 56
57 bitbake('-c cleansstate %s' % test_recipe) 57 bitbake('-c clean %s' % test_recipe)
58 bitbake(test_recipe) 58 bitbake('-f -c package_write_rpm %s' % test_recipe)
59
59 self.add_command_to_tearDown('bitbake -c clean %s' % test_recipe) 60 self.add_command_to_tearDown('bitbake -c clean %s' % test_recipe)
60 61
61 pkgdatadir = get_bb_var('PKGDATA_DIR', test_recipe) 62 pkgdatadir = get_bb_var('PKGDATA_DIR', test_recipe)
@@ -98,7 +99,6 @@ class Signing(oeSelfTest):
98 sstatedir = os.path.join(builddir, 'test-sstate') 99 sstatedir = os.path.join(builddir, 'test-sstate')
99 100
100 self.add_command_to_tearDown('bitbake -c clean %s' % test_recipe) 101 self.add_command_to_tearDown('bitbake -c clean %s' % test_recipe)
101 self.add_command_to_tearDown('bitbake -c cleansstate %s' % test_recipe)
102 self.add_command_to_tearDown('rm -rf %s' % sstatedir) 102 self.add_command_to_tearDown('rm -rf %s' % sstatedir)
103 103
104 # Determine the pub key signature 104 # Determine the pub key signature
@@ -117,7 +117,7 @@ class Signing(oeSelfTest):
117 117
118 self.write_config(feature) 118 self.write_config(feature)
119 119
120 bitbake('-c cleansstate %s' % test_recipe) 120 bitbake('-c clean %s' % test_recipe)
121 bitbake(test_recipe) 121 bitbake(test_recipe)
122 122
123 recipe_sig = glob.glob(sstatedir + '/*/*:ed:*_package.tgz.sig') 123 recipe_sig = glob.glob(sstatedir + '/*/*:ed:*_package.tgz.sig')
diff --git a/meta/lib/oeqa/selftest/sstatetests.py b/meta/lib/oeqa/selftest/sstatetests.py
index 6642539ebf..f99d74684e 100644
--- a/meta/lib/oeqa/selftest/sstatetests.py
+++ b/meta/lib/oeqa/selftest/sstatetests.py
@@ -16,7 +16,7 @@ class SStateTests(SStateBase):
16 16
17 # Test sstate files creation and their location 17 # Test sstate files creation and their location
18 def run_test_sstate_creation(self, targets, distro_specific=True, distro_nonspecific=True, temp_sstate_location=True, should_pass=True): 18 def run_test_sstate_creation(self, targets, distro_specific=True, distro_nonspecific=True, temp_sstate_location=True, should_pass=True):
19 self.config_sstate(temp_sstate_location) 19 self.config_sstate(temp_sstate_location, [self.sstate_path])
20 20
21 if self.temp_sstate_location: 21 if self.temp_sstate_location:
22 bitbake(['-cclean'] + targets) 22 bitbake(['-cclean'] + targets)
@@ -60,7 +60,7 @@ class SStateTests(SStateBase):
60 60
61 # Test the sstate files deletion part of the do_cleansstate task 61 # Test the sstate files deletion part of the do_cleansstate task
62 def run_test_cleansstate_task(self, targets, distro_specific=True, distro_nonspecific=True, temp_sstate_location=True): 62 def run_test_cleansstate_task(self, targets, distro_specific=True, distro_nonspecific=True, temp_sstate_location=True):
63 self.config_sstate(temp_sstate_location) 63 self.config_sstate(temp_sstate_location, [self.sstate_path])
64 64
65 bitbake(['-ccleansstate'] + targets) 65 bitbake(['-ccleansstate'] + targets)
66 66
@@ -92,7 +92,7 @@ class SStateTests(SStateBase):
92 92
93 # Test rebuilding of distro-specific sstate files 93 # Test rebuilding of distro-specific sstate files
94 def run_test_rebuild_distro_specific_sstate(self, targets, temp_sstate_location=True): 94 def run_test_rebuild_distro_specific_sstate(self, targets, temp_sstate_location=True):
95 self.config_sstate(temp_sstate_location) 95 self.config_sstate(temp_sstate_location, [self.sstate_path])
96 96
97 bitbake(['-ccleansstate'] + targets) 97 bitbake(['-ccleansstate'] + targets)
98 98