|
- // Copyright 2015 Google LLC
- //
- // Licensed 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 bigquery
-
- import (
- "errors"
- "strconv"
- "testing"
-
- "github.com/google/go-cmp/cmp"
-
- "cloud.google.com/go/internal/pretty"
- "cloud.google.com/go/internal/testutil"
- bq "google.golang.org/api/bigquery/v2"
- )
-
- type testSaver struct {
- row map[string]Value
- insertID string
- err error
- }
-
- func (ts testSaver) Save() (map[string]Value, string, error) {
- return ts.row, ts.insertID, ts.err
- }
-
- func TestNewInsertRequest(t *testing.T) {
- prev := randomIDFn
- n := 0
- randomIDFn = func() string { n++; return strconv.Itoa(n) }
- defer func() { randomIDFn = prev }()
-
- tests := []struct {
- ul *Uploader
- savers []ValueSaver
- req *bq.TableDataInsertAllRequest
- }{
- {
- ul: &Uploader{},
- savers: nil,
- req: nil,
- },
- {
- ul: &Uploader{},
- savers: []ValueSaver{
- testSaver{row: map[string]Value{"one": 1}},
- testSaver{row: map[string]Value{"two": 2}},
- },
- req: &bq.TableDataInsertAllRequest{
- Rows: []*bq.TableDataInsertAllRequestRows{
- {InsertId: "1", Json: map[string]bq.JsonValue{"one": 1}},
- {InsertId: "2", Json: map[string]bq.JsonValue{"two": 2}},
- },
- },
- },
- {
- ul: &Uploader{
- TableTemplateSuffix: "suffix",
- IgnoreUnknownValues: true,
- SkipInvalidRows: true,
- },
- savers: []ValueSaver{
- testSaver{insertID: "a", row: map[string]Value{"one": 1}},
- testSaver{insertID: "", row: map[string]Value{"two": 2}},
- },
- req: &bq.TableDataInsertAllRequest{
- Rows: []*bq.TableDataInsertAllRequestRows{
- {InsertId: "a", Json: map[string]bq.JsonValue{"one": 1}},
- {InsertId: "3", Json: map[string]bq.JsonValue{"two": 2}},
- },
- TemplateSuffix: "suffix",
- SkipInvalidRows: true,
- IgnoreUnknownValues: true,
- },
- },
- }
- for i, tc := range tests {
- got, err := tc.ul.newInsertRequest(tc.savers)
- if err != nil {
- t.Fatal(err)
- }
- want := tc.req
- if !testutil.Equal(got, want) {
- t.Errorf("%d: %#v: got %#v, want %#v", i, tc.ul, got, want)
- }
- }
- }
-
- func TestNewInsertRequestErrors(t *testing.T) {
- var u Uploader
- _, err := u.newInsertRequest([]ValueSaver{testSaver{err: errors.New("!")}})
- if err == nil {
- t.Error("got nil, want error")
- }
- }
-
- func TestHandleInsertErrors(t *testing.T) {
- rows := []*bq.TableDataInsertAllRequestRows{
- {InsertId: "a"},
- {InsertId: "b"},
- }
- for _, test := range []struct {
- in []*bq.TableDataInsertAllResponseInsertErrors
- want error
- }{
- {
- in: nil,
- want: nil,
- },
- {
- in: []*bq.TableDataInsertAllResponseInsertErrors{{Index: 1}},
- want: PutMultiError{RowInsertionError{InsertID: "b", RowIndex: 1}},
- },
- {
- in: []*bq.TableDataInsertAllResponseInsertErrors{{Index: 1}},
- want: PutMultiError{RowInsertionError{InsertID: "b", RowIndex: 1}},
- },
- {
- in: []*bq.TableDataInsertAllResponseInsertErrors{
- {Errors: []*bq.ErrorProto{{Message: "m0"}}, Index: 0},
- {Errors: []*bq.ErrorProto{{Message: "m1"}}, Index: 1},
- },
- want: PutMultiError{
- RowInsertionError{InsertID: "a", RowIndex: 0, Errors: []error{&Error{Message: "m0"}}},
- RowInsertionError{InsertID: "b", RowIndex: 1, Errors: []error{&Error{Message: "m1"}}},
- },
- },
- } {
- got := handleInsertErrors(test.in, rows)
- if !testutil.Equal(got, test.want) {
- t.Errorf("%#v:\ngot\n%#v\nwant\n%#v", test.in, got, test.want)
- }
- }
- }
-
- func TestValueSavers(t *testing.T) {
- ts := &testSaver{}
- type T struct{ I int }
- schema, err := InferSchema(T{})
- if err != nil {
- t.Fatal(err)
- }
- for _, test := range []struct {
- in interface{}
- want []ValueSaver
- }{
- {[]interface{}(nil), nil},
- {[]interface{}{}, nil},
- {ts, []ValueSaver{ts}},
- {T{I: 1}, []ValueSaver{&StructSaver{Schema: schema, Struct: T{I: 1}}}},
- {[]ValueSaver{ts, ts}, []ValueSaver{ts, ts}},
- {[]interface{}{ts, ts}, []ValueSaver{ts, ts}},
- {[]T{{I: 1}, {I: 2}}, []ValueSaver{
- &StructSaver{Schema: schema, Struct: T{I: 1}},
- &StructSaver{Schema: schema, Struct: T{I: 2}},
- }},
- {[]interface{}{T{I: 1}, &T{I: 2}}, []ValueSaver{
- &StructSaver{Schema: schema, Struct: T{I: 1}},
- &StructSaver{Schema: schema, Struct: &T{I: 2}},
- }},
- {&StructSaver{Struct: T{I: 3}, InsertID: "foo"},
- []ValueSaver{
- &StructSaver{Schema: schema, Struct: T{I: 3}, InsertID: "foo"},
- }},
- } {
- got, err := valueSavers(test.in)
- if err != nil {
- t.Fatal(err)
- }
- if !testutil.Equal(got, test.want, cmp.AllowUnexported(testSaver{})) {
- t.Errorf("%+v: got %v, want %v", test.in, pretty.Value(got), pretty.Value(test.want))
- }
- // Make sure Save is successful.
- for i, vs := range got {
- _, _, err := vs.Save()
- if err != nil {
- t.Fatalf("%+v, #%d: got error %v, want nil", test.in, i, err)
- }
- }
- }
- }
-
- func TestValueSaversErrors(t *testing.T) {
- inputs := []interface{}{
- nil,
- 1,
- []int{1, 2},
- []interface{}{
- testSaver{row: map[string]Value{"one": 1}, insertID: "a"},
- 1,
- },
- StructSaver{},
- }
- for _, in := range inputs {
- if _, err := valueSavers(in); err == nil {
- t.Errorf("%#v: got nil, want error", in)
- }
- }
- }
|