1// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/port.h"
6#include "platform/assert.h"
7#include "vm/lockers.h"
8#include "vm/message_handler.h"
9#include "vm/os.h"
10#include "vm/unit_test.h"
11
12namespace dart {
13
14// Provides private access to PortMap for testing.
15class PortMapTestPeer {
16 public:
17 static bool IsActivePort(Dart_Port port) {
18 MutexLocker ml(PortMap::mutex_);
19 auto it = PortMap::ports_->TryLookup(port);
20 return it != PortMap::ports_->end();
21 }
22
23 static bool IsLivePort(Dart_Port port) {
24 MutexLocker ml(PortMap::mutex_);
25 auto it = PortMap::ports_->TryLookup(port);
26 if (it == PortMap::ports_->end()) {
27 return false;
28 }
29 return (*it).state == PortMap::kLivePort;
30 }
31};
32
33class PortTestMessageHandler : public MessageHandler {
34 public:
35 PortTestMessageHandler() : notify_count(0) {}
36
37 void MessageNotify(Message::Priority priority) { notify_count++; }
38
39 MessageStatus HandleMessage(std::unique_ptr<Message> message) { return kOK; }
40
41 int notify_count;
42};
43
44TEST_CASE(PortMap_CreateAndCloseOnePort) {
45 PortTestMessageHandler handler;
46 Dart_Port port = PortMap::CreatePort(&handler);
47 EXPECT_NE(0, port);
48 EXPECT(PortMapTestPeer::IsActivePort(port));
49
50 PortMap::ClosePort(port);
51 EXPECT(!PortMapTestPeer::IsActivePort(port));
52}
53
54TEST_CASE(PortMap_CreateAndCloseTwoPorts) {
55 PortTestMessageHandler handler;
56 Dart_Port port1 = PortMap::CreatePort(&handler);
57 Dart_Port port2 = PortMap::CreatePort(&handler);
58 EXPECT(PortMapTestPeer::IsActivePort(port1));
59 EXPECT(PortMapTestPeer::IsActivePort(port2));
60
61 // Uniqueness.
62 EXPECT_NE(port1, port2);
63
64 PortMap::ClosePort(port1);
65 EXPECT(!PortMapTestPeer::IsActivePort(port1));
66 EXPECT(PortMapTestPeer::IsActivePort(port2));
67
68 PortMap::ClosePort(port2);
69 EXPECT(!PortMapTestPeer::IsActivePort(port1));
70 EXPECT(!PortMapTestPeer::IsActivePort(port2));
71}
72
73TEST_CASE(PortMap_ClosePorts) {
74 PortTestMessageHandler handler;
75 Dart_Port port1 = PortMap::CreatePort(&handler);
76 Dart_Port port2 = PortMap::CreatePort(&handler);
77 EXPECT(PortMapTestPeer::IsActivePort(port1));
78 EXPECT(PortMapTestPeer::IsActivePort(port2));
79
80 // Close all ports at once.
81 PortMap::ClosePorts(&handler);
82 EXPECT(!PortMapTestPeer::IsActivePort(port1));
83 EXPECT(!PortMapTestPeer::IsActivePort(port2));
84}
85
86TEST_CASE(PortMap_CreateManyPorts) {
87 PortTestMessageHandler handler;
88 for (int i = 0; i < 32; i++) {
89 Dart_Port port = PortMap::CreatePort(&handler);
90 EXPECT(PortMapTestPeer::IsActivePort(port));
91 PortMap::ClosePort(port);
92 EXPECT(!PortMapTestPeer::IsActivePort(port));
93 }
94}
95
96TEST_CASE(PortMap_SetPortState) {
97 PortTestMessageHandler handler;
98
99 // Regular port.
100 Dart_Port port = PortMap::CreatePort(&handler);
101 EXPECT_NE(0, port);
102 EXPECT(PortMapTestPeer::IsActivePort(port));
103 EXPECT(!PortMapTestPeer::IsLivePort(port));
104
105 PortMap::SetPortState(port, PortMap::kLivePort);
106 EXPECT(PortMapTestPeer::IsActivePort(port));
107 EXPECT(PortMapTestPeer::IsLivePort(port));
108
109 PortMap::ClosePort(port);
110 EXPECT(!PortMapTestPeer::IsActivePort(port));
111 EXPECT(!PortMapTestPeer::IsLivePort(port));
112
113 // Control port.
114 port = PortMap::CreatePort(&handler);
115 EXPECT_NE(0, port);
116 EXPECT(PortMapTestPeer::IsActivePort(port));
117 EXPECT(!PortMapTestPeer::IsLivePort(port));
118
119 PortMap::SetPortState(port, PortMap::kControlPort);
120 EXPECT(PortMapTestPeer::IsActivePort(port));
121 EXPECT(!PortMapTestPeer::IsLivePort(port));
122
123 PortMap::ClosePort(port);
124 EXPECT(!PortMapTestPeer::IsActivePort(port));
125 EXPECT(!PortMapTestPeer::IsLivePort(port));
126}
127
128TEST_CASE(PortMap_PostMessage) {
129 PortTestMessageHandler handler;
130 Dart_Port port = PortMap::CreatePort(&handler);
131 EXPECT_EQ(0, handler.notify_count);
132
133 const char* message = "msg";
134 intptr_t message_len = strlen(message) + 1;
135
136 EXPECT(PortMap::PostMessage(
137 Message::New(port, reinterpret_cast<uint8_t*>(Utils::StrDup(message)),
138 message_len, nullptr, Message::kNormalPriority)));
139
140 // Check that the message notify callback was called.
141 EXPECT_EQ(1, handler.notify_count);
142 PortMap::ClosePorts(&handler);
143}
144
145TEST_CASE(PortMap_PostIntegerMessage) {
146 PortTestMessageHandler handler;
147 Dart_Port port = PortMap::CreatePort(&handler);
148 EXPECT_EQ(0, handler.notify_count);
149
150 EXPECT(PortMap::PostMessage(
151 Message::New(port, Smi::New(42), Message::kNormalPriority)));
152
153 // Check that the message notify callback was called.
154 EXPECT_EQ(1, handler.notify_count);
155 PortMap::ClosePorts(&handler);
156}
157
158TEST_CASE(PortMap_PostNullMessage) {
159 PortTestMessageHandler handler;
160 Dart_Port port = PortMap::CreatePort(&handler);
161 EXPECT_EQ(0, handler.notify_count);
162
163 EXPECT(PortMap::PostMessage(
164 Message::New(port, Object::null(), Message::kNormalPriority)));
165
166 // Check that the message notify callback was called.
167 EXPECT_EQ(1, handler.notify_count);
168 PortMap::ClosePorts(&handler);
169}
170
171TEST_CASE(PortMap_PostMessageClosedPort) {
172 // Create a port id and make it invalid.
173 PortTestMessageHandler handler;
174 Dart_Port port = PortMap::CreatePort(&handler);
175 PortMap::ClosePort(port);
176
177 const char* message = "msg";
178 intptr_t message_len = strlen(message) + 1;
179
180 EXPECT(!PortMap::PostMessage(
181 Message::New(port, reinterpret_cast<uint8_t*>(Utils::StrDup(message)),
182 message_len, nullptr, Message::kNormalPriority)));
183}
184
185} // namespace dart
186