tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestBuffer.h (4472B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 #ifndef intl_components_gtest_TestBuffer_h_
      5 #define intl_components_gtest_TestBuffer_h_
      6 
      7 #include <string_view>
      8 #include "mozilla/DebugOnly.h"
      9 #include "mozilla/Utf8.h"
     10 #include "mozilla/Vector.h"
     11 
     12 namespace mozilla::intl {
     13 
     14 /**
     15 * A test buffer for interfacing with unified intl classes.
     16 * Closely resembles the FormatBuffer class, but without
     17 * JavaScript-specific implementation details.
     18 */
     19 template <typename C, size_t inlineCapacity = 0>
     20 class TestBuffer {
     21 public:
     22  using CharType = C;
     23 
     24  // Only allow moves, and not copies, as this class owns the mozilla::Vector.
     25  TestBuffer(TestBuffer&& other) noexcept = default;
     26  TestBuffer& operator=(TestBuffer&& other) noexcept = default;
     27 
     28  explicit TestBuffer(const size_t aSize = 0) { reserve(aSize); }
     29 
     30  /**
     31   * Ensures the buffer has enough space to accommodate |aSize| elemtns.
     32   */
     33  bool reserve(const size_t aSize) { return mBuffer.reserve(aSize); }
     34 
     35  /**
     36   * Returns the raw data inside the buffer.
     37   */
     38  CharType* data() { return mBuffer.begin(); }
     39 
     40  /**
     41   * Returns the count of elements in written to the buffer.
     42   */
     43  size_t length() const { return mBuffer.length(); }
     44 
     45  /**
     46   * Returns the buffer's overall capacity.
     47   */
     48  size_t capacity() const { return mBuffer.capacity(); }
     49 
     50  /**
     51   * Resizes the buffer to the given amount of written elements.
     52   * This is necessary because the buffer gets written to across
     53   * FFI boundaries, so this needs to happen in a separate step.
     54   */
     55  void written(size_t aAmount) {
     56    MOZ_ASSERT(aAmount <= mBuffer.capacity());
     57    mozilla::DebugOnly<bool> result = mBuffer.resizeUninitialized(aAmount);
     58    MOZ_ASSERT(result);
     59  }
     60 
     61  /**
     62   * Get a string view into the buffer, which is useful for test assertions.
     63   */
     64  std::basic_string_view<CharType> get_string_view() {
     65    return std::basic_string_view<CharType>(data(), length());
     66  }
     67 
     68  /**
     69   * Clear the buffer, allowing it to be re-used.
     70   */
     71  void clear() { mBuffer.clear(); }
     72 
     73  /**
     74   * A utility function to convert UTF-16 strings to UTF-8 strings so that they
     75   * can be logged to stderr.
     76   */
     77  static std::string toUtf8(mozilla::Span<const char16_t> input) {
     78    size_t buff_len = input.Length() * 3;
     79    std::string result(buff_len, ' ');
     80    result.reserve(buff_len);
     81    size_t result_len =
     82        ConvertUtf16toUtf8(input, mozilla::Span(result.data(), buff_len));
     83    result.resize(result_len);
     84    return result;
     85  }
     86 
     87  /**
     88   * String buffers, especially UTF-16, do not assert nicely, and are difficult
     89   * to debug. This function is verbose in that it prints the buffer contents
     90   * and expected contents to stderr when they do not match.
     91   *
     92   * Usage:
     93   *   ASSERT_TRUE(buffer.assertStringView(u"9/23/2002, 8:07:30 PM"));
     94   *
     95   * Here is what gtests output:
     96   *
     97   *   Expected equality of these values:
     98   *   buffer.get_string_view()
     99   *     Which is: { '0' (48, 0x30), '9' (57, 0x39), '/' (47, 0x2F), ... }
    100   *   "9/23/2002, 8:07:30 PM"
    101   *     Which is: 0x11600afb9
    102   *
    103   * Here is what this method outputs:
    104   *
    105   *   The buffer did not match:
    106   *     Buffer:
    107   *      u"9/23/2002, 8:07:30 PM"
    108   *     Expected:
    109   *      u"09/23/2002, 08:07:30 PM"
    110   */
    111  [[nodiscard]] bool verboseMatches(const CharType* aExpected) {
    112    std::basic_string_view<CharType> actualSV(data(), length());
    113    std::basic_string_view<CharType> expectedSV(aExpected);
    114 
    115    if (actualSV.compare(expectedSV) == 0) {
    116      return true;
    117    }
    118 
    119    static_assert(std::is_same_v<CharType, char> ||
    120                  std::is_same_v<CharType, char16_t>);
    121 
    122    std::string actual;
    123    std::string expected;
    124    const char* startQuote;
    125 
    126    if constexpr (std::is_same_v<CharType, char>) {
    127      actual = std::string(actualSV);
    128      expected = std::string(expectedSV);
    129      startQuote = "\"";
    130    }
    131    if constexpr (std::is_same_v<CharType, char16_t>) {
    132      actual = toUtf8(actualSV);
    133      expected = toUtf8(expectedSV);
    134      startQuote = "u\"";
    135    }
    136 
    137    fprintf(stderr, "The buffer did not match:\n");
    138    fprintf(stderr, "  Buffer:\n    %s%s\"\n", startQuote, actual.c_str());
    139    fprintf(stderr, "  Expected:\n    %s%s\"\n", startQuote, expected.c_str());
    140 
    141    return false;
    142  }
    143 
    144  Vector<C, inlineCapacity> mBuffer{};
    145 };
    146 
    147 }  // namespace mozilla::intl
    148 
    149 #endif