Debugging: Add code to print backtrace for guest on SIGSEGV
[nativeclient.git] / intermodule_comm / nacl_imc_test_client.cc
blobcb6c9a279f01290edacf59c5425f776f7d493ae5
1 /*
2 * Copyright 2008, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 // NaCl inter-module communication primitives.
35 // TODO: Make this program a unit test.
37 #include <assert.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <sys/types.h>
42 #include "native_client/intermodule_comm/nacl_imc.h"
44 nacl::SocketAddress server_address = {
45 "imc-server"
48 nacl::SocketAddress client_address = {
49 "imc-client"
52 namespace {
54 nacl::Handle g_front;
56 void CleanUp() {
57 nacl::Close(g_front);
60 // Writes the last error message to the standard error.
61 void PrintError(const char* message) {
62 char buffer[256];
64 if (nacl::GetLastErrorString(buffer, sizeof buffer) == 0) {
65 fprintf(stderr, "%s: %s\n", message, buffer);
69 } // namespace
71 int main() {
72 int result;
74 g_front = nacl::BoundSocket(&client_address);
75 if (g_front == nacl::kInvalidHandle) {
76 PrintError("BoundSocket");
77 exit(EXIT_FAILURE);
79 atexit(CleanUp);
81 nacl::Handle pair[2];
82 if (nacl::SocketPair(pair) != 0) {
83 PrintError("SocketPair");
84 exit(EXIT_FAILURE);
87 // Test more than one SocketPair() creation
88 nacl::Handle pair2[2];
89 result = nacl::SocketPair(pair2);
90 assert(result == 0);
91 if (result != 0) {
92 PrintError("SocketPair");
93 exit(EXIT_FAILURE);
95 nacl::Close(pair2[0]);
96 nacl::Close(pair2[1]);
98 nacl::MessageHeader header;
99 nacl::IOVec vec[2];
100 char buffer[64];
102 // Test kDontWait for a bound socket
103 vec[0].base = buffer;
104 vec[0].length = sizeof buffer;
105 header.iov = vec;
106 header.iov_length = 1;
107 header.handles = NULL;
108 header.handle_count = 0;
109 result = nacl::ReceiveDatagram(g_front, &header, nacl::kDontWait);
110 assert(result == -1);
111 PrintError("ReceiveDatagram");
112 assert(nacl::WouldBlock());
114 #if NACL_WINDOWS
115 strncpy_s(buffer, sizeof buffer, "Hello!", sizeof buffer);
116 #else
117 strncpy(buffer, "Hello!", sizeof buffer);
118 #endif // NACL_WINDOWS
119 vec[0].base = buffer;
120 vec[0].length = strlen(buffer);
122 // Test kCancel ControlHeader::command
123 nacl::Handle broken[2] = {
124 pair[1],
125 nacl::Handle(&pair[1]) // &pair[1] cannot be a valid handle
127 header.iov = vec;
128 header.iov_length = 1;
129 header.handles = broken;
130 header.handle_count = sizeof broken / sizeof broken[0];
131 result = nacl::SendDatagramTo(g_front, &header, 0, &server_address);
132 assert(result == -1);
134 // Send pair[1] to the server.
135 header.iov = vec;
136 header.iov_length = 1;
137 header.handles = &pair[1];
138 header.handle_count = 1;
139 result = nacl::SendDatagramTo(g_front, &header, 0, &server_address);
140 if (static_cast<size_t>(result) != vec[0].length) {
141 PrintError("SendDatagram");
142 exit(EXIT_FAILURE);
144 result = nacl::Close(pair[1]);
145 if (result != 0) {
146 PrintError("Close");
147 exit(EXIT_FAILURE);
150 nacl::Handle server_handle = pair[0];
151 nacl::Handle shared_memory;
153 // Test an empty message
154 memset(buffer, 0, sizeof buffer);
155 vec[0].base = buffer;
156 vec[0].length = sizeof buffer;
157 header.iov = vec;
158 header.iov_length = 1;
159 header.handles = NULL;
160 header.handle_count = 0;
161 result = nacl::ReceiveDatagram(server_handle, &header, 0);
162 assert(result == 0);
164 // Test scatter/gather
165 memset(buffer, 0, sizeof buffer);
166 header.iov = vec;
167 header.iov_length = sizeof vec / sizeof vec[0];
168 header.handles = NULL;
169 header.handle_count = 0;
170 for (size_t i = 0; i < sizeof vec / sizeof vec[0]; ++i) {
171 vec[i].base = buffer + i;
172 vec[i].length = 1;
174 result = nacl::ReceiveDatagram(server_handle, &header, 0);
175 assert(result == sizeof vec / sizeof vec[0]);
176 assert(header.flags & nacl::kMessageTruncated);
177 assert(header.flags & nacl::kHandlesTruncated);
178 printf("%s\n", buffer);
180 // Test Send()
181 result = nacl::Send(server_handle, buffer, sizeof vec / sizeof vec[0], 0);
182 assert(result == sizeof vec / sizeof vec[0]);
184 // Test shared memory
185 header.iov = vec;
186 header.iov_length = sizeof vec / sizeof vec[0];
187 header.handles = &shared_memory;
188 header.handle_count = 1;
189 if (0 <= nacl::ReceiveDatagram(server_handle, &header, 0) &&
190 header.handle_count == 1) {
191 void* shared_region = nacl::Map(0, 1024 * 1024,
192 nacl::kProtRead | nacl::kProtWrite,
193 nacl::kMapShared,
194 shared_memory, 0);
195 if (shared_region) {
196 while (*static_cast<volatile int*>(shared_region) == 0x00) {
198 printf("client: shm ok.\n");
199 result = nacl::Send(server_handle, buffer, sizeof buffer, 0);
200 assert(result == sizeof buffer);
201 memset(shared_region, 0x00, 1024 * 1024);
202 nacl::Unmap(shared_region, 1024 * 1024);
204 nacl::Close(shared_memory);
205 } else {
206 PrintError("ReceiveDatagram");
209 // Test close detection.
210 nacl::Close(server_handle);
211 return 0;