• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 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_work_queue/work_queue.h"
16 
17 #include "gtest/gtest.h"
18 #include "pw_function/function.h"
19 #include "pw_log/log.h"
20 #include "pw_sync/thread_notification.h"
21 #include "pw_thread/thread.h"
22 #include "pw_work_queue/test_thread.h"
23 
24 namespace pw::work_queue {
25 namespace {
26 
TEST(WorkQueue,PingPongOneRequestType)27 TEST(WorkQueue, PingPongOneRequestType) {
28   struct {
29     int counter = 0;
30     sync::ThreadNotification worker_ping;
31   } context;
32 
33   WorkQueueWithBuffer<10> work_queue;
34 
35   // Start the worker thread.
36   thread::Thread work_thread(test::WorkQueueThreadOptions(), work_queue);
37 
38   // Pick a number bigger than the circular buffer to ensure we loop around.
39   const int kPingPongs = 300;
40 
41   for (int i = 0; i < kPingPongs; ++i) {
42     // Ping: throw work at the queue that will increment our counter.
43     work_queue
44         .PushWork([&context] {
45           context.counter++;
46           PW_LOG_INFO("Send pong...");
47           context.worker_ping.release();
48         })
49         .IgnoreError();  // TODO(pwbug/387): Handle Status properly
50 
51     // Throw a distraction in the queue.
52     work_queue
53         .PushWork([] {
54           PW_LOG_INFO(
55               "I'm a random task in the work queue; nothing to see here!");
56         })
57         .IgnoreError();  // TODO(pwbug/387): Handle Status properly
58 
59     // Pong: wait for the callback to notify us from the worker thread.
60     context.worker_ping.acquire();
61   }
62 
63   // Wait for the worker thread to terminate.
64   work_queue.RequestStop();
65   work_thread.join();
66 
67   EXPECT_EQ(context.counter, kPingPongs);
68 }
69 
TEST(WorkQueue,PingPongTwoRequestTypesWithExtraRequests)70 TEST(WorkQueue, PingPongTwoRequestTypesWithExtraRequests) {
71   struct {
72     int counter = 0;
73     sync::ThreadNotification worker_ping;
74   } context_a, context_b;
75 
76   WorkQueueWithBuffer<10> work_queue;
77 
78   // Start the worker thread.
79   thread::Thread work_thread(test::WorkQueueThreadOptions(), work_queue);
80 
81   // Pick a number bigger than the circular buffer to ensure we loop around.
82   const int kPingPongs = 300;
83 
84   // Run a bunch of work items in the queue.
85   for (int i = 0; i < kPingPongs; ++i) {
86     // Other requests...
87     work_queue.PushWork([] { PW_LOG_INFO("Chopping onions"); })
88         .IgnoreError();  // TODO(pwbug/387): Handle Status properly
89 
90     // Ping A: throw work at the queue that will increment our counter.
91     work_queue
92         .PushWork([&context_a] {
93           context_a.counter++;
94           context_a.worker_ping.release();
95         })
96         .IgnoreError();  // TODO(pwbug/387): Handle Status properly
97 
98     // Other requests...
99     work_queue.PushWork([] { PW_LOG_INFO("Dicing carrots"); })
100         .IgnoreError();  // TODO(pwbug/387): Handle Status properly
101     work_queue.PushWork([] { PW_LOG_INFO("Blanching spinach"); })
102         .IgnoreError();  // TODO(pwbug/387): Handle Status properly
103 
104     // Ping B: throw work at the queue that will increment our counter.
105     work_queue
106         .PushWork([&context_b] {
107           context_b.counter++;
108           context_b.worker_ping.release();
109         })
110         .IgnoreError();  // TODO(pwbug/387): Handle Status properly
111 
112     // Other requests...
113     work_queue.PushWork([] { PW_LOG_INFO("Peeling potatoes"); })
114         .IgnoreError();  // TODO(pwbug/387): Handle Status properly
115 
116     // Pong A & B: wait for the callbacks to notify us from the worker thread.
117     context_a.worker_ping.acquire();
118     context_b.worker_ping.acquire();
119   }
120 
121   // Wait for the worker thread to terminate.
122   work_queue.RequestStop();
123   work_thread.join();
124 
125   EXPECT_EQ(context_a.counter, kPingPongs);
126   EXPECT_EQ(context_b.counter, kPingPongs);
127 }
128 
129 // TODO(ewout): Add unit tests for the metrics once they have been restructured.
130 
131 }  // namespace
132 }  // namespace pw::work_queue
133