Skip to content

Commit e10109c

Browse files
committed
THRIFT-5845: Return TException for union check in Write
Client: go In compiler generated Write method for union types, return a TException (TProtocolException) when the number of fields set is not exactly 1, to help customer logic to decide whether to reuse a connection after an error. While I'm here, also do the same thing for the uniqueness check failure for set fields in Write as well.
1 parent 947ad66 commit e10109c

File tree

3 files changed

+77
-7
lines changed

3 files changed

+77
-7
lines changed

compiler/cpp/src/thrift/generate/t_go_generator.cc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1701,7 +1701,7 @@ void t_go_generator::generate_go_struct_reader(ostream& out,
17011701
out << indent() << "if !isset" << field_name << "{" << '\n';
17021702
indent_up();
17031703
out << indent() << "return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, "
1704-
"fmt.Errorf(\"Required field " << field_name << " is not set\"));" << '\n';
1704+
<< "fmt.Errorf(\"Required field " << field_name << " is not set\"))" << '\n';
17051705
indent_down();
17061706
out << indent() << "}" << '\n';
17071707
}
@@ -1748,7 +1748,8 @@ void t_go_generator::generate_go_struct_writer(ostream& out,
17481748
std::string tstruct_name(publicize(tstruct->get_name()));
17491749
out << indent() << "if c := p.CountSetFields" << tstruct_name << "(); c != 1 {" << '\n';
17501750
indent_up();
1751-
out << indent() << "return fmt.Errorf(\"%T write union: exactly one field must be set (%d set)\", p, c)" << '\n';
1751+
out << indent() << "return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, "
1752+
<< "fmt.Errorf(\"%T write union: exactly one field must be set (%d set)\", p, c))" << '\n';
17521753
indent_down();
17531754
out << indent() << "}" << '\n';
17541755
}
@@ -3719,10 +3720,9 @@ void t_go_generator::generate_serialize_container(ostream& out,
37193720
indent_down();
37203721
out << indent() << "}(" << wrapped_prefix << "[i], " << wrapped_prefix << "[j]) {" << '\n';
37213722
indent_up();
3722-
out << indent()
3723-
<< "return thrift.PrependError(\"\", fmt.Errorf(\"%T error writing set field: slice is not "
3724-
"unique\", "
3725-
<< wrapped_prefix << "))" << '\n';
3723+
out << indent() << "return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, "
3724+
<< "fmt.Errorf(\"%T error writing set field: slice is not " "unique\", "
3725+
<< wrapped_prefix << "))" << '\n';
37263726
indent_down();
37273727
out << indent() << "}" << '\n';
37283728
indent_down();

lib/go/test/UnionBinaryTest.thrift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@
2121
union Sample {
2222
1: map<string, string> u1,
2323
2: binary u2,
24-
3: list<string> u3
24+
3: list<string> u3,
25+
4: set<string> u4,
2526
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package tests
21+
22+
import (
23+
"context"
24+
"errors"
25+
"testing"
26+
27+
"github.com/apache/thrift/lib/go/test/gopath/src/unionbinarytest"
28+
"github.com/apache/thrift/lib/go/thrift"
29+
)
30+
31+
func TestWriteUnionTException(t *testing.T) {
32+
// See https://issues.apache.org/jira/browse/THRIFT-5845
33+
s := unionbinarytest.NewSample()
34+
proto := thrift.NewTBinaryProtocolConf(thrift.NewTMemoryBuffer(), nil)
35+
err := s.Write(context.Background(), proto)
36+
t.Log(err)
37+
if err == nil {
38+
t.Fatal("Writing empty union did not produce error")
39+
}
40+
var te thrift.TException
41+
if !errors.As(err, &te) {
42+
t.Fatalf("Error from writing empty union is not TException: (%T) %v", err, err)
43+
}
44+
if typ := te.TExceptionType(); typ != thrift.TExceptionTypeProtocol && typ != thrift.TExceptionTypeTransport {
45+
t.Errorf("Got TExceptionType %v, want one of TProtocolException or TTransportException", typ)
46+
}
47+
}
48+
49+
func TestWriteSetTException(t *testing.T) {
50+
// See https://issues.apache.org/jira/browse/THRIFT-5845
51+
s := unionbinarytest.NewSample()
52+
s.U4 = []string{
53+
"foo",
54+
"foo", // duplicate
55+
}
56+
proto := thrift.NewTBinaryProtocolConf(thrift.NewTMemoryBuffer(), nil)
57+
err := s.Write(context.Background(), proto)
58+
t.Log(err)
59+
if err == nil {
60+
t.Fatal("Writing duplicate set did not produce error")
61+
}
62+
var te thrift.TException
63+
if !errors.As(err, &te) {
64+
t.Fatalf("Error from writing duplicate set is not TException: (%T) %v", err, err)
65+
}
66+
if typ := te.TExceptionType(); typ != thrift.TExceptionTypeProtocol && typ != thrift.TExceptionTypeTransport {
67+
t.Errorf("Got TExceptionType %v, want one of TProtocolException or TTransportException", typ)
68+
}
69+
}

0 commit comments

Comments
 (0)