From c3153b27fc349cf35cc1e21ef240f0290921cd00 Mon Sep 17 00:00:00 2001 From: Gurgen Hrachyan Date: Thu, 18 Aug 2016 15:47:02 -0700 Subject: [PATCH] Add bindings and body prefix test for transcoding Change-Id: I75ad599fa85b8251fc3dbc26635b7f444d8a670a --- src/nginx/t/BUILD | 1 + src/nginx/t/transcoding_bindings.t | 259 ++++++++++++++++++++++++++++ test/transcoding/bookstore-api.yaml | 3 + test/transcoding/service.json | 4 + 4 files changed, 267 insertions(+) create mode 100644 src/nginx/t/transcoding_bindings.t diff --git a/src/nginx/t/BUILD b/src/nginx/t/BUILD index edc85bcb5..0b6eb42e8 100644 --- a/src/nginx/t/BUILD +++ b/src/nginx/t/BUILD @@ -274,6 +274,7 @@ nginx_suite( nginx = "//src/nginx/main:nginx-esp", tests = [ "transcoding.t", + "transcoding_bindings.t", "transcoding_errors.t", "transcoding_streaming.t", ], diff --git a/src/nginx/t/transcoding_bindings.t b/src/nginx/t/transcoding_bindings.t new file mode 100644 index 000000000..92dfa2a1e --- /dev/null +++ b/src/nginx/t/transcoding_bindings.t @@ -0,0 +1,259 @@ +# Copyright (C) Endpoints Server Proxy Authors +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +################################################################################ +# +use strict; +use warnings; + +################################################################################ + +BEGIN { use FindBin; chdir($FindBin::Bin); } + +use ApiManager; # Must be first (sets up import path to the Nginx test module) +use Test::Nginx; # Imports Nginx's test module +use Test::More; # And the test framework +use HttpServer; +use ServiceControl; +use JSON::PP; + +################################################################################ + +# Port assignments +my $NginxPort = ApiManager::pick_port(); +my $ServiceControlPort = ApiManager::pick_port(); +my $GrpcServerPort = ApiManager::pick_port(); + +my $t = Test::Nginx->new()->has(qw/http proxy/)->plan(20); + +$t->write_file('service.json', + ApiManager::get_transcoding_test_service_config( + 'endpoints-transcoding-test.cloudendpointsapis.com', + "http://127.0.0.1:${ServiceControlPort}")); + +ApiManager::write_file_expand($t, 'nginx.conf', <run_daemon(\&service_control, $t, $ServiceControlPort, 'servicecontrol.log', $report_done); +ApiManager::run_transcoding_test_server($t, 'server.log', "127.0.0.1:${GrpcServerPort}"); + +is($t->waitforsocket("127.0.0.1:${ServiceControlPort}"), 1, "Service control socket ready."); +is($t->waitforsocket("127.0.0.1:${GrpcServerPort}"), 1, "GRPC test server socket ready."); +$t->run(); +is($t->waitforsocket("127.0.0.1:${NginxPort}"), 1, "Nginx socket ready."); + +################################################################################ + +# 1. Binding shelf=1 in ListBooksRequest +# HTTP template: +# GET /shelves/{shelf}/books +my $response = ApiManager::http_get($NginxPort,'/shelves/1/books?key=api-key'); +ok(ApiManager::verify_http_json_response( + $response, + { 'books' => [ {'id' => '1', 'author' => 'Neal Stephenson', 'title' => 'Readme'} ] }), + 'Got initial books for shelf 1'); + +# 2. Binding shelf=2 in ListBooksRequest +# HTTP template: +# GET /shelves/{shelf}/books +my $response = ApiManager::http_get($NginxPort,'/shelves/2/books?key=api-key'); +ok(ApiManager::verify_http_json_response( + $response, + { 'books' => [ {'id' => '2', 'author' => 'George R.R. Martin', 'title' => 'A Game of Thrones'} ] }), + 'Got initial books for shelf 2'); + +# 3. Binding shelf=1 and book= in CreateBookRequest +# HTTP template: +# POST /shelves/{shelf}/books +# body: book +$response = ApiManager::http($NginxPort,< '3', 'author' => 'Leo Tolstoy', 'title' => 'War and Peace'}), + 'Got the new book'); + +# 4. Binding shelf=1, book.id=4, book.author="Mark Twain" and book.title= +# in CreateBookRequest. +# HTTP template: +# POST /shelves/{shelf}/books/{book.id}/{book.author} +# body: book.title +$response = ApiManager::http($NginxPort,< '4', 'author' => 'Mark Twain', 'title' => 'The Adventures of Huckleberry Finn'}), + 'Got the new book'); + +# 5. Binding shelf=1 in ListBooksRequest +# HTTP template: +# GET /shelves/{shelf}/books +my $response = ApiManager::http_get($NginxPort,'/shelves/1/books?key=api-key'); +ok(ApiManager::verify_http_json_response( + $response, { 'books' => [ + {'id' => '1', 'author' => 'Neal Stephenson', 'title' => 'Readme'}, + {'id' => '3', 'author' => 'Leo Tolstoy', 'title' => 'War and Peace'}, + {'id' => '4', 'author' => 'Mark Twain', 'title' => 'The Adventures of Huckleberry Finn'}, + ] }), + 'Got all books for shelf 1'); + +# 6. Binding shelf=1 and book=3 in DeleteBookRequest +# HTTP template: +# DELETE /shelves/{shelf}/books/{book} +my $response = ApiManager::http($NginxPort,< [ + {'id' => '1', 'author' => 'Neal Stephenson', 'title' => 'Readme'}, + {'id' => '4', 'author' => 'Mark Twain', 'title' => 'The Adventures of Huckleberry Finn'}, + ] }), + 'Got final list of books for shelf 1'); + + +# Wait for the service control report +is($t->waitforfile("$t->{_testdir}/${report_done}"), 1, 'Report body file ready.'); +$t->stop_daemons(); + +################################################################################ + +# Read and verify backend logs +my $server_output = $t->read_file('server.log'); +my @translated_requests = split /\r\n\r\n/, $server_output; + +# Check the translated requests +is (scalar @translated_requests, 7, 'The server got the expected requests'); + +# 1. ListBooksRequest with shelf=1 +ok(ApiManager::compare_json($translated_requests[0], {'shelf'=>'1'})); + +# 2. ListBooksRequest with shelf=2 +ok(ApiManager::compare_json($translated_requests[1], {'shelf'=>'2'})); + +# 3. CreateBookRequest with shelf=1 and book={"author" : "Leo Tolstoy", "title" : "War and Peace"} +ok(ApiManager::compare_json( + $translated_requests[2], {'shelf'=>'1', book => {'author' => 'Leo Tolstoy', 'title' => 'War and Peace'}} )); + +# 4. CreateBookRequest with shelf=1 and book={"id" : "4", "author" : "Mark Twain", +# "title" : "The Adventures of Huckleberry Finn"} +ok(ApiManager::compare_json( + $translated_requests[3], + {'shelf'=>'1', book => {'id' => '4', 'author' => 'Mark Twain', + 'title' => 'The Adventures of Huckleberry Finn'}} )); + +# 5. ListBooksRequest with shelf=1 +ok(ApiManager::compare_json($translated_requests[4], {'shelf'=>'1'})); + +# 6. DeleteBookRequest with shelf=1 and book=3 +ok(ApiManager::compare_json($translated_requests[5], {'shelf'=>'1', 'book'=>'3'})); + +# 7. ListBooksRequest with shelf=1 +ok(ApiManager::compare_json($translated_requests[6], {'shelf'=>'1'})); + +# Check service control calls +# We expect 4 service control calls: +# - 1 check call for all calls to ListBooks (as we are using the same API key the +# second time check response is in the cache) +# - 1 check call for all calls to CreateBook, +# - 1 check call for the call to DeleteBook, +# - 1 aggregated report call +my @servicecontrol_requests = ApiManager::read_http_stream($t, 'servicecontrol.log'); +is(scalar @servicecontrol_requests, 4, 'Service control was called 2 times'); + +################################################################################ + +sub service_control { + my ($t, $port, $file, $done) = @_; + + my $server = HttpServer->new($port, $t->testdir() . '/' . $file) + or die "Can't create test server socket: $!\n"; + + local $SIG{PIPE} = 'IGNORE'; + + $server->on_sub('POST', '/v1/services/endpoints-transcoding-test.cloudendpointsapis.com:check', sub { + my ($headers, $body, $client) = @_; + print $client <on_sub('POST', '/v1/services/endpoints-transcoding-test.cloudendpointsapis.com:report', sub { + my ($headers, $body, $client) = @_; + print $client <write_file($done, ":report done"); + }); + + $server->run(); +} + +################################################################################ diff --git a/test/transcoding/bookstore-api.yaml b/test/transcoding/bookstore-api.yaml index acb77fc66..fc0e4b19e 100644 --- a/test/transcoding/bookstore-api.yaml +++ b/test/transcoding/bookstore-api.yaml @@ -48,6 +48,9 @@ http: - selector: "Bookstore.CreateBook" post: "/shelves/{shelf}/books" body: "book" + - selector: "Bookstore.CreateBook" + post: "/shelves/{shelf}/books/{book.id}/{book.author}" + body: "book.title" - selector: "Bookstore.GetBook" get: "/shelves/{shelf}/books/{book}" - selector: "Bookstore.DeleteBook" diff --git a/test/transcoding/service.json b/test/transcoding/service.json index 90eb6df43..178895982 100644 --- a/test/transcoding/service.json +++ b/test/transcoding/service.json @@ -1101,6 +1101,10 @@ "selector": "endpoints.examples.bookstore.Bookstore.CreateBook", "post": "/shelves/{shelf}/books", "body": "book" + }, { + "selector": "endpoints.examples.bookstore.Bookstore.CreateBook", + "post": "/shelves/{shelf}/books/{book.id}/{book.author}", + "body": "book.title" }, { "selector": "endpoints.examples.bookstore.Bookstore.GetBook", "get": "/shelves/{shelf}/books/{book}"