blob: 7e1cebf7d6b7fffeb31ef624f2de904a9aa97ea1 [file] [log] [blame]
Azim Khan951a2c82018-06-29 03:47:08 +01001# Greentea host test script for Mbed TLS on-target test suite testing.
Azim Khanf0e42fb2017-08-02 14:47:13 +01002#
Azim Khan8d686bf2018-07-04 23:29:46 +01003# Copyright (C) 2018, Arm Limited, All Rights Reserved
Azim Khanf0e42fb2017-08-02 14:47:13 +01004# SPDX-License-Identifier: Apache-2.0
5#
6# Licensed under the Apache License, Version 2.0 (the "License"); you may
7# not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17#
Azim Khanb31aa442018-07-03 11:57:54 +010018# This file is part of Mbed TLS (https://tls.mbed.org)
Azim Khanf0e42fb2017-08-02 14:47:13 +010019
20
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +010021"""
Azim Khan8d686bf2018-07-04 23:29:46 +010022Mbed TLS on-target test suite tests are implemented as Greentea
Azim Khan951a2c82018-06-29 03:47:08 +010023tests. Greentea tests are implemented in two parts: target test and
24host test. Target test is a C application that is built for the
25target platform and executes on the target. Host test is a Python
26class derived from mbed_host_tests.BaseHostTest. Target communicates
Azim Khan8d686bf2018-07-04 23:29:46 +010027with the host over serial for the test data and sends back the result.
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +010028
Azim Khanb31aa442018-07-03 11:57:54 +010029Python tool mbedgt (Greentea) is responsible for flashing the test
Azim Khan8d686bf2018-07-04 23:29:46 +010030binary on to the target and dynamically loading this host test module.
Azim Khan951a2c82018-06-29 03:47:08 +010031
Azim Khan8d686bf2018-07-04 23:29:46 +010032Greentea documentation can be found here:
33https://github.com/ARMmbed/greentea
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +010034"""
35
Azim Khanf0e42fb2017-08-02 14:47:13 +010036
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +010037import re
38import os
Azim Khan663d4702017-07-07 15:40:26 +010039import binascii
Gilles Peskinee915d532019-02-25 21:39:42 +010040
41from mbed_host_tests import BaseHostTest, event_callback # pylint: disable=import-error
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +010042
43
Azim Khanb98e6ee2018-06-28 17:11:33 +010044class TestDataParserError(Exception):
45 """Indicates error in test data, read from .data file."""
46 pass
47
48
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +010049class TestDataParser(object):
50 """
Azim Khan951a2c82018-06-29 03:47:08 +010051 Parses test name, dependencies, test function name and test parameters
52 from the data file.
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +010053 """
54
55 def __init__(self):
56 """
57 Constructor
58 """
59 self.tests = []
60
61 def parse(self, data_file):
62 """
Azim Khanf0e42fb2017-08-02 14:47:13 +010063 Data file parser.
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +010064
Azim Khanf0e42fb2017-08-02 14:47:13 +010065 :param data_file: Data file path
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +010066 """
Azim Khanb31aa442018-07-03 11:57:54 +010067 with open(data_file, 'r') as data_f:
68 self.__parse(data_f)
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +010069
70 @staticmethod
Azim Khanb31aa442018-07-03 11:57:54 +010071 def __escaped_split(inp_str, split_char):
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +010072 """
Azim Khanb31aa442018-07-03 11:57:54 +010073 Splits inp_str on split_char except when escaped.
Azim Khanf0e42fb2017-08-02 14:47:13 +010074
Azim Khanb31aa442018-07-03 11:57:54 +010075 :param inp_str: String to split
76 :param split_char: Split character
Azim Khanf0e42fb2017-08-02 14:47:13 +010077 :return: List of splits
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +010078 """
Ron Eldor111ba0e2018-11-18 17:05:05 +020079 split_colon_fn = lambda x: re.sub(r'\\' + split_char, split_char, x)
Azim Khanb31aa442018-07-03 11:57:54 +010080 if len(split_char) > 1:
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +010081 raise ValueError('Expected split character. Found string!')
Ron Eldor33908e82019-05-29 17:17:10 +030082 out = list(map(split_colon_fn, re.split(r'(?<!\\)' + split_char, inp_str)))
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +010083 return out
84
Azim Khanb31aa442018-07-03 11:57:54 +010085 def __parse(self, data_f):
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +010086 """
Azim Khanf0e42fb2017-08-02 14:47:13 +010087 Parses data file using supplied file object.
88
Azim Khanb31aa442018-07-03 11:57:54 +010089 :param data_f: Data file object
Azim Khanf0e42fb2017-08-02 14:47:13 +010090 :return:
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +010091 """
Ron Eldor33908e82019-05-29 17:17:10 +030092 while True:
93 line = data_f.readline().strip()
Azim Khanb31aa442018-07-03 11:57:54 +010094 if not line:
Ron Eldor33908e82019-05-29 17:17:10 +030095 break
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +010096 # Read test name
97 name = line
98
99 # Check dependencies
Azim Khanb31aa442018-07-03 11:57:54 +0100100 dependencies = []
Ron Eldor33908e82019-05-29 17:17:10 +0300101 line = data_f.readline().strip()
102 if not line:
103 break
Azim Khanb31aa442018-07-03 11:57:54 +0100104 match = re.search('depends_on:(.*)', line)
105 if match:
106 dependencies = [int(x) for x in match.group(1).split(':')]
Ron Eldor33908e82019-05-29 17:17:10 +0300107 line = data_f.readline().strip()
108 if not line:
109 break
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100110
111 # Read test vectors
Azim Khan663d4702017-07-07 15:40:26 +0100112 line = line.replace('\\n', '\n')
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100113 parts = self.__escaped_split(line, ':')
Azim Khanb31aa442018-07-03 11:57:54 +0100114 function_name = int(parts[0])
115 args = parts[1:]
116 args_count = len(args)
117 if args_count % 2 != 0:
Ron Eldor111ba0e2018-11-18 17:05:05 +0200118 err_str_fmt = "Number of test arguments({}) should be even: {}"
119 raise TestDataParserError(err_str_fmt.format(args_count, line))
Azim Khanb31aa442018-07-03 11:57:54 +0100120 grouped_args = [(args[i * 2], args[(i * 2) + 1])
Ron Eldor33908e82019-05-29 17:17:10 +0300121 for i in range(int(len(args)/2))]
Azim Khanb31aa442018-07-03 11:57:54 +0100122 self.tests.append((name, function_name, dependencies,
123 grouped_args))
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100124
125 def get_test_data(self):
126 """
Azim Khanf0e42fb2017-08-02 14:47:13 +0100127 Returns test data.
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100128 """
129 return self.tests
130
131
132class MbedTlsTest(BaseHostTest):
133 """
Azim Khanb31aa442018-07-03 11:57:54 +0100134 Host test for Mbed TLS unit tests. This script is loaded at
135 run time by Greentea for executing Mbed TLS test suites. Each
Azim Khan951a2c82018-06-29 03:47:08 +0100136 communication from the target is received in this object as
137 an event, which is then handled by the event handler method
138 decorated by the associated event. Ex: @event_callback('GO').
139
140 Target test sends requests for dispatching next test. It reads
141 tests from the intermediate data file and sends test function
142 identifier, dependency identifiers, expression identifiers and
Azim Khanb31aa442018-07-03 11:57:54 +0100143 the test data in binary form. Target test checks dependencies
Azim Khan951a2c82018-06-29 03:47:08 +0100144 , evaluate integer constant expressions and dispatches the test
Azim Khan8d686bf2018-07-04 23:29:46 +0100145 function with received test parameters. After test function is
146 finished, target sends the result. This class handles the result
147 event and prints verdict in the form that Greentea understands.
Azim Khan951a2c82018-06-29 03:47:08 +0100148
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100149 """
Azim Khan951a2c82018-06-29 03:47:08 +0100150 # status/error codes from suites/helpers.function
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100151 DEPENDENCY_SUPPORTED = 0
152 KEY_VALUE_MAPPING_FOUND = DEPENDENCY_SUPPORTED
153 DISPATCH_TEST_SUCCESS = DEPENDENCY_SUPPORTED
154
Azim Khan951a2c82018-06-29 03:47:08 +0100155 KEY_VALUE_MAPPING_NOT_FOUND = -1 # Expression Id not found.
156 DEPENDENCY_NOT_SUPPORTED = -2 # Dependency not supported.
157 DISPATCH_TEST_FN_NOT_FOUND = -3 # Test function not found.
158 DISPATCH_INVALID_TEST_DATA = -4 # Invalid parameter type.
159 DISPATCH_UNSUPPORTED_SUITE = -5 # Test suite not supported/enabled.
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100160
161 def __init__(self):
162 """
Azim Khanf0e42fb2017-08-02 14:47:13 +0100163 Constructor initialises test index to 0.
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100164 """
165 super(MbedTlsTest, self).__init__()
166 self.tests = []
167 self.test_index = -1
168 self.dep_index = 0
Ron Eldor8672cb72018-11-13 18:42:35 +0200169 self.suite_passed = True
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100170 self.error_str = dict()
Azim Khanb31aa442018-07-03 11:57:54 +0100171 self.error_str[self.DEPENDENCY_SUPPORTED] = \
172 'DEPENDENCY_SUPPORTED'
173 self.error_str[self.KEY_VALUE_MAPPING_NOT_FOUND] = \
174 'KEY_VALUE_MAPPING_NOT_FOUND'
175 self.error_str[self.DEPENDENCY_NOT_SUPPORTED] = \
176 'DEPENDENCY_NOT_SUPPORTED'
177 self.error_str[self.DISPATCH_TEST_FN_NOT_FOUND] = \
178 'DISPATCH_TEST_FN_NOT_FOUND'
179 self.error_str[self.DISPATCH_INVALID_TEST_DATA] = \
180 'DISPATCH_INVALID_TEST_DATA'
181 self.error_str[self.DISPATCH_UNSUPPORTED_SUITE] = \
182 'DISPATCH_UNSUPPORTED_SUITE'
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100183
184 def setup(self):
185 """
Azim Khan951a2c82018-06-29 03:47:08 +0100186 Setup hook implementation. Reads test suite data file and parses out
187 tests.
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100188 """
189 binary_path = self.get_config_item('image_path')
190 script_dir = os.path.split(os.path.abspath(__file__))[0]
191 suite_name = os.path.splitext(os.path.basename(binary_path))[0]
Ron Eldorc242eea2018-11-05 16:22:36 +0200192 data_file = ".".join((suite_name, 'datax'))
Azim Khan951a2c82018-06-29 03:47:08 +0100193 data_file = os.path.join(script_dir, '..', 'mbedtls',
194 suite_name, data_file)
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100195 if os.path.exists(data_file):
196 self.log("Running tests from %s" % data_file)
197 parser = TestDataParser()
198 parser.parse(data_file)
199 self.tests = parser.get_test_data()
200 self.print_test_info()
201 else:
202 self.log("Data file not found: %s" % data_file)
203 self.notify_complete(False)
204
205 def print_test_info(self):
206 """
Azim Khanf0e42fb2017-08-02 14:47:13 +0100207 Prints test summary read by Greentea to detect test cases.
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100208 """
209 self.log('{{__testcase_count;%d}}' % len(self.tests))
210 for name, _, _, _ in self.tests:
211 self.log('{{__testcase_name;%s}}' % name)
212
213 @staticmethod
Azim Khanb31aa442018-07-03 11:57:54 +0100214 def align_32bit(data_bytes):
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100215 """
Azim Khanf0e42fb2017-08-02 14:47:13 +0100216 4 byte aligns input byte array.
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100217
218 :return:
219 """
Azim Khanb31aa442018-07-03 11:57:54 +0100220 data_bytes += bytearray((4 - (len(data_bytes))) % 4)
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100221
Azim Khand59391a2017-06-01 14:04:17 +0100222 @staticmethod
223 def hex_str_bytes(hex_str):
224 """
225 Converts Hex string representation to byte array
226
Azim Khanf0e42fb2017-08-02 14:47:13 +0100227 :param hex_str: Hex in string format.
228 :return: Output Byte array
Azim Khand59391a2017-06-01 14:04:17 +0100229 """
Azim Khanb98e6ee2018-06-28 17:11:33 +0100230 if hex_str[0] != '"' or hex_str[len(hex_str) - 1] != '"':
231 raise TestDataParserError("HEX test parameter missing '\"':"
232 " %s" % hex_str)
Azim Khand59391a2017-06-01 14:04:17 +0100233 hex_str = hex_str.strip('"')
Azim Khanb98e6ee2018-06-28 17:11:33 +0100234 if len(hex_str) % 2 != 0:
235 raise TestDataParserError("HEX parameter len should be mod of "
236 "2: %s" % hex_str)
Azim Khand59391a2017-06-01 14:04:17 +0100237
Azim Khanb31aa442018-07-03 11:57:54 +0100238 data_bytes = binascii.unhexlify(hex_str)
239 return data_bytes
Azim Khand59391a2017-06-01 14:04:17 +0100240
Azim Khan663d4702017-07-07 15:40:26 +0100241 @staticmethod
Azim Khanb31aa442018-07-03 11:57:54 +0100242 def int32_to_big_endian_bytes(i):
Azim Khan663d4702017-07-07 15:40:26 +0100243 """
Azim Khanb31aa442018-07-03 11:57:54 +0100244 Coverts i to byte array in big endian format.
Azim Khan663d4702017-07-07 15:40:26 +0100245
Azim Khanf0e42fb2017-08-02 14:47:13 +0100246 :param i: Input integer
247 :return: Output bytes array in big endian or network order
Azim Khan663d4702017-07-07 15:40:26 +0100248 """
Azim Khanb31aa442018-07-03 11:57:54 +0100249 data_bytes = bytearray([((i >> x) & 0xff) for x in [24, 16, 8, 0]])
250 return data_bytes
Azim Khan663d4702017-07-07 15:40:26 +0100251
Azim Khanb31aa442018-07-03 11:57:54 +0100252 def test_vector_to_bytes(self, function_id, dependencies, parameters):
Azim Khan663d4702017-07-07 15:40:26 +0100253 """
254 Converts test vector into a byte array that can be sent to the target.
255
Azim Khanf0e42fb2017-08-02 14:47:13 +0100256 :param function_id: Test Function Identifier
Azim Khanb31aa442018-07-03 11:57:54 +0100257 :param dependencies: Dependency list
Azim Khanf0e42fb2017-08-02 14:47:13 +0100258 :param parameters: Test function input parameters
259 :return: Byte array and its length
Azim Khan663d4702017-07-07 15:40:26 +0100260 """
Azim Khanb31aa442018-07-03 11:57:54 +0100261 data_bytes = bytearray([len(dependencies)])
262 if dependencies:
263 data_bytes += bytearray(dependencies)
264 data_bytes += bytearray([function_id, len(parameters)])
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100265 for typ, param in parameters:
266 if typ == 'int' or typ == 'exp':
267 i = int(param)
Azim Khanb31aa442018-07-03 11:57:54 +0100268 data_bytes += 'I' if typ == 'int' else 'E'
269 self.align_32bit(data_bytes)
270 data_bytes += self.int32_to_big_endian_bytes(i)
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100271 elif typ == 'char*':
272 param = param.strip('"')
273 i = len(param) + 1 # + 1 for null termination
Azim Khanb31aa442018-07-03 11:57:54 +0100274 data_bytes += 'S'
275 self.align_32bit(data_bytes)
276 data_bytes += self.int32_to_big_endian_bytes(i)
277 data_bytes += bytearray(list(param))
278 data_bytes += '\0' # Null terminate
Azim Khand59391a2017-06-01 14:04:17 +0100279 elif typ == 'hex':
Azim Khanb31aa442018-07-03 11:57:54 +0100280 binary_data = self.hex_str_bytes(param)
281 data_bytes += 'H'
282 self.align_32bit(data_bytes)
283 i = len(binary_data)
284 data_bytes += self.int32_to_big_endian_bytes(i)
285 data_bytes += binary_data
286 length = self.int32_to_big_endian_bytes(len(data_bytes))
287 return data_bytes, length
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100288
289 def run_next_test(self):
290 """
Azim Khan951a2c82018-06-29 03:47:08 +0100291 Fetch next test information and execute the test.
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100292
293 """
294 self.test_index += 1
295 self.dep_index = 0
296 if self.test_index < len(self.tests):
Azim Khanb31aa442018-07-03 11:57:54 +0100297 name, function_id, dependencies, args = self.tests[self.test_index]
298 self.run_test(name, function_id, dependencies, args)
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100299 else:
Ron Eldor8672cb72018-11-13 18:42:35 +0200300 self.notify_complete(self.suite_passed)
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100301
Azim Khanb31aa442018-07-03 11:57:54 +0100302 def run_test(self, name, function_id, dependencies, args):
Azim Khan663d4702017-07-07 15:40:26 +0100303 """
Azim Khan951a2c82018-06-29 03:47:08 +0100304 Execute the test on target by sending next test information.
Azim Khan663d4702017-07-07 15:40:26 +0100305
Azim Khanf0e42fb2017-08-02 14:47:13 +0100306 :param name: Test name
307 :param function_id: function identifier
Azim Khanb31aa442018-07-03 11:57:54 +0100308 :param dependencies: Dependencies list
Azim Khanf0e42fb2017-08-02 14:47:13 +0100309 :param args: test parameters
Azim Khan663d4702017-07-07 15:40:26 +0100310 :return:
311 """
312 self.log("Running: %s" % name)
313
Azim Khanb31aa442018-07-03 11:57:54 +0100314 param_bytes, length = self.test_vector_to_bytes(function_id,
315 dependencies, args)
Ron Eldor33908e82019-05-29 17:17:10 +0300316 self.send_kv(bytes(length).decode(), bytes(param_bytes).decode())
Azim Khan663d4702017-07-07 15:40:26 +0100317
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100318 @staticmethod
319 def get_result(value):
Azim Khanf0e42fb2017-08-02 14:47:13 +0100320 """
321 Converts result from string type to integer
322 :param value: Result code in string
Azim Khan8d686bf2018-07-04 23:29:46 +0100323 :return: Integer result code. Value is from the test status
324 constants defined under the MbedTlsTest class.
Azim Khanf0e42fb2017-08-02 14:47:13 +0100325 """
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100326 try:
327 return int(value)
328 except ValueError:
Azim Khanb31aa442018-07-03 11:57:54 +0100329 ValueError("Result should return error number. "
330 "Instead received %s" % value)
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100331
332 @event_callback('GO')
Azim Khanb31aa442018-07-03 11:57:54 +0100333 def on_go(self, _key, _value, _timestamp):
Azim Khanf0e42fb2017-08-02 14:47:13 +0100334 """
Azim Khan951a2c82018-06-29 03:47:08 +0100335 Sent by the target to start first test.
Azim Khanf0e42fb2017-08-02 14:47:13 +0100336
Azim Khanb31aa442018-07-03 11:57:54 +0100337 :param _key: Event key
338 :param _value: Value. ignored
339 :param _timestamp: Timestamp ignored.
Azim Khanf0e42fb2017-08-02 14:47:13 +0100340 :return:
341 """
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100342 self.run_next_test()
343
344 @event_callback("R")
Azim Khanb31aa442018-07-03 11:57:54 +0100345 def on_result(self, _key, value, _timestamp):
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100346 """
Azim Khan951a2c82018-06-29 03:47:08 +0100347 Handle result. Prints test start, finish required by Greentea
348 to detect test execution.
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100349
Azim Khanb31aa442018-07-03 11:57:54 +0100350 :param _key: Event key
Azim Khanf0e42fb2017-08-02 14:47:13 +0100351 :param value: Value. ignored
Azim Khanb31aa442018-07-03 11:57:54 +0100352 :param _timestamp: Timestamp ignored.
Azim Khanf0e42fb2017-08-02 14:47:13 +0100353 :return:
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100354 """
355 int_val = self.get_result(value)
Azim Khanb31aa442018-07-03 11:57:54 +0100356 name, _, _, _ = self.tests[self.test_index]
Azim Khan5e7f8df2017-05-31 20:33:39 +0100357 self.log('{{__testcase_start;%s}}' % name)
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100358 self.log('{{__testcase_finish;%s;%d;%d}}' % (name, int_val == 0,
359 int_val != 0))
Ron Eldor8672cb72018-11-13 18:42:35 +0200360 if int_val != 0:
361 self.suite_passed = False
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100362 self.run_next_test()
363
364 @event_callback("F")
Azim Khanb31aa442018-07-03 11:57:54 +0100365 def on_failure(self, _key, value, _timestamp):
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100366 """
Azim Khanf0e42fb2017-08-02 14:47:13 +0100367 Handles test execution failure. That means dependency not supported or
368 Test function not supported. Hence marking test as skipped.
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100369
Azim Khanb31aa442018-07-03 11:57:54 +0100370 :param _key: Event key
Azim Khanf0e42fb2017-08-02 14:47:13 +0100371 :param value: Value. ignored
Azim Khanb31aa442018-07-03 11:57:54 +0100372 :param _timestamp: Timestamp ignored.
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100373 :return:
374 """
375 int_val = self.get_result(value)
Mohammad Azim Khan7a0d84f2017-04-01 03:18:20 +0100376 if int_val in self.error_str:
377 err = self.error_str[int_val]
378 else:
379 err = 'Unknown error'
380 # For skip status, do not write {{__testcase_finish;...}}
381 self.log("Error: %s" % err)
382 self.run_next_test()