blob: 1d8bcb25a6dcdaa2c3fba54761cb2df048702c7b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
#include <inttypes.h>
#include <string.h>
#include <unistd.h>
#include <thrift/c_glib/thrift.h>
#include <thrift/c_glib/thrift_application_exception.h>
#include "thrift_test_handler.h"
/* A handler that implements the TTestThriftTestIf interface */
G_DEFINE_TYPE (ThriftTestHandler,
thrift_test_handler,
T_TEST_TYPE_THRIFT_TEST_HANDLER);
gboolean
thrift_test_handler_test_void (TTestThriftTestIf *iface,
GError **error)
{
THRIFT_UNUSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
printf ("testVoid()\n");
return TRUE;
}
gboolean
thrift_test_handler_test_string (TTestThriftTestIf *iface,
gchar **_return,
const gchar *thing,
GError **error)
{
THRIFT_UNUSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
printf ("testString(\"%s\")\n", thing);
*_return = g_strdup (thing);
return TRUE;
}
gboolean
thrift_test_handler_test_bool (TTestThriftTestIf *iface,
gboolean *_return,
const gboolean thing,
GError **error)
{
THRIFT_UNUSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
printf ("testBool(%s)\n", thing ? "true" : "false");
*_return = thing;
return TRUE;
}
gboolean
thrift_test_handler_test_byte (TTestThriftTestIf *iface,
gint8 *_return,
const gint8 thing,
GError **error)
{
THRIFT_UNUSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
printf ("testByte(%d)\n", (gint)thing);
*_return = thing;
return TRUE;
}
gboolean
thrift_test_handler_test_i32 (TTestThriftTestIf *iface,
gint32 *_return,
const gint32 thing,
GError **error)
{
THRIFT_UNUSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
printf ("testI32(%d)\n", thing);
*_return = thing;
return TRUE;
}
gboolean
thrift_test_handler_test_i64 (TTestThriftTestIf *iface,
gint64 *_return,
const gint64 thing,
GError **error)
{
THRIFT_UNUSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
printf ("testI64(%" PRId64 ")\n", thing);
*_return = thing;
return TRUE;
}
gboolean
thrift_test_handler_test_double (TTestThriftTestIf *iface,
gdouble *_return,
const gdouble thing,
GError **error)
{
THRIFT_UNUSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
printf ("testDouble(%f)\n", thing);
*_return = thing;
return TRUE;
}
gboolean
thrift_test_handler_test_binary (TTestThriftTestIf *iface,
GByteArray ** _return,
const GByteArray * thing,
GError **error)
{
THRIFT_UNUSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
printf ("testBinary()\n"); // TODO: hex output
g_byte_array_ref((GByteArray *)thing);
*_return = (GByteArray *)thing;
return TRUE;
}
gboolean
thrift_test_handler_test_struct (TTestThriftTestIf *iface,
TTestXtruct **_return,
const TTestXtruct *thing,
GError **error)
{
gchar *string_thing = NULL;
gint byte_thing;
gint i32_thing;
gint64 i64_thing;
THRIFT_UNUSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
g_object_get ((TTestXtruct *)thing,
"string_thing", &string_thing,
"byte_thing", &byte_thing,
"i32_thing", &i32_thing,
"i64_thing", &i64_thing,
NULL);
printf ("testStruct({\"%s\", %d, %d, %" PRId64 "})\n",
string_thing,
(gint)byte_thing,
i32_thing,
i64_thing);
g_object_set (*_return,
"string_thing", string_thing,
"byte_thing", byte_thing,
"i32_thing", i32_thing,
"i64_thing", i64_thing,
NULL);
if (string_thing != NULL)
g_free (string_thing);
return TRUE;
}
gboolean
thrift_test_handler_test_nest (TTestThriftTestIf *iface,
TTestXtruct2 **_return,
const TTestXtruct2 *thing,
GError **error)
{
gchar *inner_string_thing = NULL;
gint byte_thing, inner_byte_thing;
gint i32_thing, inner_i32_thing;
gint64 inner_i64_thing;
TTestXtruct *struct_thing;
THRIFT_UNUSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
g_object_get ((TTestXtruct2 *)thing,
"byte_thing", &byte_thing,
"struct_thing", &struct_thing,
"i32_thing", &i32_thing,
NULL);
g_object_get (struct_thing,
"string_thing", &inner_string_thing,
"byte_thing", &inner_byte_thing,
"i32_thing", &inner_i32_thing,
"i64_thing", &inner_i64_thing,
NULL);
printf ("testNest({%d, {\"%s\", %d, %d, %" PRId64 "}, %d})\n",
byte_thing,
inner_string_thing,
inner_byte_thing,
inner_i32_thing,
inner_i64_thing,
i32_thing);
g_object_set (*_return,
"byte_thing", byte_thing,
"struct_thing", struct_thing,
"i32_thing", i32_thing,
NULL);
if (inner_string_thing != NULL)
g_free (inner_string_thing);
g_object_unref (struct_thing);
return TRUE;
}
gboolean
thrift_test_handler_test_map (TTestThriftTestIf *iface,
GHashTable **_return,
const GHashTable *thing,
GError **error)
{
GHashTableIter hash_table_iter;
gpointer key;
gpointer value;
gboolean first = TRUE;
THRIFT_UNUSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
printf ("testMap({");
g_hash_table_iter_init (&hash_table_iter, (GHashTable *)thing);
while (g_hash_table_iter_next (&hash_table_iter,
&key,
&value)) {
gint32 *new_key;
gint32 *new_value;
if (first)
first = FALSE;
else
printf (", ");
printf ("%d => %d", *(gint32 *)key, *(gint32 *)value);
new_key = g_malloc (sizeof *new_key);
*new_key = *(gint32 *)key;
new_value = g_malloc (sizeof *new_value);
*new_value = *(gint32 *)value;
g_hash_table_insert (*_return, new_key, new_value);
}
printf ("})\n");
return TRUE;
}
gboolean
thrift_test_handler_test_string_map (TTestThriftTestIf *iface,
GHashTable **_return,
const GHashTable *thing,
GError **error)
{
GHashTableIter hash_table_iter;
gpointer key;
gpointer value;
gboolean first = TRUE;
THRIFT_UNUSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
printf ("testStringMap({");
g_hash_table_iter_init (&hash_table_iter, (GHashTable *)thing);
while (g_hash_table_iter_next (&hash_table_iter,
&key,
&value)) {
gchar *new_key;
gchar *new_value;
if (first)
first = FALSE;
else
printf (", ");
printf ("%s => %s", (gchar *)key, (gchar *)value);
new_key = g_strdup ((gchar *)key);
new_value = g_strdup ((gchar *)value);
g_hash_table_insert (*_return, new_key, new_value);
}
printf ("})\n");
return TRUE;
}
gboolean
thrift_test_handler_test_set (TTestThriftTestIf *iface,
GHashTable **_return,
const GHashTable *thing,
GError **error)
{
GHashTableIter hash_table_iter;
gpointer key;
gboolean first = TRUE;
THRIFT_UNUSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
printf ("testSet({");
g_hash_table_iter_init (&hash_table_iter, (GHashTable *)thing);
while (g_hash_table_iter_next (&hash_table_iter,
&key,
NULL)) {
gint32 *new_key;
if (first)
first = FALSE;
else
printf (", ");
printf ("%d", *(gint32 *)key);
new_key = g_malloc (sizeof *new_key);
*new_key = *(gint32 *)key;
g_hash_table_insert (*_return, new_key, NULL);
}
printf ("})\n");
return TRUE;
}
gboolean
thrift_test_handler_test_list (TTestThriftTestIf *iface,
GArray **_return,
const GArray *thing,
GError **error)
{
guint i;
gboolean first = TRUE;
THRIFT_UNUSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
printf ("testList({");
for (i = 0; i < thing->len; i += 1) {
gint32 value;
gint32 *new_value;
if (first)
first = FALSE;
else
printf (", ");
value = g_array_index (thing, gint32, i);
printf ("%d", value);
new_value = g_malloc (sizeof *new_value);
*new_value = value;
g_array_append_val (*_return, *new_value);
}
printf ("})\n");
return TRUE;
}
gboolean
thrift_test_handler_test_enum (TTestThriftTestIf *iface,
TTestNumberz *_return,
const TTestNumberz thing,
GError **error)
{
THRIFT_UNUSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
printf ("testEnum(%d)\n", thing);
*_return = thing;
return TRUE;
}
gboolean
thrift_test_handler_test_typedef (TTestThriftTestIf *iface,
TTestUserId *_return,
const TTestUserId thing,
GError **error)
{
THRIFT_UNUSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
printf ("testTypedef(%" PRId64 ")\n", thing);
*_return = thing;
return TRUE;
}
gboolean
thrift_test_handler_test_map_map (TTestThriftTestIf *iface,
GHashTable **_return,
const gint32 hello,
GError **error)
{
GHashTable *positive;
GHashTable *negative;
gint32 *key;
gint32 *value;
guint i;
THRIFT_UNUSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
printf ("testMapMap(%d)\n", hello);
positive = g_hash_table_new_full (g_int_hash,
g_int_equal,
g_free,
g_free);
negative = g_hash_table_new_full (g_int_hash,
g_int_equal,
g_free,
g_free);
for (i = 1; i < 5; i += 1) {
key = g_malloc (sizeof *key);
value = g_malloc (sizeof *value);
*key = i;
*value = i;
g_hash_table_insert (positive, key, value);
key = g_malloc (sizeof *key);
value = g_malloc (sizeof *value);
*key = -i;
*value = -i;
g_hash_table_insert (negative, key, value);
}
key = g_malloc (sizeof *key);
*key = 4;
g_hash_table_insert (*_return, key, positive);
key = g_malloc (sizeof *key);
*key = -4;
g_hash_table_insert (*_return, key, negative);
return TRUE;
}
gboolean
thrift_test_handler_test_insanity (TTestThriftTestIf *iface,
GHashTable **_return,
const TTestInsanity *argument,
GError **error)
{
TTestXtruct *xtruct_in;
gchar *string_thing = NULL;
gint byte_thing;
gint i32_thing;
gint64 i64_thing;
GPtrArray *xtructs;
TTestInsanity *looney;
GHashTable *user_map;
GHashTable *first_map;
GHashTable *second_map;
GHashTableIter hash_table_iter;
GHashTableIter inner_hash_table_iter;
GHashTableIter user_map_iter;
gpointer key;
gpointer value;
TTestUserId *user_id;
guint i;
THRIFT_UNUSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
printf ("testInsanity()\n");
first_map = g_hash_table_new_full (g_direct_hash,
g_direct_equal,
NULL,
g_object_unref);
second_map = g_hash_table_new_full (g_direct_hash,
g_direct_equal,
NULL,
g_object_unref);
g_hash_table_insert (first_map,
GINT_TO_POINTER (T_TEST_NUMBERZ_TWO),
(gpointer)argument);
g_hash_table_insert (first_map,
GINT_TO_POINTER (T_TEST_NUMBERZ_THREE),
(gpointer)argument);
/* Increment argument's ref count by two because first_map now holds
two references to it and the caller is not aware we have made any
additional references to argument. (That is, caller owns argument
and will unref it explicitly in addition to unref-ing *_return.)
We do this instead of creating a copy of argument in order to mimic
the C++ implementation (and since, frankly, the world needs less
argument, not more). */
g_object_ref ((gpointer)argument);
g_object_ref ((gpointer)argument);
looney = g_object_new (T_TEST_TYPE_INSANITY, NULL);
g_hash_table_insert (second_map,
GINT_TO_POINTER (T_TEST_NUMBERZ_SIX),
looney);
user_id = g_malloc (sizeof *user_id);
*user_id = 1;
g_hash_table_insert (*_return, user_id, first_map);
user_id = g_malloc (sizeof *user_id);
*user_id = 2;
g_hash_table_insert (*_return, user_id, second_map);
printf ("return");
printf (" = {");
g_hash_table_iter_init (&hash_table_iter, *_return);
while (g_hash_table_iter_next (&hash_table_iter,
&key,
&value)) {
printf ("%" PRId64 " => {", *(TTestUserId *)key);
g_hash_table_iter_init (&inner_hash_table_iter,
(GHashTable *)value);
while (g_hash_table_iter_next (&inner_hash_table_iter,
&key,
&value)) {
printf ("%d => {", (TTestNumberz)key);
g_object_get ((TTestInsanity *)value,
"userMap", &user_map,
"xtructs", &xtructs,
NULL);
printf ("{");
g_hash_table_iter_init (&user_map_iter, user_map);
while (g_hash_table_iter_next (&user_map_iter,
&key,
&value)) {
printf ("%d => %" PRId64 ", ",
(TTestNumberz)key,
*(TTestUserId *)value);
}
printf ("}, ");
g_hash_table_unref (user_map);
printf ("{");
for (i = 0; i < xtructs->len; ++i) {
xtruct_in = g_ptr_array_index (xtructs, i);
g_object_get (xtruct_in,
"string_thing", &string_thing,
"byte_thing", &byte_thing,
"i32_thing", &i32_thing,
"i64_thing", &i64_thing,
NULL);
printf ("{\"%s\", %d, %d, %" PRId64 "}, ",
string_thing,
byte_thing,
i32_thing,
i64_thing);
}
printf ("}");
g_ptr_array_unref (xtructs);
printf ("}, ");
}
printf ("}, ");
}
printf ("}\n");
return TRUE;
}
gboolean
thrift_test_handler_test_multi (TTestThriftTestIf *iface,
TTestXtruct **_return,
const gint8 arg0,
const gint32 arg1,
const gint64 arg2,
const GHashTable *arg3,
const TTestNumberz arg4,
const TTestUserId arg5,
GError **error)
{
THRIFT_UNUSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
THRIFT_UNUSED_VAR (arg3);
THRIFT_UNUSED_VAR (arg4);
THRIFT_UNUSED_VAR (arg5);
printf ("testMulti()\n");
g_object_set (*_return,
"string_thing", g_strdup ("Hello2"),
"byte_thing", arg0,
"i32_thing", arg1,
"i64_thing", arg2,
NULL);
return TRUE;
}
gboolean
thrift_test_handler_test_exception (TTestThriftTestIf *iface,
const gchar *arg,
TTestXception **err1,
GError **error)
{
THRIFT_UNUSED_VAR (iface);
TTestXtruct *xtruct;
gboolean result;
printf ("testException(%s)\n", arg);
/* Unlike argument objects, exception objects are not pre-created */
g_assert (*err1 == NULL);
if (strncmp (arg, "Xception", 9) == 0) {
/* "Throw" a custom exception: Set the corresponding exception
argument, set *error to NULL and return FALSE */
*err1 = g_object_new (T_TEST_TYPE_XCEPTION,
"errorCode", 1001,
"message", g_strdup (arg),
NULL);
*error = NULL;
result = FALSE;
}
else if (strncmp (arg, "TException", 11) == 0) {
/* "Throw" a generic TException (ThriftApplicationException): Set
all exception arguments to NULL, set *error and return FALSE */
*err1 = NULL;
g_set_error (error,
thrift_application_exception_error_quark (),
THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN,
"Default TException.");
result = FALSE;
}
else {
*err1 = NULL;
*error = NULL;
/* This code is duplicated from the C++ test suite, though it
appears to serve no purpose */
xtruct = g_object_new (T_TEST_TYPE_XTRUCT,
"string_thing", g_strdup (arg),
NULL);
g_object_unref (xtruct);
result = TRUE;
}
return result;
}
gboolean
thrift_test_handler_test_multi_exception (TTestThriftTestIf *iface,
TTestXtruct **_return,
const gchar *arg0,
const gchar *arg1,
TTestXception **err1,
TTestXception2 **err2,
GError **error)
{
THRIFT_UNUSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
TTestXtruct *struct_thing;
gboolean result;
printf ("testMultiException(%s, %s)\n", arg0, arg1);
g_assert (*err1 == NULL);
g_assert (*err2 == NULL);
if (strncmp (arg0, "Xception", 8) == 0 && strlen(arg0) == 8) {
*err1 = g_object_new (T_TEST_TYPE_XCEPTION,
"errorCode", 1001,
"message", g_strdup ("This is an Xception"),
NULL);
result = FALSE;
}
else if (strncmp (arg0, "Xception2", 9) == 0) {
*err2 = g_object_new (T_TEST_TYPE_XCEPTION2,
"errorCode", 2002,
NULL);
g_object_get (*err2,
"struct_thing", &struct_thing,
NULL);
g_object_set (struct_thing,
"string_thing", g_strdup ("This is an Xception2"),
NULL);
g_object_set (*err2,
"struct_thing", struct_thing,
NULL);
g_object_unref (struct_thing);
result = FALSE;
}
else {
g_object_set (*_return,
"string_thing", g_strdup (arg1),
NULL);
result = TRUE;
}
return result;
}
gboolean
thrift_test_handler_test_oneway (TTestThriftTestIf *iface,
const gint32 secondsToSleep,
GError **error)
{
THRIFT_UNUSED_VAR (iface);
THRIFT_UNUSED_VAR (error);
printf ("testOneway(%d): Sleeping...\n", secondsToSleep);
sleep (secondsToSleep);
printf ("testOneway(%d): done sleeping!\n", secondsToSleep);
return TRUE;
}
static void
thrift_test_handler_init (ThriftTestHandler *self)
{
THRIFT_UNUSED_VAR (self);
}
static void
thrift_test_handler_class_init (ThriftTestHandlerClass *klass)
{
TTestThriftTestHandlerClass *base_class =
T_TEST_THRIFT_TEST_HANDLER_CLASS (klass);
base_class->test_void =
klass->test_void =
thrift_test_handler_test_void;
base_class->test_string =
klass->test_string =
thrift_test_handler_test_string;
base_class->test_bool =
klass->test_bool =
thrift_test_handler_test_bool;
base_class->test_byte =
klass->test_byte =
thrift_test_handler_test_byte;
base_class->test_i32 =
klass->test_i32 =
thrift_test_handler_test_i32;
base_class->test_i64 =
klass->test_i64 =
thrift_test_handler_test_i64;
base_class->test_double =
klass->test_double =
thrift_test_handler_test_double;
base_class->test_binary =
klass->test_binary =
thrift_test_handler_test_binary;
base_class->test_struct =
klass->test_struct =
thrift_test_handler_test_struct;
base_class->test_nest =
klass->test_nest =
thrift_test_handler_test_nest;
base_class->test_map =
klass->test_map =
thrift_test_handler_test_map;
base_class->test_string_map =
klass->test_string_map =
thrift_test_handler_test_string_map;
base_class->test_set =
klass->test_set =
thrift_test_handler_test_set;
base_class->test_list =
klass->test_list =
thrift_test_handler_test_list;
base_class->test_enum =
klass->test_enum =
thrift_test_handler_test_enum;
base_class->test_typedef =
klass->test_typedef =
thrift_test_handler_test_typedef;
base_class->test_map_map =
klass->test_map_map =
thrift_test_handler_test_map_map;
base_class->test_insanity =
klass->test_insanity =
thrift_test_handler_test_insanity;
base_class->test_multi =
klass->test_multi =
thrift_test_handler_test_multi;
base_class->test_exception =
klass->test_exception =
thrift_test_handler_test_exception;
base_class->test_multi_exception =
klass->test_multi_exception =
thrift_test_handler_test_multi_exception;
base_class->test_oneway =
klass->test_oneway =
thrift_test_handler_test_oneway;
}