You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
hmz007 36ed224bac
Rockchip Anroid14_SDK 20240628-rkr5 (2556df1a)
1 year ago
..
inc Rockchip Anroid14_SDK 20240628-rkr5 (2556df1a) 1 year ago
rpc Rockchip Anroid14_SDK 20240628-rkr5 (2556df1a) 1 year ago
README.md Rockchip Anroid14_SDK 20240628-rkr5 (2556df1a) 1 year ago
audio_test.cc Rockchip Anroid14_SDK 20240628-rkr5 (2556df1a) 1 year ago
ble_test.cc Rockchip Anroid14_SDK 20240628-rkr5 (2556df1a) 1 year ago
gnss_test.cc Rockchip Anroid14_SDK 20240628-rkr5 (2556df1a) 1 year ago
host_endpoint_notification_test.cc Rockchip Anroid14_SDK 20240628-rkr5 (2556df1a) 1 year ago
info_struct_version_test.cc Rockchip Anroid14_SDK 20240628-rkr5 (2556df1a) 1 year ago
memory_test.cc Rockchip Anroid14_SDK 20240628-rkr5 (2556df1a) 1 year ago
rpc_test.cc Rockchip Anroid14_SDK 20240628-rkr5 (2556df1a) 1 year ago
sensor_test.cc Rockchip Anroid14_SDK 20240628-rkr5 (2556df1a) 1 year ago
settings_test.cc Rockchip Anroid14_SDK 20240628-rkr5 (2556df1a) 1 year ago
test_base.cc Rockchip Anroid14_SDK 20240628-rkr5 (2556df1a) 1 year ago
test_util.cc Rockchip Anroid14_SDK 20240628-rkr5 (2556df1a) 1 year ago
timer_test.cc Rockchip Anroid14_SDK 20240628-rkr5 (2556df1a) 1 year ago
wifi_nan_test.cc Rockchip Anroid14_SDK 20240628-rkr5 (2556df1a) 1 year ago
wifi_scan_test.cc Rockchip Anroid14_SDK 20240628-rkr5 (2556df1a) 1 year ago
wifi_test.cc Rockchip Anroid14_SDK 20240628-rkr5 (2556df1a) 1 year ago
wifi_timeout_test.cc Rockchip Anroid14_SDK 20240628-rkr5 (2556df1a) 1 year ago

README.md

CHRE Simulation Test Framework

Background

Simulation tests are written for the CHRE linux (i.e. simulation) platform, and can be useful in validating higher level CHRE behavior. By "higher level", we mean:

  • More coverage than a module-level unit test.
  • But smaller in scope compared to a full end-to-end integration test.

You can think of a simulation test as treating the core CHRE framework as a black box, and is able to validate its output.

Running the tests

You can run simulation tests through atest:

atest --host chre_simulation_tests

How to write a test

The simulation test framework encourages writing self contained tests as follow:

