THRIFT-2451: Do not use pointers for optional fields with defaults. Do not write...
authorJens Geyer <jensg@apache.org>
Thu, 1 May 2014 22:24:24 +0000 (00:24 +0200)
committerJens Geyer <jensg@apache.org>
Thu, 1 May 2014 22:24:24 +0000 (00:24 +0200)
Client: Go
Patch: Aleksey Pesternikov

This closes #101

commit e6e5dcf3a07cd931183991ff031179b425e2740b
 Author: Aleksey Pesternikov <ap@alekseys-mbp.att.net>
 Date: 2014-04-16T14:06:52Z

initial change

commit f65730e951a4310160a9f7e3e4eeb7e55abd2c55
 Author: Aleksey Pesternikov <ap@alekseys-mbp.att.net>
 Date: 2014-04-16T14:16:03Z

no IsSet for required

commit 9865f700eb9354d6053994da989a907766c42d1d
 Author: Aleksey Pesternikov <ap@alekseys-mbp.att.net>
 Date: 2014-04-17T19:32:13Z

inlined required structs

commit ca52300c07cefcf553f1ebf35569953c933b2367
 Author: Aleksey Pesternikov <ap@alekseys-mbp.att.net>
 Date: 2014-04-17T19:44:24Z

do not use heap for args struct

commit 012ca3e512d2bc8822de8a715b4f3d3cae5c0c42
 Author: Aleksey Pesternikov <ap@alekseys-mbp.att.net>
 Date: 2014-04-17T19:52:41Z

do not use heap for result struct

commit 2fc4afc53ff7db43e08eadeaa30e34bc1fd9c889
 Author: Aleksey Pesternikov <ap@alekseys-mbp.att.net>
 Date: 2014-04-17T21:32:43Z

do not set result field on error

commit 6e5da0062b139f02dcafe3148cdf02f97c23442a
 Author: Aleksey Pesternikov <ap@alekseys-mbp.att.net>
 Date: 2014-04-17T21:57:57Z

Jens' thrift source as test case

commit 7317957ed708831e280f182f081043fbe9d38a0c
 Author: Aleksey Pesternikov <ap@alekseys-macbook-pro.local>
 Date: 2014-04-17T23:43:08Z

support for cpp.ref

commit 1c4f3efc7b54fd335db633f86faf8c426ae9c87d
 Author: Aleksey Pesternikov <ap@alekseys-macbook-pro.local>
 Date: 2014-04-18T00:13:24Z

package flag

commit c9d7e54f5c5d29c776f42fb861bc9e82da4e542f
 Author: Aleksey Pesternikov <ap@alekseys-macbook-pro.local>
 Date: 2014-04-18T00:21:18Z

Merge branch 'master' into go_inlines

compiler/cpp/src/generate/t_go_generator.cc
lib/go/test/Makefile.am
lib/go/test/OptionalFieldsTest.thrift [new file with mode: 0644]
lib/go/test/RefAnnotationFieldsTest.thrift [new file with mode: 0644]
lib/go/test/ServicesTest.thrift [new file with mode: 0644]
lib/go/test/TypedefFieldTest.thrift [new file with mode: 0644]
lib/go/test/tests/optional_fields_test.go [new file with mode: 0644]
lib/go/test/tests/protocol_mock.go [new file with mode: 0644]
lib/go/thrift/pointerize.go

index 94e1db6..4893c71 100644 (file)
@@ -60,6 +60,7 @@ static const string endl = "\n";  // avoid ostream << std::endl flushes
 bool format_go_output(const string &file_path);
 
 const string default_thrift_import = "git.apache.org/thrift.git/lib/go/thrift";
