1// Copyright 2016 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
15package main
16
17import (
18	"testing"
19	"time"
20
21	"cloud.google.com/go/bigtable"
22	"cloud.google.com/go/internal/testutil"
23	"github.com/google/go-cmp/cmp"
24)
25
26func TestParseDuration(t *testing.T) {
27	tests := []struct {
28		in string
29		// out or fail are mutually exclusive
30		out  time.Duration
31		fail bool
32	}{
33		{in: "10ms", out: 10 * time.Millisecond},
34		{in: "3s", out: 3 * time.Second},
35		{in: "60m", out: 60 * time.Minute},
36		{in: "12h", out: 12 * time.Hour},
37		{in: "7d", out: 168 * time.Hour},
38
39		{in: "", fail: true},
40		{in: "0", fail: true},
41		{in: "7ns", fail: true},
42		{in: "14mo", fail: true},
43		{in: "3.5h", fail: true},
44		{in: "106752d", fail: true}, // overflow
45	}
46	for _, tc := range tests {
47		got, err := parseDuration(tc.in)
48		if !tc.fail && err != nil {
49			t.Errorf("parseDuration(%q) unexpectedly failed: %v", tc.in, err)
50			continue
51		}
52		if tc.fail && err == nil {
53			t.Errorf("parseDuration(%q) did not fail", tc.in)
54			continue
55		}
56		if tc.fail {
57			continue
58		}
59		if got != tc.out {
60			t.Errorf("parseDuration(%q) = %v, want %v", tc.in, got, tc.out)
61		}
62	}
63}
64
65func TestParseArgs(t *testing.T) {
66	got, err := parseArgs([]string{"a=1", "b=2"}, []string{"a", "b"})
67	if err != nil {
68		t.Fatal(err)
69	}
70	want := map[string]string{"a": "1", "b": "2"}
71	if !testutil.Equal(got, want) {
72		t.Fatalf("got %v, want %v", got, want)
73	}
74
75	if _, err := parseArgs([]string{"a1"}, []string{"a1"}); err == nil {
76		t.Error("malformed: got nil, want error")
77	}
78	if _, err := parseArgs([]string{"a=1"}, []string{"b"}); err == nil {
79		t.Error("invalid: got nil, want error")
80	}
81}
82
83func TestParseColumnsFilter(t *testing.T) {
84	tests := []struct {
85		in   string
86		out  bigtable.Filter
87		fail bool
88	}{
89		{
90			in:  "columnA",
91			out: bigtable.ColumnFilter("columnA"),
92		},
93		{
94			in:  "familyA:columnA",
95			out: bigtable.ChainFilters(bigtable.FamilyFilter("familyA"), bigtable.ColumnFilter("columnA")),
96		},
97		{
98			in:  "columnA,columnB",
99			out: bigtable.InterleaveFilters(bigtable.ColumnFilter("columnA"), bigtable.ColumnFilter("columnB")),
100		},
101		{
102			in: "familyA:columnA,columnB",
103			out: bigtable.InterleaveFilters(
104				bigtable.ChainFilters(bigtable.FamilyFilter("familyA"), bigtable.ColumnFilter("columnA")),
105				bigtable.ColumnFilter("columnB"),
106			),
107		},
108		{
109			in: "columnA,familyB:columnB",
110			out: bigtable.InterleaveFilters(
111				bigtable.ColumnFilter("columnA"),
112				bigtable.ChainFilters(bigtable.FamilyFilter("familyB"), bigtable.ColumnFilter("columnB")),
113			),
114		},
115		{
116			in: "familyA:columnA,familyB:columnB",
117			out: bigtable.InterleaveFilters(
118				bigtable.ChainFilters(bigtable.FamilyFilter("familyA"), bigtable.ColumnFilter("columnA")),
119				bigtable.ChainFilters(bigtable.FamilyFilter("familyB"), bigtable.ColumnFilter("columnB")),
120			),
121		},
122		{
123			in:  "familyA:",
124			out: bigtable.FamilyFilter("familyA"),
125		},
126		{
127			in:  ":columnA",
128			out: bigtable.ColumnFilter("columnA"),
129		},
130		{
131			in: ",:columnA,,familyB:columnB,",
132			out: bigtable.InterleaveFilters(
133				bigtable.ColumnFilter("columnA"),
134				bigtable.ChainFilters(bigtable.FamilyFilter("familyB"), bigtable.ColumnFilter("columnB")),
135			),
136		},
137		{
138			in:   "familyA:columnA:cellA",
139			fail: true,
140		},
141		{
142			in:   "familyA::columnA",
143			fail: true,
144		},
145	}
146
147	for _, tc := range tests {
148		got, err := parseColumnsFilter(tc.in)
149
150		if !tc.fail && err != nil {
151			t.Errorf("parseColumnsFilter(%q) unexpectedly failed: %v", tc.in, err)
152			continue
153		}
154		if tc.fail && err == nil {
155			t.Errorf("parseColumnsFilter(%q) did not fail", tc.in)
156			continue
157		}
158		if tc.fail {
159			continue
160		}
161
162		var cmpOpts cmp.Options
163		cmpOpts =
164			append(
165				cmpOpts,
166				cmp.AllowUnexported(bigtable.ChainFilters([]bigtable.Filter{}...)),
167				cmp.AllowUnexported(bigtable.InterleaveFilters([]bigtable.Filter{}...)))
168
169		if !cmp.Equal(got, tc.out, cmpOpts) {
170			t.Errorf("parseColumnsFilter(%q) = %v, want %v", tc.in, got, tc.out)
171		}
172	}
173}
174