pw_assert: Add real assert facade tests

This splits out the tests into backend compile tests and direct facade
tests, by directly depending on the facade implementation (rather than
going through the backend header redirection) and adding a fake
capturing assert backend that captures assert arguments.

Change-Id: Ie6d8c837d5abaa9f735f9e552791e939d6f2a245
diff --git a/pw_assert/assert_backend_compile_test.cc b/pw_assert/assert_backend_compile_test.cc
new file mode 100644
index 0000000..49666eb
--- /dev/null
+++ b/pw_assert/assert_backend_compile_test.cc
@@ -0,0 +1,184 @@
+// Copyright 2020 The Pigweed Authors
+//
+// 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
+//
+//     https://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.
+
+// This series of "tests" is more a compile test to verify that the assert
+// backend is able to compile the constructs promised by the assert facade.
+// Truly testing the backend in a general way from the facade is impossible
+// since the device will go down when an assert triggers, and so that must be
+// handled inside the individual backends.
+//
+// NOTE: While these tests are not intended to run, it *is* possible to run
+// them with the assert_basic backend, in a special mode where the assert
+// statements fall through instead of aborting.
+//
+// To run these "tests" for pw_assert_basic, you must modify two things:
+//
+//   (1) Set DISABLE_ASSERT_TEST_EXECUTION 0 in assert_backend_compile_test.cc
+//   (2) Set DISABLE_ASSERT_TEST_EXECUTION 0 in assert_backend_compile_test.c
+//   (3) Set PW_ASSERT_BASIC_DISABLE_NORETURN 1 in assert_basic.h
+//   (4) Compile and run the resulting binary, paying attention to the
+//       displayed error messages. If "FAIL IF DISPLAYED" is printed, the
+//       test has failed. If any "FAIL_IF_HIDDEN" asserts are not displayed,
+//       the test has failed. Obviously manually verifying these is a pain
+//       and so this is not a suitable test for production.
+//
+// TODO(pwbug/88): Add verification of the actually recorded asserts statements.
+
+// clang-format off
+#define PW_ASSERT_USE_SHORT_NAMES 1
+#include "pw_assert/assert.h"
+// clang-format on
+
+#include "gtest/gtest.h"
+
+// This is a global constant to feed into the formatter for tests.
+// Intended to pair with FAIL_IF_DISPLAYED_ARGS or FAIL_IF_HIDDEN_ARGS.
+static const int z = 10;
+
+// At some point in the future when there is a proper test system in place for
+// crashing, the below strings can help indicate pass/fail for a check.
+
+#define FAIL_IF_DISPLAYED "FAIL IF DISPLAYED"
+#define FAIL_IF_DISPLAYED_ARGS "FAIL IF DISPLAYED: %d"
+
+#define FAIL_IF_HIDDEN "FAIL IF HIDDEN"
+#define FAIL_IF_HIDDEN_ARGS "FAIL IF HIDDEN: %d"
+
+// This switch exists to support compiling and/or running the tests.
+#define DISABLE_ASSERT_TEST_EXECUTION 1
+#if DISABLE_ASSERT_TEST_EXECUTION
+#define MAYBE_SKIP_TEST return
+#else
+#define MAYBE_SKIP_TEST ;
+#endif
+
+namespace {
+
+TEST(Crash, WithAndWithoutMessageArguments) {
+  MAYBE_SKIP_TEST;
+  PW_CRASH(FAIL_IF_HIDDEN);
+  PW_CRASH(FAIL_IF_HIDDEN_ARGS, z);
+}
+
+TEST(Check, NoMessage) {
+  MAYBE_SKIP_TEST;
+  PW_CHECK(true);
+  PW_CHECK(false);
+}
+
+TEST(Check, WithMessageAndArgs) {
+  MAYBE_SKIP_TEST;
+  PW_CHECK(true, FAIL_IF_DISPLAYED);
+  PW_CHECK(true, FAIL_IF_DISPLAYED_ARGS, z);
+
+  PW_CHECK(false, FAIL_IF_HIDDEN);
+  PW_CHECK(false, FAIL_IF_HIDDEN_ARGS, z);
+}
+
+TEST(Check, IntComparison) {
+  MAYBE_SKIP_TEST;
+  int x_int = 50;
+  int y_int = 66;
+
+  PW_CHECK_INT_LE(x_int, y_int);
+  PW_CHECK_INT_LE(x_int, y_int, "INT: " FAIL_IF_DISPLAYED);
+  PW_CHECK_INT_LE(x_int, y_int, "INT: " FAIL_IF_DISPLAYED_ARGS, z);
+
+  PW_CHECK_INT_GE(x_int, y_int);
+  PW_CHECK_INT_GE(x_int, y_int, "INT: " FAIL_IF_HIDDEN);
+  PW_CHECK_INT_GE(x_int, y_int, "INT: " FAIL_IF_HIDDEN_ARGS, z);
+}
+
+TEST(Check, UintComparison) {
+  MAYBE_SKIP_TEST;
+  unsigned int x_uint = 50;
+  unsigned int y_uint = 66;
+
+  PW_CHECK_UINT_LE(x_uint, y_uint);
+  PW_CHECK_UINT_LE(x_uint, y_uint, "UINT: " FAIL_IF_DISPLAYED);
+  PW_CHECK_UINT_LE(x_uint, y_uint, "UINT: " FAIL_IF_DISPLAYED_ARGS, z);
+
+  PW_CHECK_UINT_GE(x_uint, y_uint);
+  PW_CHECK_UINT_GE(x_uint, y_uint, "UINT: " FAIL_IF_HIDDEN);
+  PW_CHECK_UINT_GE(x_uint, y_uint, "UINT: " FAIL_IF_HIDDEN_ARGS, z);
+}
+
+TEST(Check, FloatComparison) {
+  MAYBE_SKIP_TEST;
+  float x_float = 50.5;
+  float y_float = 66.5;
+
+  PW_CHECK_FLOAT_LE(x_float, y_float);
+  PW_CHECK_FLOAT_LE(x_float, y_float, "FLOAT: " FAIL_IF_DISPLAYED);
+  PW_CHECK_FLOAT_LE(x_float, y_float, "FLOAT: " FAIL_IF_DISPLAYED_ARGS, z);
+
+  PW_CHECK_FLOAT_GE(x_float, y_float);
+  PW_CHECK_FLOAT_GE(x_float, y_float, "FLOAT: " FAIL_IF_HIDDEN);
+  PW_CHECK_FLOAT_GE(x_float, y_float, "FLOAT: " FAIL_IF_HIDDEN_ARGS, z);
+}
+
+static int Add3(int a, int b, int c) { return a + b + c; }
+
+TEST(Check, ComparisonArgumentsWithCommas) {
+  MAYBE_SKIP_TEST;
+  int x_int = 50;
+  int y_int = 66;
+
+  PW_CHECK_INT_LE(Add3(1, 2, 3), y_int);
+  PW_CHECK_INT_LE(x_int, Add3(1, 2, 3));
+
+  PW_CHECK_INT_LE(Add3(1, 2, 3), y_int, FAIL_IF_DISPLAYED);
+  PW_CHECK_INT_LE(x_int, Add3(1, 2, 3), FAIL_IF_DISPLAYED_ARGS, z);
+
+  PW_CHECK_INT_LE(Add3(1, 2, 3), Add3(1, 2, 3), "INT: " FAIL_IF_DISPLAYED);
+  PW_CHECK_INT_LE(x_int, y_int, "INT: " FAIL_IF_DISPLAYED_ARGS, z);
+}
+
+// Note: This requires enabling PW_ASSERT_USE_SHORT_NAMES 1 above.
+TEST(Check, ShortNamesWork) {
+  MAYBE_SKIP_TEST;
+
+  // Crash
+  CRASH(FAIL_IF_HIDDEN);
+  CRASH(FAIL_IF_HIDDEN_ARGS, z);
+
+  // Check
+  CHECK(true, FAIL_IF_DISPLAYED);
+  CHECK(true, FAIL_IF_DISPLAYED_ARGS, z);
+  CHECK(false, FAIL_IF_HIDDEN);
+  CHECK(false, FAIL_IF_HIDDEN_ARGS, z);
+
+  // Check with binary comparison
+  int x_int = 50;
+  int y_int = 66;
+
+  CHECK_INT_LE(Add3(1, 2, 3), y_int);
+  CHECK_INT_LE(x_int, Add3(1, 2, 3));
+
+  CHECK_INT_LE(Add3(1, 2, 3), y_int, FAIL_IF_DISPLAYED);
+  CHECK_INT_LE(x_int, Add3(1, 2, 3), FAIL_IF_DISPLAYED_ARGS, z);
+
+  CHECK_INT_LE(Add3(1, 2, 3), Add3(1, 2, 3), "INT: " FAIL_IF_DISPLAYED);
+  CHECK_INT_LE(x_int, y_int, "INT: " FAIL_IF_DISPLAYED_ARGS, z);
+}
+
+// These are defined in assert_test.c, to test C compatibility.
+extern "C" void AssertBackendCompileTestsInC();
+
+TEST(Check, AssertBackendCompileTestsInC) {
+  MAYBE_SKIP_TEST;
+  AssertBackendCompileTestsInC();
+}
+
+}  // namespace