1/* 2Copyright 2017 Google LLC 3 4Licensed under the Apache License, Version 2.0 (the "License"); 5you may not use this file except in compliance with the License. 6You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10Unless required by applicable law or agreed to in writing, software 11distributed under the License is distributed on an "AS IS" BASIS, 12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13See the License for the specific language governing permissions and 14limitations under the License. 15*/ 16 17package spanner 18 19import ( 20 "testing" 21 "time" 22 23 pbd "github.com/golang/protobuf/ptypes/duration" 24 pbt "github.com/golang/protobuf/ptypes/timestamp" 25 sppb "google.golang.org/genproto/googleapis/spanner/v1" 26) 27 28// Test generating TimestampBound for strong reads. 29func TestStrong(t *testing.T) { 30 got := StrongRead() 31 want := TimestampBound{mode: strong} 32 if !testEqual(got, want) { 33 t.Errorf("Strong() = %v; want %v", got, want) 34 } 35} 36 37// Test generating TimestampBound for reads with exact staleness. 38func TestExactStaleness(t *testing.T) { 39 got := ExactStaleness(10 * time.Second) 40 want := TimestampBound{mode: exactStaleness, d: 10 * time.Second} 41 if !testEqual(got, want) { 42 t.Errorf("ExactStaleness(10*time.Second) = %v; want %v", got, want) 43 } 44} 45 46// Test generating TimestampBound for reads with max staleness. 47func TestMaxStaleness(t *testing.T) { 48 got := MaxStaleness(10 * time.Second) 49 want := TimestampBound{mode: maxStaleness, d: 10 * time.Second} 50 if !testEqual(got, want) { 51 t.Errorf("MaxStaleness(10*time.Second) = %v; want %v", got, want) 52 } 53} 54 55// Test generating TimestampBound for reads with minimum freshness requirement. 56func TestMinReadTimestamp(t *testing.T) { 57 ts := time.Now() 58 got := MinReadTimestamp(ts) 59 want := TimestampBound{mode: minReadTimestamp, t: ts} 60 if !testEqual(got, want) { 61 t.Errorf("MinReadTimestamp(%v) = %v; want %v", ts, got, want) 62 } 63} 64 65// Test generating TimestampBound for reads requesting data at a exact timestamp. 66func TestReadTimestamp(t *testing.T) { 67 ts := time.Now() 68 got := ReadTimestamp(ts) 69 want := TimestampBound{mode: readTimestamp, t: ts} 70 if !testEqual(got, want) { 71 t.Errorf("ReadTimestamp(%v) = %v; want %v", ts, got, want) 72 } 73} 74 75// Test TimestampBound.String. 76func TestTimestampBoundString(t *testing.T) { 77 ts := time.Unix(1136239445, 0).UTC() 78 var tests = []struct { 79 tb TimestampBound 80 want string 81 }{ 82 { 83 tb: TimestampBound{mode: strong}, 84 want: "(strong)", 85 }, 86 { 87 tb: TimestampBound{mode: exactStaleness, d: 10 * time.Second}, 88 want: "(exactStaleness: 10s)", 89 }, 90 { 91 tb: TimestampBound{mode: maxStaleness, d: 10 * time.Second}, 92 want: "(maxStaleness: 10s)", 93 }, 94 { 95 tb: TimestampBound{mode: minReadTimestamp, t: ts}, 96 want: "(minReadTimestamp: 2006-01-02 22:04:05 +0000 UTC)", 97 }, 98 { 99 tb: TimestampBound{mode: readTimestamp, t: ts}, 100 want: "(readTimestamp: 2006-01-02 22:04:05 +0000 UTC)", 101 }, 102 } 103 for _, test := range tests { 104 got := test.tb.String() 105 if got != test.want { 106 t.Errorf("%#v.String():\ngot %q\nwant %q", test.tb, got, test.want) 107 } 108 } 109} 110 111// Test time.Duration to pdb.Duration conversion. 112func TestDurationProto(t *testing.T) { 113 var tests = []struct { 114 d time.Duration 115 want pbd.Duration 116 }{ 117 {time.Duration(0), pbd.Duration{Seconds: 0, Nanos: 0}}, 118 {time.Second, pbd.Duration{Seconds: 1, Nanos: 0}}, 119 {time.Millisecond, pbd.Duration{Seconds: 0, Nanos: 1e6}}, 120 {15 * time.Nanosecond, pbd.Duration{Seconds: 0, Nanos: 15}}, 121 {42 * time.Hour, pbd.Duration{Seconds: 151200}}, 122 {-(1*time.Hour + 4*time.Millisecond), pbd.Duration{Seconds: -3600, Nanos: -4e6}}, 123 } 124 for _, test := range tests { 125 got := durationProto(test.d) 126 if !testEqual(got, &test.want) { 127 t.Errorf("durationProto(%v) = %v; want %v", test.d, got, test.want) 128 } 129 } 130} 131 132// Test time.Time to pbt.Timestamp conversion. 133func TestTimeProto(t *testing.T) { 134 var tests = []struct { 135 t time.Time 136 want pbt.Timestamp 137 }{ 138 {time.Unix(0, 0), pbt.Timestamp{}}, 139 {time.Unix(1136239445, 12345), pbt.Timestamp{Seconds: 1136239445, Nanos: 12345}}, 140 {time.Unix(-1000, 12345), pbt.Timestamp{Seconds: -1000, Nanos: 12345}}, 141 } 142 for _, test := range tests { 143 got := timestampProto(test.t) 144 if !testEqual(got, &test.want) { 145 t.Errorf("timestampProto(%v) = %v; want %v", test.t, got, test.want) 146 } 147 } 148} 149 150// Test readonly transaction option builder. 151func TestBuildTransactionOptionsReadOnly(t *testing.T) { 152 ts := time.Unix(1136239445, 12345) 153 var tests = []struct { 154 tb TimestampBound 155 ts bool 156 want sppb.TransactionOptions_ReadOnly 157 }{ 158 { 159 StrongRead(), false, 160 sppb.TransactionOptions_ReadOnly{ 161 TimestampBound: &sppb.TransactionOptions_ReadOnly_Strong{ 162 Strong: true}, 163 ReturnReadTimestamp: false, 164 }, 165 }, 166 { 167 ExactStaleness(10 * time.Second), true, 168 sppb.TransactionOptions_ReadOnly{ 169 TimestampBound: &sppb.TransactionOptions_ReadOnly_ExactStaleness{ 170 ExactStaleness: &pbd.Duration{Seconds: 10}}, 171 ReturnReadTimestamp: true, 172 }, 173 }, 174 { 175 MaxStaleness(10 * time.Second), true, 176 sppb.TransactionOptions_ReadOnly{ 177 TimestampBound: &sppb.TransactionOptions_ReadOnly_MaxStaleness{ 178 MaxStaleness: &pbd.Duration{Seconds: 10}}, 179 ReturnReadTimestamp: true, 180 }, 181 }, 182 183 { 184 MinReadTimestamp(ts), true, 185 sppb.TransactionOptions_ReadOnly{ 186 TimestampBound: &sppb.TransactionOptions_ReadOnly_MinReadTimestamp{ 187 MinReadTimestamp: &pbt.Timestamp{Seconds: 1136239445, Nanos: 12345}}, 188 ReturnReadTimestamp: true, 189 }, 190 }, 191 { 192 ReadTimestamp(ts), true, 193 sppb.TransactionOptions_ReadOnly{ 194 TimestampBound: &sppb.TransactionOptions_ReadOnly_ReadTimestamp{ 195 ReadTimestamp: &pbt.Timestamp{Seconds: 1136239445, Nanos: 12345}}, 196 ReturnReadTimestamp: true, 197 }, 198 }, 199 } 200 for _, test := range tests { 201 got := buildTransactionOptionsReadOnly(test.tb, test.ts) 202 if !testEqual(got, &test.want) { 203 t.Errorf("buildTransactionOptionsReadOnly(%v,%v) = %v; want %v", test.tb, test.ts, got, test.want) 204 } 205 } 206} 207