boost_test_technical_details.qbk 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. [/
  2. / Copyright (c) 2015 Boost.Test contributors
  3. /
  4. / Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. /]
  7. [section:internal_details `BOOST_TEST`: details on expressions]
  8. Let's consider the following example:
  9. [bt_example boost_test_macro3..BOOST_TEST reporting..run-fail]
  10. It was already mentioned that the reporting is not symmetrical (see [link boost_test.testing_tools.reports here]).
  11. An expression is constructed from the `statement` appearing in the `BOOST_TEST` macro. This expression allows evaluation and reporting such
  12. as `"13 - 1 >= 12" failed` along with a copy of the `statement`, which contains more details than `"a - 1 < b" failed`.
  13. In details, what happens is the following:
  14. # a special object, the `seed` of the expression, is composed from the left side of `statement`.
  15. This initial composition has highest precedence over the supported operations. The expression below:
  16. a op1 b op2 c op3 d
  17. is actually seen as
  18. ( seed a ) op1 b op2 c op3 d
  19. # The "`seed a`" returns an `expression` object that keep tracks of the type of `a`. This expression
  20. has overloads for left-to-right associativity, and the
  21. operations `op1`, `op2` ... are /chained/ to the right of this expression object:
  22. a op1 b
  23. yields to the pseudo-code
  24. expression1 = create-expression(a)
  25. expression2 = create-expression(expression1, op1, b)
  26. `expression1` and `expression2` keep track of their left and right operands, and the operation on those operands. The
  27. expressions keep also track of the result type of the associated sub-expression. In the above example, `expression1` and `expression2`
  28. have result type `decltype(a)` and `decltype(a op1 b)` respectively. The result type allows for chaining
  29. sub-expressions.
  30. # The C++ operators precedence rules apply in any case. What is seen by the expression is what is reachable with left-to-right
  31. composition. Any other operation that happens before it reaches the expression's right operand is not parsed as a sub-expression
  32. and is seen as a single operand: the right operand is not developed further by the framework.
  33. Let's suppose `op2` below has higher precedence than `op1`, then
  34. a op1 b op2 c
  35. is equivalent to:
  36. create-expression(create-expression(a), op1, (b op2 c))
  37. In the above statement, the final expression can only see the result of `(b op2 c)` to its right, for which no further detail
  38. can be provided in the logs. This is also the case for /right-to-left/ associative operators, such as `!`, `~`, `-` (unary negation)
  39. etc.
  40. [caution Since the `expression` object is composed from left-to-right, it actually observes a chain of operations and
  41. not the full expression tree.]
  42. # Once the full expression chain is built, it is evaluated as a chain of sub-expressions from left-to-right, exactly as the
  43. composition rule above. The evaluated elements are the ones of the expression itself. The expression
  44. a op1 b
  45. yields to the following evaluation chain:
  46. expression2.result = expression1.result op1 b
  47. expression1.result = a
  48. The final expression of the statement is cast to a boolean, which is in turn evaluated by the __UTF__.
  49. The example below illustrates the construction of the left-to-right /chained/ expression.
  50. [bt_example boost_test_macro2..BOOST_TEST compound statements..run-fail]
  51. [endsect]