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
This commit is contained in:
Mark Slee 2006-06-07 06:53:25 +00:00
parent 83c52a8d7a
commit 9577100f3c
8 changed files with 665 additions and 17 deletions

View File

@ -7,28 +7,29 @@
target: all target: all
# Tools # Tools
THRIFT = /usr/local/bin/thrift THRIFT = thrift
CC = g++ CC = g++
LD = g++ LD = g++
# Compiler flags # Compiler flags
LIBS = ../../lib/cpp/server/TSimpleServer.cc \ LIBS = ../../lib/cpp/server/TSimpleServer.cc \
../../lib/cpp/protocol/TBinaryProtocol.cc \ ../../lib/cpp/protocol/TBinaryProtocol.cc \
../../lib/cpp/transport/TBufferedTransport.cc \
../../lib/cpp/transport/TServerSocket.cc \ ../../lib/cpp/transport/TServerSocket.cc \
../../lib/cpp/transport/TSocket.cc ../../lib/cpp/transport/TSocket.cc
CFL = -Wall -g -I../../lib/cpp $(LIBS) CFL = -Wall -O3 -Igen-cpp -I../../lib/cpp $(LIBS)
CFL = -Wall -g -lthrift -I../../lib/cpp CFL = -Wall -O3 -Igen-cpp -I../../lib/cpp -lthrift
all: server client all: server client
stubs: ../ThriftTest.thrift stubs: ../ThriftTest.thrift
$(THRIFT) ../ThriftTest.thrift $(THRIFT) -cpp ../ThriftTest.thrift
server: stubs 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 client: stubs
g++ -o TestClient $(CFL) TestClient.cc gen-cpp/ThriftTest.cc g++ -o TestClient $(CFL) src/TestClient.cc gen-cpp/ThriftTest.cc
clean: clean:
rm -fr TestServer TestClient gen-cpp rm -fr TestServer TestClient gen-cpp

View File

@ -1,11 +1,26 @@
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <sys/time.h>
#include "protocol/TBinaryProtocol.h" #include "protocol/TBinaryProtocol.h"
#include "client/TSimpleClient.h" #include "transport/TBufferedTransport.h"
#include "transport/TSocket.h" #include "transport/TSocket.h"
#include "gen-cpp/ThriftTest.h" #include "ThriftTest.h"
using namespace std; 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) { int main(int argc, char** argv) {
string host = "localhost"; string host = "localhost";
int port = 9090; int port = 9090;
@ -22,19 +37,26 @@ int main(int argc, char** argv) {
} }
TSocket socket(host, port); TSocket socket(host, port);
TSimpleClient simpleClient(&socket); TBufferedTransport bufferedSocket(&socket, 2048);
TBinaryProtocol binaryProtocol; TBinaryProtocol binaryProtocol;
ThriftTestClient testClient(&simpleClient, &binaryProtocol); ThriftTestClient testClient(&bufferedSocket, &binaryProtocol);
int test = 0; int test = 0;
for (test = 0; test < numTests; ++test) { for (test = 0; test < numTests; ++test) {
/**
* CONNECT TEST
*/
printf("Test #%d, connect %s:%d\n", test+1, host.c_str(), port); printf("Test #%d, connect %s:%d\n", test+1, host.c_str(), port);
bool success = simpleClient.open(); try {
if (!success) { bufferedSocket.open();
printf("Connect failed, server down?\n"); } catch (TTransportException& ttx) {
printf("Connect failed: %s\n", ttx.getMessage().c_str());
continue; continue;
} }
uint64_t start = now();
/** /**
* VOID TEST * VOID TEST
*/ */
@ -319,9 +341,13 @@ int main(int argc, char** argv) {
} }
printf("}\n"); 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"); printf("\nAll tests done.\n");
return 0; return 0;
} }

View File

