You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

233 lines
5.0 KiB

  1. // Copyright 2017 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. package firestore
  15. import (
  16. "reflect"
  17. "strings"
  18. "testing"
  19. "cloud.google.com/go/internal/testutil"
  20. )
  21. func TestFieldPathValidate(t *testing.T) {
  22. for _, in := range [][]string{nil, {}, {"a", "", "b"}} {
  23. if err := FieldPath(in).validate(); err == nil {
  24. t.Errorf("%v: want error, got nil", in)
  25. }
  26. }
  27. }
  28. func TestFieldPathLess(t *testing.T) {
  29. for _, test := range []struct {
  30. in1, in2 string
  31. want bool
  32. }{
  33. {"a b", "a b", false},
  34. {"a", "b", true},
  35. {"b", "a", false},
  36. {"a", "a b", true},
  37. {"a b", "a", false},
  38. {"a b c", "a b d", true},
  39. {"a b d", "a b c", false},
  40. } {
  41. fp1 := FieldPath(strings.Fields(test.in1))
  42. fp2 := FieldPath(strings.Fields(test.in2))
  43. got := fp1.less(fp2)
  44. if got != test.want {
  45. t.Errorf("%q.less(%q): got %t, want %t", test.in1, test.in2, got, test.want)
  46. }
  47. }
  48. }
  49. func TestCheckForPrefix(t *testing.T) {
  50. for _, test := range []struct {
  51. in []string // field paths as space-separated strings
  52. wantErr bool
  53. }{
  54. {in: []string{"a", "b", "c"}, wantErr: false},
  55. {in: []string{"a b", "b", "c d"}, wantErr: false},
  56. {in: []string{"a b", "a c", "a d"}, wantErr: false},
  57. {in: []string{"a b", "b", "b d"}, wantErr: true},
  58. {in: []string{"a b", "b", "b d"}, wantErr: true},
  59. {in: []string{"b c d", "c d", "b c"}, wantErr: true},
  60. } {
  61. var fps []FieldPath
  62. for _, s := range test.in {
  63. fps = append(fps, strings.Fields(s))
  64. }
  65. err := checkNoDupOrPrefix(fps)
  66. if got, want := (err != nil), test.wantErr; got != want {
  67. t.Errorf("%#v: got '%v', want %t", test.in, err, want)
  68. }
  69. }
  70. }
  71. func TestGetAtPath(t *testing.T) {
  72. type S struct {
  73. X int
  74. Y int `firestore:"y"`
  75. M map[string]interface{}
  76. Next *S
  77. }
  78. const fail = "ERROR" // value for expected error
  79. for _, test := range []struct {
  80. val interface{}
  81. fp FieldPath
  82. want interface{}
  83. }{
  84. {
  85. val: map[string]int(nil),
  86. fp: nil,
  87. want: map[string]int(nil),
  88. },
  89. {
  90. val: 1,
  91. fp: nil,
  92. want: 1,
  93. },
  94. {
  95. val: 1,
  96. fp: []string{"a"},
  97. want: fail,
  98. },
  99. {
  100. val: map[string]int{"a": 2},
  101. fp: []string{"a"},
  102. want: 2,
  103. },
  104. {
  105. val: map[string]int{"a": 2},
  106. fp: []string{"b"},
  107. want: fail,
  108. },
  109. {
  110. val: map[string]interface{}{"a": map[string]int{"b": 3}},
  111. fp: []string{"a", "b"},
  112. want: 3,
  113. },
  114. {
  115. val: map[string]interface{}{"a": map[string]int{"b": 3}},
  116. fp: []string{"a", "b", "c"},
  117. want: fail,
  118. },
  119. {
  120. val: S{X: 1, Y: 2},
  121. fp: nil,
  122. want: S{X: 1, Y: 2},
  123. },
  124. {
  125. val: S{X: 1, Y: 2},
  126. fp: []string{"X"},
  127. want: 1,
  128. },
  129. {
  130. val: S{X: 1, Y: 2},
  131. fp: []string{"Y"},
  132. want: fail, // because Y is tagged with name "y"
  133. },
  134. {
  135. val: S{X: 1, Y: 2},
  136. fp: []string{"y"},
  137. want: 2,
  138. },
  139. {
  140. val: &S{X: 1},
  141. fp: []string{"X"},
  142. want: 1,
  143. },
  144. {
  145. val: &S{X: 1, Next: nil},
  146. fp: []string{"Next"},
  147. want: (*S)(nil),
  148. },
  149. {
  150. val: &S{X: 1, Next: nil},
  151. fp: []string{"Next", "Next"},
  152. want: fail,
  153. },
  154. {
  155. val: map[string]S{"a": {X: 1, Y: 2}},
  156. fp: []string{"a", "y"},
  157. want: 2,
  158. },
  159. {
  160. val: map[string]S{"a": {X: 1, Y: 2}},
  161. fp: []string{"a", "z"},
  162. want: fail,
  163. },
  164. {
  165. val: map[string]*S{
  166. "a": {
  167. M: map[string]interface{}{
  168. "b": S{
  169. Next: &S{
  170. X: 17,
  171. },
  172. },
  173. },
  174. },
  175. },
  176. fp: []string{"a", "M", "b", "Next", "X"},
  177. want: 17,
  178. },
  179. } {
  180. got, err := getAtPath(reflect.ValueOf(test.val), test.fp)
  181. if err != nil && test.want != fail {
  182. t.Errorf("%+v: got error <%v>, want nil", test, err)
  183. }
  184. if err == nil && !testutil.Equal(got, test.want) {
  185. t.Errorf("%+v: got %v, want %v, want nil", test, got, test.want)
  186. }
  187. }
  188. }
  189. func TestToServiceFieldPath(t *testing.T) {
  190. for _, test := range []struct {
  191. in FieldPath
  192. want string
  193. }{
  194. {[]string{"a"}, "a"},
  195. {[]string{"a", "b"}, "a.b"},
  196. {[]string{"a.", "[b*", "c2"}, "`a.`.`[b*`.c2"},
  197. {[]string{"`a", `b\`}, "`\\`a`.`b\\\\`"},
  198. } {
  199. got := test.in.toServiceFieldPath()
  200. if got != test.want {
  201. t.Errorf("%v: got %s, want %s", test.in, got, test.want)
  202. }
  203. }
  204. }
  205. func TestToServiceFieldPathComponent(t *testing.T) {
  206. for _, test := range []struct {
  207. in, want string
  208. }{
  209. {"", "``"},
  210. {"clam_chowder23", "clam_chowder23"},
  211. {"23skidoo", "`23skidoo`"},
  212. {"bak`tik", "`bak\\`tik`"},
  213. {"a\\b", "`a\\\\b`"},
  214. {"dots.are.confusing", "`dots.are.confusing`"},
  215. } {
  216. got := toServiceFieldPathComponent(test.in)
  217. if got != test.want {
  218. t.Errorf("%q: got %q, want %q", test.in, got, test.want)
  219. }
  220. }
  221. }