Skip to content

Commit b3dd0ad

Browse files
author
Mohit Paddhariya
authored
[#21384] Increase sql package test coverage from 35% to 70% (#33711)
1 parent 72102b5 commit b3dd0ad

File tree

1 file changed

+155
-2
lines changed

1 file changed

+155
-2
lines changed

sdks/go/pkg/beam/transforms/sql/sql_test.go

Lines changed: 155 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,14 @@
1616
package sql
1717

1818
import (
19-
"github.com/apache/beam/sdks/v2/go/pkg/beam"
20-
"github.com/apache/beam/sdks/v2/go/pkg/beam/transforms/sql/sqlx"
2119
"reflect"
2220
"testing"
21+
22+
"github.com/apache/beam/sdks/v2/go/pkg/beam"
23+
"github.com/apache/beam/sdks/v2/go/pkg/beam/core/typex"
24+
"github.com/apache/beam/sdks/v2/go/pkg/beam/transforms/sql/sqlx"
25+
"github.com/google/go-cmp/cmp"
26+
"github.com/google/go-cmp/cmp/cmpopts"
2327
)
2428

2529
func TestOptions_Add(t *testing.T) {
@@ -94,3 +98,152 @@ func TestExpansionAddr(t *testing.T) {
9498
t.Errorf("The function that ExpansionAddr(%v) returned did not work correctly. For the expansionAddr field in options, got %v, want %v", test.addr, o.expansionAddr, test.addr)
9599
}
96100
}
101+
102+
// TestOutputType tests the OutputType option for setting the output type
103+
// in an SQL transformation in Beam. It verifies both cases: when
104+
// components are provided and when they are not. The test checks if
105+
// the 'outType' field in the options is set correctly based on the
106+
// output type and components.
107+
func TestOutputType(t *testing.T) {
108+
testCases := []struct {
109+
name string
110+
typ reflect.Type
111+
components []typex.FullType
112+
wantNil bool
113+
}{
114+
{
115+
name: "output_type_without_components",
116+
typ: reflect.TypeOf(int64(0)),
117+
},
118+
{
119+
name: "output_type_with_components",
120+
typ: reflect.TypeOf(int64(0)),
121+
components: []typex.FullType{typex.New(reflect.TypeOf(""))},
122+
},
123+
}
124+
125+
for _, tc := range testCases {
126+
t.Run(tc.name, func(t *testing.T) {
127+
o := &options{}
128+
129+
var opt Option
130+
if len(tc.components) > 0 {
131+
opt = OutputType(tc.typ, tc.components...)
132+
} else {
133+
opt = OutputType(tc.typ)
134+
}
135+
136+
opt(o)
137+
138+
var expected typex.FullType
139+
if len(tc.components) > 0 {
140+
expected = typex.New(tc.typ, tc.components...)
141+
} else {
142+
expected = typex.New(tc.typ)
143+
}
144+
145+
opts := cmp.Options{
146+
cmp.Comparer(func(x, y typex.FullType) bool {
147+
// Compare only the type and components
148+
return x.Type() == y.Type()
149+
}),
150+
}
151+
if d := cmp.Diff(expected, o.outType, opts); d != "" {
152+
t.Errorf("OutputType() failed: (-want, +got)\n%s", d)
153+
}
154+
})
155+
}
156+
}
157+
158+
// TestTransform tests the behavior of the Transform function
159+
// in the context of SQL transformations. It checks that the function
160+
// panics when an output type is missing.
161+
func TestTransform_MissingOutputType(t *testing.T) {
162+
p := beam.NewPipeline()
163+
s := p.Root()
164+
col := beam.Create(s, 1, 2, 3)
165+
166+
defer func() {
167+
r := recover()
168+
if r == nil {
169+
t.Error("Transform() with missing output type should panic")
170+
}
171+
if msg, ok := r.(string); !ok || msg != "output type must be specified for sql.Transform" {
172+
t.Errorf("Transform() unexpected panic message: %v", r)
173+
}
174+
}()
175+
176+
Transform(s, "SELECT value FROM test", Input("test", col))
177+
}
178+
179+
// TestMultipleOptions tests applying multiple options at once
180+
// and verifying that they are all correctly applied to the options object.
181+
func TestMultipleOptions(t *testing.T) {
182+
testCases := []struct {
183+
name string
184+
inputName string
185+
dialect string
186+
expansionAddr string
187+
typ reflect.Type
188+
customOpt sqlx.Option
189+
}{
190+
{
191+
name: "all_options",
192+
inputName: "test",
193+
dialect: "zetasql",
194+
expansionAddr: "localhost:8080",
195+
typ: reflect.TypeOf(int64(0)),
196+
customOpt: sqlx.Option{Urn: "test"},
197+
},
198+
}
199+
200+
for _, tc := range testCases {
201+
t.Run(tc.name, func(t *testing.T) {
202+
p := beam.NewPipeline()
203+
s := p.Root()
204+
col := beam.Create(s, 1, 2, 3)
205+
206+
o := &options{
207+
inputs: make(map[string]beam.PCollection),
208+
}
209+
210+
opts := []Option{
211+
Input(tc.inputName, col),
212+
Dialect(tc.dialect),
213+
ExpansionAddr(tc.expansionAddr),
214+
OutputType(tc.typ),
215+
}
216+
217+
for _, opt := range opts {
218+
opt(o)
219+
}
220+
o.Add(tc.customOpt)
221+
222+
// Construct the expected options struct
223+
expected := &options{
224+
inputs: map[string]beam.PCollection{
225+
tc.inputName: col,
226+
},
227+
dialect: tc.dialect,
228+
expansionAddr: tc.expansionAddr,
229+
outType: typex.New(tc.typ),
230+
customs: []sqlx.Option{tc.customOpt},
231+
}
232+
233+
// Define a custom comparer for typex.FullType
234+
fullTypeComparer := cmp.Comparer(func(x, y typex.FullType) bool {
235+
return x.Type() == y.Type() // Compare only the underlying reflect.Type
236+
})
237+
238+
if d := cmp.Diff(
239+
expected,
240+
o,
241+
cmp.AllowUnexported(options{}),
242+
cmpopts.IgnoreUnexported(beam.PCollection{}),
243+
fullTypeComparer, // Use the custom comparer for typex.FullType
244+
); d != "" {
245+
t.Errorf("Options mismatch: (-want, +got)\n%s", d)
246+
}
247+
})
248+
}
249+
}

0 commit comments

Comments
 (0)