From 9577100f3c317ed0bc5974bd8b12cc07675263a0 Mon Sep 17 00:00:00 2001 From: Mark Slee Date: Wed, 7 Jun 2006 06:53:25 +0000 Subject: [PATCH] Thrift test code Summary: Did I promise you this or what?! Interoperable test servers and clients in both C++ and Java that you can use to check that they all work, all perform well, and that they all actually talk to each other! Problem: How we gon' test this Thrift bizniss? Solution: Write some test scenarios in each language. Reviewed By: aditya Test Plan: This IS the test plan. Notes: These tools are actually pretty easy to use, so long as you remember to type 'ant' in the java directory instead of 'make'. git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664716 13f79535-47bb-0310-9956-ffa450edef68 --- test/cpp/Makefile | 13 +- test/cpp/{ => src}/TestClient.cc | 42 +++- test/cpp/{ => src}/TestServer.cc | 6 +- test/java/TestClient | 2 + test/java/TestServer | 2 + test/java/build.xml | 36 ++++ test/java/src/TestClient.java | 351 +++++++++++++++++++++++++++++++ test/java/src/TestServer.java | 230 ++++++++++++++++++++ 8 files changed, 665 insertions(+), 17 deletions(-) rename test/cpp/{ => src}/TestClient.cc (90%) rename test/cpp/{ => src}/TestServer.cc (98%) create mode 100755 test/java/TestClient create mode 100755 test/java/TestServer create mode 100644 test/java/build.xml create mode 100644 test/java/src/TestClient.java create mode 100644 test/java/src/TestServer.java diff --git a/test/cpp/Makefile b/test/cpp/Makefile index 6afb30be..21c09ec5 100644 --- a/test/cpp/Makefile +++ b/test/cpp/Makefile @@ -7,28 +7,29 @@ target: all # Tools -THRIFT = /usr/local/bin/thrift +THRIFT = thrift CC = g++ LD = g++ # Compiler flags LIBS = ../../lib/cpp/server/TSimpleServer.cc \ ../../lib/cpp/protocol/TBinaryProtocol.cc \ + ../../lib/cpp/transport/TBufferedTransport.cc \ ../../lib/cpp/transport/TServerSocket.cc \ ../../lib/cpp/transport/TSocket.cc -CFL = -Wall -g -I../../lib/cpp $(LIBS) -CFL = -Wall -g -lthrift -I../../lib/cpp +CFL = -Wall -O3 -Igen-cpp -I../../lib/cpp $(LIBS) +CFL = -Wall -O3 -Igen-cpp -I../../lib/cpp -lthrift all: server client stubs: ../ThriftTest.thrift - $(THRIFT) ../ThriftTest.thrift + $(THRIFT) -cpp ../ThriftTest.thrift server: stubs - g++ -o TestServer $(CFL) TestServer.cc gen-cpp/ThriftTest.cc + g++ -o TestServer $(CFL) src/TestServer.cc gen-cpp/ThriftTest.cc client: stubs - g++ -o TestClient $(CFL) TestClient.cc gen-cpp/ThriftTest.cc + g++ -o TestClient $(CFL) src/TestClient.cc gen-cpp/ThriftTest.cc clean: rm -fr TestServer TestClient gen-cpp diff --git a/test/cpp/TestClient.cc b/test/cpp/src/TestClient.cc similarity index 90% rename from test/cpp/TestClient.cc rename to test/cpp/src/TestClient.cc index 6d2a68e1..6bd06b9d 100644 --- a/test/cpp/TestClient.cc +++ b/test/cpp/src/TestClient.cc @@ -1,11 +1,26 @@ #include #include +#include #include "protocol/TBinaryProtocol.h" -#include "client/TSimpleClient.h" +#include "transport/TBufferedTransport.h" #include "transport/TSocket.h" -#include "gen-cpp/ThriftTest.h" +#include "ThriftTest.h" using namespace std; +extern uint32_t g_socket_syscalls; + +// Current time, microseconds since the epoch +uint64_t now() +{ + long long ret; + struct timeval tv; + + gettimeofday(&tv, NULL); + ret = tv.tv_sec; + ret = ret*1000*1000 + tv.tv_usec; + return ret; +} + int main(int argc, char** argv) { string host = "localhost"; int port = 9090; @@ -22,18 +37,25 @@ int main(int argc, char** argv) { } TSocket socket(host, port); - TSimpleClient simpleClient(&socket); + TBufferedTransport bufferedSocket(&socket, 2048); TBinaryProtocol binaryProtocol; - ThriftTestClient testClient(&simpleClient, &binaryProtocol); + ThriftTestClient testClient(&bufferedSocket, &binaryProtocol); int test = 0; for (test = 0; test < numTests; ++test) { + + /** + * CONNECT TEST + */ printf("Test #%d, connect %s:%d\n", test+1, host.c_str(), port); - bool success = simpleClient.open(); - if (!success) { - printf("Connect failed, server down?\n"); + try { + bufferedSocket.open(); + } catch (TTransportException& ttx) { + printf("Connect failed: %s\n", ttx.getMessage().c_str()); continue; } + + uint64_t start = now(); /** * VOID TEST @@ -319,9 +341,13 @@ int main(int argc, char** argv) { } printf("}\n"); - simpleClient.close(); + uint64_t stop = now(); + printf("Total time: %lu us\n", stop-start); + + bufferedSocket.close(); } + printf("\nSocket syscalls: %u", g_socket_syscalls); printf("\nAll tests done.\n"); return 0; } diff --git a/test/cpp/TestServer.cc b/test/cpp/src/TestServer.cc similarity index 98% rename from test/cpp/TestServer.cc rename to test/cpp/src/TestServer.cc index 8138166e..206b6f56 100644 --- a/test/cpp/TestServer.cc +++ b/test/cpp/src/TestServer.cc @@ -2,7 +2,7 @@ #include "protocol/TBinaryProtocol.h" #include "server/TSimpleServer.h" #include "transport/TServerSocket.h" -#include "gen-cpp/ThriftTest.h" +#include "ThriftTest.h" using namespace std; class TestServer : public ThriftTestServerIf { @@ -117,12 +117,12 @@ class TestServer : public ThriftTestServerIf { return thing; } - Numberz testEnum(Numberz thing = 0) { + Numberz testEnum(Numberz thing) { printf("testEnum(%d)\n", thing); return thing; } - UserId testTypedef(UserId thing = 0) { + UserId testTypedef(UserId thing) { printf("testTypedef(%lu)\n", thing); return thing; } diff --git a/test/java/TestClient b/test/java/TestClient new file mode 100755 index 00000000..ba7d81f1 --- /dev/null +++ b/test/java/TestClient @@ -0,0 +1,2 @@ +#!/bin/bash -v +java -cp thrifttest.jar:/usr/local/lib/libthrift.jar com.facebook.thrift.test.TestClient $1 $2 $3 diff --git a/test/java/TestServer b/test/java/TestServer new file mode 100755 index 00000000..7c272c1f --- /dev/null +++ b/test/java/TestServer @@ -0,0 +1,2 @@ +#!/bin/bash -v +java -server -cp thrifttest.jar:/usr/local/lib/libthrift.jar com.facebook.thrift.test.TestServer $1 diff --git a/test/java/build.xml b/test/java/build.xml new file mode 100644 index 00000000..80a73d75 --- /dev/null +++ b/test/java/build.xml @@ -0,0 +1,36 @@ + + + Thrift Test Build File + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/java/src/TestClient.java b/test/java/src/TestClient.java new file mode 100644 index 00000000..70cf826b --- /dev/null +++ b/test/java/src/TestClient.java @@ -0,0 +1,351 @@ +package com.facebook.thrift.test; + +import ThriftTest.*; +import com.facebook.thrift.types.*; +import com.facebook.thrift.transport.TSocket; +import com.facebook.thrift.transport.TTransportException; +import com.facebook.thrift.protocol.TBinaryProtocol; +import com.facebook.thrift.protocol.TString; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.ArrayList; + +/** + * Test Java client for thrift. Essentially just a copy of the C++ version, + * this makes a variety of requests to enable testing for both performance and + * correctness of the output. + * + * @author Mark Slee + */ +public class TestClient { + public static void main(String [] args) { + try { + String host = "localhost"; + int port = 9090; + int numTests = 1; + + if (args.length > 0) { + host = args[0]; + } + if (args.length > 1) { + port = Integer.valueOf(args[1]); + } + if (args.length > 2) { + numTests = Integer.valueOf(args[2]); + } + + TSocket tSocket = + new TSocket(host, port); + TBinaryProtocol binaryProtocol = + new TBinaryProtocol(); + ThriftTestClient testClient = + new ThriftTestClient(tSocket, binaryProtocol); + + for (int test = 0; test < numTests; ++test) { + + /** + * CONNECT TEST + */ + System.out.println("Test #" + (test+1) + ", " + + "connect " + host + ":" + port); + try { + tSocket.open(); + } catch (TTransportException ttx) { + System.out.println("Connect failed: " + ttx.getMessage()); + continue; + } + + long start = System.currentTimeMillis(); + + /** + * VOID TEST + */ + System.out.print("testVoid()"); + testClient.testVoid(); + System.out.print(" = void\n"); + + /** + * STRING TEST + */ + System.out.print("testString(\"Test\")"); + TString s = testClient.testString(new TString("Test")); + System.out.print(" = \"" + s.value + "\"\n"); + + /** + * BYTE TEST + */ + System.out.print("testByte(1)"); + UInt8 u8 = testClient.testByte(new UInt8((short)1)); + System.out.print(" = " + u8.get() + "\n"); + + /** + * U32 TEST + */ + System.out.print("testU32(1)"); + UInt32 u32 = testClient.testU32(new UInt32(1)); + System.out.print(" = " + u32.get() + "\n"); + + /** + * I32 TEST + */ + System.out.print("testI32(-1)"); + Int32 i32 = testClient.testI32(new Int32(-1)); + System.out.print(" = " + i32.get() + "\n"); + + /** + * U64 TEST + */ + System.out.print("testU64(34359738368)"); + UInt64 u64 = testClient.testU64(new UInt64(34359738368L)); + System.out.print(" = " + u64.toLong() + "\n"); + + /** + * I64 TEST + */ + System.out.print("testI64(-34359738368)"); + Int64 i64 = testClient.testI64(new Int64(-34359738368L)); + System.out.print(" = " + i64.get() + "\n"); + + /** + * STRUCT TEST + */ + System.out.print("testStruct({\"Zero\", 1, 2, -3, 4, -5})"); + Xtruct out = new Xtruct(); + out.string_thing.value = "Zero"; + out.byte_thing.set((short)1); + out.u32_thing.set(2); + out.i32_thing.set(-3); + out.u64_thing.set(4); + out.i64_thing.set(-5); + Xtruct in = testClient.testStruct(out); + System.out.print(" = {" + + "\"" + in.string_thing.value + "\", " + + in.byte_thing.get() + ", " + + in.u32_thing.get() + ", " + + in.i32_thing.get() + ", " + + in.u64_thing.toLong() + ", " + + in.i64_thing.get() + "}\n"); + + /** + * NESTED STRUCT TEST + */ + System.out.print("testNest({1, {\"Zero\", 1, 2, -3, 4, -5}), 5}"); + Xtruct2 out2 = new Xtruct2(); + out2.byte_thing.set((short)1); + out2.struct_thing = out; + out2.i32_thing.set(5); + Xtruct2 in2 = testClient.testNest(out2); + in = in2.struct_thing; + System.out.print(" = {" + + in2.byte_thing.get() + ", {" + + "\"" + in.string_thing.value + "\", " + + in.byte_thing.get() + ", " + + in.u32_thing.get() + ", " + + in.i32_thing.get() + ", " + + in.u64_thing.toLong() + ", " + + in.i64_thing.get() + "}, " + + in2.i32_thing.get() + "}\n"); + + /** + * MAP TEST + */ + HashMap mapout = new HashMap(); + for (int i = 0; i < 5; ++i) { + mapout.put(new Int32(i), new Int32(i-10)); + } + System.out.print("testMap({"); + boolean first = true; + for (Int32 key : mapout.keySet()) { + if (first) { + first = false; + } else { + System.out.print(", "); + } + System.out.print(key.get() + " => " + mapout.get(key).get()); + } + System.out.print("})"); + HashMap mapin = testClient.testMap(mapout); + System.out.print(" = {"); + first = true; + for (Int32 key : mapin.keySet()) { + if (first) { + first = false; + } else { + System.out.print(", "); + } + System.out.print(key.get() + " => " + mapout.get(key).get()); + } + System.out.print("}\n"); + + /** + * SET TEST + */ + HashSet setout = new HashSet(); + for (int i = -2; i < 3; ++i) { + setout.add(new Int32(i)); + } + System.out.print("testSet({"); + first = true; + for (Int32 elem : setout) { + if (first) { + first = false; + } else { + System.out.print(", "); + } + System.out.print(elem.get()); + } + System.out.print("})"); + HashSet setin = testClient.testSet(setout); + System.out.print(" = {"); + first = true; + for (Int32 elem : setin) { + if (first) { + first = false; + } else { + System.out.print(", "); + } + System.out.print(elem.get()); + } + System.out.print("}\n"); + + /** + * LIST TEST + */ + ArrayList listout = new ArrayList(); + for (int i = -2; i < 3; ++i) { + listout.add(new Int32(i)); + } + System.out.print("testList({"); + first = true; + for (Int32 elem : listout) { + if (first) { + first = false; + } else { + System.out.print(", "); + } + System.out.print(elem.get()); + } + System.out.print("})"); + ArrayList listin = testClient.testList(listout); + System.out.print(" = {"); + first = true; + for (Int32 elem : listin) { + if (first) { + first = false; + } else { + System.out.print(", "); + } + System.out.print(elem.get()); + } + System.out.print("}\n"); + + /** + * ENUM TEST + */ + System.out.print("testEnum(ONE)"); + Int32 ret = testClient.testEnum(Numberz.ONE); + System.out.print(" = " + ret.get() + "\n"); + + System.out.print("testEnum(TWO)"); + ret = testClient.testEnum(Numberz.TWO); + System.out.print(" = " + ret.get() + "\n"); + + System.out.print("testEnum(THREE)"); + ret = testClient.testEnum(Numberz.THREE); + System.out.print(" = " + ret.get() + "\n"); + + System.out.print("testEnum(FIVE)"); + ret = testClient.testEnum(Numberz.FIVE); + System.out.print(" = " + ret.get() + "\n"); + + System.out.print("testEnum(EIGHT)"); + ret = testClient.testEnum(Numberz.EIGHT); + System.out.print(" = " + ret.get() + "\n"); + + /** + * TYPEDEF TEST + */ + System.out.print("testTypedef(309858235082523)"); + UInt64 uid = testClient.testTypedef(new UInt64(309858235082523L)); + System.out.print(" = " + uid.toLong() + "\n"); + + /** + * NESTED MAP TEST + */ + System.out.print("testMapMap(1)"); + HashMap> mm = + testClient.testMapMap(new Int32(1)); + System.out.print(" = {"); + for (Int32 key : mm.keySet()) { + System.out.print(key.get() + " => {"); + HashMap m2 = mm.get(key); + for (Int32 k2 : m2.keySet()) { + System.out.print(k2.get() + " => " + m2.get(k2).get() + ", "); + } + System.out.print("}, "); + } + System.out.print("}\n"); + + /** + * INSANITY TEST + */ + Insanity insane = new Insanity(); + insane.userMap.put(Numberz.FIVE, new UInt64(5000)); + Xtruct truck = new Xtruct(); + truck.string_thing.value = "Truck"; + truck.byte_thing.set((short)8); + truck.u32_thing.set(8); + truck.i32_thing.set(8); + truck.u64_thing.set(8); + truck.i64_thing.set(8); + insane.xtructs.add(truck); + System.out.print("testInsanity()"); + HashMap> whoa = + testClient.testInsanity(insane); + System.out.print(" = {"); + for (UInt64 key : whoa.keySet()) { + HashMap val = whoa.get(key); + System.out.print(key.toLong() + " => {"); + + for (Int32 k2 : val.keySet()) { + Insanity v2 = val.get(k2); + System.out.print(k2.get() + " => {"); + HashMap userMap = v2.userMap; + System.out.print("{"); + for (Int32 k3 : userMap.keySet()) { + System.out.print(k3.get() + " => " + + userMap.get(k3).toLong() + ", "); + } + System.out.print("}, "); + + ArrayList xtructs = v2.xtructs; + System.out.print("{"); + for (Xtruct x : xtructs) { + System.out.print("{" + + "\"" + x.string_thing.value + "\", " + + x.byte_thing.get() + ", " + + x.u32_thing.get() + ", "+ + x.i32_thing.get() + ", "+ + x.u64_thing.toLong() + ", "+ + x.i64_thing.get() + "}, "); + } + System.out.print("}"); + + System.out.print("}, "); + } + System.out.print("}, "); + } + System.out.print("}\n"); + + long stop = System.currentTimeMillis(); + System.out.println("Total time: " + (stop-start) + "ms"); + + tSocket.close(); + } + + } catch (Exception x) { + x.printStackTrace(); + } + } +} diff --git a/test/java/src/TestServer.java b/test/java/src/TestServer.java new file mode 100644 index 00000000..c5edca47 --- /dev/null +++ b/test/java/src/TestServer.java @@ -0,0 +1,230 @@ +package com.facebook.thrift.test; + +import com.facebook.thrift.types.*; +import com.facebook.thrift.protocol.TBinaryProtocol; +import com.facebook.thrift.protocol.TProtocol; +import com.facebook.thrift.protocol.TString; +import com.facebook.thrift.server.TServer; +import com.facebook.thrift.server.TSimpleServer; +import com.facebook.thrift.transport.TServerSocket; +import com.facebook.thrift.transport.TServerTransport; + +import ThriftTest.*; + +import java.net.ServerSocket; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; + +public class TestServer extends ThriftTestServerIf { + public TestServer(TProtocol prot) { + super(prot); + } + + public void testVoid() { + System.out.print("testVoid()\n"); + } + + public TString testString(TString thing) { + System.out.print("testString(\"" + thing.value + "\")\n"); + return thing; + } + + public UInt8 testByte(UInt8 thing) { + System.out.print("testByte(" + thing.get() + ")\n"); + return thing; + } + + public UInt32 testU32(UInt32 thing) { + System.out.print("testU32(" + thing.get() + ")\n"); + return thing; + } + + public Int32 testI32(Int32 thing) { + System.out.print("testI32(" + thing.get() + ")\n"); + return thing; + } + + public UInt64 testU64(UInt64 thing) { + System.out.print("testU64(" + thing.toLong() + ")\n"); + return thing; + } + + public Int64 testI64(Int64 thing) { + System.out.print("testI64(" + thing.get() + ")\n"); + return thing; + } + + public Xtruct testStruct(Xtruct thing) { + System.out.print("testStruct({" + + "\"" + thing.string_thing.value + "\", " + + thing.byte_thing.get() + ", " + + thing.u32_thing.get() + ", " + + thing.i32_thing.get() + ", " + + thing.u64_thing.toLong() + ", " + + thing.i64_thing.get() + "})\n"); + return thing; + } + + public Xtruct2 testNest(Xtruct2 nest) { + Xtruct thing = nest.struct_thing; + System.out.print("testNest({" + + nest.byte_thing.get() + ", {" + + "\"" + thing.string_thing.value + "\", " + + thing.byte_thing.get() + ", " + + thing.u32_thing.get() + ", " + + thing.i32_thing.get() + ", " + + thing.u64_thing.toLong() + ", " + + thing.i64_thing.get() + "}, " + + nest.i32_thing.get() + "})\n"); + return nest; + } + + public HashMap testMap(HashMap thing) { + System.out.print("testMap({"); + boolean first = true; + for (Int32 key : thing.keySet()) { + if (first) { + first = false; + } else { + System.out.print(", "); + } + System.out.print(key.get() + " => " + thing.get(key).get()); + } + System.out.print("})\n"); + return thing; + } + + public HashSet testSet(HashSet thing) { + System.out.print("testSet({"); + boolean first = true; + for (Int32 elem : thing) { + if (first) { + first = false; + } else { + System.out.print(", "); + } + System.out.print(elem.get()); + } + System.out.print("})\n"); + return thing; + } + + public ArrayList testList(ArrayList thing) { + System.out.print("testList({"); + boolean first = true; + for (Int32 elem : thing) { + if (first) { + first = false; + } else { + System.out.print(", "); + } + System.out.print(elem.get()); + } + System.out.print("})\n"); + return thing; + } + + public Int32 testEnum(Int32 thing) { + System.out.print("testEnum(" + thing.get() + ")\n"); + return thing; + } + + public UInt64 testTypedef(UInt64 thing) { + System.out.print("testTypedef(" + thing.toLong() + ")\n"); + return thing; + } + + public HashMap> testMapMap(Int32 hello) { + System.out.print("testMapMap(" + hello.get() + ")\n"); + HashMap> mapmap = + new HashMap>(); + + HashMap pos = new HashMap(); + HashMap neg = new HashMap(); + for (int i = 1; i < 5; i++) { + pos.put(new Int32(i), new Int32(i)); + neg.put(new Int32(-i), new Int32(-i)); + } + + mapmap.put(new Int32(4), pos); + mapmap.put(new Int32(-4), neg); + + return mapmap; + } + + public HashMap> testInsanity(Insanity argument) { + System.out.print("testInsanity()\n"); + + Xtruct hello = new Xtruct(); + hello.string_thing.value = "Hello2"; + hello.byte_thing.set((short)2); + hello.u32_thing.set(2); + hello.i32_thing.set(2); + hello.u64_thing.set(2); + hello.i64_thing.set(2); + + Xtruct goodbye = new Xtruct(); + goodbye.string_thing.value = "Goodbye4"; + goodbye.byte_thing.set((short)4); + goodbye.u32_thing.set(4); + goodbye.i32_thing.set(4); + goodbye.u64_thing.set(4); + goodbye.i64_thing.set(4); + + Insanity crazy = new Insanity(); + crazy.userMap.put(Numberz.EIGHT, new UInt64(8)); + crazy.xtructs.add(goodbye); + + Insanity looney = new Insanity(); + crazy.userMap.put(Numberz.FIVE, new UInt64(5)); + crazy.xtructs.add(hello); + + HashMap first_map = new HashMap(); + HashMap second_map = new HashMap();; + + first_map.put(Numberz.TWO, crazy); + first_map.put(Numberz.THREE, crazy); + + second_map.put(Numberz.SIX, looney); + + HashMap> insane = + new HashMap>(); + insane.put(new UInt64(1), first_map); + insane.put(new UInt64(2), second_map); + + return insane; + } + + public static void main(String [] args) { + try { + int port = 9090; + if (args.length > 1) { + port = Integer.valueOf(args[0]); + } + + // Processor + TBinaryProtocol binaryProtocol = new TBinaryProtocol(); + TestServer testServer = new TestServer(binaryProtocol); + + // Options + TServer.Options serverOptions = new TServer.Options(); + + // Transport + ServerSocket serverSocket = new ServerSocket(port); + TServerSocket tServerSocket = new TServerSocket(serverSocket); + + // Server + TSimpleServer simpleServer = new TSimpleServer(testServer, + serverOptions, + tServerSocket); + + // Run it + System.out.println("Starting the server on port " + port + "..."); + simpleServer.run(); + } catch (Exception x) { + x.printStackTrace(); + } + System.out.println("done."); + } +} -- 2.17.1