|  | // Copyright 2018 The Fuchsia Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include <lib/async-loop/default.h> | 
|  | #include <lib/async-loop/loop.h> | 
|  | #include <lib/fidl-async/bind.h> | 
|  | #include <string.h> | 
|  | #include <zircon/fidl.h> | 
|  | #include <zircon/syscalls.h> | 
|  |  | 
|  | #include <fidl/test/spaceship/c/fidl.h> | 
|  | #include <zxtest/zxtest.h> | 
|  |  | 
|  | static zx_status_t SpaceShip_AdjustHeading(void* ctx, const uint32_t* stars_data, | 
|  | size_t stars_count, fidl_txn_t* txn) { | 
|  | EXPECT_EQ(3u, stars_count, ""); | 
|  | EXPECT_EQ(11u, stars_data[0], ""); | 
|  | EXPECT_EQ(0u, stars_data[1], ""); | 
|  | EXPECT_EQ(UINT32_MAX, stars_data[2], ""); | 
|  | return fidl_test_spaceship_SpaceShipAdjustHeading_reply(txn, -12); | 
|  | } | 
|  |  | 
|  | static zx_status_t SpaceShip_ScanForLifeforms(void* ctx, fidl_txn_t* txn) { | 
|  | const uint32_t lifesigns[5] = {42u, 43u, UINT32_MAX, 0u, 9u}; | 
|  | return fidl_test_spaceship_SpaceShipScanForLifeforms_reply(txn, lifesigns, 5); | 
|  | } | 
|  |  | 
|  | static zx_status_t SpaceShip_ScanForTensorLifeforms(void* ctx, fidl_txn_t* txn) { | 
|  | uint32_t lifesigns[8][5][3] = {}; | 
|  | // fill the array with increasing counter | 
|  | uint32_t counter = 0; | 
|  | for (size_t i = 0; i < 8; i++) { | 
|  | for (size_t j = 0; j < 5; j++) { | 
|  | for (size_t k = 0; k < 3; k++) { | 
|  | lifesigns[i][j][k] = counter; | 
|  | counter += 1; | 
|  | } | 
|  | } | 
|  | } | 
|  | return fidl_test_spaceship_SpaceShipScanForTensorLifeforms_reply(txn, lifesigns); | 
|  | } | 
|  |  | 
|  | static zx_status_t SpaceShip_SetAstrometricsListener(void* ctx, zx_handle_t listener) { | 
|  | EXPECT_EQ(ZX_OK, fidl_test_spaceship_AstrometricsListenerOnNova(listener), ""); | 
|  | EXPECT_EQ(ZX_OK, zx_handle_close(listener), ""); | 
|  | return ZX_OK; | 
|  | } | 
|  |  | 
|  | static zx_status_t SpaceShip_SetDefenseCondition(void* ctx, fidl_test_spaceship_Alert alert) { | 
|  | EXPECT_EQ(fidl_test_spaceship_Alert_RED, alert, ""); | 
|  | return ZX_OK; | 
|  | } | 
|  |  | 
|  | static zx_status_t SpaceShip_GetFuelRemaining(void* ctx, zx_handle_t cancel, fidl_txn_t* txn) { | 
|  | EXPECT_EQ(ZX_HANDLE_INVALID, cancel, ""); | 
|  | const fidl_test_spaceship_FuelLevel level = { | 
|  | .reaction_mass = 1641u, | 
|  | }; | 
|  | return fidl_test_spaceship_SpaceShipGetFuelRemaining_reply(txn, ZX_OK, &level); | 
|  | } | 
|  |  | 
|  | static zx_status_t SpaceShip_AddFuelTank(void* ctx, const fidl_test_spaceship_FuelLevel* level, | 
|  | fidl_txn_t* txn) { | 
|  | return fidl_test_spaceship_SpaceShipAddFuelTank_reply(txn, level->reaction_mass / 2); | 
|  | } | 
|  |  | 
|  | static const fidl_test_spaceship_SpaceShip_ops_t kOps = { | 
|  | .AdjustHeading = SpaceShip_AdjustHeading, | 
|  | .ScanForLifeforms = SpaceShip_ScanForLifeforms, | 
|  | .SetAstrometricsListener = SpaceShip_SetAstrometricsListener, | 
|  | .SetDefenseCondition = SpaceShip_SetDefenseCondition, | 
|  | .GetFuelRemaining = SpaceShip_GetFuelRemaining, | 
|  | .AddFuelTank = SpaceShip_AddFuelTank, | 
|  | .ScanForTensorLifeforms = SpaceShip_ScanForTensorLifeforms, | 
|  | }; | 
|  |  | 
|  | TEST(SpaceshipTests, spaceship_test) { | 
|  | zx_handle_t client, server; | 
|  | zx_status_t status = zx_channel_create(0, &client, &server); | 
|  | ASSERT_EQ(ZX_OK, status, ""); | 
|  |  | 
|  | async_loop_t* loop = NULL; | 
|  | ASSERT_EQ(ZX_OK, async_loop_create(&kAsyncLoopConfigNoAttachToCurrentThread, &loop), ""); | 
|  | ASSERT_EQ(ZX_OK, async_loop_start_thread(loop, "spaceship-dispatcher", NULL), ""); | 
|  |  | 
|  | async_dispatcher_t* dispatcher = async_loop_get_dispatcher(loop); | 
|  | fidl_bind(dispatcher, server, (fidl_dispatch_t*)fidl_test_spaceship_SpaceShip_dispatch, NULL, | 
|  | &kOps); | 
|  |  | 
|  | { | 
|  | const uint32_t stars[3] = {11u, 0u, UINT32_MAX}; | 
|  | int8_t result = 0; | 
|  | ASSERT_EQ(ZX_OK, fidl_test_spaceship_SpaceShipAdjustHeading(client, stars, 3, &result), ""); | 
|  | ASSERT_EQ(-12, result, ""); | 
|  | } | 
|  |  | 
|  | { | 
|  | const uint32_t num_stars_overflow = fidl_test_spaceship_MaxStarsAdjustHeading * 2; | 
|  | const uint32_t stars[num_stars_overflow]; | 
|  | int8_t result = 0; | 
|  | ASSERT_EQ( | 
|  | ZX_ERR_INVALID_ARGS, | 
|  | fidl_test_spaceship_SpaceShipAdjustHeading(client, stars, num_stars_overflow, &result), ""); | 
|  | } | 
|  |  | 
|  | { | 
|  | int8_t result = 0; | 
|  | ASSERT_EQ(ZX_ERR_INVALID_ARGS, | 
|  | fidl_test_spaceship_SpaceShipAdjustHeading(client, NULL, 1u << 31, &result), ""); | 
|  | } | 
|  |  | 
|  | { | 
|  | uint32_t lifesigns[64]; | 
|  | size_t actual = 0; | 
|  | ASSERT_EQ(ZX_OK, fidl_test_spaceship_SpaceShipScanForLifeforms(client, lifesigns, 64, &actual), | 
|  | ""); | 
|  | ASSERT_EQ(5u, actual, ""); | 
|  | ASSERT_EQ(42u, lifesigns[0], ""); | 
|  | ASSERT_EQ(43u, lifesigns[1], ""); | 
|  | ASSERT_EQ(UINT32_MAX, lifesigns[2], ""); | 
|  | ASSERT_EQ(0u, lifesigns[3], ""); | 
|  | ASSERT_EQ(9u, lifesigns[4], ""); | 
|  | } | 
|  |  | 
|  | { | 
|  | uint32_t lifesigns[8][5][3]; | 
|  | ASSERT_EQ(ZX_OK, fidl_test_spaceship_SpaceShipScanForTensorLifeforms(client, lifesigns), ""); | 
|  | uint32_t counter = 0; | 
|  | for (size_t i = 0; i < 8; i++) { | 
|  | for (size_t j = 0; j < 5; j++) { | 
|  | for (size_t k = 0; k < 3; k++) { | 
|  | ASSERT_EQ(counter, lifesigns[i][j][k], ""); | 
|  | counter += 1; | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | { | 
|  | zx_handle_t listener_client, listener_server; | 
|  | status = zx_channel_create(0, &listener_client, &listener_server); | 
|  | ASSERT_EQ(ZX_OK, status, ""); | 
|  | ASSERT_EQ(ZX_OK, fidl_test_spaceship_SpaceShipSetAstrometricsListener(client, listener_client), | 
|  | ""); | 
|  | ASSERT_EQ(ZX_OK, | 
|  | zx_object_wait_one(listener_server, ZX_CHANNEL_READABLE, ZX_TIME_INFINITE, NULL), ""); | 
|  | ASSERT_EQ(ZX_OK, zx_handle_close(listener_server), ""); | 
|  | } | 
|  |  | 
|  | { | 
|  | ASSERT_EQ( | 
|  | ZX_OK, | 
|  | fidl_test_spaceship_SpaceShipSetDefenseCondition(client, fidl_test_spaceship_Alert_RED), | 
|  | ""); | 
|  | } | 
|  |  | 
|  | { | 
|  | fidl_test_spaceship_FuelLevel level; | 
|  | ASSERT_EQ( | 
|  | ZX_OK, | 
|  | fidl_test_spaceship_SpaceShipGetFuelRemaining(client, ZX_HANDLE_INVALID, &status, &level), | 
|  | ""); | 
|  | ASSERT_EQ(ZX_OK, status, ""); | 
|  | ASSERT_EQ(1641u, level.reaction_mass, ""); | 
|  | } | 
|  |  | 
|  | { | 
|  | fidl_test_spaceship_FuelLevel level = { | 
|  | .reaction_mass = 9482, | 
|  | }; | 
|  | uint32_t out_consumed = 0u; | 
|  | ASSERT_EQ(ZX_OK, fidl_test_spaceship_SpaceShipAddFuelTank(client, &level, &out_consumed), ""); | 
|  | ASSERT_EQ(4741u, out_consumed, ""); | 
|  | } | 
|  |  | 
|  | ASSERT_EQ(ZX_OK, zx_handle_close(client), ""); | 
|  |  | 
|  | async_loop_destroy(loop); | 
|  | } |