@ -2,7 +2,7 @@
#include "protocol/TBinaryProtocol.h" #include "protocol/TBinaryProtocol.h"
#include "server/TSimpleServer.h" #include "server/TSimpleServer.h"
#include "transport/TServerSocket.h" #include "transport/TServerSocket.h"
#include "gen-cpp/ThriftTest.h" #include "ThriftTest.h"
using namespace std; using namespace std;
class TestServer : public ThriftTestServerIf { class TestServer : public ThriftTestServerIf {
@ -117,12 +117,12 @@ class TestServer : public ThriftTestServerIf {
return thing; return thing;
} }
Numberz testEnum(Numberz thing = 0) { Numberz testEnum(Numberz thing) {
printf("testEnum(%d)\n", thing); printf("testEnum(%d)\n", thing);
return thing; return thing;
} }
UserId testTypedef(UserId thing = 0) { UserId testTypedef(UserId thing) {
printf("testTypedef(%lu)\n", thing); printf("testTypedef(%lu)\n", thing);
return thing; return thing;
} }

2
test/java/TestClient Executable file
View File

@ -0,0 +1,2 @@
#!/bin/bash -v
java -cp thrifttest.jar:/usr/local/lib/libthrift.jar com.facebook.thrift.test.TestClient $1 $2 $3

2
test/java/TestServer Executable file
View File

@ -0,0 +1,2 @@
#!/bin/bash -v
java -server -cp thrifttest.jar:/usr/local/lib/libthrift.jar com.facebook.thrift.test.TestServer $1

36
test/java/build.xml Normal file
View File

@ -0,0 +1,36 @@
<project name="thrifttest" default="test" basedir=".">
<description>Thrift Test Build File</description>
<property name="src" location="src" />
<property name="gen" location="gen-java" />
<property name="build" location="build" />
<property name="cpath" location="/usr/local/lib/libthrift.jar" />
<target name="init">
<tstamp />
<mkdir dir="${build}"/>
</target>
<target name="generate">
<exec executable="thrift">
<arg line="-java ../ThriftTest.thrift" />
</exec>
</target>
<target name="compile" depends="init,generate">
<javac srcdir="${gen}" destdir="${build}" classpath="${cpath}" />
<javac srcdir="${src}" destdir="${build}" classpath="${cpath}:${gen}" />
</target>
<target name="test" depends="compile">
<jar jarfile="thrifttest.jar" basedir="${build}"/>
</target>
<target name="clean">
<delete dir="gen-java" />
<delete dir="${build}" />
<delete file="thrifttest.jar" />
</target>
</project>

View File

@ -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 <mcslee@facebook.com>
*/
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<Int32,Int32> mapout = new HashMap<Int32,Int32>();
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<Int32,Int32> 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<Int32> setout = new HashSet<Int32>();
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<Int32> 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<Int32> listout = new ArrayList<Int32>();
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<Int32> 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<Int32,HashMap<Int32,Int32>> mm =
testClient.testMapMap(new Int32(1));
System.out.print(" = {");
for (Int32 key : mm.keySet()) {
System.out.print(key.get() + " => {");
HashMap<Int32,Int32> 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<UInt64,HashMap<Int32,Insanity>> whoa =
testClient.testInsanity(insane);
System.out.print(" = {");
for (UInt64 key : whoa.keySet()) {
HashMap<Int32,Insanity> 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<Int32, UInt64> userMap = v2.userMap;
System.out.print("{");
for (Int32 k3 : userMap.keySet()) {
System.out.print(k3.get() + " => " +
userMap.get(k3).toLong() + ", ");
}
System.out.print("}, ");
ArrayList<Xtruct> 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();
}
}
}

View File

@ -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<Int32,Int32> testMap(HashMap<Int32,Int32> 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<Int32> testSet(HashSet<Int32> 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<Int32> testList(ArrayList<Int32> 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<Int32,HashMap<Int32,Int32>> testMapMap(Int32 hello) {
System.out.print("testMapMap(" + hello.get() + ")\n");
HashMap<Int32,HashMap<Int32,Int32>> mapmap =
new HashMap<Int32,HashMap<Int32,Int32>>();
HashMap<Int32,Int32> pos = new HashMap<Int32,Int32>();
HashMap<Int32,Int32> neg = new HashMap<Int32,Int32>();
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<UInt64, HashMap<Int32,Insanity>> 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<Int32,Insanity> first_map = new HashMap<Int32, Insanity>();
HashMap<Int32,Insanity> second_map = new HashMap<Int32, Insanity>();;
first_map.put(Numberz.TWO, crazy);
first_map.put(Numberz.THREE, crazy);
second_map.put(Numberz.SIX, looney);
HashMap<UInt64,HashMap<Int32,Insanity>> insane =
new HashMap<UInt64, HashMap<Int32,Insanity>>();
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.");
}
}