1 /*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "include/core/SkRefCnt.h"
9 #include "include/core/SkTypes.h"
10 #include "include/gpu/GrDirectContext.h"
11 #include "include/private/base/SkTArray.h"
12 #include "src/core/SkMessageBus.h"
13 #include "tests/Test.h"
14
15 #include <cstdint>
16 #include <utility>
17
18 namespace {
19
20 struct TestMessage {
TestMessage__anonb67a4caf0111::TestMessage21 TestMessage(int i, float f) : x(i), y(f) {}
22
23 int x;
24 float y;
25 };
26
SkShouldPostMessageToBus(const TestMessage &,uint32_t)27 static inline bool SkShouldPostMessageToBus(const TestMessage&, uint32_t) {
28 return true;
29 }
30
31 } // namespace
32
DECLARE_SKMESSAGEBUS_MESSAGE(TestMessage,uint32_t,true)33 DECLARE_SKMESSAGEBUS_MESSAGE(TestMessage, uint32_t, true)
34
35 DEF_TEST(MessageBus, r) {
36 using TestMessageBus = SkMessageBus<TestMessage, uint32_t>;
37 // Register two inboxes to receive all TestMessages.
38 TestMessageBus::Inbox inbox1(0), inbox2(0);
39
40 // Send two messages.
41 const TestMessage m1 = { 5, 4.2f };
42 const TestMessage m2 = { 6, 4.3f };
43 TestMessageBus::Post(std::move(m1));
44 TestMessageBus::Post(std::move(m2));
45
46 // Make sure we got two.
47 SkTArray<TestMessage> messages;
48 inbox1.poll(&messages);
49 REPORTER_ASSERT(r, 2 == messages.size());
50 REPORTER_ASSERT(r, 5 == messages[0].x);
51 REPORTER_ASSERT(r, 6 == messages[1].x);
52
53 // Send another; check we get just that one.
54 const TestMessage m3 = { 1, 0.3f };
55 TestMessageBus::Post(m3);
56 inbox1.poll(&messages);
57 REPORTER_ASSERT(r, 1 == messages.size());
58 REPORTER_ASSERT(r, 1 == messages[0].x);
59
60 // Nothing was sent since the last read.
61 inbox1.poll(&messages);
62 REPORTER_ASSERT(r, 0 == messages.size());
63
64 // Over all this time, inbox2 should have piled up 3 messages.
65 inbox2.poll(&messages);
66 REPORTER_ASSERT(r, 3 == messages.size());
67 REPORTER_ASSERT(r, 5 == messages[0].x);
68 REPORTER_ASSERT(r, 6 == messages[1].x);
69 REPORTER_ASSERT(r, 1 == messages[2].x);
70 }
71
72 namespace {
73
74 struct TestMessageRefCnt : public SkRefCnt {
TestMessageRefCnt__anonb67a4caf0211::TestMessageRefCnt75 TestMessageRefCnt(int i, float f) : x(i), y(f) {}
76
77 int x;
78 float y;
79 };
80
SkShouldPostMessageToBus(const sk_sp<TestMessageRefCnt> &,uint32_t)81 static inline bool SkShouldPostMessageToBus(const sk_sp<TestMessageRefCnt>&, uint32_t) {
82 return true;
83 }
84
85 } // namespace
86
DECLARE_SKMESSAGEBUS_MESSAGE(sk_sp<TestMessageRefCnt>,uint32_t,false)87 DECLARE_SKMESSAGEBUS_MESSAGE(sk_sp<TestMessageRefCnt>, uint32_t, false)
88
89 DEF_TEST(MessageBusSp, r) {
90 // Register two inboxes to receive all TestMessages.
91 using TestMessageBus = SkMessageBus<sk_sp<TestMessageRefCnt>, uint32_t, false>;
92 TestMessageBus::Inbox inbox1(0);
93
94 // Send two messages.
95 auto m1 = sk_make_sp<TestMessageRefCnt>(5, 4.2f);
96 auto m2 = sk_make_sp<TestMessageRefCnt>(6, 4.3f);
97 TestMessageBus::Post(std::move(m1));
98 TestMessageBus::Post(std::move(m2));
99
100 // Make sure we got two.
101 SkTArray<sk_sp<TestMessageRefCnt>> messages;
102 inbox1.poll(&messages);
103 REPORTER_ASSERT(r, 2 == messages.size());
104 REPORTER_ASSERT(r, messages[0]->unique());
105 REPORTER_ASSERT(r, messages[1]->unique());
106 REPORTER_ASSERT(r, 5 == messages[0]->x);
107 REPORTER_ASSERT(r, 6 == messages[1]->x);
108
109 // Send another; check we get just that one.
110 auto m3 = sk_make_sp<TestMessageRefCnt>(1, 0.3f);
111 TestMessageBus::Post(std::move(m3));
112 inbox1.poll(&messages);
113 REPORTER_ASSERT(r, 1 == messages.size());
114 REPORTER_ASSERT(r, messages[0]->unique());
115 REPORTER_ASSERT(r, 1 == messages[0]->x);
116
117 // Send another without std::move(), it should trigger SkASSERT().
118 // auto m4 = sk_make_sp<TestMessageRefCnt>(1, 0.3f);
119 // TestMessageBus::Post(m4);
120
121 // Nothing was sent since the last read.
122 inbox1.poll(&messages);
123 REPORTER_ASSERT(r, 0 == messages.size());
124 }
125
126 namespace {
127
128 struct AddressedMessage {
129 GrDirectContext::DirectContextID fInboxID;
130 };
131
SkShouldPostMessageToBus(const AddressedMessage & msg,GrDirectContext::DirectContextID msgBusUniqueID)132 static inline bool SkShouldPostMessageToBus(const AddressedMessage& msg,
133 GrDirectContext::DirectContextID msgBusUniqueID) {
134 SkASSERT(msgBusUniqueID.isValid());
135 if (!msg.fInboxID.isValid()) {
136 return true;
137 }
138 return msgBusUniqueID == msg.fInboxID;
139 }
140
141 } // namespace
142
DECLARE_SKMESSAGEBUS_MESSAGE(AddressedMessage,GrDirectContext::DirectContextID,true)143 DECLARE_SKMESSAGEBUS_MESSAGE(AddressedMessage, GrDirectContext::DirectContextID, true)
144
145 DEF_TEST(MessageBus_SkShouldPostMessageToBus, r) {
146 using ID = GrDirectContext::DirectContextID;
147 using AddressedMessageBus = SkMessageBus<AddressedMessage, ID>;
148
149 ID idInvalid;
150 ID id1 = ID::Next(),
151 id2 = ID::Next(),
152 id3 = ID::Next();
153
154 AddressedMessageBus::Inbox inbox1(id1), inbox2(id2);
155
156 AddressedMessageBus::Post({idInvalid}); // Should go to both
157 AddressedMessageBus::Post({id1}); // Should go to inbox1
158 AddressedMessageBus::Post({id2}); // Should go to inbox2
159 AddressedMessageBus::Post({id3}); // Should go nowhere
160
161 SkTArray<AddressedMessage> messages;
162 inbox1.poll(&messages);
163 REPORTER_ASSERT(r, messages.size() == 2);
164 if (messages.size() == 2) {
165 REPORTER_ASSERT(r, !messages[0].fInboxID.isValid());
166 REPORTER_ASSERT(r, messages[1].fInboxID == id1);
167 }
168 inbox2.poll(&messages);
169 REPORTER_ASSERT(r, messages.size() == 2);
170 if (messages.size() == 2) {
171 REPORTER_ASSERT(r, !messages[0].fInboxID.isValid());
172 REPORTER_ASSERT(r, messages[1].fInboxID == id2);
173 }
174 }
175
176 // Multithreaded tests tbd.
177