...

Source file src/cloud.google.com/go/bigquery/intervalvalue_test.go

Documentation: cloud.google.com/go/bigquery

     1  // Copyright 2022 Google LLC
     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 bigquery
    16  
    17  import (
    18  	"testing"
    19  	"time"
    20  
    21  	"cloud.google.com/go/internal/testutil"
    22  )
    23  
    24  func TestParseInterval(t *testing.T) {
    25  	testcases := []struct {
    26  		inputStr     string
    27  		wantInterval *IntervalValue
    28  		wantErr      bool
    29  	}{
    30  		{
    31  			inputStr: "",
    32  			wantErr:  true,
    33  		},
    34  		{
    35  			inputStr: "1-2 3",
    36  			wantErr:  true,
    37  		},
    38  		{
    39  			inputStr:     "1-2 3 4:5:6",
    40  			wantInterval: &IntervalValue{Years: 1, Months: 2, Days: 3, Hours: 4, Minutes: 5, Seconds: 6, SubSecondNanos: 0},
    41  		},
    42  		{
    43  			inputStr:     "1-2 3 4:5:6.5",
    44  			wantInterval: &IntervalValue{Years: 1, Months: 2, Days: 3, Hours: 4, Minutes: 5, Seconds: 6, SubSecondNanos: 500000000},
    45  		},
    46  		{
    47  			inputStr:     "-1-2 3 -4:5:6.123",
    48  			wantInterval: &IntervalValue{Years: -1, Months: -2, Days: 3, Hours: -4, Minutes: -5, Seconds: -6, SubSecondNanos: -123000000},
    49  		},
    50  		{
    51  			inputStr:     "0-0 0 1:1:1.000000001",
    52  			wantInterval: &IntervalValue{Hours: 1, Minutes: 1, Seconds: 1, SubSecondNanos: 1},
    53  		},
    54  	}
    55  
    56  	for _, tc := range testcases {
    57  		gotInterval, err := ParseInterval(tc.inputStr)
    58  		if tc.wantErr {
    59  			if err != nil {
    60  				continue
    61  			}
    62  			t.Errorf("input %s: wanted err, got success", tc.inputStr)
    63  		}
    64  		if err != nil {
    65  			t.Errorf("input %s got err: %v", tc.inputStr, err)
    66  		}
    67  		if diff := testutil.Diff(gotInterval, tc.wantInterval); diff != "" {
    68  			t.Errorf("input %s: got=-, want=+:\n%s", tc.inputStr, diff)
    69  		}
    70  	}
    71  }
    72  
    73  func TestCanonicalInterval(t *testing.T) {
    74  	testcases := []struct {
    75  		description   string
    76  		input         *IntervalValue
    77  		wantCanonical *IntervalValue
    78  		wantString    string
    79  	}{
    80  		{
    81  			description:   "already canonical",
    82  			input:         &IntervalValue{Years: 1, Months: 2, Days: 3, Hours: 4, Minutes: 5, Seconds: 6, SubSecondNanos: 0},
    83  			wantCanonical: &IntervalValue{Years: 1, Months: 2, Days: 3, Hours: 4, Minutes: 5, Seconds: 6, SubSecondNanos: 0},
    84  			wantString:    "1-2 3 4:5:6",
    85  		},
    86  		{
    87  			description:   "mixed Y-M",
    88  			input:         &IntervalValue{Years: -1, Months: 28},
    89  			wantCanonical: &IntervalValue{Years: 1, Months: 4, Days: 0, Hours: 0, Minutes: 0, Seconds: 0, SubSecondNanos: 0},
    90  			wantString:    "1-4 0 0:0:0",
    91  		},
    92  		{
    93  			description:   "mixed Y-M",
    94  			input:         &IntervalValue{Years: -1, Months: 28},
    95  			wantCanonical: &IntervalValue{Years: 1, Months: 4, Days: 0, Hours: 0, Minutes: 0, Seconds: 0, SubSecondNanos: 0},
    96  			wantString:    "1-4 0 0:0:0",
    97  		},
    98  		{
    99  			description:   "big month Y-M",
   100  			input:         &IntervalValue{Years: 0, Months: -13},
   101  			wantCanonical: &IntervalValue{Years: -1, Months: -1, Days: 0, Hours: 0, Minutes: 0, Seconds: 0, SubSecondNanos: 0},
   102  			wantString:    "-1-1 0 0:0:0",
   103  		},
   104  		{
   105  			description:   "big days not normalized",
   106  			input:         &IntervalValue{Days: 1000},
   107  			wantCanonical: &IntervalValue{Years: 0, Months: 0, Days: 1000, Hours: 0, Minutes: 0, Seconds: 0, SubSecondNanos: 0},
   108  			wantString:    "0-0 1000 0:0:0",
   109  		},
   110  		{
   111  			description:   "time reduced",
   112  			input:         &IntervalValue{Minutes: 181, Seconds: 61, SubSecondNanos: 5},
   113  			wantCanonical: &IntervalValue{Hours: 3, Minutes: 2, Seconds: 1, SubSecondNanos: 5},
   114  			wantString:    "0-0 0 3:2:1.000000005",
   115  		},
   116  		{
   117  			description:   "subseconds oversized",
   118  			input:         &IntervalValue{SubSecondNanos: 1900000000},
   119  			wantCanonical: &IntervalValue{Years: 0, Months: 0, Days: 0, Hours: 0, Minutes: 0, Seconds: 1, SubSecondNanos: 900000000},
   120  			wantString:    "0-0 0 0:0:1.9",
   121  		},
   122  	}
   123  
   124  	for _, tc := range testcases {
   125  		gotCanonical := tc.input.Canonicalize()
   126  
   127  		if diff := testutil.Diff(gotCanonical, tc.wantCanonical); diff != "" {
   128  			t.Errorf("%s: got=-, want=+:\n%s", tc.description, diff)
   129  		}
   130  
   131  		gotStr := tc.input.String()
   132  		if gotStr != tc.wantString {
   133  			t.Errorf("%s mismatched strings. got %s want %s", tc.description, gotStr, tc.wantString)
   134  		}
   135  	}
   136  }
   137  
   138  func TestIntervalDuration(t *testing.T) {
   139  	testcases := []struct {
   140  		description   string
   141  		inputInterval *IntervalValue
   142  		wantDuration  time.Duration
   143  		wantInterval  *IntervalValue
   144  	}{
   145  		{
   146  			description:   "hour",
   147  			inputInterval: &IntervalValue{Hours: 1},
   148  			wantDuration:  time.Duration(time.Hour),
   149  			wantInterval:  &IntervalValue{Hours: 1},
   150  		},
   151  		{
   152  			description:   "minute oversized",
   153  			inputInterval: &IntervalValue{Minutes: 62},
   154  			wantDuration:  time.Duration(62 * time.Minute),
   155  			wantInterval:  &IntervalValue{Hours: 1, Minutes: 2},
   156  		},
   157  		{
   158  			description:   "other parts",
   159  			inputInterval: &IntervalValue{Months: 1, Days: 2},
   160  			wantDuration:  time.Duration(32 * 24 * time.Hour),
   161  			wantInterval:  &IntervalValue{Hours: 32 * 24},
   162  		},
   163  	}
   164  
   165  	for _, tc := range testcases {
   166  		gotDuration := tc.inputInterval.ToDuration()
   167  
   168  		// interval -> duration
   169  		if gotDuration != tc.wantDuration {
   170  			t.Errorf("%s: mismatched duration, got %v want %v", tc.description, gotDuration, tc.wantDuration)
   171  		}
   172  
   173  		// duration -> interval (canonical)
   174  		gotInterval := IntervalValueFromDuration(gotDuration)
   175  		if diff := testutil.Diff(gotInterval, tc.wantInterval); diff != "" {
   176  			t.Errorf("%s: got=-, want=+:\n%s", tc.description, diff)
   177  		}
   178  	}
   179  }
   180  

View as plain text