+static std::string package_flag;
 
 /**
  * Go code generator.
@@ -87,6 +88,12 @@ public:
         if (iter != parsed_options.end()) {
             gen_thrift_import_ = (iter->second);
         }
+
+        iter = parsed_options.find("package");
+
+        if (iter != parsed_options.end()) {
+               package_flag = (iter->second);
+        }
     }
 
     /**
@@ -115,6 +122,7 @@ public:
 
     void generate_go_struct(t_struct* tstruct, bool is_exception);
     void generate_go_struct_definition(std::ofstream& out, t_struct* tstruct, bool is_xception = false, bool is_result = false, bool is_args = false);
+    void generate_go_struct_initializer(std::ofstream& out, t_struct* tstruct, bool is_args_or_result = false);
     void generate_isset_helpers(std::ofstream& out, t_struct* tstruct, const string& tstruct_name, bool is_result = false);
     void generate_go_struct_reader(std::ofstream& out, t_struct* tstruct, const string& tstruct_name, bool is_result = false);
     void generate_go_struct_writer(std::ofstream& out, t_struct* tstruct, const string& tstruct_name, bool is_result = false);
@@ -144,16 +152,18 @@ public:
                                     std::string prefix = "",
                                     bool inclass = false,
                                     bool coerceData = false,
-                                    bool inkey = false);
+                                    bool inkey = false,
+                                    bool in_container = false);
 
     void generate_deserialize_struct(std::ofstream &out,
                                      t_struct*   tstruct,
+                                     bool        is_pointer_field,
                                      bool        declare,
                                      std::string prefix = "");
 
     void generate_deserialize_container(std::ofstream &out,
                                         t_type*       ttype,
-                                        bool          optional_field,
+                                        bool          pointer_field,
                                         bool          declare,
                                         std::string   prefix = "");
 
@@ -183,7 +193,7 @@ public:
 
     void generate_serialize_container(std::ofstream &out,
                                       t_type*       ttype,
-                                      bool          optional_field,
+                                      bool          pointer_field,
                                       std::string   prefix = "");
 
     void generate_serialize_map_element(std::ofstream &out,
@@ -233,12 +243,16 @@ public:
     std::string function_signature_if(t_function* tfunction, std::string prefix = "", bool addError = false);
     std::string argument_list(t_struct* tstruct);
     std::string type_to_enum(t_type* ttype);
-    std::string type_to_go_type(t_type* ttype);
-    std::string type_to_go_type_with_opt(t_type* ttype, bool optional_field);
+    std::string type_to_go_type(t_type* ttype, bool is_container_value = false);
+    std::string type_to_go_type_with_opt(t_type* ttype, bool optional_field, bool is_container_value = false);
     std::string type_to_go_key_type(t_type* ttype);
     std::string type_to_spec_args(t_type* ttype);
 
     static std::string get_real_go_module(const t_program* program) {
+
+       if (!package_flag.empty()) {
+            return package_flag;
+        }
         std::string real_module = program->get_namespace("go");
 
         if (real_module.empty()) {
@@ -271,10 +285,116 @@ private:
     static std::string new_prefix(const std::string& value);
     static std::string privatize(const std::string& value);
     static std::string variable_name_to_go_name(const std::string& value);
-    static bool can_be_nil(t_type* value);
-
+    static bool is_pointer_field(t_field* tfield, bool in_container = false);
+    static bool omit_initialization(t_field* tfield);
 };
 
+//returns true if field initialization can be omitted since it has corresponding go type zero value
+//or default value is not set
+bool t_go_generator::omit_initialization(t_field* tfield) {
+       t_const_value* value = tfield->get_value();
+       if (!value) {
+               return true;
+       }
+       t_type* type = tfield->get_type()->get_true_type();
+    if (type->is_base_type()) {
+        t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+
+        switch (tbase) {
+        case t_base_type::TYPE_VOID:
+            throw "";
+
+        case t_base_type::TYPE_STRING:
+            if (((t_base_type*)type)->is_binary()) {
+               //[]byte are always inline
+                return false;
+            }
+            //strings are pointers if has no default
+            return value->get_string().empty();
+
+        case t_base_type::TYPE_BOOL:
+        case t_base_type::TYPE_BYTE:
+        case t_base_type::TYPE_I16:
+        case t_base_type::TYPE_I32:
+        case t_base_type::TYPE_I64:
+            return value->get_integer()==0;
+        case t_base_type::TYPE_DOUBLE:
+            if (value->get_type() == t_const_value::CV_INTEGER) {
+                return value->get_integer()==0;
+            } else {
+                return value->get_double()==0.;
+            }
+        }
+    }
+       return false;
+}
+
+//Returns true if the type need a reference if used as optional without default
+static bool type_need_reference(t_type* type) {
+       type = type->get_true_type();
+       if( type->is_map()
+        || type->is_set()
+        || type->is_list()
+        || (type->is_string() && ((t_base_type*)type)->is_binary() )) {
+               return false;
+       }
+       return true;
+}
+
+//returns false if field could not use comparison to default value as !IsSet*
+bool t_go_generator::is_pointer_field(t_field* tfield, bool in_container_value) {
+       if (tfield->annotations_.count("cpp.ref")!=0) {
+               return true;
+       }
+       t_type* type = tfield->get_type()->get_true_type();
+       //Structs in containers are pointers
+       if (in_container_value && type->is_struct()) {
+               return true;
+       }
+       if (!(tfield->get_req() == t_field::T_OPTIONAL)) {
+               return false;
+       }
+
+       bool has_default = tfield->get_value();
+    if (type->is_base_type()) {
+        t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
+
+        switch (tbase) {
+        case t_base_type::TYPE_VOID:
+            throw "";
+
+        case t_base_type::TYPE_STRING:
+            if (((t_base_type*)type)->is_binary()) {
+               //[]byte are always inline
+                return false;
+            }
+            //strings are pointers if has no default
+            return !has_default;
+
+        case t_base_type::TYPE_BOOL:
+        case t_base_type::TYPE_BYTE:
+        case t_base_type::TYPE_I16:
+        case t_base_type::TYPE_I32:
+        case t_base_type::TYPE_I64:
+        case t_base_type::TYPE_DOUBLE:
+            return !has_default;
+        }
+    } else if (type->is_enum()) {
+        return !has_default;
+    } else if (type->is_struct() || type->is_xception()) {
+       return true;
+    } else if (type->is_map()) {
+       return has_default;
+    } else if (type->is_set()) {
+       return has_default;
+    } else if (type->is_list()) {
+               return has_default;
+    } else if (type->is_typedef()) {
+               return has_default;
+    }
+
+    throw "INVALID TYPE IN type_to_go_type: " + type->get_name();
+}
 
 std::string t_go_generator::publicize(const std::string& value, bool is_args_or_result)
 {
@@ -622,7 +742,8 @@ string t_go_generator::go_imports_begin()
 {
     return
         string("import (\n"
-               "\t\"fmt\"\n"
+                "\t\"bytes\"\n"
+                "\t\"fmt\"\n"
                "\t\"" + gen_thrift_import_ + "\"\n");
 }
 
@@ -639,7 +760,8 @@ string t_go_generator::go_imports_end()
             ")\n\n"
             "// (needed to ensure safety because of naive import list construction.)\n"
             "var _ = thrift.ZERO\n"
-            "var _ = fmt.Printf\n\n");
+            "var _ = fmt.Printf\n"
+               "var _ = bytes.Equal\n\n");
 }
 
 /**
@@ -864,7 +986,7 @@ string t_go_generator::render_const_value(t_type* type, t_const_value* value, co
         t_type* vtype = ((t_map*)type)->get_val_type();
         const map<t_const_value*, t_const_value*>& val = value->get_map();
         out <<
-            "map[" << type_to_go_type(ktype) << "]" << type_to_go_type(vtype) << "{" << endl;
+            "map[" << type_to_go_type(ktype) << "]" << type_to_go_type(vtype, true) << "{" << endl;
         indent_up();
         map<t_const_value*, t_const_value*>::const_iterator v_iter;
 
@@ -955,6 +1077,24 @@ void t_go_generator::get_publicized_name_and_def_value(t_field* tfield,
     *OUT_def_value = tfield->get_value();
 }
 
+void t_go_generator::generate_go_struct_initializer(ofstream& out,
+        t_struct* tstruct,
+        bool is_args_or_result)
+{
+    out << publicize(type_name(tstruct), is_args_or_result) << "{";
+    const vector<t_field*>& members = tstruct->get_members();
+    for (vector<t_field*>::const_iterator m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+        bool pointer_field = is_pointer_field(*m_iter);
+        string publicized_name;
+        t_const_value* def_value;
+        get_publicized_name_and_def_value(*m_iter, &publicized_name, &def_value);
+        if (!pointer_field && def_value != NULL && !omit_initialization(*m_iter)) {
+            out << endl << indent() << publicized_name << ": " << render_field_initial_value(*m_iter, (*m_iter)->get_name(), pointer_field) << "," << endl;
+        }
+    }
+
+    out << "}" << endl;
+}
 
 /**
  * Generates a struct definition for a thrift data type.
@@ -1010,8 +1150,7 @@ void t_go_generator::generate_go_struct_definition(ofstream& out,
             }
 
             t_type* fieldType = (*m_iter)->get_type();
-            bool optional_field = ((*m_iter)->get_req() == t_field::T_OPTIONAL);
-            string goType = type_to_go_type_with_opt(fieldType, optional_field);
+            string goType = type_to_go_type_with_opt(fieldType, is_pointer_field(*m_iter));
 
             indent(out) << publicize(variable_name_to_go_name((*m_iter)->get_name())) << " "
                         << goType << " `thrift:\""
@@ -1038,42 +1177,43 @@ void t_go_generator::generate_go_struct_definition(ofstream& out,
     out <<
         indent() << "}" << endl << endl <<
         indent() << "func New" << tstruct_name << "() *" << tstruct_name << " {" << endl <<
-        indent() << "  rval := &" << tstruct_name << "{";
-
+        indent() << "  return &";
+    generate_go_struct_initializer(out, tstruct, is_result || is_args);
+       out <<
+        indent() << "}" << endl << endl;
+    // Default values for optional fields
     for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-        bool optional_field = ((*m_iter)->get_req() == t_field::T_OPTIONAL);
-
-        // Initialize struct fields, assigning defaults for non-optional (i.e.,
-        // non-pointer) fields.
         string publicized_name;
         t_const_value* def_value;
         get_publicized_name_and_def_value(*m_iter, &publicized_name, &def_value);
-        if (def_value != NULL) {
-            out << endl << indent() << publicized_name << ": " << render_field_initial_value(*m_iter, (*m_iter)->get_name(), optional_field) << "," << endl;
-        }
-    }
-
-    out << "}" << endl;
-
-    // Assign actual default values for optional fields in a second pass. See
-    // the comment in render_field_initial_value for context and motivation.
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-        if ((*m_iter)->get_req() == t_field::T_OPTIONAL) {
-            string publicized_name;
-            t_const_value* def_value;
-            get_publicized_name_and_def_value(*m_iter, &publicized_name, &def_value);
+        t_type* fieldType = (*m_iter)->get_type();
+        string goType = type_to_go_type_with_opt(fieldType, false);
+        string def_var_name = tstruct_name + "_" + publicized_name + "_DEFAULT";
+        if ((*m_iter)->get_req() == t_field::T_OPTIONAL || is_pointer_field(*m_iter)) {
+            out << indent() << "var " << def_var_name <<" "<<goType ;
             if (def_value != NULL) {
-                // XXX
-                // t_type* ttype = get_true_type((*m_iter)->get_type());
-                t_type* ttype = (*m_iter)->get_type();
-                out << indent() << "*(rval." << publicized_name << ") = " << render_const_value(ttype, def_value, (*m_iter)->get_name()) << endl;
+                out << " = " << render_const_value(fieldType, def_value, (*m_iter)->get_name()) ;
             }
+            out <<endl;
+        }
+        if (is_pointer_field(*m_iter)) {
+            string goOptType = type_to_go_type_with_opt(fieldType, true);
+            string maybepointer = goOptType!=goType?"*":"";
+            out <<indent() << "func (p *" << tstruct_name << ") Get" << publicized_name << "() "<< goType<<" {" << endl
+                <<indent() << "  if !p.IsSet" <<publicized_name <<"() {" <<endl
+                <<indent() << "    return " <<def_var_name <<endl
+                <<indent() << "  }" <<endl
+                <<indent() << "return "<<maybepointer <<"p." <<publicized_name <<endl
+                <<indent() << "}" <<endl;
+        } else {
+            out <<endl
+               <<indent() << "func (p *" << tstruct_name << ") Get" << publicized_name << "() "<< goType<<" {" << endl
+                <<indent() << "return p." <<publicized_name <<endl
+                <<indent() << "}" <<endl;
+
         }
     }
 
-    out << "return rval" << endl;
-
-    out << "}" << endl << endl;
     generate_isset_helpers(out, tstruct, tstruct_name, is_result);
     generate_go_struct_reader(out, tstruct, tstruct_name, is_result);
     generate_go_struct_writer(out, tstruct, tstruct_name, is_result);
@@ -1108,12 +1248,27 @@ void t_go_generator::generate_isset_helpers(ofstream& out,
 
     for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
         const string field_name(publicize(variable_name_to_go_name(escape_string((*f_iter)->get_name()))));
-        if ((*f_iter)->get_req() == t_field::T_OPTIONAL) {
+        if ((*f_iter)->get_req() == t_field::T_OPTIONAL || is_pointer_field(*f_iter)) {
             out <<
                 indent() << "func (p *" << tstruct_name << ") IsSet" << field_name << "() bool {" << endl;
             indent_up();
-            out <<
-                indent() << "return p." << field_name << " != nil" << endl;
+               t_type* ttype = (*f_iter)->get_type()->get_true_type();
+               bool is_byteslice = ttype->is_base_type() && ((t_base_type*)ttype)->is_binary() ;
+               bool compare_to_nil_only = ttype->is_set()
+                               || ttype->is_list()
+                               || ttype->is_map()
+                               || (is_byteslice && !(*f_iter)->get_value());
+            if (is_pointer_field(*f_iter) || compare_to_nil_only) {
+                               out <<
+                                       indent() << "return p." << field_name << " != nil" << endl;
+            } else {
+                string def_var_name = tstruct_name + "_" + field_name + "_DEFAULT";
+                if (is_byteslice) {
+                               out << indent() << "return !bytes.Equal(p." << field_name << ", "<<def_var_name  << ")" << endl;
+                } else {
+                               out << indent() << "return p." << field_name << " != "<<def_var_name  << endl;
+                }
+            }
             indent_down();
             out <<
                 indent() << "}" << endl << endl;
@@ -1267,53 +1422,22 @@ void t_go_generator::generate_go_struct_writer(ofstream& out,
     string escape_field_name;
     //t_const_value* field_default_value;
     t_field::e_req field_required;
-    bool field_can_be_nil = false;
     int32_t field_id = -1;
 
-    if (is_result && fields.size()) {
-        out <<
-            indent() << "switch {" << endl;
-        vector<t_field*>::const_reverse_iterator fr_iter;
-
-        for (fr_iter = fields.rbegin(); fr_iter != fields.rend(); ++fr_iter) {
-            string field_method_prefix("writeField");
-            field_name = (*fr_iter)->get_name();
-            field_id = (*fr_iter)->get_key();
-
-            if (field_id < 0) {
-                field_method_prefix += "_";
-                field_id *= -1;
-            }
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        string field_method_prefix("writeField");
+        field_name = (*f_iter)->get_name();
+        escape_field_name = escape_string(field_name);
+        field_id = (*f_iter)->get_key();
 
-            if (can_be_nil((*fr_iter)->get_type()) && field_id != 0) {
-                out <<
-                    indent() << "case p." << publicize(variable_name_to_go_name(field_name)) << " != nil:" << endl <<
-                    indent() << "  if err := p." << field_method_prefix << field_id << "(oprot); err != nil { return err }" << endl;
-            } else {
-                out <<
-                    indent() << "default:" << endl <<
-                    indent() << "  if err := p." << field_method_prefix << field_id << "(oprot); err != nil { return err }" << endl;
-            }
+        if (field_id < 0) {
+            field_method_prefix += "_";
+            field_id *= -1;
         }
 
         out <<
-            indent() << "}" << endl;
-    } else {
-        for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-            string field_method_prefix("writeField");
-            field_name = (*f_iter)->get_name();
-            escape_field_name = escape_string(field_name);
-            field_id = (*f_iter)->get_key();
-
-            if (field_id < 0) {
-                field_method_prefix += "_";
-                field_id *= -1;
-            }
-
-            out <<
-                indent() << "if err := p." << field_method_prefix << field_id << "(oprot); err != nil { return err }" << endl;
+            indent() << "if err := p." << field_method_prefix << field_id << "(oprot); err != nil { return err }" << endl;
 
-        }
     }
 
     // Write the struct map
@@ -1334,7 +1458,6 @@ void t_go_generator::generate_go_struct_writer(ofstream& out,
         escape_field_name = escape_string(field_name);
         //field_default_value = (*f_iter)->get_value();
         field_required = (*f_iter)->get_req();
-        field_can_be_nil = can_be_nil((*f_iter)->get_type());
 
         if (field_id < 0) {
             field_method_prefix += "_";
@@ -1345,13 +1468,6 @@ void t_go_generator::generate_go_struct_writer(ofstream& out,
             indent() << "func (p *" << tstruct_name << ") " << field_method_prefix << field_id << "(oprot thrift.TProtocol) (err error) {" << endl;
         indent_up();
 
-        // Write field header
-        if (field_can_be_nil) {
-            out <<
-                indent() << "if p." << publicize(variable_name_to_go_name(field_name)) << " != nil {" << endl;
-            indent_up();
-        }
-
         if (field_required == t_field::T_OPTIONAL) {
             out <<
                 indent() << "if p.IsSet" << publicize(variable_name_to_go_name(field_name)) << "() {" << endl;
@@ -1380,12 +1496,6 @@ void t_go_generator::generate_go_struct_writer(ofstream& out,
                 indent() << "}" << endl;
         }
 
-        if (field_can_be_nil) {
-            indent_down();
-            out <<
-                indent() << "}" << endl;
-        }
-
         indent_down();
         out <<
             indent() << "  return err" << endl <<
@@ -1447,6 +1557,7 @@ void t_go_generator::generate_go_function_helpers(t_function* tfunction)
     if (!tfunction->is_oneway()) {
         t_struct result(program_, tfunction->get_name() + "_result");
         t_field success(tfunction->get_returntype(), "success", 0);
+        success.set_req(t_field::T_OPTIONAL);
 
         if (!tfunction->get_returntype()->is_void()) {
             result.append(&success);
@@ -1457,7 +1568,9 @@ void t_go_generator::generate_go_function_helpers(t_function* tfunction)
         vector<t_field*>::const_iterator f_iter;
 
         for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-            result.append(*f_iter);
+               t_field* f = *f_iter;
+               f->set_req(t_field::T_OPTIONAL);
+            result.append(f);
         }
 
         generate_go_struct_definition(f_service_, &result, false, true);
@@ -1664,7 +1777,6 @@ void t_go_generator::generate_service_client(t_service* tservice)
         indent_up();
         std::string argsname = publicize((*f_iter)->get_name() + "_args",true);
         // Serialize the request header
-        string args(tmp("args"));
         f_service_ <<
                    indent() << "oprot := p.OutputProtocol" << endl <<
                    indent() << "if oprot == nil {" << endl <<
@@ -1679,16 +1791,18 @@ void t_go_generator::generate_service_client(t_service* tservice)
         indent_down();
         f_service_ <<
                    indent() << "}" << endl <<
-                   indent() << args << " := New" << argsname << "()" << endl;
+                   indent() << "args := " << argsname << "{" << endl;
 
         for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
             f_service_ <<
-                       indent() << args << "." << publicize(variable_name_to_go_name((*fld_iter)->get_name())) << " = " << variable_name_to_go_name((*fld_iter)->get_name()) << endl;
+                       indent() << publicize(variable_name_to_go_name((*fld_iter)->get_name())) << " : " << variable_name_to_go_name((*fld_iter)->get_name()) << ","<< endl;
         }
+        f_service_ <<
+                indent() << "}" << endl;
 
         // Write to the stream
         f_service_ <<
-                   indent() << "if err = " << args << ".Write(oprot); err != nil {" << endl;
+                   indent() << "if err = args.Write(oprot); err != nil {" << endl;
         indent_up();
         f_service_ <<
                    indent() << "return" << endl;
@@ -1723,7 +1837,6 @@ void t_go_generator::generate_service_client(t_service* tservice)
                        "err error) {" << endl;
             indent_up();
             // TODO(mcslee): Validate message reply here, seq ids etc.
-            string result(tmp("result"));
             string error(tmp("error"));
             string error2(tmp("error"));
             f_service_ <<
@@ -1753,8 +1866,8 @@ void t_go_generator::generate_service_client(t_service* tservice)
                        indent() << "  err = thrift.NewTApplicationException(thrift.BAD_SEQUENCE_ID, \"" << (*f_iter)->get_name() << " failed: out of sequence response\")" << endl <<
                        indent() << "  return" << endl <<
                        indent() << "}" << endl <<
-                       indent() << result << " := New" << resultname << "()" << endl <<
-                       indent() << "if err = " << result << ".Read(iprot); err != nil {" << endl <<
+                       indent() << "result := " << resultname << "{}" << endl <<
+                       indent() << "if err = result.Read(iprot); err != nil {" << endl <<
                        indent() << "  return" << endl <<
                        indent() << "}" << endl <<
                        indent() << "if err = iprot.ReadMessageEnd(); err != nil {" << endl <<
@@ -1770,8 +1883,8 @@ void t_go_generator::generate_service_client(t_service* tservice)
                 const std::string pubname = publicize(varname);
 
                 f_service_ <<
-                           indent() << "if " << result << "." << pubname << " != nil {" << endl <<
-                           indent() << "err = " << result << "." << pubname << endl <<
+                           indent() << "if result." << pubname << " != nil {" << endl <<
+                           indent() << "err = result." << pubname << endl <<
                            indent() << "return " << endl <<
                            indent() << "}";
 
@@ -1785,7 +1898,7 @@ void t_go_generator::generate_service_client(t_service* tservice)
             // Careful, only return _result if not a void function
             if (!(*f_iter)->get_returntype()->is_void()) {
                 f_service_ <<
-                           indent() << "value = " << result << ".Success" << endl;
+                           indent() << "value = result.GetSuccess()" << endl;
             }
 
             f_service_ <<
@@ -2344,7 +2457,7 @@ void t_go_generator::generate_process_function(t_service* tservice,
                indent() << "func (p *" << processorName << ") Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {" << endl;
     indent_up();
     f_service_ <<
-               indent() << "args := New" << argsname << "()" << endl <<
+               indent() << "args := " << argsname << "{}" << endl <<
                indent() << "if err = args.Read(iprot); err != nil {" << endl <<
                indent() << "  iprot.ReadMessageEnd()" << endl;
     if (!tfunction->is_oneway()) {
@@ -2362,7 +2475,11 @@ void t_go_generator::generate_process_function(t_service* tservice,
 
     if (!tfunction->is_oneway()) {
         f_service_ <<
-                   indent() << "result := New" << resultname << "()" << endl;
+                   indent() << "result := " << resultname << "{}" << endl;
+    }
+    bool need_reference = type_need_reference(tfunction->get_returntype());
+    if (need_reference && !tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
+               f_service_ << "var retval " <<type_to_go_type(tfunction->get_returntype()) <<endl;
     }
 
     f_service_ <<
@@ -2371,7 +2488,11 @@ void t_go_generator::generate_process_function(t_service* tservice,
 
     if (!tfunction->is_oneway()) {
         if (!tfunction->get_returntype()->is_void()) {
-            f_service_ << "result.Success, ";
+               if( need_reference) {
+                f_service_ << "retval, ";
+               } else {
+                f_service_ << "result.Success, ";
+               }
         }
     }
 
@@ -2404,7 +2525,7 @@ void t_go_generator::generate_process_function(t_service* tservice,
 
         for (xf_iter = x_fields.begin(); xf_iter != x_fields.end(); ++xf_iter) {
             f_service_ <<
-                        indent() << "  case *" << type_name((*xf_iter)->get_type()) << ":" << endl <<
+                        indent() << "  case *" << type_to_go_type(((*xf_iter)->get_type())) << ":" << endl <<
                         indent() << "result." << publicize(variable_name_to_go_name((*xf_iter)->get_name())) << " = v" << endl;
         }
         
@@ -2434,6 +2555,9 @@ void t_go_generator::generate_process_function(t_service* tservice,
                indent() << "}" << endl;
 
     if (!tfunction->is_oneway()) {
+        if (need_reference && !tfunction->get_returntype()->is_void()) {
+               f_service_ << "result.Success = &retval" << endl;
+        }
         f_service_ <<
                    indent() << "if err2 = oprot.WriteMessageBegin(\"" << escape_string(tfunction->get_name()) << 
                                "\", thrift.REPLY, seqId); err2 != nil {" << endl <<
@@ -2470,7 +2594,8 @@ void t_go_generator::generate_deserialize_field(ofstream &out,
         string prefix,
         bool inclass,
         bool coerceData,
-        bool inkey)
+        bool inkey,
+        bool in_container_value)
 {
     t_type* orig_type = tfield->get_type();
     t_type* type = get_true_type(orig_type);
@@ -2483,12 +2608,13 @@ void t_go_generator::generate_deserialize_field(ofstream &out,
     if (type->is_struct() || type->is_xception()) {
         generate_deserialize_struct(out,
                                     (t_struct*)type,
+                                    is_pointer_field(tfield, in_container_value),
                                     declare,
                                     name);
     } else if (type->is_container()) {
         generate_deserialize_container(out,
                                        orig_type,
-                                       tfield->get_req() == t_field::T_OPTIONAL,
+                                       is_pointer_field(tfield),
                                        declare,
                                        name);
     } else if (type->is_base_type() || type->is_enum()) {
@@ -2564,7 +2690,7 @@ void t_go_generator::generate_deserialize_field(ofstream &out,
             wrap = "int8";
         }
 
-        string maybe_address = ((tfield->get_req() == t_field::T_OPTIONAL) ? "&" : "");
+        string maybe_address = (is_pointer_field(tfield) ? "&" : "");
         if (wrap == "") {
             indent(out) << name << " = " << maybe_address << "v" << endl;
         } else {
@@ -2583,17 +2709,15 @@ void t_go_generator::generate_deserialize_field(ofstream &out,
  */
 void t_go_generator::generate_deserialize_struct(ofstream &out,
         t_struct* tstruct,
+        bool pointer_field,
         bool declare,
         string prefix)
 {
-    string eq(" := ");
-
-    if (!declare) {
-        eq = " = ";
-    }
+    string eq(declare ? " := " : " = ");
 
+    out << indent() << prefix << eq <<(pointer_field?"&":"");
+    generate_go_struct_initializer(out, tstruct);
     out <<
-        indent() << prefix << eq << new_prefix(type_name(tstruct)) << "()" << endl <<
         indent() << "if err := " << prefix << ".Read(iprot); err != nil {" << endl <<
         indent() << "  return fmt.Errorf(\"%T error reading struct: %s\", " << prefix << ", err)" << endl <<
         indent() << "}" << endl;
@@ -2605,7 +2729,7 @@ void t_go_generator::generate_deserialize_struct(ofstream &out,
  */
 void t_go_generator::generate_deserialize_container(ofstream &out,
         t_type* orig_type,
-        bool optional_field,
+        bool pointer_field,
         bool declare,
         string prefix)
 {
@@ -2624,7 +2748,7 @@ void t_go_generator::generate_deserialize_container(ofstream &out,
             indent() << "  return fmt.Errorf(\"error reading map begin: %s\", err)" << endl <<
             indent() << "}" << endl <<
             indent() << "tMap := make(" << type_to_go_type(orig_type) << ", size)" << endl <<
-            indent() << prefix << eq << " " << (optional_field ? "&" : "") << "tMap" << endl;
+            indent() << prefix << eq << " " << (pointer_field ? "&" : "") << "tMap" << endl;
     } else if (ttype->is_set()) {
         t_set* t = (t_set*)ttype;
         out <<
@@ -2633,7 +2757,7 @@ void t_go_generator::generate_deserialize_container(ofstream &out,
             indent() << "  return fmt.Errorf(\"error reading set begin: %s\", err)" << endl <<
             indent() << "}" << endl <<
             indent() << "tSet := make(map[" << type_to_go_key_type(t->get_elem_type()) << "]bool, size)" << endl <<
-            indent() << prefix << eq << " " << (optional_field ? "&" : "") << "tSet" << endl;
+            indent() << prefix << eq << " " << (pointer_field ? "&" : "") << "tSet" << endl;
     } else if (ttype->is_list()) {
         out <<
             indent() << "_, size, err := iprot.ReadListBegin()" << endl <<
@@ -2641,7 +2765,7 @@ void t_go_generator::generate_deserialize_container(ofstream &out,
             indent() << "  return fmt.Errorf(\"error reading list begin: %s\", err)" << endl <<
             indent() << "}" << endl <<
             indent() << "tSlice := make(" << type_to_go_type(orig_type) << ", 0, size)" << endl <<
-            indent() << prefix << eq << " " << (optional_field ? "&" : "") << "tSlice" << endl;
+            indent() << prefix << eq << " " << (pointer_field ? "&" : "") << "tSlice" << endl;
     } else {
         throw "INVALID TYPE IN generate_deserialize_container '" + ttype->get_name() + "' for prefix '" + prefix + "'";
     }
@@ -2651,7 +2775,7 @@ void t_go_generator::generate_deserialize_container(ofstream &out,
         indent() << "for i := 0; i < size; i ++ {" << endl;
     indent_up();
 
-    if (optional_field) {
+    if (pointer_field) {
         prefix = "(*" + prefix + ")";
     }
     if (ttype->is_map()) {
@@ -2701,7 +2825,7 @@ void t_go_generator::generate_deserialize_map_element(ofstream &out,
     fkey.set_req(t_field::T_OPT_IN_REQ_OUT);
     fval.set_req(t_field::T_OPT_IN_REQ_OUT);
     generate_deserialize_field(out, &fkey, true, "", false, false, true);
-    generate_deserialize_field(out, &fval, true);
+    generate_deserialize_field(out, &fval, true, "", false, false, false, true);
     indent(out) <<
                 prefix << "[" << key << "] = " << val << endl;
 
@@ -2734,7 +2858,7 @@ void t_go_generator::generate_deserialize_list_element(ofstream &out,
     string elem = tmp("_elem");
     t_field felem(((t_list*)tlist)->get_elem_type(), elem);
     felem.set_req(t_field::T_OPT_IN_REQ_OUT);
-    generate_deserialize_field(out, &felem, true, "");
+    generate_deserialize_field(out, &felem, true, "", false, false, false, true);
     indent(out) <<
                 prefix << " = append(" << prefix << ", " << elem << ")" << endl;
 }
@@ -2766,13 +2890,13 @@ void t_go_generator::generate_serialize_field(ofstream &out,
     } else if (type->is_container()) {
         generate_serialize_container(out,
                                      type,
-                                     tfield->get_req() == t_field::T_OPTIONAL,
+                                     is_pointer_field(tfield),
                                      name);
     } else if (type->is_base_type() || type->is_enum()) {
         indent(out) <<
                     "if err := oprot.";
 
-        if (tfield->get_req() == t_field::T_OPTIONAL) {
+        if (is_pointer_field(tfield)) {
             name = "*" + name;
         }
 
@@ -2851,10 +2975,10 @@ void t_go_generator::generate_serialize_struct(ofstream &out,
 
 void t_go_generator::generate_serialize_container(ofstream &out,
         t_type* ttype,
-        bool optional_field,
+        bool pointer_field,
         string prefix)
 {
-    if (optional_field) {
+    if (pointer_field) {
         prefix = "*" + prefix;
     }
     if (ttype->is_map()) {
@@ -3264,17 +3388,17 @@ string t_go_generator::type_to_go_key_type(t_type* type)
 /**
  * Converts the parse type to a go type
  */
-string t_go_generator::type_to_go_type(t_type* type) {
-    return type_to_go_type_with_opt(type, false);
+string t_go_generator::type_to_go_type(t_type* type, bool is_container_value) {
+    return type_to_go_type_with_opt(type, false, is_container_value);
 }
 
 /**
  * Converts the parse type to a go type, taking into account whether the field
  * associated with the type is T_OPTIONAL.
  */
-string t_go_generator::type_to_go_type_with_opt(t_type* type, bool optional_field)
+string t_go_generator::type_to_go_type_with_opt(t_type* type, bool optional_field, bool is_container_value)
 {
-    string maybe_pointer = (optional_field ? "*" : "");
+    string maybe_pointer(optional_field ? "*" : "");
     if (type->is_base_type()) {
         t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
 
@@ -3310,13 +3434,14 @@ string t_go_generator::type_to_go_type_with_opt(t_type* type, bool optional_fiel
     } else if (type->is_enum()) {
         return maybe_pointer + publicize(type_name(type));
     } else if (type->is_struct() || type->is_xception()) {
-        // Note that we always have a pointer type for the is_struct() or
-        // is_xception() cases, regardless of optional_field.
-        return string("*") + publicize(type_name(type));
+       if (is_container_value) {
+               maybe_pointer = "*";
+       }
+        return maybe_pointer + publicize(type_name(type));
     } else if (type->is_map()) {
         t_map* t = (t_map*)type;
         string keyType = type_to_go_key_type(t->get_key_type());
-        string valueType = type_to_go_type(t->get_val_type());
+        string valueType = type_to_go_type(t->get_val_type(), true);
         return maybe_pointer + string("map[") + keyType + "]" + valueType;
     } else if (type->is_set()) {
         t_set* t = (t_set*)type;
@@ -3324,7 +3449,7 @@ string t_go_generator::type_to_go_type_with_opt(t_type* type, bool optional_fiel
         return maybe_pointer + string("map[") + elemType + string("]bool");
     } else if (type->is_list()) {
         t_list* t = (t_list*)type;
-        string elemType = type_to_go_type(t->get_elem_type());
+        string elemType = type_to_go_type(t->get_elem_type(), true);
         return maybe_pointer + string("[]") + elemType;
     } else if (type->is_typedef()) {
         return maybe_pointer + publicize(type_name(type));
@@ -3333,49 +3458,6 @@ string t_go_generator::type_to_go_type_with_opt(t_type* type, bool optional_fiel
     throw "INVALID TYPE IN type_to_go_type: " + type->get_name();
 }
 
-
-/**
- * Converts the parse type to a go tyoe
- */
-bool t_go_generator::can_be_nil(t_type* type)
-{
-    type = get_true_type(type);
-
-    if (type->is_base_type()) {
-        t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
-
-        switch (tbase) {
-        case t_base_type::TYPE_VOID:
-            throw "Invalid Type for can_be_nil";
-
-        case t_base_type::TYPE_BOOL:
-        case t_base_type::TYPE_BYTE:
-        case t_base_type::TYPE_I16:
-        case t_base_type::TYPE_I32:
-        case t_base_type::TYPE_I64:
-        case t_base_type::TYPE_DOUBLE:
-            return false;
-
-        case t_base_type::TYPE_STRING:
-            return (((t_base_type*)type)->is_binary());
-        }
-    } else if (type->is_enum()) {
-        return false;
-    } else if (type->is_struct() || type->is_xception()) {
-        return true;
-    } else if (type->is_map()) {
-        return true;
-    } else if (type->is_set()) {
-        return true;
-    } else if (type->is_list()) {
-        return true;
-    }
-
-    throw "INVALID TYPE IN can_be_nil: " + type->get_name();
-}
-
-
-
 /** See the comment inside generate_go_struct_definition for what this is. */
 string t_go_generator::type_to_spec_args(t_type* ttype)
 {
@@ -3424,4 +3506,5 @@ bool format_go_output(const string &file_path)
 
 THRIFT_REGISTER_GENERATOR(go, "Go",
                           "    package_prefix= Package prefix for generated files.\n" \
-                          "    thrift_import=  Override thrift package import path (default:" + default_thrift_import + ")\n")
+                          "    thrift_import=  Override thrift package import path (default:" + default_thrift_import + ")\n" \
+                          "    package=  Package name (default: inferred from thrift file name)\n")
index ca8fa64..5499fb7 100644 (file)
@@ -25,19 +25,33 @@ gopath: $(top_srcdir)/compiler/cpp/thrift $(THRIFTTEST) \
                                IncludesTest.thrift \
                                NamespacedTest.thrift \
                                MultiplexedProtocolTest.thrift \
-                               OnewayTest.thrift
+                               OnewayTest.thrift \
+                               OptionalFieldsTest.thrift \
+                               ServicesTest.thrift \
+                               TypedefFieldTest.thrift \
+                               RefAnnotationFieldsTest.thrift
        mkdir -p gopath/src
-       grep -v list.*map.*list.*map $(THRIFTTEST) > ThriftTest.thrift
+       grep -v list.*map.*list.*map $(THRIFTTEST) | grep -v 'set<Insanity>' > ThriftTest.thrift
        $(THRIFT) -r IncludesTest.thrift
        $(THRIFT) BinaryKeyTest.thrift
        $(THRIFT) MultiplexedProtocolTest.thrift
        $(THRIFT) OnewayTest.thrift
+       $(THRIFT) OptionalFieldsTest.thrift
+       $(THRIFT) ServicesTest.thrift
+       $(THRIFT) TypedefFieldTest.thrift
+       $(THRIFT) RefAnnotationFieldsTest.thrift
+       GOPATH=`pwd`/gopath $(GO) get code.google.com/p/gomock/gomock
        ln -nfs ../../../thrift gopath/src/thrift
        ln -nfs ../../tests gopath/src/tests
        touch gopath
 
 check: gopath
-       GOPATH=`pwd`/gopath $(GO) build IncludesTest BinaryKeyTest
+       GOPATH=`pwd`/gopath $(GO) build \
+                               IncludesTest \
+                               BinaryKeyTest \
+                               ServicesTest \
+                               TypedefFieldTest \
+                               RefAnnotationFieldsTest
        GOPATH=`pwd`/gopath $(GO) test thrift tests
 
 clean-local:
diff --git a/lib/go/test/OptionalFieldsTest.thrift b/lib/go/test/OptionalFieldsTest.thrift
new file mode 100644 (file)
index 0000000..25b0ef6
--- /dev/null
@@ -0,0 +1,43 @@
+#
+# 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.
+#
+
+struct structA {
+ 1: required i64 sa_i
+}
+
+struct all_optional {
+ 1: optional string s = "DEFAULT",
+ 2: optional i64 i = 42,
+ 3: optional bool b = false,
+ 4: optional string s2,
+ 5: optional i64 i2,
+ 6: optional bool b2,
+ 7: optional structA aa,
+ 9: optional list<i64> l,
+ 10: optional list<i64> l2 = [1, 2],
+ 11: optional map<i64, i64> m,
+ 12: optional map<i64, i64> m2 = {1:2, 3:4},
+ 13: optional binary bin,
+ 14: optional binary bin2 = "asdf",
+}
+
+struct structB {
+ 1: required structA required_struct_thing
+ 2: optional structA optional_struct_thing
+}
diff --git a/lib/go/test/RefAnnotationFieldsTest.thrift b/lib/go/test/RefAnnotationFieldsTest.thrift
new file mode 100644 (file)
index 0000000..b7f28c2
--- /dev/null
@@ -0,0 +1,58 @@
+#
+# 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.
+#
+
+struct structA {
+ 1: required i64 sa_i
+}
+
+struct all_referenced {
+ 1: optional string s = "DEFAULT" (cpp.ref = ""),
+ 2: optional i64 i = 42 (cpp.ref = ""),
+ 3: optional bool b = false (cpp.ref = ""),
+ 4: optional string s2 (cpp.ref = ""),
+ 5: optional i64 i2 (cpp.ref = ""),
+ 6: optional bool b2 (cpp.ref = ""),
+ 7: optional structA aa (cpp.ref = ""),
+ 9: optional list<i64> l (cpp.ref = ""),
+ 10: optional list<i64> l2 = [1, 2] (cpp.ref = ""),
+ 11: optional map<i64, i64> m (cpp.ref = ""),
+ 12: optional map<i64, i64> m2 = {1:2, 3:4} (cpp.ref = ""),
+ 13: optional binary bin (cpp.ref = ""),
+ 14: optional binary bin2 = "asdf" (cpp.ref = ""),
+
+ 15: required string ref_s = "DEFAULT" (cpp.ref = ""),
+ 16: required i64 ref_i = 42 (cpp.ref = ""),
+ 17: required bool ref_b = false (cpp.ref = ""),
+ 18: required string ref_s2 (cpp.ref = ""),
+ 19: required i64 ref_i2 (cpp.ref = ""),
+ 20: required bool ref_b2 (cpp.ref = ""),
+ 21: required structA ref_aa (cpp.ref = ""),
+ 22: required list<i64> ref_l (cpp.ref = ""),
+ 23: required list<i64> ref_l2 = [1, 2] (cpp.ref = ""),
+ 24: required map<i64, i64> ref_m (cpp.ref = ""),
+ 25: required map<i64, i64> ref_m2 = {1:2, 3:4} (cpp.ref = ""),
+ 26: required binary ref_bin (cpp.ref = ""),
+ 27: required binary ref_bin2 = "asdf" (cpp.ref = ""),
+
+}
+
+struct structB {
+ 1: required structA required_struct_thing
+ 2: optional structA optional_struct_thing
+}
diff --git a/lib/go/test/ServicesTest.thrift b/lib/go/test/ServicesTest.thrift
new file mode 100644 (file)
index 0000000..1b8be36
--- /dev/null
@@ -0,0 +1,109 @@
+#
+# 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.
+#
+
+# We are only testing that generated code compiles, no correctness checking is done
+
+exception moderate_disaster {
+  1: i32 errorCode,
+  2: string message
+}
+
+exception total_disaster {
+  1: string message
+  2: optional bool president_was_woken_up = false
+}
+
+struct struct_a {
+  1: required i64 whatever
+}
+
+service a_serv {
+       void voidfunc(),
+       void void_with_1ex() throws(1: moderate_disaster err1)
+       void void_with_2ex() throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+       string stringfunc()
+       string stringfunc_1ex() throws(1: moderate_disaster err1)
+       string stringfunc_2ex() throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+       i64 i64func()
+       i64 i64func_1ex() throws(1: moderate_disaster err1)
+       i64 i64func_2ex() throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+       list<string> list_of_strings_func()
+       list<string> list_of_strings_func_1ex() throws(1: moderate_disaster err1)
+       list<string> list_of_strings_func_2ex() throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+       map<i64,string> map_func()
+       map<i64,string> map_func_1ex() throws(1: moderate_disaster err1)
+       map<i64,string> map_func_2ex() throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+       struct_a struct_a_func()
+       struct_a struct_a_func_1ex() throws(1: moderate_disaster err1)
+       struct_a struct_a_func_2ex() throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+       void voidfunc_1int(1: i64 i),
+       void void_with_1ex_1int(1: i64 i) throws(1: moderate_disaster err1)
+       void void_with_2ex_1int(1: i64 i) throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+       string stringfunc_1int(1: i64 i)
+       string stringfunc_1ex_1int(1: i64 i) throws(1: moderate_disaster err1)
+       string stringfunc_2ex_1int(1: i64 i) throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+       i64 i64func_1int(1: i64 i)
+       i64 i64func_1ex_1int(1: i64 i) throws(1: moderate_disaster err1)
+       i64 i64func_2ex_1int(1: i64 i) throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+       list<string> list_of_strings_func_1int(1: i64 i)
+       list<string> list_of_strings_func_1ex_1int(1: i64 i) throws(1: moderate_disaster err1)
+       list<string> list_of_strings_func_2ex_1int(1: i64 i) throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+       map<i64,string> map_func_1int(1: i64 i)
+       map<i64,string> map_func_1ex_1int(1: i64 i) throws(1: moderate_disaster err1)
+       map<i64,string> map_func_2ex_1int(1: i64 i) throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+       struct_a struct_a_func_1int(1: i64 i)
+       struct_a struct_a_func_1ex_1int(1: i64 i) throws(1: moderate_disaster err1)
+       struct_a struct_a_func_2ex_1int(1: i64 i) throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+       void voidfunc_1int_1s(1: i64 i, 2: string s),
+       void void_with_1ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1)
+       void void_with_2ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+       string stringfunc_1int_1s(1: i64 i, 2: string s)
+       string stringfunc_1ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1)
+       string stringfunc_2ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+       i64 i64func_1int_1s(1: i64 i, 2: string s)
+       i64 i64func_1ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1)
+       i64 i64func_2ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+       list<string> list_of_strings_func_1int_1s(1: i64 i, 2: string s)
+       list<string> list_of_strings_func_1ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1)
+       list<string> list_of_strings_func_2ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+       map<i64,string> map_func_1int_1s(1: i64 i, 2: string s)
+       map<i64,string> map_func_1ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1)
+       map<i64,string> map_func_2ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+       struct_a struct_a_func_1int_1s(1: i64 i, 2: string s)
+       struct_a struct_a_func_1ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1)
+       struct_a struct_a_func_2ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1, 2:total_disaster err2)
+
+}
diff --git a/lib/go/test/TypedefFieldTest.thrift b/lib/go/test/TypedefFieldTest.thrift
new file mode 100644 (file)
index 0000000..390e8c8
--- /dev/null
@@ -0,0 +1,39 @@
+#
+# 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.
+#
+
+# We are only testing that generated code compiles, no correctness checking is done
+
+enum Details {
+  Everything = 0
+  StateOnly = 1
+  StateAndOptions = 2
+  SomethingElse = 3
+}
+
+typedef list< Details>  DetailsWanted
+
+struct BaseRequest {
+  1 : optional string RequestID
+}
+
+struct GetMyDetails {
+  1 : required BaseRequest base_
+  2 : required string ObjectID
+  3 : optional DetailsWanted DetailsWanted
+}
diff --git a/lib/go/test/tests/optional_fields_test.go b/lib/go/test/tests/optional_fields_test.go
new file mode 100644 (file)
index 0000000..4b0797c
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * 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.
+ */
+
+package tests
+
+import (
+       "OptionalFieldsTest"
+       "bytes"
+       gomock "code.google.com/p/gomock/gomock"
+       "testing"
+       "thrift"
+)
+
+func TestIsSetReturnFalseOnCreation(t *testing.T) {
+       ao := OptionalFieldsTest.NewAllOptional()
+       if ao.IsSetS() {
+               t.Errorf("Optional field S is set on initialization")
+       }
+       if ao.IsSetI() {
+               t.Errorf("Optional field I is set on initialization")
+       }
+       if ao.IsSetB() {
+               t.Errorf("Optional field B is set on initialization")
+       }
+       if ao.IsSetS2() {
+               t.Errorf("Optional field S2 is set on initialization")
+       }
+       if ao.IsSetI2() {
+               t.Errorf("Optional field I2 is set on initialization")
+       }
+       if ao.IsSetB2() {
+               t.Errorf("Optional field B2 is set on initialization")
+       }
+       if ao.IsSetAa() {
+               t.Errorf("Optional field Aa is set on initialization")
+       }
+       if ao.IsSetL() {
+               t.Errorf("Optional field L is set on initialization")
+       }
+       if ao.IsSetL2() {
+               t.Errorf("Optional field L2 is set on initialization")
+       }
+       if ao.IsSetM() {
+               t.Errorf("Optional field M is set on initialization")
+       }
+       if ao.IsSetM2() {
+               t.Errorf("Optional field M2 is set on initialization")
+       }
+       if ao.IsSetBin() {
+               t.Errorf("Optional field Bin is set on initialization")
+       }
+       if ao.IsSetBin2() {
+               t.Errorf("Optional field Bin2 is set on initialization")
+       }
+}
+
+func TestDefaultValuesOnCreation(t *testing.T) {
+       ao := OptionalFieldsTest.NewAllOptional()
+       if ao.GetS() != "DEFAULT" {
+               t.Errorf("Unexpected default value %#v for field S", ao.GetS())
+       }
+       if ao.GetI() != 42 {
+               t.Errorf("Unexpected default value %#v for field I", ao.GetI())
+       }
+       if ao.GetB() != false {
+               t.Errorf("Unexpected default value %#v for field B", ao.GetB())
+       }
+       if ao.GetS2() != "" {
+               t.Errorf("Unexpected default value %#v for field S2", ao.GetS2())
+       }
+       if ao.GetI2() != 0 {
+               t.Errorf("Unexpected default value %#v for field I2", ao.GetI2())
+       }
+       if ao.GetB2() != false {
+               t.Errorf("Unexpected default value %#v for field B2", ao.GetB2())
+       }
+       if l := ao.GetL(); len(l) != 0 {
+               t.Errorf("Unexpected default value %#v for field L", l)
+       }
+       if l := ao.GetL2(); len(l) != 2 || l[0] != 1 || l[1] != 2 {
+               t.Errorf("Unexpected default value %#v for field L2", l)
+       }
+       //FIXME: should we return empty map here?
+       if m := ao.GetM(); m != nil {
+               t.Errorf("Unexpected default value %#v for field M", m)
+       }
+       if m := ao.GetM2(); len(m) != 2 || m[1] != 2 || m[3] != 4 {
+               t.Errorf("Unexpected default value %#v for field M2", m)
+       }
+       if bv := ao.GetBin(); bv != nil {
+               t.Errorf("Unexpected default value %#v for field Bin", bv)
+       }
+       if bv := ao.GetBin2(); !bytes.Equal(bv, []byte("asdf")) {
+               t.Errorf("Unexpected default value %#v for field Bin2", bv)
+       }
+}
+
+func TestInitialValuesOnCreation(t *testing.T) {
+       ao := OptionalFieldsTest.NewAllOptional()
+       if ao.S != "DEFAULT" {
+               t.Errorf("Unexpected initial value %#v for field S", ao.S)
+       }
+       if ao.I != 42 {
+               t.Errorf("Unexpected initial value %#v for field I", ao.I)
+       }
+       if ao.B != false {
+               t.Errorf("Unexpected initial value %#v for field B", ao.B)
+       }
+       if ao.S2 != nil {
+               t.Errorf("Unexpected initial value %#v for field S2", ao.S2)
+       }
+       if ao.I2 != nil {
+               t.Errorf("Unexpected initial value %#v for field I2", ao.I2)
+       }
+       if ao.B2 != nil {
+               t.Errorf("Unexpected initial value %#v for field B2", ao.B2)
+       }
+       if ao.L != nil || len(ao.L) != 0 {
+               t.Errorf("Unexpected initial value %#v for field L", ao.L)
+       }
+       if ao.L2 != nil {
+               t.Errorf("Unexpected initial value %#v for field L2", ao.L2)
+       }
+       if ao.M != nil {
+               t.Errorf("Unexpected initial value %#v for field M", ao.M)
+       }
+       if ao.M2 != nil {
+               t.Errorf("Unexpected initial value %#v for field M2", ao.M2)
+       }
+       if ao.Bin != nil || len(ao.Bin) != 0 {
+               t.Errorf("Unexpected initial value %#v for field Bin", ao.Bin)
+       }
+       if !bytes.Equal(ao.Bin2, []byte("asdf")) {
+               t.Errorf("Unexpected initial value %#v for field Bin2", ao.Bin2)
+       }
+}
+
+func TestIsSetReturnTrueAfterUpdate(t *testing.T) {
+       ao := OptionalFieldsTest.NewAllOptional()
+       ao.S = "somevalue"
+       ao.I = 123
+       ao.B = true
+       ao.Aa = OptionalFieldsTest.NewStructA()
+       if !ao.IsSetS() {
+               t.Errorf("Field S should be set")
+       }
+       if !ao.IsSetI() {
+               t.Errorf("Field I should be set")
+       }
+       if !ao.IsSetB() {
+               t.Errorf("Field B should be set")
+       }
+       if !ao.IsSetAa() {
+               t.Errorf("Field aa should be set")
+       }
+}
+
+func TestListNotEmpty(t *testing.T) {
+       ao := OptionalFieldsTest.NewAllOptional()
+       ao.L = []int64{1, 2, 3}
+       if !ao.IsSetL() {
+               t.Errorf("Field L should be set")
+       }
+}
+
+//Make sure that optional fields are not being serialized
+func TestNoOptionalUnsetFieldsOnWire(t *testing.T) {
+       mockCtrl := gomock.NewController(t)
+       defer mockCtrl.Finish()
+       proto := NewMockTProtocol(mockCtrl)
+       gomock.InOrder(
+               proto.EXPECT().WriteStructBegin("all_optional").Return(nil),
+               proto.EXPECT().WriteFieldStop().Return(nil),
+               proto.EXPECT().WriteStructEnd().Return(nil),
+       )
+       ao := OptionalFieldsTest.NewAllOptional()
+       ao.Write(proto)
+}
+
+func TestNoSetToDefaultFieldsOnWire(t *testing.T) {
+       mockCtrl := gomock.NewController(t)
+       defer mockCtrl.Finish()
+       proto := NewMockTProtocol(mockCtrl)
+       gomock.InOrder(
+               proto.EXPECT().WriteStructBegin("all_optional").Return(nil),
+               proto.EXPECT().WriteFieldStop().Return(nil),
+               proto.EXPECT().WriteStructEnd().Return(nil),
+       )
+       ao := OptionalFieldsTest.NewAllOptional()
+       ao.I = 42
+       ao.Write(proto)
+}
+
+//Make sure that only one field is being serialized when set to non-default
+func TestOneISetFieldOnWire(t *testing.T) {
+       mockCtrl := gomock.NewController(t)
+       defer mockCtrl.Finish()
+       proto := NewMockTProtocol(mockCtrl)
+       gomock.InOrder(
+               proto.EXPECT().WriteStructBegin("all_optional").Return(nil),
+               proto.EXPECT().WriteFieldBegin("i", thrift.TType(thrift.I64), int16(2)).Return(nil),
+               proto.EXPECT().WriteI64(int64(123)).Return(nil),
+               proto.EXPECT().WriteFieldEnd().Return(nil),
+               proto.EXPECT().WriteFieldStop().Return(nil),
+               proto.EXPECT().WriteStructEnd().Return(nil),
+       )
+       ao := OptionalFieldsTest.NewAllOptional()
+       ao.I = 123
+       ao.Write(proto)
+}
+
+func TestOneLSetFieldOnWire(t *testing.T) {
+       mockCtrl := gomock.NewController(t)
+       defer mockCtrl.Finish()
+       proto := NewMockTProtocol(mockCtrl)
+       gomock.InOrder(
+               proto.EXPECT().WriteStructBegin("all_optional").Return(nil),
+               proto.EXPECT().WriteFieldBegin("l", thrift.TType(thrift.LIST), int16(9)).Return(nil),
+               proto.EXPECT().WriteListBegin(thrift.TType(thrift.I64), 2).Return(nil),
+               proto.EXPECT().WriteI64(int64(1)).Return(nil),
+               proto.EXPECT().WriteI64(int64(2)).Return(nil),
+               proto.EXPECT().WriteListEnd().Return(nil),
+               proto.EXPECT().WriteFieldEnd().Return(nil),
+               proto.EXPECT().WriteFieldStop().Return(nil),
+               proto.EXPECT().WriteStructEnd().Return(nil),
+       )
+       ao := OptionalFieldsTest.NewAllOptional()
+       ao.L = []int64{1, 2}
+       ao.Write(proto)
+}
+
+func TestOneBinSetFieldOnWire(t *testing.T) {
+       mockCtrl := gomock.NewController(t)
+       defer mockCtrl.Finish()
+       proto := NewMockTProtocol(mockCtrl)
+       gomock.InOrder(
+               proto.EXPECT().WriteStructBegin("all_optional").Return(nil),
+               proto.EXPECT().WriteFieldBegin("bin", thrift.TType(thrift.STRING), int16(13)).Return(nil),
+               proto.EXPECT().WriteBinary([]byte("somebytestring")).Return(nil),
+               proto.EXPECT().WriteFieldEnd().Return(nil),
+               proto.EXPECT().WriteFieldStop().Return(nil),
+               proto.EXPECT().WriteStructEnd().Return(nil),
+       )
+       ao := OptionalFieldsTest.NewAllOptional()
+       ao.Bin = []byte("somebytestring")
+       ao.Write(proto)
+}
+
+func TestOneEmptyBinSetFieldOnWire(t *testing.T) {
+       mockCtrl := gomock.NewController(t)
+       defer mockCtrl.Finish()
+       proto := NewMockTProtocol(mockCtrl)
+       gomock.InOrder(
+               proto.EXPECT().WriteStructBegin("all_optional").Return(nil),
+               proto.EXPECT().WriteFieldBegin("bin", thrift.TType(thrift.STRING), int16(13)).Return(nil),
+               proto.EXPECT().WriteBinary([]byte{}).Return(nil),
+               proto.EXPECT().WriteFieldEnd().Return(nil),
+               proto.EXPECT().WriteFieldStop().Return(nil),
+               proto.EXPECT().WriteStructEnd().Return(nil),
+       )
+       ao := OptionalFieldsTest.NewAllOptional()
+       ao.Bin = []byte{}
+       ao.Write(proto)
+}
diff --git a/lib/go/test/tests/protocol_mock.go b/lib/go/test/tests/protocol_mock.go
new file mode 100644 (file)
index 0000000..d3f4078
--- /dev/null
@@ -0,0 +1,511 @@
+/*
+ * 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.
+ */
+
+// Automatically generated by MockGen. DO NOT EDIT!
+// Source: thrift (interfaces: TProtocol)
+
+package tests
+
+import (
+       thrift "thrift"
+       gomock "code.google.com/p/gomock/gomock"
+)
+
+// Mock of TProtocol interface
+type MockTProtocol struct {
+       ctrl     *gomock.Controller
+       recorder *_MockTProtocolRecorder
+}
+
+// Recorder for MockTProtocol (not exported)
+type _MockTProtocolRecorder struct {
+       mock *MockTProtocol
+}
+
+func NewMockTProtocol(ctrl *gomock.Controller) *MockTProtocol {
+       mock := &MockTProtocol{ctrl: ctrl}
+       mock.recorder = &_MockTProtocolRecorder{mock}
+       return mock
+}
+
+func (_m *MockTProtocol) EXPECT() *_MockTProtocolRecorder {
+       return _m.recorder
+}
+
+func (_m *MockTProtocol) Flush() error {
+       ret := _m.ctrl.Call(_m, "Flush")
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) Flush() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "Flush")
+}
+
+func (_m *MockTProtocol) ReadBinary() ([]byte, error) {
+       ret := _m.ctrl.Call(_m, "ReadBinary")
+       ret0, _ := ret[0].([]byte)
+       ret1, _ := ret[1].(error)
+       return ret0, ret1
+}
+
+func (_mr *_MockTProtocolRecorder) ReadBinary() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadBinary")
+}
+
+func (_m *MockTProtocol) ReadBool() (bool, error) {
+       ret := _m.ctrl.Call(_m, "ReadBool")
+       ret0, _ := ret[0].(bool)
+       ret1, _ := ret[1].(error)
+       return ret0, ret1
+}
+
+func (_mr *_MockTProtocolRecorder) ReadBool() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadBool")
+}
+
+func (_m *MockTProtocol) ReadByte() (byte, error) {
+       ret := _m.ctrl.Call(_m, "ReadByte")
+       ret0, _ := ret[0].(byte)
+       ret1, _ := ret[1].(error)
+       return ret0, ret1
+}
+
+func (_mr *_MockTProtocolRecorder) ReadByte() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadByte")
+}
+
+func (_m *MockTProtocol) ReadDouble() (float64, error) {
+       ret := _m.ctrl.Call(_m, "ReadDouble")
+       ret0, _ := ret[0].(float64)
+       ret1, _ := ret[1].(error)
+       return ret0, ret1
+}
+
+func (_mr *_MockTProtocolRecorder) ReadDouble() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadDouble")
+}
+
+func (_m *MockTProtocol) ReadFieldBegin() (string, thrift.TType, int16, error) {
+       ret := _m.ctrl.Call(_m, "ReadFieldBegin")
+       ret0, _ := ret[0].(string)
+       ret1, _ := ret[1].(thrift.TType)
+       ret2, _ := ret[2].(int16)
+       ret3, _ := ret[3].(error)
+       return ret0, ret1, ret2, ret3
+}
+
+func (_mr *_MockTProtocolRecorder) ReadFieldBegin() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadFieldBegin")
+}
+
+func (_m *MockTProtocol) ReadFieldEnd() error {
+       ret := _m.ctrl.Call(_m, "ReadFieldEnd")
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) ReadFieldEnd() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadFieldEnd")
+}
+
+func (_m *MockTProtocol) ReadI16() (int16, error) {
+       ret := _m.ctrl.Call(_m, "ReadI16")
+       ret0, _ := ret[0].(int16)
+       ret1, _ := ret[1].(error)
+       return ret0, ret1
+}
+
+func (_mr *_MockTProtocolRecorder) ReadI16() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadI16")
+}
+
+func (_m *MockTProtocol) ReadI32() (int32, error) {
+       ret := _m.ctrl.Call(_m, "ReadI32")
+       ret0, _ := ret[0].(int32)
+       ret1, _ := ret[1].(error)
+       return ret0, ret1
+}
+
+func (_mr *_MockTProtocolRecorder) ReadI32() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadI32")
+}
+
+func (_m *MockTProtocol) ReadI64() (int64, error) {
+       ret := _m.ctrl.Call(_m, "ReadI64")
+       ret0, _ := ret[0].(int64)
+       ret1, _ := ret[1].(error)
+       return ret0, ret1
+}
+
+func (_mr *_MockTProtocolRecorder) ReadI64() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadI64")
+}
+
+func (_m *MockTProtocol) ReadListBegin() (thrift.TType, int, error) {
+       ret := _m.ctrl.Call(_m, "ReadListBegin")
+       ret0, _ := ret[0].(thrift.TType)
+       ret1, _ := ret[1].(int)
+       ret2, _ := ret[2].(error)
+       return ret0, ret1, ret2
+}
+
+func (_mr *_MockTProtocolRecorder) ReadListBegin() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadListBegin")
+}
+
+func (_m *MockTProtocol) ReadListEnd() error {
+       ret := _m.ctrl.Call(_m, "ReadListEnd")
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) ReadListEnd() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadListEnd")
+}
+
+func (_m *MockTProtocol) ReadMapBegin() (thrift.TType, thrift.TType, int, error) {
+       ret := _m.ctrl.Call(_m, "ReadMapBegin")
+       ret0, _ := ret[0].(thrift.TType)
+       ret1, _ := ret[1].(thrift.TType)
+       ret2, _ := ret[2].(int)
+       ret3, _ := ret[3].(error)
+       return ret0, ret1, ret2, ret3
+}
+
+func (_mr *_MockTProtocolRecorder) ReadMapBegin() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadMapBegin")
+}
+
+func (_m *MockTProtocol) ReadMapEnd() error {
+       ret := _m.ctrl.Call(_m, "ReadMapEnd")
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) ReadMapEnd() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadMapEnd")
+}
+
+func (_m *MockTProtocol) ReadMessageBegin() (string, thrift.TMessageType, int32, error) {
+       ret := _m.ctrl.Call(_m, "ReadMessageBegin")
+       ret0, _ := ret[0].(string)
+       ret1, _ := ret[1].(thrift.TMessageType)
+       ret2, _ := ret[2].(int32)
+       ret3, _ := ret[3].(error)
+       return ret0, ret1, ret2, ret3
+}
+
+func (_mr *_MockTProtocolRecorder) ReadMessageBegin() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadMessageBegin")
+}
+
+func (_m *MockTProtocol) ReadMessageEnd() error {
+       ret := _m.ctrl.Call(_m, "ReadMessageEnd")
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) ReadMessageEnd() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadMessageEnd")
+}
+
+func (_m *MockTProtocol) ReadSetBegin() (thrift.TType, int, error) {
+       ret := _m.ctrl.Call(_m, "ReadSetBegin")
+       ret0, _ := ret[0].(thrift.TType)
+       ret1, _ := ret[1].(int)
+       ret2, _ := ret[2].(error)
+       return ret0, ret1, ret2
+}
+
+func (_mr *_MockTProtocolRecorder) ReadSetBegin() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadSetBegin")
+}
+
+func (_m *MockTProtocol) ReadSetEnd() error {
+       ret := _m.ctrl.Call(_m, "ReadSetEnd")
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) ReadSetEnd() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadSetEnd")
+}
+
+func (_m *MockTProtocol) ReadString() (string, error) {
+       ret := _m.ctrl.Call(_m, "ReadString")
+       ret0, _ := ret[0].(string)
+       ret1, _ := ret[1].(error)
+       return ret0, ret1
+}
+
+func (_mr *_MockTProtocolRecorder) ReadString() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadString")
+}
+
+func (_m *MockTProtocol) ReadStructBegin() (string, error) {
+       ret := _m.ctrl.Call(_m, "ReadStructBegin")
+       ret0, _ := ret[0].(string)
+       ret1, _ := ret[1].(error)
+       return ret0, ret1
+}
+
+func (_mr *_MockTProtocolRecorder) ReadStructBegin() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadStructBegin")
+}
+
+func (_m *MockTProtocol) ReadStructEnd() error {
+       ret := _m.ctrl.Call(_m, "ReadStructEnd")
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) ReadStructEnd() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadStructEnd")
+}
+
+func (_m *MockTProtocol) Skip(_param0 thrift.TType) error {
+       ret := _m.ctrl.Call(_m, "Skip", _param0)
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) Skip(arg0 interface{}) *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "Skip", arg0)
+}
+
+func (_m *MockTProtocol) Transport() thrift.TTransport {
+       ret := _m.ctrl.Call(_m, "Transport")
+       ret0, _ := ret[0].(thrift.TTransport)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) Transport() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "Transport")
+}
+
+func (_m *MockTProtocol) WriteBinary(_param0 []byte) error {
+       ret := _m.ctrl.Call(_m, "WriteBinary", _param0)
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteBinary(arg0 interface{}) *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteBinary", arg0)
+}
+
+func (_m *MockTProtocol) WriteBool(_param0 bool) error {
+       ret := _m.ctrl.Call(_m, "WriteBool", _param0)
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteBool(arg0 interface{}) *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteBool", arg0)
+}
+
+func (_m *MockTProtocol) WriteByte(_param0 byte) error {
+       ret := _m.ctrl.Call(_m, "WriteByte", _param0)
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteByte(arg0 interface{}) *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteByte", arg0)
+}
+
+func (_m *MockTProtocol) WriteDouble(_param0 float64) error {
+       ret := _m.ctrl.Call(_m, "WriteDouble", _param0)
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteDouble(arg0 interface{}) *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteDouble", arg0)
+}
+
+func (_m *MockTProtocol) WriteFieldBegin(_param0 string, _param1 thrift.TType, _param2 int16) error {
+       ret := _m.ctrl.Call(_m, "WriteFieldBegin", _param0, _param1, _param2)
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteFieldBegin(arg0, arg1, arg2 interface{}) *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteFieldBegin", arg0, arg1, arg2)
+}
+
+func (_m *MockTProtocol) WriteFieldEnd() error {
+       ret := _m.ctrl.Call(_m, "WriteFieldEnd")
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteFieldEnd() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteFieldEnd")
+}
+
+func (_m *MockTProtocol) WriteFieldStop() error {
+       ret := _m.ctrl.Call(_m, "WriteFieldStop")
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteFieldStop() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteFieldStop")
+}
+
+func (_m *MockTProtocol) WriteI16(_param0 int16) error {
+       ret := _m.ctrl.Call(_m, "WriteI16", _param0)
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteI16(arg0 interface{}) *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteI16", arg0)
+}
+
+func (_m *MockTProtocol) WriteI32(_param0 int32) error {
+       ret := _m.ctrl.Call(_m, "WriteI32", _param0)
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteI32(arg0 interface{}) *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteI32", arg0)
+}
+
+func (_m *MockTProtocol) WriteI64(_param0 int64) error {
+       ret := _m.ctrl.Call(_m, "WriteI64", _param0)
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteI64(arg0 interface{}) *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteI64", arg0)
+}
+
+func (_m *MockTProtocol) WriteListBegin(_param0 thrift.TType, _param1 int) error {
+       ret := _m.ctrl.Call(_m, "WriteListBegin", _param0, _param1)
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteListBegin(arg0, arg1 interface{}) *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteListBegin", arg0, arg1)
+}
+
+func (_m *MockTProtocol) WriteListEnd() error {
+       ret := _m.ctrl.Call(_m, "WriteListEnd")
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteListEnd() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteListEnd")
+}
+
+func (_m *MockTProtocol) WriteMapBegin(_param0 thrift.TType, _param1 thrift.TType, _param2 int) error {
+       ret := _m.ctrl.Call(_m, "WriteMapBegin", _param0, _param1, _param2)
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteMapBegin(arg0, arg1, arg2 interface{}) *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteMapBegin", arg0, arg1, arg2)
+}
+
+func (_m *MockTProtocol) WriteMapEnd() error {
+       ret := _m.ctrl.Call(_m, "WriteMapEnd")
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteMapEnd() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteMapEnd")
+}
+
+func (_m *MockTProtocol) WriteMessageBegin(_param0 string, _param1 thrift.TMessageType, _param2 int32) error {
+       ret := _m.ctrl.Call(_m, "WriteMessageBegin", _param0, _param1, _param2)
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteMessageBegin(arg0, arg1, arg2 interface{}) *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteMessageBegin", arg0, arg1, arg2)
+}
+
+func (_m *MockTProtocol) WriteMessageEnd() error {
+       ret := _m.ctrl.Call(_m, "WriteMessageEnd")
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteMessageEnd() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteMessageEnd")
+}
+
+func (_m *MockTProtocol) WriteSetBegin(_param0 thrift.TType, _param1 int) error {
+       ret := _m.ctrl.Call(_m, "WriteSetBegin", _param0, _param1)
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteSetBegin(arg0, arg1 interface{}) *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteSetBegin", arg0, arg1)
+}
+
+func (_m *MockTProtocol) WriteSetEnd() error {
+       ret := _m.ctrl.Call(_m, "WriteSetEnd")
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteSetEnd() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteSetEnd")
+}
+
+func (_m *MockTProtocol) WriteString(_param0 string) error {
+       ret := _m.ctrl.Call(_m, "WriteString", _param0)
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteString(arg0 interface{}) *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteString", arg0)
+}
+
+func (_m *MockTProtocol) WriteStructBegin(_param0 string) error {
+       ret := _m.ctrl.Call(_m, "WriteStructBegin", _param0)
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteStructBegin(arg0 interface{}) *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteStructBegin", arg0)
+}
+
+func (_m *MockTProtocol) WriteStructEnd() error {
+       ret := _m.ctrl.Call(_m, "WriteStructEnd")
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+func (_mr *_MockTProtocolRecorder) WriteStructEnd() *gomock.Call {
+       return _mr.mock.ctrl.RecordCall(_mr.mock, "WriteStructEnd")
+}
index c2ae261..8d6b2c2 100644 (file)
@@ -46,3 +46,5 @@ func Int64Ptr(v int64) *int64       { return &v }
 func StringPtr(v string) *string    { return &v }
 func Uint32Ptr(v uint32) *uint32    { return &v }
 func Uint64Ptr(v uint64) *uint64    { return &v }
+func BoolPtr(v bool) *bool          { return &v }
+func ByteSlicePtr(v []byte) *[]byte { return &v }