--- /dev/null
+#
+# Component Makefile
+#
+# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
+
--- /dev/null
+
+/* @brief macro to print IDF performance
+ * @param mode : performance item name. a string pointer.
+ * @param value_fmt: print format and unit of the value, for example: "%02fms", "%dKB"
+ * @param value : the performance value.
+*/
+#define IDF_LOG_PERFORMANCE(item, value_fmt, value) \
+ printf("[Performance][%s]: "value_fmt"\n", item, value)
+
+
+/* declare the performance here */
+#define IDF_PERFORMANCE_MAX_HTTPS_REQUEST_BIN_SIZE 610
+#define IDF_PERFORMANCE_MAX_FREERTOS_SPINLOCK_CYCLES_PER_OP 200
+#define IDF_PERFORMANCE_MAX_FREERTOS_SPINLOCK_CYCLES_PER_OP_UNICORE 130
+#define IDF_PERFORMANCE_MAX_ESP_TIMER_GET_TIME_PER_CALL 1000
import serial
from serial.tools import list_ports
+import Utility
+
if sys.version_info[0] == 2:
import Queue as _queue
else:
return handler
+def _decode_data(data):
+ """ for python3, if the data is bytes, then decode it to string """
+ if isinstance(data, bytes):
+ # convert bytes to string
+ try:
+ data = data.decode("utf-8", "ignore")
+ except UnicodeDecodeError:
+ data = data.decode("iso8859-1", )
+ return data
+
+
class _DataCache(_queue.Queue):
"""
Data cache based on Queue. Allow users to process data cache based on bytes instead of Queue."
try:
data = self.get(timeout=timeout)
- if isinstance(data, bytes):
- # convert bytes to string
- try:
- data = data.decode("utf-8", "ignore")
- except UnicodeDecodeError:
- data = data.decode("iso8859-1",)
- self.data_cache += data
+ self.data_cache += _decode_data(data)
except _queue.Empty:
# don't do anything when on update for cache
pass
class _RecvThread(threading.Thread):
+ PERFORMANCE_PATTERN = re.compile(r"\[Performance]\[(\w+)]: ([^\r\n]+)\r?\n")
+
def __init__(self, read, data_cache):
super(_RecvThread, self).__init__()
self.exit_event = threading.Event()
self.setDaemon(True)
self.read = read
self.data_cache = data_cache
+ # cache the last line of recv data for collecting performance
+ self._line_cache = str()
+
+ def collect_performance(self, data):
+ """ collect performance """
+ if data:
+ decoded_data = _decode_data(data)
+
+ matches = self.PERFORMANCE_PATTERN.findall(self._line_cache + decoded_data)
+ for match in matches:
+ Utility.console_log("[Performance][{}]: {}".format(match[0], match[1]),
+ color="orange")
+
+ # cache incomplete line to later process
+ lines = decoded_data.splitlines(True)
+ last_line = lines[-1]
+
+ if last_line[-1] != "\n":
+ if len(lines) == 1:
+ # only one line and the line is not finished, then append this to cache
+ self._line_cache += lines[-1]
+ else:
+ # more than one line and not finished, replace line cache
+ self._line_cache = lines[-1]
+ else:
+ # line finishes, flush cache
+ self._line_cache = str()
def run(self):
while not self.exit_event.isSet():
data = self.read(1000)
if data:
self.data_cache.put(data)
+ self.collect_performance(data)
def exit(self):
self.exit_event.set()
timestamp = time.time()
timestamp = "{}:{}".format(time.strftime("%m-%d %H:%M:%S", time.localtime(timestamp)),
str(timestamp % 1)[2:5])
- try:
- formatted_data = "[{}]:\r\n{}\r\n".format(timestamp, data.decode("utf-8", "ignore"))
- except UnicodeDecodeError:
- # if utf-8 fail, use iso-8859-1 (single char codec with range 0-255)
- formatted_data = "[{}]:\r\n{}\r\n".format(timestamp, data.decode("iso8859-1",))
+ formatted_data = "[{}]:\r\n{}\r\n".format(timestamp, _decode_data(data))
return formatted_data
def _port_open(self):
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+import os
+import re
import TinyFW
-from IDF.IDFApp import Example, UT
+import Utility
+from IDF.IDFApp import IDFApp, Example, UT
from IDF.IDFDUT import IDFDUT
# not use partial function as define as function support auto generating document
return TinyFW.test_method(app=app, dut=dut, chip=chip, module=module,
execution_time=execution_time, **kwargs)
+
+
+def log_performance(item, value):
+ """
+ do print performance with pre-defined format to console
+
+ :param item: performance item name
+ :param value: performance value
+ """
+ Utility.console_log("[Performance][{}]: {}".format(item, value), "orange")
+
+
+def check_performance(item, value):
+ """
+ check if idf performance meet pass standard
+
+ :param item: performance item name
+ :param value: performance item value
+ :raise: AssertionError: if check fails
+ """
+ ret = True
+ standard_value = 0
+
+ idf_path = IDFApp.get_sdk_path()
+ performance_file = os.path.join(idf_path, "components", "idf_test", "include", "idf_performance.h")
+
+ if os.path.exists(performance_file):
+ with open(performance_file, "r") as f:
+ data = f.read()
+ match = re.search(r"#define\s+IDF_PERFORMANCE_(MIN|MAX)_{}\s+([\d.]+)".format(item.upper()), data)
+ if match:
+ op = match.group(1)
+ standard_value = float(match.group(2))
+ if op == "MAX":
+ ret = value <= standard_value
+ else:
+ ret = value >= standard_value
+ if not ret:
+ raise AssertionError("[Performance] {} value is {}, doesn't meet pass standard {}"
+ .format(item, value, standard_value))
import Env
import DUT
import App
+import Utility
XUNIT_FILE_NAME = "XUNIT_RESULT.xml"
XUNIT_DEFAULT_TEST_SUITE = "test-suite"
-_COLOR_CODES = {
- "white": '\033[0m',
- "red": '\033[31m',
- "green": '\033[32m',
- "orange": '\033[33m',
- "blue": '\033[34m',
- "purple": '\033[35m',
- "W": '\033[0m',
- "R": '\033[31m',
- "G": '\033[32m',
- "O": '\033[33m',
- "B": '\033[34m',
- "P": '\033[35m'
-}
-
-
-def console_log(data, color="white"):
- """
- log data to console.
- (if not flush console log, Gitlab-CI won't update logs during job execution)
-
- :param data: data content
- :param color: color
- """
- if color not in _COLOR_CODES:
- color = "white"
- color_codes = _COLOR_CODES[color]
- print(color_codes + data)
- if color not in ["white", "W"]:
- # reset color to white for later logs
- print(_COLOR_CODES["white"] + "\r")
- sys.stdout.flush()
-
-
class DefaultEnvConfig(object):
"""
default test configs. There're 3 places to set configs, priority is (high -> low):
XUNIT_FILE_NAME)
XUNIT_RECEIVER.begin_case(test_func.__name__, time.time(), test_func_file_name)
try:
- console_log("starting running test: " + test_func.__name__, color="green")
+ Utility.console_log("starting running test: " + test_func.__name__, color="green")
# execute test function
test_func(env_inst, extra_data)
# if finish without exception, test result is True
XUNIT_DEFAULT_TEST_SUITE))
if result:
- console_log("Test Succeed: " + test_func.__name__, color="green")
+ Utility.console_log("Test Succeed: " + test_func.__name__, color="green")
else:
- console_log(("Test Fail: " + test_func.__name__), color="red")
+ Utility.console_log(("Test Fail: " + test_func.__name__), color="red")
TestResult.set_result(result, test_func.__name__)
return result
+import sys
+
+
+_COLOR_CODES = {
+ "white": '\033[0m',
+ "red": '\033[31m',
+ "green": '\033[32m',
+ "orange": '\033[33m',
+ "blue": '\033[34m',
+ "purple": '\033[35m',
+ "W": '\033[0m',
+ "R": '\033[31m',
+ "G": '\033[32m',
+ "O": '\033[33m',
+ "B": '\033[34m',
+ "P": '\033[35m'
+}
+
+
+def console_log(data, color="white"):
+ """
+ log data to console.
+ (if not flush console log, Gitlab-CI won't update logs during job execution)
+
+ :param data: data content
+ :param color: color
+ """
+ if color not in _COLOR_CODES:
+ color = "white"
+ color_codes = _COLOR_CODES[color]
+ print(color_codes + data)
+ if color not in ["white", "W"]:
+ # reset color to white for later logs
+ print(_COLOR_CODES["white"] + "\r")
+ sys.stdout.flush()
\ No newline at end of file
#define UNITY_INCLUDE_CONFIG_H
#include "unity_internals.h"
+/* include performance pass standards header file */
+#include "idf_performance.h"
+
void setUp(void);
void tearDown(void);
#define TEST_ASSERT_DOUBLE_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, (message))
#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, (message))
+/* For performance check with unity test on IDF */
+/* These macros should only be used with ESP-IDF.
+ * To use performance check, we need to first define pass standard in idf_performance.h.
+ */
+#define TEST_PERFORMANCE_LESS_THAN(name, value_fmt, value) do { \
+ printf("[Performance]["#name"]: "value_fmt"\n", value); \
+ TEST_ASSERT(value < IDF_PERFORMANCE_MAX_##name); \
+} while(0)
+
+#define TEST_PERFORMANCE_GREATER_THAN(name, value_fmt, value) do { \
+ printf("[Performance]["#name"]: "value_fmt"\n", value); \
+ TEST_ASSERT(value > IDF_PERFORMANCE_MIN_##name); \
+} while(0)
+
/* end of UNITY_FRAMEWORK_H */
#ifdef __cplusplus
}