1645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Copyright 2014 The Chromium Authors. All rights reserved.
2645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Use of this source code is governed by a BSD-style license that can be
3645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// found in the LICENSE file.
4645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
5645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#ifdef __cplusplus
6645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#error "This file should be compiled as C, not C++."
7645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif
8645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
9645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <stddef.h>
10645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <stdint.h>
11645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <string.h>
12645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
13645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Include all the header files that are meant to be compilable as C. Start with
14645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// core.h, since it's the most important one.
15645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/public/c/system/core.h"
16645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/public/c/system/macros.h"
17645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
18645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// The joys of the C preprocessor....
19645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#define STRINGIFY(x) #x
20645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#define STRINGIFY2(x) STRINGIFY(x)
21645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#define FAILURE(message) \
22645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  __FILE__ "(" STRINGIFY2(__LINE__) "): Failure: " message
23645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
24645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Poor man's gtest.
25645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#define EXPECT_EQ(a, b)                                                  \
26645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  do {                                                                   \
27645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if ((a) != (b))                                                      \
28645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      return FAILURE(STRINGIFY(a) " != " STRINGIFY(b) " (expected ==)"); \
29645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  } while (0)
30645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#define EXPECT_NE(a, b)                                                  \
31645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  do {                                                                   \
32645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if ((a) == (b))                                                      \
33645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      return FAILURE(STRINGIFY(a) " == " STRINGIFY(b) " (expected !=)"); \
34645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  } while (0)
35645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
36645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// This function exists mainly to be compiled and linked. We do some cursory
37645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// checks and call it from a unit test, to make sure that link problems aren't
38645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// missed due to deadstripping. Returns null on success and a string on failure
39645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// (describing the failure).
40645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezconst char* MinimalCTest(void) {
41645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // MSVS before 2013 *really* only supports C90: All variables must be declared
42645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // at the top. (MSVS 2013 is more reasonable.)
43645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  MojoTimeTicks ticks;
44645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  MojoHandle handle0, handle1;
45645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  MojoHandleSignals signals;
46645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  const char kHello[] = "hello";
47645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  char buffer[200] = {0};
48645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  uint32_t num_bytes;
49645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
50645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  ticks = MojoGetTimeTicksNow();
51645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  EXPECT_NE(ticks, 0);
52645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
53645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  handle0 = MOJO_HANDLE_INVALID;
54645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  EXPECT_NE(MOJO_RESULT_OK, MojoClose(handle0));
55645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
56645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
57645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            MojoWait(handle0, ~MOJO_HANDLE_SIGNAL_NONE,
58645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                     MOJO_DEADLINE_INDEFINITE, NULL));
59645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
60645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  handle1 = MOJO_HANDLE_INVALID;
61645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(NULL, &handle0, &handle1));
62645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
63645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  signals = MOJO_HANDLE_SIGNAL_READABLE;
64645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  uint32_t result_index = 123;
65645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  struct MojoHandleSignalsState states[1];
66645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
67645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            MojoWaitMany(&handle0, &signals, 1, 1, &result_index, states));
68645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
69645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // "Deadline exceeded" doesn't apply to a single handle, so this should leave
70645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // |result_index| untouched.
71645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  EXPECT_EQ(123u, result_index);
72645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, states[0].satisfied_signals);
73645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE |
74645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                MOJO_HANDLE_SIGNAL_PEER_CLOSED,
75645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            states[0].satisfiable_signals);
76645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
77645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  EXPECT_EQ(MOJO_RESULT_OK,
78645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            MojoWriteMessage(handle0, kHello, (uint32_t)sizeof(kHello), NULL,
79645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                             0u, MOJO_WRITE_DATA_FLAG_NONE));
80645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
81645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  struct MojoHandleSignalsState state;
82645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  EXPECT_EQ(MOJO_RESULT_OK, MojoWait(handle1, MOJO_HANDLE_SIGNAL_READABLE,
83645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                     MOJO_DEADLINE_INDEFINITE, &state));
84645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
85645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
86645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            state.satisfied_signals);
87645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE |
88645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                MOJO_HANDLE_SIGNAL_PEER_CLOSED,
89645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            state.satisfiable_signals);
90645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
91645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  num_bytes = (uint32_t)sizeof(buffer);
92645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  EXPECT_EQ(MOJO_RESULT_OK, MojoReadMessage(handle1, buffer, &num_bytes, NULL,
93645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                            NULL, MOJO_READ_MESSAGE_FLAG_NONE));
94645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  EXPECT_EQ((uint32_t)sizeof(kHello), num_bytes);
95645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  EXPECT_EQ(0, memcmp(buffer, kHello, sizeof(kHello)));
96645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
97645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  EXPECT_EQ(MOJO_RESULT_OK, MojoClose(handle0));
98645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  EXPECT_EQ(MOJO_RESULT_OK, MojoClose(handle1));
99645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
100645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // TODO(vtl): data pipe
101645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
102645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  return NULL;
103645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}
104