go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/tools/cmd/bqschemaupdater/local_table_store_test.go (about)

     1  // Copyright 2018 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package main
    16  
    17  import (
    18  	"context"
    19  	"net/http"
    20  	"reflect"
    21  	"testing"
    22  
    23  	"cloud.google.com/go/bigquery"
    24  
    25  	"google.golang.org/api/googleapi"
    26  )
    27  
    28  type testSchemaA struct {
    29  	testField string
    30  }
    31  
    32  type testSchemaB struct {
    33  	testField int
    34  }
    35  
    36  func newTestSchema(t *testing.T) bigquery.Schema {
    37  	s, err := bigquery.InferSchema(testSchemaA{})
    38  	if err != nil {
    39  		t.Fatal(err)
    40  	}
    41  	return s
    42  }
    43  
    44  func TestCreateTable(t *testing.T) {
    45  	ctx := context.Background()
    46  	datasetID := "test_dataset"
    47  	tableID := "test_table"
    48  	s := newTestSchema(t)
    49  	md := &bigquery.TableMetadata{Schema: s}
    50  	t.Run("SimpleCreate", func(t *testing.T) {
    51  		ts := localTableStore{}
    52  		if err := ts.createTable(ctx, datasetID, tableID, md); err != nil {
    53  			t.Fatal(err)
    54  		}
    55  		want := &bigquery.TableMetadata{Schema: s}
    56  		got, err := ts.getTableMetadata(ctx, datasetID, tableID)
    57  		if err != nil {
    58  			t.Fatal(err)
    59  		}
    60  		if !reflect.DeepEqual(got, want) {
    61  			t.Errorf("got: %v; want: %v", got, want)
    62  		}
    63  	})
    64  	t.Run("AlreadyCreated", func(t *testing.T) {
    65  		ts := localTableStore{}
    66  		if err := ts.createTable(ctx, datasetID, tableID, md); err != nil {
    67  			t.Fatal(err)
    68  		}
    69  		want := &googleapi.Error{Code: http.StatusConflict}
    70  		got := ts.createTable(ctx, datasetID, tableID, md)
    71  		if !reflect.DeepEqual(got, want) {
    72  			t.Errorf("got: %v; want: %v", got, want)
    73  		}
    74  	})
    75  }
    76  
    77  func TestGetTableMetadata(t *testing.T) {
    78  	ctx := context.Background()
    79  	datasetID := "test_dataset"
    80  	tableID := "test_table"
    81  	t.Run("TableDoesNotExist", func(t *testing.T) {
    82  		ts := localTableStore{}
    83  		want := &googleapi.Error{Code: http.StatusNotFound}
    84  		_, got := ts.getTableMetadata(ctx, datasetID, tableID)
    85  		if !reflect.DeepEqual(got, want) {
    86  			t.Errorf("got: %v; want: %v", got, want)
    87  		}
    88  	})
    89  	t.Run("TableExists", func(t *testing.T) {
    90  		ts := localTableStore{}
    91  		want := newTestSchema(t)
    92  		md := &bigquery.TableMetadata{Schema: want}
    93  		if err := ts.createTable(ctx, datasetID, tableID, md); err != nil {
    94  			t.Fatal(err)
    95  		}
    96  		md, err := ts.getTableMetadata(ctx, datasetID, tableID)
    97  		got := md.Schema
    98  		if err != nil {
    99  			t.Fatal(err)
   100  		}
   101  		if !reflect.DeepEqual(got, want) {
   102  			t.Errorf("got: %v; want: %v", got, want)
   103  		}
   104  	})
   105  }
   106  
   107  func TestUpdateTable(t *testing.T) {
   108  	ctx := context.Background()
   109  	ts := localTableStore{}
   110  	datasetID := "test_dataset"
   111  	s := newTestSchema(t)
   112  	initialMD := &bigquery.TableMetadata{Schema: s}
   113  	otherS, err := bigquery.InferSchema(testSchemaB{})
   114  	if err != nil {
   115  		t.Fatal(err)
   116  	}
   117  	type updateTestCase struct {
   118  		tableID     string
   119  		toUpdate    bigquery.TableMetadataToUpdate
   120  		want        *bigquery.TableMetadata
   121  		wantErr     error
   122  		createTable bool
   123  	}
   124  	cases := []updateTestCase{
   125  		{
   126  			tableID:     "table_dne",
   127  			toUpdate:    bigquery.TableMetadataToUpdate{},
   128  			want:        nil,
   129  			wantErr:     &googleapi.Error{Code: http.StatusNotFound},
   130  			createTable: false,
   131  		},
   132  		{
   133  			tableID:     "table_noop",
   134  			toUpdate:    bigquery.TableMetadataToUpdate{},
   135  			want:        &bigquery.TableMetadata{Schema: s},
   136  			createTable: true,
   137  		},
   138  		{
   139  			tableID: "table_change_one_thing",
   140  			toUpdate: bigquery.TableMetadataToUpdate{
   141  				Name: "test_name",
   142  			},
   143  			want: &bigquery.TableMetadata{
   144  				Schema: s,
   145  				Name:   "test_name",
   146  			},
   147  			createTable: true,
   148  		},
   149  		{
   150  			tableID: "table_change_everything",
   151  			toUpdate: bigquery.TableMetadataToUpdate{
   152  				Name:        "test_name",
   153  				Description: "test_desc",
   154  				Schema:      otherS,
   155  			},
   156  			want: &bigquery.TableMetadata{
   157  				Name:        "test_name",
   158  				Description: "test_desc",
   159  				Schema:      otherS,
   160  			},
   161  			createTable: true,
   162  		},
   163  	}
   164  	for _, tc := range cases {
   165  		if tc.createTable {
   166  			if err := ts.createTable(ctx, datasetID, tc.tableID, initialMD); err != nil {
   167  				t.Fatal(err)
   168  			}
   169  		}
   170  		err = ts.updateTable(ctx, datasetID, tc.tableID, tc.toUpdate)
   171  		if got := err; !reflect.DeepEqual(got, tc.wantErr) {
   172  			t.Errorf("unexpected error: got: %v; want: %v", got, tc.wantErr)
   173  		}
   174  		md, err := ts.getTableMetadata(ctx, datasetID, tc.tableID)
   175  		if got := err; !reflect.DeepEqual(got, tc.wantErr) {
   176  			t.Errorf("unexpected error: got: %v; want: %v", got, tc.wantErr)
   177  		}
   178  		if got := md; !reflect.DeepEqual(got, tc.want) {
   179  			t.Errorf("update failed for: %v; got: %v; want: %v", tc.tableID, got, tc.want)
   180  		}
   181  	}
   182  }