14d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro/*
24d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro * Copyright (C) 2016 The Android Open Source Project
34d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro *
44d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro * Licensed under the Apache License, Version 2.0 (the "License");
54d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro * you may not use this file except in compliance with the License.
64d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro * You may obtain a copy of the License at
74d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro *
84d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro *      http://www.apache.org/licenses/LICENSE-2.0
94d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro *
104d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro * Unless required by applicable law or agreed to in writing, software
114d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro * distributed under the License is distributed on an "AS IS" BASIS,
124d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro * See the License for the specific language governing permissions and
144d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro * limitations under the License.
154d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro */
164d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro
174d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#include <general_test/simple_heap_alloc_test.h>
184d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro
194d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#include <cstddef>
204d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro
214d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#include <general_test/test_names.h>
224d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#include <shared/abort.h>
234d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#include <shared/array_length.h>
244d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#include <shared/nano_string.h>
254d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#include <shared/send_message.h>
264d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro
274d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#include <chre.h>
284d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro
294d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishigurousing nanoapp_testing::MessageType;
304d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishigurousing nanoapp_testing::sendFatalFailureToHost;
314d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishigurousing nanoapp_testing::sendMessageToHost;
324d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishigurousing nanoapp_testing::sendSuccessToHost;
334d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro
344d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguronamespace general_test {
354d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro
364d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro// For most platforms, we expect that what the compiler toolchain claims
374d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro// is the maximum alignment needed for any type is accurate.  However, we
384d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro// do support one CHRE implementation where it is configured for a lower
394d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro// max alignment than what the toolchain claims.
404d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro// To support this, we allow for a compiler define set for building this
414d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro// test.  For the most part, we need to just trust the CHRE implementation
424d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro// that this number is correct.  However, we make a basic sanity check of
434d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro// this in testMaxAlignment().
444d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro
454d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguroconstexpr size_t kMaxAlignment =
464d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#ifdef CHRE_CUSTOM_MAX_ALIGNMENT
474d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro    CHRE_CUSTOM_MAX_ALIGNMENT;
484d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#else
494d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro    alignof(max_align_t);
504d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#endif  // else CHRE_CUSTOM_MAX_ALIGNMENT
514d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro
524d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#ifdef CHRE_CUSTOM_MAX_ALIGNMENT
534d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro// We only test this when a CHRE implementation claims a custom max aligment.
544d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro// We use an argument here to try to keep the compiler from performing any
554d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro// of these calculations at compile-time, so they're forced to happen at
564d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro// runtime.  We do a mixture of multiplication and division, to force
574d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro// various instructions which might have alignment constraints.
584d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishigurostatic void testMaxAlignment(uint32_t zero) {
594d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  // It's not sufficient to use alignas(kMaxAlignment).  Say kMaxAlignment
604d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  // is 4.  Then alignas(4) could legally give something aligned on 32 bytes,
614d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  // and we wouldn't be testing what we hoped to test.  So we ask for double
624d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  // the alignment (alignas(8), in our example), and then offset into that
634d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  // to assure that we're at exactly kMaxAlignment, and no more.
644d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro
654d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#ifdef CHRE_NO_DOUBLE_SUPPORT
664d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  typedef float MyFloat;
674d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#define FLOAT_C(value) value##f
684d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#else
694d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  typedef long double myFloat;
704d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#define FLOAT_C(value) value
714d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#endif
724d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro
734d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  alignas(kMaxAlignment * 2) uint8_t
744d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro      myFloatMemory[sizeof(MyFloat) * 3 + kMaxAlignment];
754d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  MyFloat *mfArray =
764d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro      reinterpret_cast<MyFloat*>(myFloatMemory + kMaxAlignment);
774d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  mfArray[0] = static_cast<MyFloat>(zero) + FLOAT_C(1.0);
784d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  mfArray[1] = static_cast<MyFloat>(zero) + FLOAT_C(3.0);
794d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  mfArray[2] = mfArray[0] / mfArray[1];
804d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  if ((mfArray[0] * mfArray[1] + mfArray[2]) / FLOAT_C(3.0) == FLOAT_C(1.0)) {
814d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro    sendFatalFailureToHost("Float math is wrong");
824d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  }
834d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro
844d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  constexpr size_t kUllSize = sizeof(unsigned long long);
854d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  static_assert(kUllSize >= 8, "Size of long long violates spec");
864d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  alignas(kMaxAlignment * 2) uint8_t
874d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro      longlongMemory[kUllSize * 3 + kMaxAlignment];
884d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  unsigned long long *ullArray =
894d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro      reinterpret_cast<unsigned long long*>(longlongMemory + kMaxAlignment);
904d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  ullArray[0] = static_cast<unsigned long long>(zero) +
914d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro      (1ULL << (kUllSize * 8 - 4));
924d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  ullArray[1] = static_cast<unsigned long long>(zero) + (1ULL << 3);
934d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  ullArray[2] = ullArray[0] * ullArray[1];
944d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  constexpr unsigned long long kExpected = 747134227367742ULL;
954d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  unsigned long long result = ullArray[2] / 12345ULL;
964d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  if (((kUllSize == 8) && (result != kExpected)) ||
974d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro      ((kUllSize > 8) && (result <= kExpected))) {
984d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro    sendFatalFailureToHost("Long long math is wrong");
994d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  }
1004d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro}
1014d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#endif  // CHRE_CUSTOM_MAX_ALIGNMENT
1024d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro
1034d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro
1044d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur IshiguroSimpleHeapAllocTest::SimpleHeapAllocTest()
1054d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  : Test(CHRE_API_VERSION_1_0), mHasFreed(false) {
1064d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro}
1074d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro
1084d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishigurovoid SimpleHeapAllocTest::setUp(uint32_t messageSize,
1094d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro                                const void * /* message */) {
1104d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  nanoapp_testing::memset(mPtrs, 0, sizeof(mPtrs));
1114d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro
1124d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  if (messageSize != 0) {
1134d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro    sendFatalFailureToHost(
1144d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro        "SimpleHeapAlloc message expects 0 additional bytes, got ",
1154d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro        &messageSize);
1164d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  }
1174d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro
1184d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  // Allocate random small-ish sizes.
1194d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  static constexpr size_t kSizes[5] = {
1204d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro    16, 53, 2, 32, 40 };
1214d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro
1224d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  mPtrs[0] = chreHeapAlloc(kSizes[0]);
1234d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  mPtrs[1] = chreHeapAlloc(kSizes[1]);
1244d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  // For mPtrs[2] we do _not_ use kSizes[2], because we're going to free
1254d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  // this in a moment, and intentionally want a different size.
1264d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  mPtrs[2] = chreHeapAlloc(23);
1274d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  mPtrs[3] = chreHeapAlloc(kSizes[3]);
1284d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  // We want to mix in a free among the allocs, just to make sure there
1294d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  // isn't some issue there.
1304d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  if (mPtrs[2] == nullptr) {
1314d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro    sendFatalFailureToHost("Failed first allocation of mPtrs[2]");
1324d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  } else {
1334d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro    chreHeapFree(mPtrs[2]);
1344d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  }
1354d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  mPtrs[4] = chreHeapAlloc(kSizes[4]);
1364d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  mPtrs[2] = chreHeapAlloc(kSizes[2]);
1374d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro
1384d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  for (uint32_t i = 0; i < arrayLength(mPtrs); i++) {
1394d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro    if (mPtrs[i] == nullptr) {
1404d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro      // If we're getting this failure, but convinced the CHRE is
1414d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro      // correct, make sure that we're actually performing an allocation
1424d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro      // for each element of mPtrs.
1434d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro      sendFatalFailureToHost("Failed to allocate index ", &i);
1444d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro    }
1454d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro    const uintptr_t ptrValue = reinterpret_cast<uintptr_t>(mPtrs[i]);
1464d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro    if ((ptrValue & (kMaxAlignment - 1)) != 0) {
1474d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro      sendFatalFailureToHost("Misaligned allocation at index ", &i);
1484d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro    }
1494d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro    // Make sure all of the bytes are addressable.  Our assumption
1504d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro    // is we'll crash here if that's not the case.  Not the most
1514d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro    // friendly test, but it's better than allowing a bad CHRE.
1524d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro    // TODO: If we convince ourselves that chreLog() should be
1534d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro    //     safe enough to use here, we could log an 'info' message
1544d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro    //     prior to each memset attempt.
1554d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro    nanoapp_testing::memset(mPtrs[i], 0xFF, kSizes[i]);
1564d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  }
1574d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#ifdef CHRE_CUSTOM_MAX_ALIGNMENT
1584d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  testMaxAlignment(messageSize);
1594d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro#endif  // CHRE_CUSTOM_MAX_ALIGNMENT
1604d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  sendMessageToHost(MessageType::kContinue);
1614d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro}
1624d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro
1634d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishigurovoid SimpleHeapAllocTest::handleEvent(uint32_t senderInstanceId,
1644d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro                                      uint16_t eventType,
1654d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro                                      const void* eventData) {
1664d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  // We ignore the return value, since we expect no data.
1674d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  getMessageDataFromHostEvent(senderInstanceId, eventType, eventData,
1684d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro                              MessageType::kContinue, 0);
1694d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  if (mHasFreed) {
1704d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro    sendFatalFailureToHost("Multiple kContinue messages sent");
1714d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  }
1724d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro
1734d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  chreHeapFree(mPtrs[3]);
1744d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  chreHeapFree(mPtrs[1]);
1754d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  chreHeapFree(mPtrs[2]);
1764d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  chreHeapFree(mPtrs[0]);
1774d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  chreHeapFree(mPtrs[4]);
1784d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  mHasFreed = true;
1794d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro
1804d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro  sendSuccessToHost();
1814d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro}
1824d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro
1834d04a937b1bf7a949dfb00650b2640a9ed0c8acaArthur Ishiguro}  // namespace general_test
184