From bfd66deb37ccbae8f431ccad9704c568a2de9e1a Mon Sep 17 00:00:00 2001 From: Valeriy Koval Date: Mon, 30 May 2016 17:50:37 +0300 Subject: [PATCH] Initial support for unit testing // Issue #408 --- platformio/builder/main.py | 4 +- platformio/builder/tools/piotest.py | 146 +++++++++++++++++++++++++ platformio/builder/tools/platformio.py | 3 + platformio/util.py | 7 ++ 4 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 platformio/builder/tools/piotest.py diff --git a/platformio/builder/main.py b/platformio/builder/main.py index b4f00241..faaa1e1a 100644 --- a/platformio/builder/main.py +++ b/platformio/builder/main.py @@ -62,7 +62,7 @@ commonvars.AddVariables( DefaultEnvironment( tools=[ "gcc", "g++", "as", "ar", "gnulink", - "platformio", "devplatform", "pioupload", "pioar", "piomisc" + "platformio", "devplatform", "piotest", "pioupload", "pioar", "piomisc" ], toolpath=[join(util.get_source_dir(), "builder", "tools")], variables=commonvars, @@ -77,11 +77,13 @@ DefaultEnvironment( PROJECT_DIR=util.get_project_dir(), PROJECTLIB_DIR=util.get_projectlib_dir(), PROJECTSRC_DIR=util.get_projectsrc_dir(), + PROJECTTEST_DIR=util.get_projecttest_dir(), PROJECTDATA_DIR=util.get_projectdata_dir(), PIOENVS_DIR=util.get_pioenvs_dir(), BUILD_DIR=join("$PIOENVS_DIR", "$PIOENV"), BUILDSRC_DIR=join("$BUILD_DIR", "src"), + BUILDTEST_DIR=join("$BUILD_DIR", "test"), LIBSOURCE_DIRS=[ "$PROJECTLIB_DIR", util.get_lib_dir() diff --git a/platformio/builder/tools/piotest.py b/platformio/builder/tools/piotest.py new file mode 100644 index 00000000..c8044d93 --- /dev/null +++ b/platformio/builder/tools/piotest.py @@ -0,0 +1,146 @@ +# Copyright 2014-2016 Ivan Kravets +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# 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. + +from __future__ import absolute_import + +import atexit +from os import remove +from os.path import isdir, isfile, join +from string import Template + +FRAMEWORKS_PARAMETERS = { + "arduino": { + "framework": "Arduino.h", + "serial_obj": "", + "serial_putc": "Serial.write(a)", + "serial_flush": "Serial.flush()", + "serial_begin": "Serial.begin(9600)", + "serial_end": "Serial.end()" + }, + + "mbed": { + "framework": "mbed.h", + "serial_obj": "Serial pc(USBTX, USBRX);", + "serial_putc": "pc.putc(a)", + "serial_flush": "", + "serial_begin": "pc.baud(9600)", + "serial_end": "" + }, + + "energia": { + "framework": "Energia.h", + "serial_obj": "", + "serial_putc": "Serial.write(a)", + "serial_flush": "Serial.flush()", + "serial_begin": "Serial.begin(9600)", + "serial_end": "Serial.end()" + } +} + + +def ProcessTest(env): + + test_dir = env.subst("$PROJECTTEST_DIR") + + env.Append( + CPPDEFINES=[ + "UNIT_TEST", + "UNITY_INCLUDE_CONFIG_H" + ], + + CPPPATH=[ + join("$BUILD_DIR", "UnityTestLib") + ] + ) + + unitylib = env.BuildLibrary( + join("$BUILD_DIR", "UnityTestLib"), + env.DevPlatform().get_package_dir("tool-unity") + + ) + + env.Prepend(LIBS=[unitylib]) + + env.GenerateOutputReplacement(test_dir) + + return env.LookupSources( + "$BUILDTEST_DIR", test_dir, duplicate=False) + + +def GenerateOutputReplacement(env, destination_dir): + + if not isdir(env.subst(destination_dir)): + env.Exit( + "Error: Test folder doesn't exist. Please put your test suite " + 'to \"test\" folder in project\'s root directory.') + + TEMPLATECPP = """ +# include <$framework> +# include + +$serial_obj + +void output_char(int a) +{ + $serial_putc; +} + +void output_flush(void) +{ + $serial_flush; +} + +void output_start(unsigned int baudrate) +{ + $serial_begin; +} + +void output_complete(void) +{ + $serial_end; +} + +""" + + def delete_tmptest_file(file_): + try: + remove(file_) + except: # pylint: disable=bare-except + if isfile(file_): + print("Warning: Could not remove temporary file '%s'. " + "Please remove it manually." % file_) + + framework = env.subst("$FRAMEWORK").lower() + if framework not in FRAMEWORKS_PARAMETERS.keys(): + env.Exit( + "Error: %s framework doesn't support testing feature!" % framework) + else: + data = Template(TEMPLATECPP).substitute( + FRAMEWORKS_PARAMETERS[framework]) + + tmp_file = join(destination_dir, "output_export.cpp") + with open(tmp_file, "w") as f: + f.write(data) + + atexit.register(delete_tmptest_file, tmp_file) + + +def exists(_): + return True + + +def generate(env): + env.AddMethod(ProcessTest) + env.AddMethod(GenerateOutputReplacement) + return env diff --git a/platformio/builder/tools/platformio.py b/platformio/builder/tools/platformio.py index f7c88fd5..9599dbd6 100644 --- a/platformio/builder/tools/platformio.py +++ b/platformio/builder/tools/platformio.py @@ -88,6 +88,9 @@ def BuildProgram(env): "$BUILDSRC_DIR", "$PROJECTSRC_DIR", duplicate=False, src_filter=env.get("SRC_FILTER")) + if "test" in COMMAND_LINE_TARGETS: + sources.extend(env.ProcessTest()) + if not sources and not COMMAND_LINE_TARGETS: env.Exit( "Error: Nothing to build. Please put your source code files " diff --git a/platformio/util.py b/platformio/util.py index dd6026e9..394b3201 100644 --- a/platformio/util.py +++ b/platformio/util.py @@ -207,6 +207,13 @@ def get_projectsrc_dir(): ) +def get_projecttest_dir(): + return _get_projconf_option_dir( + "test_dir", + join(get_project_dir(), "test") + ) + + def get_projectlib_dir(): return join(get_project_dir(), "lib")