// Use the same unique prefix for all the tests in a single file
TEST_F(TestBase, <PrefixedTestName>) {
  // 1. Create tests event to trigger code in the Nanoapp context.
  CREATE_CHRE_TEST_EVENT(MY_TEST_EVENT, 0);

  // 2. Create a test Nanpoapp by inheriting TestNanoapp.
  struct App : public TestNanoapp {
    decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
                                                   const void *eventData) {
      switch (eventType) {
        // 3. Handle system events.
        case CHRE_EVENT_WIFI_ASYNC_RESULT: {
          // ...
          // 4. Send event back to the test.
          TestEventQueueSingleton::get()->pushEvent(
            CHRE_EVENT_WIFI_ASYNC_RESULT)
          break;
        }

        case CHRE_EVENT_TEST_EVENT: {
          auto event = static_cast<const TestEvent *>(eventData);
          switch (event->type) {
            // 5. Handle test events to execute code in the context the Nanoapp.
            case MY_TEST_EVENT:
              // ...
              break;
          }
        }
      }
    };
  };

  // 6. Load the app and add initial expectations.
  auto app = loadNanoapp<App>();
  EXPECT_TRUE(...);

  // 7. Send test events to the Nanoapp to execute some actions and add
  //    expectations about the result.
  sendEventToNanoapp(app, MY_TEST_EVENT);
  waitForEvent(CHRE_EVENT_WIFI_ASYNC_RESULT);
  EXPECT_TRUE(...);

  // 8. Optionally unload the Nanoapp
  unloadNanoapp(app);
}
Test app (#2, #6, #8)

Inherit from TestNanoapp to create a test nanoapp. The following properties oif a nanoapp can be overridden name, id, version, perms, start, handleEvent, and end.

Typical tests only override of few of the above properties:

  • perms to set the permissions required for the test,
  • start to put the system in a known state before each test,
  • handleEvent is probably the most important function where system and test events are handled. See the sections below for more details.
Test events (#1)

The test events are local to a single test and created using the CREATE_CHRE_TEST_EVENT(name, id) macro. The id must be unique in a single test and in the range [0, 0xfff].

System event (#3)

Add code to handleEvent to handle the system events you are interested in for the test:

decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
                                               const void *eventData) {
  switch (eventType) {
    case CHRE_EVENT_WIFI_ASYNC_RESULT: {
      // ...
      break;
    }
  }
};

The handler would typically send an event back to the nanoapp, see the next section for more details.

Send event from the nanoapp (#4)

You can send an event from the nanoapp (typically inside handleEvent):

// Sending a system event.
TestEventQueueSingleton::get()->pushEvent(CHRE_EVENT_WIFI_ASYNC_RESULT);

// Sending a test event.
TestEventQueueSingleton::get()->pushEvent(MY_TEST_EVENT);

Use waitForEvent to wait for an event in your test code:

// Wait for a system event.
waitForEvent(CHRE_EVENT_WIFI_ASYNC_RESULT);

// Wait for a test event.
waitForEvent(MY_TEST_EVENT);

Waiting for an event as described above is sufficient to express a boolean expectation. For example the status of an event:

  decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
                                                 const void *eventData) {
    switch (eventType) {
      case CHRE_EVENT_WIFI_ASYNC_RESULT: {
        auto *event = static_cast<const chreAsyncResult *>(eventData);
        if (event->success) {
          TestEventQueueSingleton::get()->pushEvent(
              CHRE_EVENT_WIFI_ASYNC_RESULT);
        }
        break;
      }
    }
  };
};

With the above snippet waitForEvent(CHRE_EVENT_WIFI_ASYNC_RESULT) will timeout if the nanoapp did not receive a successful status.

Sometimes you want to attach additional data alongside the event. Simply pass the data as the second argument to pushEvent:

    decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
                                                   const void *eventData) {
      switch (eventType) {
        case CHRE_EVENT_WIFI_ASYNC_RESULT: {
          auto *event = static_cast<const chreAsyncResult *>(eventData);
          if (event->success) {
            TestEventQueueSingleton::get()->pushEvent(
                CHRE_EVENT_WIFI_ASYNC_RESULT,
                *(static_cast<const uint32_t *>(event->cookie)));
          }
          break;
        }
      }
    };

The data must be trivially copyable (a scalar or a struct of scalar are safe).

Use the second argument of waitForEvent to retrieve the data in your test code:

uint32_t cookie;
waitForEvent(CHRE_EVENT_WIFI_ASYNC_RESULT, &cookie);
EXPECT_EQ(cookie, ...);
Send event to the nanoapp (#5)

To execute the code in the nanoapp context, you will need to create a test event and send it to the nanoapp as follow:

CREATE_CHRE_TEST_EVENT(MY_TEST_EVENT, 0);

// ...

sendEventToNanoapp(app, MY_TEST_EVENT);

The code to be executed in the context of the nanoapp should be added to its handleEvent function:

decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
                                               const void *eventData) {
  switch (eventType) {
    // Test event are received with a CHRE_EVENT_TEST_EVENT type.
    case CHRE_EVENT_TEST_EVENT: {
      auto event = static_cast<const TestEvent *>(eventData);
      switch (event->type) {
        // Create a case for each of the test events.
        case MY_TEST_EVENT:
          // Code running in the context of the nanoapp.
          break;
      }
    }
  }
};

It is possible to send data alongside a test event:

bool enable = true;
sendEventToNanoapp(app, MY_TEST_EVENT, &enable);

The data should be a scalar type or a struct of scalars. Be careful not to send a pointer to a memory block that might be released before the data is consumed in handleEvent. This would result in a use after free error and flaky tests.

The handleEvent function receives a copy of the data in the data field of the TestEvent:

decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
                                               const void *eventData) {
  switch (eventType) {
    // Test event are received with a CHRE_EVENT_TEST_EVENT type.
    case CHRE_EVENT_TEST_EVENT: {
      auto event = static_cast<const TestEvent *>(eventData);
      switch (event->type) {
        // Create a case for each of the test events.
        case MY_TEST_EVENT:
          chreFunctionTakingABool(*(bool*(event->data)));
          break;
      }
    }
  }
};