android13/system/chre/test/simulation/inc/test_event_queue.h

144 lines
4.6 KiB
C++

/*
* Copyright (C) 2021 The Android Open Source Project
*
* 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
*
* http://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.
*/
#ifndef CHRE_SIMULATION_TEST_EVENT_QUEUE_H_
#define CHRE_SIMULATION_TEST_EVENT_QUEUE_H_
#include <gtest/gtest.h>
#include <cinttypes>
#include "chre/platform/memory.h"
#include "chre/util/fixed_size_blocking_queue.h"
#include "chre/util/memory.h"
#include "chre/util/non_copyable.h"
#include "chre/util/singleton.h"
#include "test_event.h"
namespace chre {
//! A test event type to indicate the test nanoapp has loaded.
#define CHRE_EVENT_SIMULATION_TEST_NANOAPP_LOADED \
CHRE_SIMULATION_TEST_EVENT_ID(0)
//! A test event type to indicate the test has timed out, and should abort.
#define CHRE_EVENT_SIMULATION_TEST_TIMEOUT CHRE_SIMULATION_TEST_EVENT_ID(1)
//! A test event type to indicate the test nanoapp has unloaded.
#define CHRE_EVENT_SIMULATION_TEST_NANOAPP_UNLOADED \
CHRE_SIMULATION_TEST_EVENT_ID(2)
/**
* A class that monitors events for the test to consume.
*
* This class can be used as an execution barrier for the test, i.e. waiting
* for a specific event to occur. The barrier is done through the semantics of
* CHRE events, and can be used e.g. for nanoapps to redirect incoming events
* using pushEvent().
*
* The main test thread can then wait for this event using waitForEvent().
*
* Note 1) pushEvent() can also be invoked outside the nanoapp, for instance
* using deferred system callbacks.
* Note 2) The CHRE_EVENT_SIMULATION_TEST_TIMEOUT event type can be used to
* abort the test due to a timeout (this usage is recommended in order to avoid
* the test framework from stalling).
*/
class TestEventQueue : public NonCopyable {
public:
//! Push an event to the queue.
void pushEvent(uint16_t eventType) {
mQueue.push({eventType});
}
/**
* Push an event with data to the queue.
*
* Note: The data passed to this method must be trivially copyable. It is
* recommended to pass a scalar or a struct composed of scalars only. If this
* method is used in the test nanoapp handleEvent be careful not to forward
* pointers to memory that could be freed by the CHRE framework before the
* data is received using @ref waitForEvent.
*
* @param eventType The type of event.
* @param eventData The data to send together with the event, which must not
* contain references to dynamically allocated memory.
*/
template <class T>
void pushEvent(uint16_t eventType, T eventData) {
static_assert(std::is_trivial<T>::value);
auto ptr = memoryAlloc<T>();
ASSERT_NE(ptr, nullptr);
*ptr = eventData;
mQueue.push({eventType, static_cast<void *>(ptr)});
}
//! Block until the event happens.
void waitForEvent(uint16_t eventType) {
while (true) {
auto event = mQueue.pop();
LOGD("Got event type 0x%" PRIx16, eventType);
ASSERT_NE(event.type, CHRE_EVENT_SIMULATION_TEST_TIMEOUT)
<< "Timeout waiting for event " << eventType;
memoryFree(event.data);
if (event.type == eventType) {
break;
}
}
}
//! Block until the event happens and populate the event data.
template <class T>
void waitForEvent(uint16_t eventType, T *data) {
static_assert(std::is_trivial<T>::value);
while (true) {
auto event = mQueue.pop();
LOGD("Got event type 0x%" PRIx16, eventType);
ASSERT_NE(event.type, CHRE_EVENT_SIMULATION_TEST_TIMEOUT)
<< "Timeout waiting for event " << eventType;
if (event.type == eventType) {
*data = *(static_cast<T *>(event.data));
memoryFree(event.data);
break;
}
memoryFree(event.data);
}
}
//! Flush the queue.
void flush() {
while (!mQueue.empty()) {
auto event = mQueue.pop();
memoryFree(event.data);
}
}
private:
static const size_t kQueueCapacity = 64;
FixedSizeBlockingQueue<TestEvent, kQueueCapacity> mQueue;
};
//! Provide an alias to the TestEventQueue singleton.
typedef Singleton<TestEventQueue> TestEventQueueSingleton;
//! Extern the explicit TestEventQueueSingleton to force non-inline method
//! calls.
extern template class Singleton<TestEventQueue>;
} // namespace chre
#endif // CHRE_SIMULATION_TEST_EVENT_QUEUE_H_