From 82e5f3ee320f6beb62084ead63087cf35c8e8208 Mon Sep 17 00:00:00 2001 From: Alexander Apalikov Date: Wed, 5 Feb 2020 02:26:53 +0300 Subject: [PATCH] Conformance test for CPP SDK (#1282) Build CPP SDK requirements to a local folder, put this into CI cache, on the subsequent builds it would reduce the time of the build to a minute, building just cpp library and test binary. Contains main logic of the conformance test, which was taken from cpp-simple. --- build/build-sdk-images/cpp/build-sdk-test.sh | 41 ++++++ build/build-sdk-images/cpp/clean.sh | 19 +++ build/build-sdk-images/cpp/sdktest.sh | 18 +++ build/includes/sdk.mk | 5 +- cloudbuild.yaml | 24 +++- test/sdk/cpp/CMakeLists.txt | 53 ++++++++ test/sdk/cpp/server.cc | 135 +++++++++++++++++++ 7 files changed, 293 insertions(+), 2 deletions(-) create mode 100644 build/build-sdk-images/cpp/build-sdk-test.sh create mode 100644 build/build-sdk-images/cpp/clean.sh create mode 100644 build/build-sdk-images/cpp/sdktest.sh create mode 100644 test/sdk/cpp/CMakeLists.txt create mode 100644 test/sdk/cpp/server.cc diff --git a/build/build-sdk-images/cpp/build-sdk-test.sh b/build/build-sdk-images/cpp/build-sdk-test.sh new file mode 100644 index 0000000000..efbb4e6fdd --- /dev/null +++ b/build/build-sdk-images/cpp/build-sdk-test.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +# Copyright 2020 Google LLC All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -ex +GO111MODULE=off +DIR=/go/src/agones.dev/agones/test/sdk/cpp/ +echo "$DIR"/sdk + +# Copy all CPP SDK files into a new directory +if [[ ! -d $DIR/sdk ]] +then + mkdir -p "$DIR"/sdk/.build + cp -r /go/src/agones.dev/agones/sdks/cpp/* $DIR/sdk + cd $DIR/sdk/.build + cmake .. -DCMAKE_BUILD_TYPE=Release -DAGONES_SILENT_OUTPUT=OFF -DCMAKE_INSTALL_PREFIX=$DIR/sdk/.build -DAGONES_THIRDPARTY_INSTALL_PATH=$DIR/sdk/.build -G "Unix Makefiles" -Wno-dev +else + echo "Directory with cpp SDK third party dependencies \ +has already built - using cached version. \ +Use make clean-sdk-conformance-tests if you want to start from scratch" +fi +cd $DIR/sdk/.build +cmake --build . --target install +cd $DIR && mkdir -p .build && cd .build +cmake .. -G "Unix Makefiles" \ + -DCMAKE_PREFIX_PATH=$DIR/sdk/.build \ + -Dagones_DIR=$DIR/sdk/.build/agones/cmake \ + -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=.bin +cmake --build . --target install diff --git a/build/build-sdk-images/cpp/clean.sh b/build/build-sdk-images/cpp/clean.sh new file mode 100644 index 0000000000..eeab0452d3 --- /dev/null +++ b/build/build-sdk-images/cpp/clean.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +# Copyright 2020 Google LLC All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -ex +rm -rf /go/src/agones.dev/agones/test/sdk/cpp/.build +rm -rf /go/src/agones.dev/agones/test/sdk/cpp/sdk diff --git a/build/build-sdk-images/cpp/sdktest.sh b/build/build-sdk-images/cpp/sdktest.sh new file mode 100644 index 0000000000..3ce811ab77 --- /dev/null +++ b/build/build-sdk-images/cpp/sdktest.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +# Copyright 2020 Google LLC All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -ex +/go/src/agones.dev/agones/test/sdk/cpp/.build/.bin/cpp-simple diff --git a/build/includes/sdk.mk b/build/includes/sdk.mk index bbcb534a5b..b08a5ccb27 100644 --- a/build/includes/sdk.mk +++ b/build/includes/sdk.mk @@ -146,6 +146,9 @@ run-sdk-conformance-test: ensure-build-sdk-image $(MAKE) run-sdk-command COMMAND=build-sdk-test $(MAKE) run-sdk-conformance-no-build +run-sdk-conformance-test-cpp: + $(MAKE) run-sdk-conformance-test SDK_FOLDER=cpp GRPC_PORT=9003 HTTP_PORT=9103 + run-sdk-conformance-test-node: $(MAKE) run-sdk-conformance-test SDK_FOLDER=node GRPC_PORT=9002 HTTP_PORT=9102 @@ -160,7 +163,7 @@ run-sdk-conformance-test-rest: $(MAKE) run-sdk-command COMMAND=clean SDK_FOLDER=restapi # Run a conformance test for all SDKs supported -run-sdk-conformance-tests: run-sdk-conformance-test-node run-sdk-conformance-test-go run-sdk-conformance-test-rust run-sdk-conformance-test-rest +run-sdk-conformance-tests: run-sdk-conformance-test-node run-sdk-conformance-test-go run-sdk-conformance-test-rust run-sdk-conformance-test-rest run-sdk-conformance-test-cpp # Clean package directories and binary files left # after building conformance tests for all SDKs supported diff --git a/cloudbuild.yaml b/cloudbuild.yaml index 3eaa26888d..f8f021aa6b 100644 --- a/cloudbuild.yaml +++ b/cloudbuild.yaml @@ -36,6 +36,14 @@ steps: - '--key=$_CPP_SDK_BUILD_CACHE_KEY-$( checksum sdks/cpp/cmake/prerequisites.cmake )' waitFor: ['-'] +- name: gcr.io/$PROJECT_ID/restore_cache + id: cpp-sdk-conformance-restore-cache + args: + - '--bucket=gs://$_CACHE_BUCKET' + - '--key=$_CPP_SDK_CONFORMANCE_CACHE_KEY-$( checksum sdks/cpp/cmake/prerequisites.cmake )' + waitFor: ['-'] + + - name: gcr.io/$PROJECT_ID/restore_cache id: rust-sdk-build-restore-cache args: @@ -238,10 +246,23 @@ steps: - name: "make-docker" id: sdk-conformance dir: "build" - args: [ "-j", "4", "--output-sync=target", "run-sdk-conformance-tests"] + args: [ "-j", "5", "--output-sync=target", "run-sdk-conformance-tests"] waitFor: - build-images +# +# Cache the CPP conformance build directory, to speed up subsequent builds (considerably) +# + +- name: 'gcr.io/$PROJECT_ID/save_cache' + args: + - '--bucket=gs://$_CACHE_BUCKET' + - '--key=$_CPP_SDK_CONFORMANCE_CACHE_KEY-$( checksum sdks/cpp/cmake/prerequisites.cmake )' + - '--path=test/sdk/cpp/sdk' + id: cpp-sdk-conformance-save-cache + waitFor: + - sdk-conformance + # # Cache the Rust SDK build directory, to speed up subsequent builds (considerably) # @@ -278,6 +299,7 @@ substitutions: _CACHE_BUCKET: agones-build-cache _HTMLTEST_CACHE_KEY: htmltest-0.10.1 _CPP_SDK_BUILD_CACHE_KEY: cpp-sdk-build + _CPP_SDK_CONFORMANCE_CACHE_KEY: cpp-sdk-conformance _RUST_SDK_BUILD_CACHE_KEY: rust-sdk-build tags: ['ci'] diff --git a/test/sdk/cpp/CMakeLists.txt b/test/sdk/cpp/CMakeLists.txt new file mode 100644 index 0000000000..df3e9028cf --- /dev/null +++ b/test/sdk/cpp/CMakeLists.txt @@ -0,0 +1,53 @@ +# Copyright 2020 Google LLC All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +cmake_minimum_required (VERSION 3.13.0) + +project(cpp-simple CXX) + +# Settings +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED TRUE) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_INCLUDE_CURRENT_DIR ON) +set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON) +set_property(GLOBAL PROPERTY USE_FOLDERS ON) +set(CMAKE_DEBUG_POSTFIX "d") + +find_package(agones CONFIG REQUIRED) + +if(WIN32) + # Windows + add_definitions(-D_WIN32_WINNT=0x0600) + set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT cpp-simple) +elseif(APPLE) + # Mac OS +elseif(UNIX AND NOT APPLE) + # Linux +endif() + + +include_directories(${agones_INCLUDE_DIRS}) +set(SRC_FILES "server.cc") + +# Executable +add_executable(${PROJECT_NAME} ${SRC_FILES}) +target_link_libraries(${PROJECT_NAME} PUBLIC agones) + +if (MSVS) + target_compile_options(${PROJECT_NAME} PUBLIC /wd4101 /wd4146 /wd4251 /wd4661) +endif() + +# Installation +install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME} RUNTIME DESTINATION .) \ No newline at end of file diff --git a/test/sdk/cpp/server.cc b/test/sdk/cpp/server.cc new file mode 100644 index 0000000000..ef639e457b --- /dev/null +++ b/test/sdk/cpp/server.cc @@ -0,0 +1,135 @@ +// Copyright 2020 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// A server that starts, and then stops after 60 seconds. +// This example really does nothing other than show how to integrate +// the C++ SDK. + +#include +#include +#include +#include + +// send health check pings +void DoHealth(std::shared_ptr sdk) { + bool ok = sdk->Health(); + std::cout << "Health ping " << (ok ? "sent" : "failed") << "\n" << std::flush; +} + +// watch GameServer Updates +void WatchUpdates(std::shared_ptr sdk) { + std::cout << "Starting to watch GameServer updates...\n" << std::flush; + sdk->WatchGameServer([](const agones::dev::sdk::GameServer& gameserver) { + std::cout << "GameServer Update:\n" // + << "\tname: " << gameserver.object_meta().name() << "\n" // + << "\tstate: " << gameserver.status().state() << "\n" + << std::flush; + }); +} + +int main() { + std::cout << "C++ Game Server has started!\n" + << "Getting the instance of the SDK.\n" << std::flush; + auto sdk = std::make_shared(); + + std::cout << "Attempting to connect...\n" << std::flush; + if (!sdk->Connect()) { + std::cerr << "Exiting!\n"; + return -1; + } + std::cout << "...handshake complete.\n" << std::flush; + + DoHealth(sdk); + std::thread watch(WatchUpdates, sdk); + + std::cout << "Marking server as ready...\n" << std::flush; + grpc::Status status = sdk->Ready(); + if (!status.ok()) { + std::cerr << "Could not run Ready(): " << status.error_message() + << ". Exiting!\n"; + return -1; + } + std::cout << "...marked Ready\n" << std::flush; + + status = sdk->Allocate(); + if (!status.ok()) { + std::cerr << "Could not run Allocate(): " << status.error_message() + << ". Exiting!\n"; + return -1; + } + std::cout << "...marked Allocated\n" << std::flush; + + std::chrono::seconds sec(1); + status = sdk->Reserve(sec); + if (!status.ok()) { + std::cerr << "Could not run Reserve(): " << status.error_message() + << ". Exiting!\n"; + return -1; + } + std::cout << "...marked Reserved\n" << std::flush; + + std::cout << "Getting GameServer details...\n" << std::flush; + agones::dev::sdk::GameServer gameserver; + status = sdk->GameServer(&gameserver); + + if (!status.ok()) { + std::cerr << "Could not run GameServer(): " << status.error_message() + << ". Exiting!\n"; + return -1; + } + + std::cout << "GameServer name: " << gameserver.object_meta().name() << "\n" + << std::flush; + + std::cout << "Setting a label\n" << std::flush; + status = sdk->SetLabel( + "test-label", + std::to_string(gameserver.object_meta().creation_timestamp())); + if (!status.ok()) { + std::cerr << "Could not run SetLabel(): " << status.error_message() + << ". Exiting!\n"; + return -1; + } + + std::cout << "Setting an annotation\n" << std::flush; + status = + sdk->SetAnnotation("test-annotation", gameserver.object_meta().uid()); + if (!status.ok()) { + std::cerr << "Could not run SetAnnotation(): " << status.error_message() + << ". Exiting!\n"; + return -1; + } + + for (int i = 0; i < 2; i++) { + int time = i * 10; + std::cout << "Running for " + std::to_string(time) + " seconds !\n" + << std::flush; + + std::this_thread::sleep_for(std::chrono::seconds(10)); + + if (i == 1) { + std::cout << "Shutting down after 10 seconds...\n" << std::flush; + grpc::Status status = sdk->Shutdown(); + if (!status.ok()) { + std::cerr << "Could not run Shutdown():" << status.error_message() + << ". Exiting!\n"; + return -1; + } + std::cout << "...marked for Shutdown\n" << std::flush; + } + } + watch.join(); + + return 0; +}