query_test.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. // Copyright 2014 Google Inc. All Rights Reserved.
  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 datastore
  15. import (
  16. "errors"
  17. "fmt"
  18. "reflect"
  19. "testing"
  20. "github.com/golang/protobuf/proto"
  21. "golang.org/x/net/context"
  22. pb "google.golang.org/cloud/internal/datastore"
  23. )
  24. var (
  25. key1 = &pb.Key{
  26. PathElement: []*pb.Key_PathElement{
  27. {
  28. Kind: proto.String("Gopher"),
  29. Id: proto.Int64(6),
  30. },
  31. },
  32. }
  33. key2 = &pb.Key{
  34. PathElement: []*pb.Key_PathElement{
  35. {
  36. Kind: proto.String("Gopher"),
  37. Id: proto.Int64(6),
  38. },
  39. {
  40. Kind: proto.String("Gopher"),
  41. Id: proto.Int64(8),
  42. },
  43. },
  44. }
  45. )
  46. type fakeClient func(req, resp proto.Message) (err error)
  47. func (c fakeClient) Call(ctx context.Context, method string, req, resp proto.Message) error {
  48. return c(req, resp)
  49. }
  50. func fakeRunQuery(in *pb.RunQueryRequest, out *pb.RunQueryResponse) error {
  51. expectedIn := &pb.RunQueryRequest{
  52. Query: &pb.Query{
  53. Kind: []*pb.KindExpression{&pb.KindExpression{Name: proto.String("Gopher")}},
  54. },
  55. }
  56. if !proto.Equal(in, expectedIn) {
  57. return fmt.Errorf("unsupported argument: got %v want %v", in, expectedIn)
  58. }
  59. *out = pb.RunQueryResponse{
  60. Batch: &pb.QueryResultBatch{
  61. MoreResults: pb.QueryResultBatch_NO_MORE_RESULTS.Enum(),
  62. EntityResultType: pb.EntityResult_FULL.Enum(),
  63. EntityResult: []*pb.EntityResult{
  64. &pb.EntityResult{
  65. Entity: &pb.Entity{
  66. Key: key1,
  67. Property: []*pb.Property{
  68. {
  69. Name: proto.String("Name"),
  70. Value: &pb.Value{StringValue: proto.String("George")},
  71. },
  72. {
  73. Name: proto.String("Height"),
  74. Value: &pb.Value{
  75. IntegerValue: proto.Int64(32),
  76. },
  77. },
  78. },
  79. },
  80. },
  81. &pb.EntityResult{
  82. Entity: &pb.Entity{
  83. Key: key2,
  84. Property: []*pb.Property{
  85. {
  86. Name: proto.String("Name"),
  87. Value: &pb.Value{StringValue: proto.String("Rufus")},
  88. },
  89. // No height for Rufus.
  90. },
  91. },
  92. },
  93. },
  94. },
  95. }
  96. return nil
  97. }
  98. type StructThatImplementsPLS struct{}
  99. func (StructThatImplementsPLS) Load(p []Property) error { return nil }
  100. func (StructThatImplementsPLS) Save() ([]Property, error) { return nil, nil }
  101. var _ PropertyLoadSaver = StructThatImplementsPLS{}
  102. type StructPtrThatImplementsPLS struct{}
  103. func (*StructPtrThatImplementsPLS) Load(p []Property) error { return nil }
  104. func (*StructPtrThatImplementsPLS) Save() ([]Property, error) { return nil, nil }
  105. var _ PropertyLoadSaver = &StructPtrThatImplementsPLS{}
  106. type PropertyMap map[string]Property
  107. func (m PropertyMap) Load(props []Property) error {
  108. for _, p := range props {
  109. m[p.Name] = p
  110. }
  111. return nil
  112. }
  113. func (m PropertyMap) Save() ([]Property, error) {
  114. props := make([]Property, 0, len(m))
  115. for _, p := range m {
  116. props = append(props, p)
  117. }
  118. return props, nil
  119. }
  120. var _ PropertyLoadSaver = PropertyMap{}
  121. type Gopher struct {
  122. Name string
  123. Height int
  124. }
  125. // typeOfEmptyInterface is the type of interface{}, but we can't use
  126. // reflect.TypeOf((interface{})(nil)) directly because TypeOf takes an
  127. // interface{}.
  128. var typeOfEmptyInterface = reflect.TypeOf((*interface{})(nil)).Elem()
  129. func TestCheckMultiArg(t *testing.T) {
  130. testCases := []struct {
  131. v interface{}
  132. mat multiArgType
  133. elemType reflect.Type
  134. }{
  135. // Invalid cases.
  136. {nil, multiArgTypeInvalid, nil},
  137. {Gopher{}, multiArgTypeInvalid, nil},
  138. {&Gopher{}, multiArgTypeInvalid, nil},
  139. {PropertyList{}, multiArgTypeInvalid, nil}, // This is a special case.
  140. {PropertyMap{}, multiArgTypeInvalid, nil},
  141. {[]*PropertyList(nil), multiArgTypeInvalid, nil},
  142. {[]*PropertyMap(nil), multiArgTypeInvalid, nil},
  143. {[]**Gopher(nil), multiArgTypeInvalid, nil},
  144. {[]*interface{}(nil), multiArgTypeInvalid, nil},
  145. // Valid cases.
  146. {
  147. []PropertyList(nil),
  148. multiArgTypePropertyLoadSaver,
  149. reflect.TypeOf(PropertyList{}),
  150. },
  151. {
  152. []PropertyMap(nil),
  153. multiArgTypePropertyLoadSaver,
  154. reflect.TypeOf(PropertyMap{}),
  155. },
  156. {
  157. []StructThatImplementsPLS(nil),
  158. multiArgTypePropertyLoadSaver,
  159. reflect.TypeOf(StructThatImplementsPLS{}),
  160. },
  161. {
  162. []StructPtrThatImplementsPLS(nil),
  163. multiArgTypePropertyLoadSaver,
  164. reflect.TypeOf(StructPtrThatImplementsPLS{}),
  165. },
  166. {
  167. []Gopher(nil),
  168. multiArgTypeStruct,
  169. reflect.TypeOf(Gopher{}),
  170. },
  171. {
  172. []*Gopher(nil),
  173. multiArgTypeStructPtr,
  174. reflect.TypeOf(Gopher{}),
  175. },
  176. {
  177. []interface{}(nil),
  178. multiArgTypeInterface,
  179. typeOfEmptyInterface,
  180. },
  181. }
  182. for _, tc := range testCases {
  183. mat, elemType := checkMultiArg(reflect.ValueOf(tc.v))
  184. if mat != tc.mat || elemType != tc.elemType {
  185. t.Errorf("checkMultiArg(%T): got %v, %v want %v, %v",
  186. tc.v, mat, elemType, tc.mat, tc.elemType)
  187. }
  188. }
  189. }
  190. func TestSimpleQuery(t *testing.T) {
  191. struct1 := Gopher{Name: "George", Height: 32}
  192. struct2 := Gopher{Name: "Rufus"}
  193. pList1 := PropertyList{
  194. {
  195. Name: "Name",
  196. Value: "George",
  197. },
  198. {
  199. Name: "Height",
  200. Value: int64(32),
  201. },
  202. }
  203. pList2 := PropertyList{
  204. {
  205. Name: "Name",
  206. Value: "Rufus",
  207. },
  208. }
  209. pMap1 := PropertyMap{
  210. "Name": Property{
  211. Name: "Name",
  212. Value: "George",
  213. },
  214. "Height": Property{
  215. Name: "Height",
  216. Value: int64(32),
  217. },
  218. }
  219. pMap2 := PropertyMap{
  220. "Name": Property{
  221. Name: "Name",
  222. Value: "Rufus",
  223. },
  224. }
  225. testCases := []struct {
  226. dst interface{}
  227. want interface{}
  228. }{
  229. // The destination must have type *[]P, *[]S or *[]*S, for some non-interface
  230. // type P such that *P implements PropertyLoadSaver, or for some struct type S.
  231. {new([]Gopher), &[]Gopher{struct1, struct2}},
  232. {new([]*Gopher), &[]*Gopher{&struct1, &struct2}},
  233. {new([]PropertyList), &[]PropertyList{pList1, pList2}},
  234. {new([]PropertyMap), &[]PropertyMap{pMap1, pMap2}},
  235. // Any other destination type is invalid.
  236. {0, nil},
  237. {Gopher{}, nil},
  238. {PropertyList{}, nil},
  239. {PropertyMap{}, nil},
  240. {[]int{}, nil},
  241. {[]Gopher{}, nil},
  242. {[]PropertyList{}, nil},
  243. {new(int), nil},
  244. {new(Gopher), nil},
  245. {new(PropertyList), nil}, // This is a special case.
  246. {new(PropertyMap), nil},
  247. {new([]int), nil},
  248. {new([]map[int]int), nil},
  249. {new([]map[string]Property), nil},
  250. {new([]map[string]interface{}), nil},
  251. {new([]*int), nil},
  252. {new([]*map[int]int), nil},
  253. {new([]*map[string]Property), nil},
  254. {new([]*map[string]interface{}), nil},
  255. {new([]**Gopher), nil},
  256. {new([]*PropertyList), nil},
  257. {new([]*PropertyMap), nil},
  258. }
  259. for _, tc := range testCases {
  260. nCall := 0
  261. client := &Client{
  262. client: fakeClient(func(in, out proto.Message) error {
  263. nCall++
  264. return fakeRunQuery(in.(*pb.RunQueryRequest), out.(*pb.RunQueryResponse))
  265. }),
  266. }
  267. ctx := context.Background()
  268. var (
  269. expectedErr error
  270. expectedNCall int
  271. )
  272. if tc.want == nil {
  273. expectedErr = ErrInvalidEntityType
  274. } else {
  275. expectedNCall = 1
  276. }
  277. keys, err := client.GetAll(ctx, NewQuery("Gopher"), tc.dst)
  278. if err != expectedErr {
  279. t.Errorf("dst type %T: got error %v, want %v", tc.dst, err, expectedErr)
  280. continue
  281. }
  282. if nCall != expectedNCall {
  283. t.Errorf("dst type %T: Context.Call was called an incorrect number of times: got %d want %d", tc.dst, nCall, expectedNCall)
  284. continue
  285. }
  286. if err != nil {
  287. continue
  288. }
  289. key1 := NewKey(ctx, "Gopher", "", 6, nil)
  290. expectedKeys := []*Key{
  291. key1,
  292. NewKey(ctx, "Gopher", "", 8, key1),
  293. }
  294. if l1, l2 := len(keys), len(expectedKeys); l1 != l2 {
  295. t.Errorf("dst type %T: got %d keys, want %d keys", tc.dst, l1, l2)
  296. continue
  297. }
  298. for i, key := range keys {
  299. if !keysEqual(key, expectedKeys[i]) {
  300. t.Errorf("dst type %T: got key #%d %v, want %v", tc.dst, i, key, expectedKeys[i])
  301. continue
  302. }
  303. }
  304. if !reflect.DeepEqual(tc.dst, tc.want) {
  305. t.Errorf("dst type %T: Entities got %+v, want %+v", tc.dst, tc.dst, tc.want)
  306. continue
  307. }
  308. }
  309. }
  310. // keysEqual is like (*Key).Equal, but ignores the App ID.
  311. func keysEqual(a, b *Key) bool {
  312. for a != nil && b != nil {
  313. if a.Kind() != b.Kind() || a.Name() != b.Name() || a.ID() != b.ID() {
  314. return false
  315. }
  316. a, b = a.Parent(), b.Parent()
  317. }
  318. return a == b
  319. }
  320. func TestQueriesAreImmutable(t *testing.T) {
  321. // Test that deriving q2 from q1 does not modify q1.
  322. q0 := NewQuery("foo")
  323. q1 := NewQuery("foo")
  324. q2 := q1.Offset(2)
  325. if !reflect.DeepEqual(q0, q1) {
  326. t.Errorf("q0 and q1 were not equal")
  327. }
  328. if reflect.DeepEqual(q1, q2) {
  329. t.Errorf("q1 and q2 were equal")
  330. }
  331. // Test that deriving from q4 twice does not conflict, even though
  332. // q4 has a long list of order clauses. This tests that the arrays
  333. // backed by a query's slice of orders are not shared.
  334. f := func() *Query {
  335. q := NewQuery("bar")
  336. // 47 is an ugly number that is unlikely to be near a re-allocation
  337. // point in repeated append calls. For example, it's not near a power
  338. // of 2 or a multiple of 10.
  339. for i := 0; i < 47; i++ {
  340. q = q.Order(fmt.Sprintf("x%d", i))
  341. }
  342. return q
  343. }
  344. q3 := f().Order("y")
  345. q4 := f()
  346. q5 := q4.Order("y")
  347. q6 := q4.Order("z")
  348. if !reflect.DeepEqual(q3, q5) {
  349. t.Errorf("q3 and q5 were not equal")
  350. }
  351. if reflect.DeepEqual(q5, q6) {
  352. t.Errorf("q5 and q6 were equal")
  353. }
  354. }
  355. func TestFilterParser(t *testing.T) {
  356. testCases := []struct {
  357. filterStr string
  358. wantOK bool
  359. wantFieldName string
  360. wantOp operator
  361. }{
  362. // Supported ops.
  363. {"x<", true, "x", lessThan},
  364. {"x <", true, "x", lessThan},
  365. {"x <", true, "x", lessThan},
  366. {" x < ", true, "x", lessThan},
  367. {"x <=", true, "x", lessEq},
  368. {"x =", true, "x", equal},
  369. {"x >=", true, "x", greaterEq},
  370. {"x >", true, "x", greaterThan},
  371. {"in >", true, "in", greaterThan},
  372. {"in>", true, "in", greaterThan},
  373. // Valid but (currently) unsupported ops.
  374. {"x!=", false, "", 0},
  375. {"x !=", false, "", 0},
  376. {" x != ", false, "", 0},
  377. {"x IN", false, "", 0},
  378. {"x in", false, "", 0},
  379. // Invalid ops.
  380. {"x EQ", false, "", 0},
  381. {"x lt", false, "", 0},
  382. {"x <>", false, "", 0},
  383. {"x >>", false, "", 0},
  384. {"x ==", false, "", 0},
  385. {"x =<", false, "", 0},
  386. {"x =>", false, "", 0},
  387. {"x !", false, "", 0},
  388. {"x ", false, "", 0},
  389. {"x", false, "", 0},
  390. // Quoted and interesting field names.
  391. {"x > y =", true, "x > y", equal},
  392. {"` x ` =", true, " x ", equal},
  393. {`" x " =`, true, " x ", equal},
  394. {`" \"x " =`, true, ` "x `, equal},
  395. {`" x =`, false, "", 0},
  396. {`" x ="`, false, "", 0},
  397. {"` x \" =", false, "", 0},
  398. }
  399. for _, tc := range testCases {
  400. q := NewQuery("foo").Filter(tc.filterStr, 42)
  401. if ok := q.err == nil; ok != tc.wantOK {
  402. t.Errorf("%q: ok=%t, want %t", tc.filterStr, ok, tc.wantOK)
  403. continue
  404. }
  405. if !tc.wantOK {
  406. continue
  407. }
  408. if len(q.filter) != 1 {
  409. t.Errorf("%q: len=%d, want %d", tc.filterStr, len(q.filter), 1)
  410. continue
  411. }
  412. got, want := q.filter[0], filter{tc.wantFieldName, tc.wantOp, 42}
  413. if got != want {
  414. t.Errorf("%q: got %v, want %v", tc.filterStr, got, want)
  415. continue
  416. }
  417. }
  418. }
  419. func TestNamespaceQuery(t *testing.T) {
  420. gotNamespace := make(chan string, 1)
  421. ctx := context.Background()
  422. client := &Client{
  423. client: fakeClient(func(req, resp proto.Message) error {
  424. gotNamespace <- req.(*pb.RunQueryRequest).GetPartitionId().GetNamespace()
  425. return errors.New("not implemented")
  426. }),
  427. }
  428. var gs []Gopher
  429. client.GetAll(ctx, NewQuery("gopher"), &gs)
  430. if got, want := <-gotNamespace, ""; got != want {
  431. t.Errorf("GetAll: got namespace %q, want %q", got, want)
  432. }
  433. client.Count(ctx, NewQuery("gopher"))
  434. if got, want := <-gotNamespace, ""; got != want {
  435. t.Errorf("Count: got namespace %q, want %q", got, want)
  436. }
  437. const ns = "not_default"
  438. ctx = WithNamespace(ctx, ns)
  439. client.GetAll(ctx, NewQuery("gopher"), &gs)
  440. if got, want := <-gotNamespace, ns; got != want {
  441. t.Errorf("GetAll: got namespace %q, want %q", got, want)
  442. }
  443. client.Count(ctx, NewQuery("gopher"))
  444. if got, want := <-gotNamespace, ns; got != want {
  445. t.Errorf("Count: got namespace %q, want %q", got, want)
  446. }
  447. }