1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 #include "pw_trace_tokenized/trace_service_pwpb.h"
16
17 #include "pw_chrono/system_clock.h"
18 #include "pw_rpc/pwpb/test_method_context.h"
19 #include "pw_stream/memory_stream.h"
20 #include "pw_trace/trace.h"
21 #include "pw_trace_tokenized/trace_tokenized.h"
22 #include "pw_unit_test/framework.h"
23
24 namespace pw::trace {
25 namespace {
26
27 class TraceServiceTest : public ::testing::Test {
28 public:
TraceServiceTest()29 TraceServiceTest() {}
30
31 static constexpr uint32_t kTraceTransferHandlerId = 7;
32 };
33
TEST_F(TraceServiceTest,Start)34 TEST_F(TraceServiceTest, Start) {
35 auto& tracer = trace::GetTokenizedTracer();
36
37 std::array<std::byte, PW_TRACE_BUFFER_SIZE_BYTES> dest_buffer;
38 stream::MemoryWriter writer(dest_buffer);
39 PW_PWPB_TEST_METHOD_CONTEXT(TraceService, Start)
40 context(tracer, writer);
41
42 ASSERT_FALSE(tracer.IsEnabled());
43 ASSERT_EQ(context.call({}), OkStatus());
44 ASSERT_TRUE(tracer.IsEnabled());
45
46 // multiple calls to start are disallowed
47 ASSERT_EQ(context.call({}), Status::FailedPrecondition());
48 }
49
TEST_F(TraceServiceTest,Stop)50 TEST_F(TraceServiceTest, Stop) {
51 auto& tracer = trace::GetTokenizedTracer();
52
53 std::array<std::byte, PW_TRACE_BUFFER_SIZE_BYTES> dest_buffer;
54 stream::MemoryWriter writer(dest_buffer);
55 PW_PWPB_TEST_METHOD_CONTEXT(TraceService, Stop)
56 context(tracer, writer);
57 context.service().SetTransferId(kTraceTransferHandlerId);
58
59 tracer.Enable(true);
60 PW_TRACE_INSTANT("TestTrace");
61
62 ASSERT_EQ(context.call({}), OkStatus());
63 ASSERT_FALSE(tracer.IsEnabled());
64 EXPECT_EQ(kTraceTransferHandlerId, context.response().file_id);
65 EXPECT_LT(0u, writer.bytes_written());
66 }
67
TEST_F(TraceServiceTest,StopNoTransferHandlerId)68 TEST_F(TraceServiceTest, StopNoTransferHandlerId) {
69 auto& tracer = trace::GetTokenizedTracer();
70
71 std::array<std::byte, PW_TRACE_BUFFER_SIZE_BYTES> dest_buffer;
72 stream::MemoryWriter writer(dest_buffer);
73 PW_PWPB_TEST_METHOD_CONTEXT(TraceService, Stop)
74 context(tracer, writer);
75
76 tracer.Enable(true);
77 PW_TRACE_INSTANT("TestTrace");
78
79 ASSERT_EQ(context.call({}), OkStatus());
80 ASSERT_FALSE(tracer.IsEnabled());
81 EXPECT_FALSE(context.response().file_id.has_value());
82 EXPECT_LT(0u, writer.bytes_written());
83 }
84
TEST_F(TraceServiceTest,StopNotStarted)85 TEST_F(TraceServiceTest, StopNotStarted) {
86 auto& tracer = trace::GetTokenizedTracer();
87
88 std::array<std::byte, PW_TRACE_BUFFER_SIZE_BYTES> dest_buffer;
89 stream::MemoryWriter writer(dest_buffer);
90 PW_PWPB_TEST_METHOD_CONTEXT(TraceService, Stop)
91 context(tracer, writer);
92
93 // stopping while tracing is disabled results in FailedPrecondition
94 ASSERT_EQ(context.call({}), Status::FailedPrecondition());
95 }
96
TEST_F(TraceServiceTest,StopNoData)97 TEST_F(TraceServiceTest, StopNoData) {
98 auto& tracer = trace::GetTokenizedTracer();
99
100 std::array<std::byte, PW_TRACE_BUFFER_SIZE_BYTES> dest_buffer;
101 stream::MemoryWriter writer(dest_buffer);
102 PW_PWPB_TEST_METHOD_CONTEXT(TraceService, Stop)
103 context(tracer, writer);
104
105 tracer.Enable(true);
106
107 // stopping with no trace data results in Unavailable
108 ASSERT_EQ(context.call({}), Status::Unavailable());
109 }
110
TEST_F(TraceServiceTest,GetClockParameters)111 TEST_F(TraceServiceTest, GetClockParameters) {
112 auto& tracer = trace::GetTokenizedTracer();
113
114 std::array<std::byte, PW_TRACE_BUFFER_SIZE_BYTES> dest_buffer;
115 stream::MemoryWriter writer(dest_buffer);
116
117 PW_PWPB_TEST_METHOD_CONTEXT(TraceService, GetClockParameters)
118 context(tracer, writer);
119
120 ASSERT_EQ(context.call({}), OkStatus());
121 EXPECT_EQ(
122 static_cast<int32_t>(PW_CHRONO_SYSTEM_CLOCK_PERIOD_SECONDS_NUMERATOR),
123 context.response().clock_parameters.tick_period_seconds_numerator);
124 EXPECT_EQ(
125 static_cast<int32_t>(PW_CHRONO_SYSTEM_CLOCK_PERIOD_SECONDS_DENOMINATOR),
126 context.response().clock_parameters.tick_period_seconds_denominator);
127 EXPECT_EQ(
128 static_cast<int32_t>(chrono::SystemClock::epoch),
129 static_cast<int32_t>(*context.response().clock_parameters.epoch_type));
130 }
131
132 } // namespace
133 } // namespace pw::trace
134