blob: 88a3f503fcd6c9645c2eb18227ecb14d448ea8aa [file] [log] [blame]
// Copyright 2020 The Pigweed Authors
//
// 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
//
// https://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.
#include "pw_log_rpc/logs_rpc.h"
#include "gtest/gtest.h"
#include "pw_log/log.h"
#include "pw_rpc/raw_test_method_context.h"
namespace pw::log_rpc {
namespace {
#define LOGS_METHOD_CONTEXT PW_RAW_TEST_METHOD_CONTEXT(Logs, Get)
constexpr size_t kEncodeBufferSize = 128;
constexpr size_t kLogBufferSize = 4096;
class LogQueueTester : public LogQueueWithEncodeBuffer<kLogBufferSize> {
public:
LogQueueTester(ByteSpan log_queue)
: LogQueueWithEncodeBuffer<kLogBufferSize>(log_queue) {}
void SetPopStatus(Status error_status) {
pop_status_for_test_ = error_status;
}
};
class LogsService : public ::testing::Test {
public:
LogsService() : log_queue_(log_queue_buffer_) {}
protected:
void AddLogs(const size_t log_count = 1) {
constexpr char kTokenizedMessage[] = "message";
for (size_t i = 0; i < log_count; i++) {
EXPECT_EQ(
OkStatus(),
log_queue_.PushTokenizedMessage(
std::as_bytes(std::span(kTokenizedMessage)), 0, 0, 0, 0, 0));
}
}
static Logs& GetLogs(LOGS_METHOD_CONTEXT& context) {
return (Logs&)(context.service());
}
std::array<std::byte, kEncodeBufferSize> log_queue_buffer_;
LogQueueWithEncodeBuffer<kLogBufferSize> log_queue_;
};
TEST_F(LogsService, Get) {
constexpr size_t kLogEntryCount = 3;
std::array<std::byte, 1> rpc_buffer;
LOGS_METHOD_CONTEXT context(log_queue_);
context.call(rpc_buffer);
// Flush all logs from the buffer, then close the RPC.
AddLogs(kLogEntryCount);
GetLogs(context).Flush();
GetLogs(context).Finish();
EXPECT_TRUE(context.done());
EXPECT_EQ(OkStatus(), context.status());
// Although |kLogEntryCount| messages were in the queue, they are batched
// before being written to the client, so there is only one response.
EXPECT_EQ(1U, context.total_responses());
}
TEST_F(LogsService, GetMultiple) {
constexpr size_t kLogEntryCount = 1;
constexpr size_t kFlushCount = 3;
std::array<std::byte, 1> rpc_buffer;
LOGS_METHOD_CONTEXT context(log_queue_);
context.call(rpc_buffer);
for (size_t i = 0; i < kFlushCount; i++) {
AddLogs(kLogEntryCount);
GetLogs(context).Flush();
}
GetLogs(context).Finish();
EXPECT_TRUE(context.done());
EXPECT_EQ(OkStatus(), context.status());
EXPECT_EQ(kFlushCount, context.total_responses());
}
TEST_F(LogsService, NoEntriesOnEmptyQueue) {
std::array<std::byte, 1> rpc_buffer;
LOGS_METHOD_CONTEXT context(log_queue_);
// Invoking flush with no logs in the queue should behave like a no-op.
context.call(rpc_buffer);
GetLogs(context).Flush();
GetLogs(context).Finish();
EXPECT_TRUE(context.done());
EXPECT_EQ(OkStatus(), context.status());
EXPECT_EQ(0U, context.total_responses());
}
TEST_F(LogsService, QueueError) {
std::array<std::byte, 1> rpc_buffer;
LogQueueTester log_queue_tester(log_queue_buffer_);
LOGS_METHOD_CONTEXT context(log_queue_tester);
// Generate failure on log queue.
log_queue_tester.SetPopStatus(Status::Internal());
context.call(rpc_buffer);
GetLogs(context).Flush();
GetLogs(context).Finish();
EXPECT_TRUE(context.done());
EXPECT_EQ(OkStatus(), context.status());
EXPECT_EQ(0U, context.total_responses());
}
} // namespace
} // namespace pw::log_rpc