Daniel Konegen / MNIST_example

Dependencies:   mbed-os

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers micro_test.h Source File

micro_test.h

00001 /* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
00002 
00003 Licensed under the Apache License, Version 2.0 (the "License");
00004 you may not use this file except in compliance with the License.
00005 You may obtain a copy of the License at
00006 
00007     http://www.apache.org/licenses/LICENSE-2.0
00008 
00009 Unless required by applicable law or agreed to in writing, software
00010 distributed under the License is distributed on an "AS IS" BASIS,
00011 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 See the License for the specific language governing permissions and
00013 limitations under the License.
00014 ==============================================================================*/
00015 
00016 // An ultra-lightweight testing framework designed for use with microcontroller
00017 // applications. Its only dependency is on TensorFlow Lite's ErrorReporter
00018 // interface, where log messages are output. This is designed to be usable even
00019 // when no standard C or C++ libraries are available, and without any dynamic
00020 // memory allocation or reliance on global constructors.
00021 //
00022 // To build a test, you use syntax similar to gunit, but with some extra
00023 // decoration to create a hidden 'main' function containing each of the tests to
00024 // be run. Your code should look something like:
00025 // ----------------------------------------------------------------------------
00026 // #include "path/to/this/header"
00027 //
00028 // TF_LITE_MICRO_TESTS_BEGIN
00029 //
00030 // TF_LITE_MICRO_TEST(SomeTest) {
00031 //   TF_LITE_LOG_EXPECT_EQ(true, true);
00032 // }
00033 //
00034 // TF_LITE_MICRO_TESTS_END
00035 // ----------------------------------------------------------------------------
00036 // If you compile this for your platform, you'll get a normal binary that you
00037 // should be able to run. Executing it will output logging information like this
00038 // to stderr (or whatever equivalent is available and written to by
00039 // ErrorReporter):
00040 // ----------------------------------------------------------------------------
00041 // Testing SomeTest
00042 // 1/1 tests passed
00043 // ~~~ALL TESTS PASSED~~~
00044 // ----------------------------------------------------------------------------
00045 // This is designed to be human-readable, so you can just run tests manually,
00046 // but the string "~~~ALL TESTS PASSED~~~" should only appear if all of the
00047 // tests do pass. This makes it possible to integrate with automated test
00048 // systems by scanning the output logs and looking for that magic value.
00049 //
00050 // This framework is intended to be a rudimentary alternative to no testing at
00051 // all on systems that struggle to run more conventional approaches, so use with
00052 // caution!
00053 
00054 #ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_TESTING_MICRO_TEST_H_
00055 #define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_TESTING_MICRO_TEST_H_
00056 
00057 #include "tensorflow/lite/experimental/micro/micro_error_reporter.h"
00058 
00059 namespace micro_test {
00060 extern int tests_passed;
00061 extern int tests_failed;
00062 extern bool is_test_complete;
00063 extern bool did_test_fail;
00064 extern tflite::ErrorReporter* reporter;
00065 }  // namespace micro_test
00066 
00067 #define TF_LITE_MICRO_TESTS_BEGIN              \
00068   namespace micro_test {                       \
00069   int tests_passed;                            \
00070   int tests_failed;                            \
00071   bool is_test_complete;                       \
00072   bool did_test_fail;                          \
00073   tflite::ErrorReporter* reporter;             \
00074   }                                            \
00075                                                \
00076   int main(int argc, char** argv) {            \
00077     micro_test::tests_passed = 0;              \
00078     micro_test::tests_failed = 0;              \
00079     tflite::MicroErrorReporter error_reporter; \
00080     micro_test::reporter = &error_reporter;
00081 
00082 #define TF_LITE_MICRO_TESTS_END                                \
00083   micro_test::reporter->Report(                                \
00084       "%d/%d tests passed", micro_test::tests_passed,          \
00085       (micro_test::tests_failed + micro_test::tests_passed));  \
00086   if (micro_test::tests_failed == 0) {                         \
00087     micro_test::reporter->Report("~~~ALL TESTS PASSED~~~\n");  \
00088   } else {                                                     \
00089     micro_test::reporter->Report("~~~SOME TESTS FAILED~~~\n"); \
00090   }                                                            \
00091   }
00092 
00093 // TODO(petewarden): I'm going to hell for what I'm doing to this poor for loop.
00094 #define TF_LITE_MICRO_TEST(name)                                           \
00095   micro_test::reporter->Report("Testing %s", #name);                       \
00096   for (micro_test::is_test_complete = false,                               \
00097       micro_test::did_test_fail = false;                                   \
00098        !micro_test::is_test_complete; micro_test::is_test_complete = true, \
00099       micro_test::tests_passed += (micro_test::did_test_fail) ? 0 : 1,     \
00100       micro_test::tests_failed += (micro_test::did_test_fail) ? 1 : 0)
00101 
00102 #define TF_LITE_MICRO_EXPECT(x)                                                \
00103   do {                                                                         \
00104     if (!(x)) {                                                                \
00105       micro_test::reporter->Report(#x " failed at %s:%d", __FILE__, __LINE__); \
00106       micro_test::did_test_fail = true;                                        \
00107     }                                                                          \
00108   } while (false)
00109 
00110 #define TF_LITE_MICRO_EXPECT_EQ(x, y)                                          \
00111   do {                                                                         \
00112     if ((x) != (y)) {                                                          \
00113       micro_test::reporter->Report(#x " == " #y " failed at %s:%d (%d vs %d)", \
00114                                    __FILE__, __LINE__, (x), (y));              \
00115       micro_test::did_test_fail = true;                                        \
00116     }                                                                          \
00117   } while (false)
00118 
00119 #define TF_LITE_MICRO_EXPECT_NE(x, y)                                         \
00120   do {                                                                        \
00121     if ((x) == (y)) {                                                         \
00122       micro_test::reporter->Report(#x " != " #y " failed at %s:%d", __FILE__, \
00123                                    __LINE__);                                 \
00124       micro_test::did_test_fail = true;                                       \
00125     }                                                                         \
00126   } while (false)
00127 
00128 // TODO(wangtz): Making it more generic once needed.
00129 #define TF_LITE_MICRO_ARRAY_ELEMENT_EXPECT_NEAR(arr1, idx1, arr2, idx2, \
00130                                                 epsilon)                \
00131   do {                                                                  \
00132     auto delta = ((arr1)[(idx1)] > (arr2)[(idx2)])                      \
00133                      ? ((arr1)[(idx1)] - (arr2)[(idx2)])                \
00134                      : ((arr2)[(idx2)] - (arr1)[(idx1)]);               \
00135     if (delta > epsilon) {                                              \
00136       micro_test::reporter->Report(                                     \
00137           #arr1 "[%d] (%f) near " #arr2 "[%d] (%f) failed at %s:%d",    \
00138           static_cast<int>(idx1), static_cast<float>((arr1)[(idx1)]),   \
00139           static_cast<int>(idx2), static_cast<float>((arr2)[(idx2)]),   \
00140           __FILE__, __LINE__);                                          \
00141       micro_test::did_test_fail = true;                                 \
00142     }                                                                   \
00143   } while (false)
00144 
00145 #define TF_LITE_MICRO_EXPECT_NEAR(x, y, epsilon)                              \
00146   do {                                                                        \
00147     auto delta = ((x) > (y)) ? ((x) - (y)) : ((y) - (x));                     \
00148     if (delta > epsilon) {                                                    \
00149       micro_test::reporter->Report(                                           \
00150           #x " (%f) near " #y " (%f) failed at %s:%d", static_cast<float>(x), \
00151           static_cast<float>(y), __FILE__, __LINE__);                         \
00152       micro_test::did_test_fail = true;                                       \
00153     }                                                                         \
00154   } while (false)
00155 
00156 #define TF_LITE_MICRO_EXPECT_GT(x, y)                                        \
00157   do {                                                                       \
00158     if ((x) <= (y)) {                                                        \
00159       micro_test::reporter->Report(#x " > " #y " failed at %s:%d", __FILE__, \
00160                                    __LINE__);                                \
00161       micro_test::did_test_fail = true;                                      \
00162     }                                                                        \
00163   } while (false)
00164 
00165 #define TF_LITE_MICRO_EXPECT_LT(x, y)                                        \
00166   do {                                                                       \
00167     if ((x) >= (y)) {                                                        \
00168       micro_test::reporter->Report(#x " < " #y " failed at %s:%d", __FILE__, \
00169                                    __LINE__);                                \
00170       micro_test::did_test_fail = true;                                      \
00171     }                                                                        \
00172   } while (false)
00173 
00174 #define TF_LITE_MICRO_EXPECT_GE(x, y)                                         \
00175   do {                                                                        \
00176     if ((x) < (y)) {                                                          \
00177       micro_test::reporter->Report(#x " >= " #y " failed at %s:%d", __FILE__, \
00178                                    __LINE__);                                 \
00179       micro_test::did_test_fail = true;                                       \
00180     }                                                                         \
00181   } while (false)
00182 
00183 #define TF_LITE_MICRO_EXPECT_LE(x, y)                                         \
00184   do {                                                                        \
00185     if ((x) > (y)) {                                                          \
00186       micro_test::reporter->Report(#x " <= " #y " failed at %s:%d", __FILE__, \
00187                                    __LINE__);                                 \
00188       micro_test::did_test_fail = true;                                       \
00189     }                                                                         \
00190   } while (false)
00191 
00192 #define TF_LITE_MICRO_EXPECT_TRUE(x)                                   \
00193   do {                                                                 \
00194     if (!x) {                                                          \
00195       micro_test::reporter->Report(#x " was not true failed at %s:%d", \
00196                                    __FILE__, __LINE__);                \
00197       micro_test::did_test_fail = true;                                \
00198     }                                                                  \
00199   } while (false)
00200 
00201 #define TF_LITE_MICRO_EXPECT_FALSE(x)                                   \
00202   do {                                                                  \
00203     if (x) {                                                            \
00204       micro_test::reporter->Report(#x " was not false failed at %s:%d", \
00205                                    __FILE__, __LINE__);                 \
00206       micro_test::did_test_fail = true;                                 \
00207     }                                                                   \
00208   } while (false)
00209 
00210 #endif  // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_TESTING_MICRO_TEST_H_