diff --git a/ci/build-examples.yaml b/ci/build-examples.yaml index fbce570c..059d5e0d 100644 --- a/ci/build-examples.yaml +++ b/ci/build-examples.yaml @@ -234,7 +234,6 @@ steps: waitFor: ['gcf-builder-ready'] id: 'site-hello_world_http' args: ['build', - '--env', 'GOOGLE_FUNCTION_SIGNATURE_TYPE=http', '--env', 'GOOGLE_FUNCTION_TARGET=hello_world_http', '--path', 'examples/site/hello_world_http', 'site-hello_world_http', @@ -243,7 +242,6 @@ steps: waitFor: ['gcf-builder-ready'] id: 'site-hello_world_pubsub' args: ['build', - '--env', 'GOOGLE_FUNCTION_SIGNATURE_TYPE=cloudevent', '--env', 'GOOGLE_FUNCTION_TARGET=hello_world_pubsub', '--path', 'examples/site/hello_world_pubsub', 'site-hello_world_pubsub', @@ -252,7 +250,6 @@ steps: waitFor: ['gcf-builder-ready'] id: 'site-hello_world_storage' args: ['build', - '--env', 'GOOGLE_FUNCTION_SIGNATURE_TYPE=cloudevent', '--env', 'GOOGLE_FUNCTION_TARGET=hello_world_storage', '--path', 'examples/site/hello_world_storage', 'site-hello_world_storage', diff --git a/ci/generate-build-examples.sh b/ci/generate-build-examples.sh index 5b8c06e4..33483354 100755 --- a/ci/generate-build-examples.sh +++ b/ci/generate-build-examples.sh @@ -113,6 +113,9 @@ site_example() { if grep -E -q 'gcf::CloudEvent|google::cloud::functions::CloudEvent' ${example}/*; then signature="cloudevent" fi + if grep -E -q 'gcf::Function|google::cloud::functions::Function' ${example}/*; then + signature="declarative" + fi local container="site-${function}" cat <<_EOF_ diff --git a/examples/site/hello_world_http/hello_world_http.cc b/examples/site/hello_world_http/hello_world_http.cc index 26ce9ca3..eae24855 100644 --- a/examples/site/hello_world_http/hello_world_http.cc +++ b/examples/site/hello_world_http/hello_world_http.cc @@ -13,13 +13,12 @@ // limitations under the License. // [START functions_helloworld_http] -#include -#include +#include #include namespace gcf = ::google::cloud::functions; -gcf::HttpResponse hello_world_http(gcf::HttpRequest request) { +gcf::HttpResponse hello_world_http_impl(gcf::HttpRequest request) { auto greeting = [r = std::move(request)] { auto request_json = nlohmann::json::parse(r.payload(), /*cb=*/nullptr, /*allow_exceptions=*/false); @@ -33,4 +32,8 @@ gcf::HttpResponse hello_world_http(gcf::HttpRequest request) { .set_header("content-type", "text/plain") .set_payload(greeting()); } + +gcf::Function hello_world_http() { + return gcf::MakeFunction(hello_world_http_impl); +} // [END functions_helloworld_http] diff --git a/examples/site/hello_world_pubsub/hello_world_pubsub.cc b/examples/site/hello_world_pubsub/hello_world_pubsub.cc index 779ef27d..7eaf20c0 100644 --- a/examples/site/hello_world_pubsub/hello_world_pubsub.cc +++ b/examples/site/hello_world_pubsub/hello_world_pubsub.cc @@ -13,16 +13,14 @@ // limitations under the License. // [START functions_helloworld_pubsub] -#include +#include #include #include #include namespace gcf = ::google::cloud::functions; -// Though not used in this example, the event is passed by value to support -// applications that move-out its data. -void hello_world_pubsub(gcf::CloudEvent event) { // NOLINT +void hello_world_pubsub_impl(gcf::CloudEvent const& event) { if (event.data_content_type().value_or("") != "application/json") { BOOST_LOG_TRIVIAL(error) << "expected application/json data"; return; @@ -32,4 +30,8 @@ void hello_world_pubsub(gcf::CloudEvent event) { // NOLINT payload["message"]["data"].get()); BOOST_LOG_TRIVIAL(info) << "Hello " << (name.empty() ? "World" : name); } + +gcf::Function hello_world_pubsub() { + return gcf::MakeFunction(hello_world_pubsub_impl); +} // [END functions_helloworld_pubsub] diff --git a/examples/site/hello_world_storage/hello_world_storage.cc b/examples/site/hello_world_storage/hello_world_storage.cc index 4687288a..428bca64 100644 --- a/examples/site/hello_world_storage/hello_world_storage.cc +++ b/examples/site/hello_world_storage/hello_world_storage.cc @@ -13,15 +13,13 @@ // limitations under the License. // [START functions_helloworld_storage] -#include +#include #include #include namespace gcf = ::google::cloud::functions; -// Though not used in this example, the event is passed by value to support -// applications that move-out its data. -void hello_world_storage(gcf::CloudEvent event) { // NOLINT +void hello_world_storage_impl(gcf::CloudEvent const& event) { if (event.data_content_type().value_or("") != "application/json") { BOOST_LOG_TRIVIAL(error) << "expected application/json data"; return; @@ -36,4 +34,8 @@ void hello_world_storage(gcf::CloudEvent event) { // NOLINT BOOST_LOG_TRIVIAL(info) << "Created: " << payload.value("timeCreated", ""); BOOST_LOG_TRIVIAL(info) << "Updated: " << payload.value("updated", ""); } + +gcf::Function hello_world_storage() { + return gcf::MakeFunction(hello_world_storage_impl); +} // [END functions_helloworld_storage] diff --git a/examples/site/howto_create_container/README.md b/examples/site/howto_create_container/README.md index 41000677..c0e22ba0 100644 --- a/examples/site/howto_create_container/README.md +++ b/examples/site/howto_create_container/README.md @@ -30,13 +30,12 @@ In this guide we will be using this [function][snippet source]: [snippet source]: /examples/site/hello_world_http/hello_world_http.cc ```cc -#include -#include +#include #include namespace gcf = ::google::cloud::functions; -gcf::HttpResponse hello_world_http(gcf::HttpRequest request) { +gcf::HttpResponse hello_world_http_impl(gcf::HttpRequest request) { auto greeting = [r = std::move(request)] { auto request_json = nlohmann::json::parse(r.payload(), /*cb=*/nullptr, /*allow_exceptions=*/false); @@ -50,6 +49,10 @@ gcf::HttpResponse hello_world_http(gcf::HttpRequest request) { .set_header("content-type", "text/plain") .set_payload(greeting()); } + +gcf::Function hello_world_http() { + return gcf::MakeFunction(hello_world_http_impl); +} ``` @@ -85,7 +88,6 @@ containing your function: ```shell pack build \ --builder gcr.io/buildpacks/builder:latest \ - --env GOOGLE_FUNCTION_SIGNATURE_TYPE=http \ --env GOOGLE_FUNCTION_TARGET=hello_world_http \ --path examples/site/hello_world_http \ gcf-cpp-hello-world-http diff --git a/examples/site/howto_deploy_cloud_event/README.md b/examples/site/howto_deploy_cloud_event/README.md index fb7369aa..4f234d49 100644 --- a/examples/site/howto_deploy_cloud_event/README.md +++ b/examples/site/howto_deploy_cloud_event/README.md @@ -33,14 +33,14 @@ In this guide we will be using this [function][snippet source]: [snippet source]: /examples/site/hello_world_pubsub/hello_world_pubsub.cc ```cc -#include +#include #include #include #include namespace gcf = ::google::cloud::functions; -void hello_world_pubsub(gcf::CloudEvent event) { +void hello_world_pubsub_impl(gcf::CloudEvent const& event) { if (event.data_content_type().value_or("") != "application/json") { BOOST_LOG_TRIVIAL(error) << "expected application/json data"; return; @@ -50,6 +50,10 @@ void hello_world_pubsub(gcf::CloudEvent event) { payload["message"]["data"].get()); BOOST_LOG_TRIVIAL(info) << "Hello " << (name.empty() ? "World" : name); } + +gcf::Function hello_world_pubsub() { + return gcf::MakeFunction(hello_world_pubsub_impl); +} ``` @@ -87,7 +91,6 @@ containing your function: GOOGLE_CLOUD_PROJECT=... # put the right value here pack build \ --builder gcr.io/buildpacks/builder:latest \ - --env GOOGLE_FUNCTION_SIGNATURE_TYPE=cloudevent \ --env GOOGLE_FUNCTION_TARGET=hello_world_pubsub \ --path examples/site/hello_world_pubsub \ "gcr.io/${GOOGLE_CLOUD_PROJECT}/gcf-cpp-hello-world-pubsub" diff --git a/examples/site/howto_deploy_to_cloud_run/README.md b/examples/site/howto_deploy_to_cloud_run/README.md index c05e45e8..e6e4bc44 100644 --- a/examples/site/howto_deploy_to_cloud_run/README.md +++ b/examples/site/howto_deploy_to_cloud_run/README.md @@ -43,13 +43,12 @@ In this guide we will be using this [function][snippet source]: [snippet source]: /examples/site/hello_world_http/hello_world_http.cc ```cc -#include -#include +#include #include namespace gcf = ::google::cloud::functions; -gcf::HttpResponse hello_world_http(gcf::HttpRequest request) { +gcf::HttpResponse hello_world_http_impl(gcf::HttpRequest request) { auto greeting = [r = std::move(request)] { auto request_json = nlohmann::json::parse(r.payload(), /*cb=*/nullptr, /*allow_exceptions=*/false); @@ -63,6 +62,10 @@ gcf::HttpResponse hello_world_http(gcf::HttpRequest request) { .set_header("content-type", "text/plain") .set_payload(greeting()); } + +gcf::Function hello_world_http() { + return gcf::MakeFunction(hello_world_http_impl); +} ``` @@ -100,7 +103,6 @@ containing your function: GOOGLE_CLOUD_PROJECT=... # put the right value here pack build \ --builder gcr.io/buildpacks/builder:latest \ - --env GOOGLE_FUNCTION_SIGNATURE_TYPE=http \ --env GOOGLE_FUNCTION_TARGET=hello_world_http \ --path examples/site/hello_world_http \ "gcr.io/${GOOGLE_CLOUD_PROJECT}/gcf-cpp-hello-world-http" diff --git a/examples/site/howto_local_development/CMakeLists.txt b/examples/site/howto_local_development/CMakeLists.txt index 455e2e99..8cfdd3e5 100644 --- a/examples/site/howto_local_development/CMakeLists.txt +++ b/examples/site/howto_local_development/CMakeLists.txt @@ -18,7 +18,7 @@ # CMake-based projects. cmake_minimum_required(VERSION 3.5) -project(functions-framework-cpp-howto-local-development CXX C) +project(functions-framework-cpp-howto-local-development CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/examples/site/howto_local_development/local_server.cc b/examples/site/howto_local_development/local_server.cc index 9a511e17..0cd00951 100644 --- a/examples/site/howto_local_development/local_server.cc +++ b/examples/site/howto_local_development/local_server.cc @@ -19,14 +19,14 @@ namespace gcf = ::google::cloud::functions; namespace { -gcf::HttpResponse HelloWithShutdown(gcf::HttpRequest const& /*request*/) { - return gcf::HttpResponse{} - .set_header("Content-Type", "text/plain") - .set_payload("Hello World\n"); +gcf::Function HelloLocal() { + return gcf::MakeFunction([](gcf::HttpRequest const& /*request*/) { + return gcf::HttpResponse{} + .set_header("Content-Type", "text/plain") + .set_payload("Hello World\n"); + }); } } // namespace -int main(int argc, char* argv[]) { - return ::google::cloud::functions::Run(argc, argv, HelloWithShutdown); -} +int main(int argc, char* argv[]) { return gcf::Run(argc, argv, HelloLocal()); } diff --git a/examples/site/testing_http/http_integration_server.cc b/examples/site/testing_http/http_integration_server.cc index 5d8e3abd..09727aec 100644 --- a/examples/site/testing_http/http_integration_server.cc +++ b/examples/site/testing_http/http_integration_server.cc @@ -15,8 +15,8 @@ #include namespace gcf = ::google::cloud::functions; -extern gcf::HttpResponse hello_world_http(gcf::HttpRequest request); +extern gcf::Function hello_world_http(); int main(int argc, char* argv[]) { - return gcf::Run(argc, argv, hello_world_http); + return gcf::Run(argc, argv, hello_world_http()); } diff --git a/examples/site/testing_http/http_unit_test.cc b/examples/site/testing_http/http_unit_test.cc index 040592e3..ce13067c 100644 --- a/examples/site/testing_http/http_unit_test.cc +++ b/examples/site/testing_http/http_unit_test.cc @@ -18,20 +18,20 @@ #include namespace gcf = ::google::cloud::functions; -extern gcf::HttpResponse hello_world_http(gcf::HttpRequest request); +extern gcf::HttpResponse hello_world_http_impl(gcf::HttpRequest request); namespace { TEST(HttpUnitTest, Success) { - auto actual = hello_world_http( + auto actual = hello_world_http_impl( gcf::HttpRequest{}.set_payload(R"js({ "name": "Foo" })js")); EXPECT_EQ(actual.payload(), "Hello Foo!"); - actual = hello_world_http( + actual = hello_world_http_impl( gcf::HttpRequest{}.set_payload(R"js({ "unused": 7 })js")); EXPECT_EQ(actual.payload(), "Hello World!"); - actual = hello_world_http(gcf::HttpRequest{}.set_payload("Bar")); + actual = hello_world_http_impl(gcf::HttpRequest{}.set_payload("Bar")); EXPECT_EQ(actual.payload(), "Hello World!"); } diff --git a/examples/site/testing_pubsub/README.md b/examples/site/testing_pubsub/README.md index 542f1531..2bcd6958 100644 --- a/examples/site/testing_pubsub/README.md +++ b/examples/site/testing_pubsub/README.md @@ -12,14 +12,14 @@ We will use this [function][snippet source] throughput this guide: [snippet source]: /examples/site/hello_world_pubsub/hello_world_pubsub.cc ```cc -#include +#include #include #include #include namespace gcf = ::google::cloud::functions; -void hello_world_pubsub(gcf::CloudEvent event) { +void hello_world_pubsub_impl(gcf::CloudEvent const& event) { if (event.data_content_type().value_or("") != "application/json") { BOOST_LOG_TRIVIAL(error) << "expected application/json data"; return; @@ -29,6 +29,10 @@ void hello_world_pubsub(gcf::CloudEvent event) { payload["message"]["data"].get()); BOOST_LOG_TRIVIAL(info) << "Hello " << (name.empty() ? "World" : name); } + +gcf::Function hello_world_pubsub() { + return gcf::MakeFunction(hello_world_pubsub_impl); +} ``` diff --git a/examples/site/testing_pubsub/pubsub_integration_server.cc b/examples/site/testing_pubsub/pubsub_integration_server.cc index d8f4a21b..2d71cef4 100644 --- a/examples/site/testing_pubsub/pubsub_integration_server.cc +++ b/examples/site/testing_pubsub/pubsub_integration_server.cc @@ -15,8 +15,8 @@ #include namespace gcf = ::google::cloud::functions; -extern void hello_world_pubsub(gcf::CloudEvent event); +extern gcf::Function hello_world_pubsub(); int main(int argc, char* argv[]) { - return gcf::Run(argc, argv, hello_world_pubsub); + return gcf::Run(argc, argv, hello_world_pubsub()); } diff --git a/examples/site/testing_pubsub/pubsub_unit_test.cc b/examples/site/testing_pubsub/pubsub_unit_test.cc index a0dd1b07..140d83b0 100644 --- a/examples/site/testing_pubsub/pubsub_unit_test.cc +++ b/examples/site/testing_pubsub/pubsub_unit_test.cc @@ -24,7 +24,7 @@ #include namespace gcf = ::google::cloud::functions; -extern void hello_world_pubsub(gcf::CloudEvent event); +extern void hello_world_pubsub_impl(gcf::CloudEvent const& event); namespace { @@ -65,7 +65,7 @@ TEST(PubsubUnitTest, Basic) { event.set_data_content_type("application/json"); event.set_data(test.data); stream->str({}); - EXPECT_NO_THROW(hello_world_pubsub(event)); + EXPECT_NO_THROW(hello_world_pubsub_impl(event)); auto log_lines = stream->str(); EXPECT_THAT(log_lines, HasSubstr(test.expected)); } diff --git a/examples/site/testing_storage/README.md b/examples/site/testing_storage/README.md index ba3beea0..edb0b78a 100644 --- a/examples/site/testing_storage/README.md +++ b/examples/site/testing_storage/README.md @@ -13,13 +13,13 @@ We will use this [function][snippet source] throughout this guide: [snippet source]: /examples/site/hello_world_storage/hello_world_storage.cc ```cc -#include +#include #include #include namespace gcf = ::google::cloud::functions; -void hello_world_storage(gcf::CloudEvent event) { +void hello_world_storage_impl(gcf::CloudEvent const& event) { if (event.data_content_type().value_or("") != "application/json") { BOOST_LOG_TRIVIAL(error) << "expected application/json data"; return; @@ -34,6 +34,10 @@ void hello_world_storage(gcf::CloudEvent event) { BOOST_LOG_TRIVIAL(info) << "Created: " << payload.value("timeCreated", ""); BOOST_LOG_TRIVIAL(info) << "Updated: " << payload.value("updated", ""); } + +gcf::Function hello_world_storage() { + return gcf::MakeFunction(hello_world_storage_impl); +} ``` diff --git a/examples/site/testing_storage/storage_integration_server.cc b/examples/site/testing_storage/storage_integration_server.cc index f8781910..ee480736 100644 --- a/examples/site/testing_storage/storage_integration_server.cc +++ b/examples/site/testing_storage/storage_integration_server.cc @@ -15,8 +15,8 @@ #include namespace gcf = ::google::cloud::functions; -extern void hello_world_storage(gcf::CloudEvent event); +extern gcf::Function hello_world_storage(); int main(int argc, char* argv[]) { - return gcf::Run(argc, argv, hello_world_storage); + return gcf::Run(argc, argv, hello_world_storage()); } diff --git a/examples/site/testing_storage/storage_unit_test.cc b/examples/site/testing_storage/storage_unit_test.cc index af1393ab..77781680 100644 --- a/examples/site/testing_storage/storage_unit_test.cc +++ b/examples/site/testing_storage/storage_unit_test.cc @@ -24,7 +24,7 @@ #include namespace gcf = ::google::cloud::functions; -extern void hello_world_storage(gcf::CloudEvent event); +extern void hello_world_storage_impl(gcf::CloudEvent const& event); namespace { @@ -74,7 +74,7 @@ TEST(StorageUnitTest, Basic) { data["name"] = test.name; event.set_data(data.dump()); stream->str({}); - EXPECT_NO_THROW(hello_world_storage(event)); + EXPECT_NO_THROW(hello_world_storage_impl(event)); auto log_lines = stream->str(); EXPECT_THAT(log_lines, HasSubstr(test.expected)); } diff --git a/examples/site_test.cc b/examples/site_test.cc index b7f18cb6..852a503a 100644 --- a/examples/site_test.cc +++ b/examples/site_test.cc @@ -12,9 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "google/cloud/functions/internal/function_impl.h" +#include "google/cloud/functions/internal/http_message_types.h" #include "google/cloud/functions/internal/parse_cloud_event_json.h" #include "google/cloud/functions/internal/setenv.h" #include "google/cloud/functions/cloud_event.h" +#include "google/cloud/functions/function.h" #include "google/cloud/functions/http_request.h" #include "google/cloud/functions/http_response.h" #include @@ -26,6 +29,8 @@ #include namespace gcf = ::google::cloud::functions; +namespace gcf_internal = ::google::cloud::functions_internal; + extern gcf::HttpResponse bearer_token(gcf::HttpRequest request); extern gcf::HttpResponse concepts_after_response(gcf::HttpRequest request); extern gcf::HttpResponse concepts_after_timeout(gcf::HttpRequest request); @@ -35,9 +40,9 @@ extern gcf::HttpResponse concepts_stateless(gcf::HttpRequest request); extern gcf::HttpResponse env_vars(gcf::HttpRequest request); extern gcf::HttpResponse hello_world_error(gcf::HttpRequest request); extern gcf::HttpResponse hello_world_get(gcf::HttpRequest request); -extern gcf::HttpResponse hello_world_http(gcf::HttpRequest request); -extern void hello_world_pubsub(gcf::CloudEvent event); -extern void hello_world_storage(gcf::CloudEvent event); +extern gcf::Function hello_world_http(); +extern gcf::Function hello_world_pubsub(); +extern gcf::Function hello_world_storage(); extern gcf::HttpResponse http_content(gcf::HttpRequest request); extern gcf::HttpResponse http_cors(gcf::HttpRequest request); extern gcf::HttpResponse http_cors_auth(gcf::HttpRequest request); @@ -59,6 +64,18 @@ using ::testing::AllOf; using ::testing::HasSubstr; using ::testing::IsEmpty; +auto TriggerFunctionHttp(gcf::Function const& function, + gcf::HttpRequest const& r) { + gcf_internal::BeastRequest request; + request.target(r.target()); + request.body() = r.payload(); + for (auto const& [k, v] : r.headers()) request.insert(k, v); + + auto handler = + gcf_internal::FunctionImpl::GetImpl(function)->GetHandler("unused"); + return handler(std::move(request)); +} + TEST(ExamplesSiteTest, BearerToken) { google::cloud::functions_internal::SetEnv("TARGET_URL", std::nullopt); google::cloud::functions_internal::SetEnv("GOOGLE_APPLICATION_CREDENTIALS", @@ -190,16 +207,17 @@ TEST(ExamplesSiteTest, HelloWorldGet) { } TEST(ExamplesSiteTest, HelloWorlHttp) { - auto actual = hello_world_http( - gcf::HttpRequest{}.set_payload(R"js({ "name": "Foo" })js")); - EXPECT_EQ(actual.payload(), "Hello Foo!"); + auto function = hello_world_http(); + auto actual = TriggerFunctionHttp( + function, gcf::HttpRequest{}.set_payload(R"js({ "name": "Foo" })js")); + EXPECT_EQ(actual.body(), "Hello Foo!"); - actual = hello_world_http( - gcf::HttpRequest{}.set_payload(R"js({ "unused": 7 })js")); - EXPECT_EQ(actual.payload(), "Hello World!"); + actual = TriggerFunctionHttp( + function, gcf::HttpRequest{}.set_payload(R"js({ "unused": 7 })js")); + EXPECT_EQ(actual.body(), "Hello World!"); - actual = hello_world_http(gcf::HttpRequest{}.set_payload("Bar")); - EXPECT_EQ(actual.payload(), "Hello World!"); + actual = TriggerFunctionHttp(function, gcf::HttpRequest{}.set_payload("Bar")); + EXPECT_EQ(actual.body(), "Hello World!"); } TEST(ExamplesSiteTest, HelloWorldPubSub) { @@ -228,12 +246,17 @@ TEST(ExamplesSiteTest, HelloWorldPubSub) { for (auto const* data : {"dGVzdCBtZXNzYWdlIDM=", "YWJjZA==", ""}) { auto json = base; json["data"]["message"]["data"] = data; - EXPECT_NO_THROW(hello_world_pubsub( - google::cloud::functions_internal::ParseCloudEventJson(json.dump()))); + auto response = + TriggerFunctionHttp(hello_world_pubsub(), + gcf::HttpRequest{} + .set_payload(json.dump()) + .add_header("ce-type", "com.example.someevent") + .add_header("ce-source", "/mycontext") + .add_header("ce-id", "A234-1234-1234")); + EXPECT_EQ(response.result_int(), 200); } - EXPECT_NO_THROW(hello_world_pubsub( - google::cloud::functions_internal::ParseCloudEventJson(R"js({ + auto constexpr kBodyDataText = R"js({ "specversion": "1.0", "type": "test.invalid.invalid", "source": "//pubsub.googleapis.com/projects/sample-project/topics/gcf-test", @@ -241,10 +264,8 @@ TEST(ExamplesSiteTest, HelloWorldPubSub) { "time": "2020-09-29T11:32:00.000Z", "datacontenttype": "text/plain", "data": "some data" - })js"))); - - EXPECT_THROW(hello_world_pubsub( - google::cloud::functions_internal::ParseCloudEventJson(R"js({ + })js"; + auto constexpr kBodyDataJson = R"js({ "specversion": "1.0", "type": "google.cloud.pubsub.topic.v1.messagePublished", "source": "//pubsub.googleapis.com/projects/sample-project/topics/gcf-test", @@ -255,8 +276,27 @@ TEST(ExamplesSiteTest, HelloWorldPubSub) { "subscription": "projects/sample-project/subscriptions/sample-subscription" } } - })js")), - std::exception); + })js"; + + struct TestCase { + std::string name; + std::string body; + } cases[] = { + {"text", kBodyDataText}, + {"json", kBodyDataJson}, + }; + + for (auto const& [name, body] : cases) { + SCOPED_TRACE("Testing for " + name); + auto response = + TriggerFunctionHttp(hello_world_storage(), + gcf::HttpRequest{} + .set_payload(body) + .add_header("ce-type", "com.example.someevent") + .add_header("ce-source", "/mycontext") + .add_header("ce-id", "A234-1234-1234")); + EXPECT_EQ(response.result_int(), 200); + } } TEST(ExamplesSiteTest, HelloWorldStorage) { @@ -291,11 +331,7 @@ TEST(ExamplesSiteTest, HelloWorldStorage) { } })js"); - EXPECT_NO_THROW(hello_world_storage( - google::cloud::functions_internal::ParseCloudEventJson(base.dump()))); - - EXPECT_NO_THROW(hello_world_storage( - google::cloud::functions_internal::ParseCloudEventJson(R"js({ + auto constexpr kBodyDataText = R"js({ "specversion": "1.0", "type": "test.invalid.invalid", "source": "//pubsub.googleapis.com/projects/sample-project/topics/gcf-test", @@ -303,17 +339,37 @@ TEST(ExamplesSiteTest, HelloWorldStorage) { "time": "2020-09-29T11:32:00.000Z", "datacontenttype": "text/plain", "data": "some data" - })js"))); + })js"; - EXPECT_NO_THROW(hello_world_storage( - google::cloud::functions_internal::ParseCloudEventJson(R"js({ + auto constexpr kBodyDataJson = R"js({ "specversion": "1.0", "type": "test.invalid.invalid", "source": "//pubsub.googleapis.com/projects/sample-project/topics/gcf-test", "id": "aaaaaa-1111-bbbb-2222-cccccccccccc", "time": "2020-09-29T11:32:00.000Z", "datacontenttype": "application/json" - })js"))); + })js"; + + struct TestCase { + std::string name; + std::string body; + } cases[] = { + {"base", base.dump()}, + {"text", kBodyDataText}, + {"json", kBodyDataJson}, + }; + + for (auto const& [name, body] : cases) { + SCOPED_TRACE("Testing for " + name); + auto response = + TriggerFunctionHttp(hello_world_storage(), + gcf::HttpRequest{} + .set_payload(body) + .add_header("ce-type", "com.example.someevent") + .add_header("ce-source", "/mycontext") + .add_header("ce-id", "A234-1234-1234")); + EXPECT_EQ(response.result_int(), 200); + } } TEST(ExamplesSiteTest, HttpContent) {