datastore_test.go 72 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563
  1. // Copyright 2014 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 datastore
  15. import (
  16. "context"
  17. "encoding/json"
  18. "errors"
  19. "fmt"
  20. "reflect"
  21. "sort"
  22. "strings"
  23. "testing"
  24. "time"
  25. "cloud.google.com/go/internal/testutil"
  26. "github.com/golang/protobuf/proto"
  27. "github.com/google/go-cmp/cmp"
  28. pb "google.golang.org/genproto/googleapis/datastore/v1"
  29. "google.golang.org/grpc"
  30. )
  31. type (
  32. myBlob []byte
  33. myByte byte
  34. myString string
  35. )
  36. func makeMyByteSlice(n int) []myByte {
  37. b := make([]myByte, n)
  38. for i := range b {
  39. b[i] = myByte(i)
  40. }
  41. return b
  42. }
  43. func makeInt8Slice(n int) []int8 {
  44. b := make([]int8, n)
  45. for i := range b {
  46. b[i] = int8(i)
  47. }
  48. return b
  49. }
  50. func makeUint8Slice(n int) []uint8 {
  51. b := make([]uint8, n)
  52. for i := range b {
  53. b[i] = uint8(i)
  54. }
  55. return b
  56. }
  57. func newKey(stringID string, parent *Key) *Key {
  58. return NameKey("kind", stringID, parent)
  59. }
  60. var (
  61. testKey0 = newKey("name0", nil)
  62. testKey1a = newKey("name1", nil)
  63. testKey1b = newKey("name1", nil)
  64. testKey2a = newKey("name2", testKey0)
  65. testKey2b = newKey("name2", testKey0)
  66. testGeoPt0 = GeoPoint{Lat: 1.2, Lng: 3.4}
  67. testGeoPt1 = GeoPoint{Lat: 5, Lng: 10}
  68. testBadGeoPt = GeoPoint{Lat: 1000, Lng: 34}
  69. ts = time.Unix(1e9, 0).UTC()
  70. )
  71. type B0 struct {
  72. B []byte `datastore:",noindex"`
  73. }
  74. type B1 struct {
  75. B []int8
  76. }
  77. type B2 struct {
  78. B myBlob `datastore:",noindex"`
  79. }
  80. type B3 struct {
  81. B []myByte `datastore:",noindex"`
  82. }
  83. type B4 struct {
  84. B [][]byte
  85. }
  86. type C0 struct {
  87. I int
  88. C chan int
  89. }
  90. type C1 struct {
  91. I int
  92. C *chan int
  93. }
  94. type C2 struct {
  95. I int
  96. C []chan int
  97. }
  98. type C3 struct {
  99. C string
  100. }
  101. type c4 struct {
  102. C string
  103. }
  104. type E struct{}
  105. type G0 struct {
  106. G GeoPoint
  107. }
  108. type G1 struct {
  109. G []GeoPoint
  110. }
  111. type K0 struct {
  112. K *Key
  113. }
  114. type K1 struct {
  115. K []*Key
  116. }
  117. type S struct {
  118. St string
  119. }
  120. type NoOmit struct {
  121. A string
  122. B int `datastore:"Bb"`
  123. C bool `datastore:",noindex"`
  124. }
  125. type OmitAll struct {
  126. A string `datastore:",omitempty"`
  127. B int `datastore:"Bb,omitempty"`
  128. C bool `datastore:",omitempty,noindex"`
  129. D time.Time `datastore:",omitempty"`
  130. F []int `datastore:",omitempty"`
  131. }
  132. type Omit struct {
  133. A string `datastore:",omitempty"`
  134. B int `datastore:"Bb,omitempty"`
  135. C bool `datastore:",omitempty,noindex"`
  136. D time.Time `datastore:",omitempty"`
  137. F []int `datastore:",omitempty"`
  138. S `datastore:",omitempty"`
  139. }
  140. type NoOmits struct {
  141. No []NoOmit `datastore:",omitempty"`
  142. S `datastore:",omitempty"`
  143. Ss S `datastore:",omitempty"`
  144. }
  145. type N0 struct {
  146. X0
  147. Nonymous X0
  148. Ignore string `datastore:"-"`
  149. Other string
  150. }
  151. type N1 struct {
  152. X0
  153. Nonymous []X0
  154. Ignore string `datastore:"-"`
  155. Other string
  156. }
  157. type N2 struct {
  158. N1 `datastore:"red"`
  159. Green N1 `datastore:"green"`
  160. Blue N1
  161. White N1 `datastore:"-"`
  162. }
  163. type N3 struct {
  164. C3 `datastore:"red"`
  165. }
  166. type N4 struct {
  167. c4
  168. }
  169. type N5 struct {
  170. c4 `datastore:"red"`
  171. }
  172. type O0 struct {
  173. I int64
  174. }
  175. type O1 struct {
  176. I int32
  177. }
  178. type U0 struct {
  179. U uint
  180. }
  181. type U1 struct {
  182. U string
  183. }
  184. type T struct {
  185. T time.Time
  186. }
  187. type X0 struct {
  188. S string
  189. I int
  190. i int
  191. }
  192. type X1 struct {
  193. S myString
  194. I int32
  195. J int64
  196. }
  197. type X2 struct {
  198. Z string
  199. }
  200. type X3 struct {
  201. S bool
  202. I int
  203. }
  204. type Y0 struct {
  205. B bool
  206. F []float64
  207. G []float64
  208. }
  209. type Y1 struct {
  210. B bool
  211. F float64
  212. }
  213. type Y2 struct {
  214. B bool
  215. F []int64
  216. }
  217. type Pointers struct {
  218. Pi *int
  219. Ps *string
  220. Pb *bool
  221. Pf *float64
  222. Pg *GeoPoint
  223. Pt *time.Time
  224. }
  225. type PointersOmitEmpty struct {
  226. Pi *int `datastore:",omitempty"`
  227. Ps *string `datastore:",omitempty"`
  228. Pb *bool `datastore:",omitempty"`
  229. Pf *float64 `datastore:",omitempty"`
  230. Pg *GeoPoint `datastore:",omitempty"`
  231. Pt *time.Time `datastore:",omitempty"`
  232. }
  233. func populatedPointers() *Pointers {
  234. var (
  235. i int
  236. s string
  237. b bool
  238. f float64
  239. g GeoPoint
  240. t time.Time
  241. )
  242. return &Pointers{
  243. Pi: &i,
  244. Ps: &s,
  245. Pb: &b,
  246. Pf: &f,
  247. Pg: &g,
  248. Pt: &t,
  249. }
  250. }
  251. type Tagged struct {
  252. A int `datastore:"a,noindex"`
  253. B []int `datastore:"b"`
  254. C int `datastore:",noindex"`
  255. D int `datastore:""`
  256. E int
  257. I int `datastore:"-"`
  258. J int `datastore:",noindex" json:"j"`
  259. Y0 `datastore:"-"`
  260. Z chan int `datastore:"-"`
  261. }
  262. type InvalidTagged1 struct {
  263. I int `datastore:"\t"`
  264. }
  265. type InvalidTagged2 struct {
  266. I int
  267. J int `datastore:"I"`
  268. }
  269. type InvalidTagged3 struct {
  270. X string `datastore:"-,noindex"`
  271. }
  272. type InvalidTagged4 struct {
  273. X string `datastore:",garbage"`
  274. }
  275. type Inner1 struct {
  276. W int32
  277. X string
  278. }
  279. type Inner2 struct {
  280. Y float64
  281. }
  282. type Inner3 struct {
  283. Z bool
  284. }
  285. type Inner5 struct {
  286. WW int
  287. }
  288. type Inner4 struct {
  289. X Inner5
  290. }
  291. type Outer struct {
  292. A int16
  293. I []Inner1
  294. J Inner2
  295. Inner3
  296. }
  297. type OuterFlatten struct {
  298. A int16
  299. I []Inner1 `datastore:",flatten"`
  300. J Inner2 `datastore:",flatten,noindex"`
  301. Inner3 `datastore:",flatten"`
  302. K Inner4 `datastore:",flatten"`
  303. }
  304. type OuterEquivalent struct {
  305. A int16
  306. IDotW []int32 `datastore:"I.W"`
  307. IDotX []string `datastore:"I.X"`
  308. JDotY float64 `datastore:"J.Y"`
  309. Z bool
  310. }
  311. type Dotted struct {
  312. A DottedA `datastore:"A0.A1.A2"`
  313. }
  314. type DottedA struct {
  315. B DottedB `datastore:"B3"`
  316. }
  317. type DottedB struct {
  318. C int `datastore:"C4.C5"`
  319. }
  320. type SliceOfSlices struct {
  321. I int
  322. S []struct {
  323. J int
  324. F []float64
  325. } `datastore:",flatten"`
  326. }
  327. type Recursive struct {
  328. I int
  329. R []Recursive
  330. }
  331. type MutuallyRecursive0 struct {
  332. I int
  333. R []MutuallyRecursive1
  334. }
  335. type MutuallyRecursive1 struct {
  336. I int
  337. R []MutuallyRecursive0
  338. }
  339. type EntityWithKey struct {
  340. I int
  341. S string
  342. K *Key `datastore:"__key__"`
  343. }
  344. type WithNestedEntityWithKey struct {
  345. N EntityWithKey
  346. }
  347. type WithNonKeyField struct {
  348. I int
  349. K string `datastore:"__key__"`
  350. }
  351. type NestedWithNonKeyField struct {
  352. N WithNonKeyField
  353. }
  354. type Basic struct {
  355. A string
  356. }
  357. type PtrToStructField struct {
  358. B *Basic
  359. C *Basic `datastore:"c,noindex"`
  360. *Basic
  361. D []*Basic
  362. }
  363. type EmbeddedTime struct {
  364. time.Time
  365. }
  366. type SpecialTime struct {
  367. MyTime EmbeddedTime
  368. }
  369. type Doubler struct {
  370. S string
  371. I int64
  372. B bool
  373. }
  374. type Repeat struct {
  375. Key string
  376. Value []byte
  377. }
  378. type Repeated struct {
  379. Repeats []Repeat
  380. }
  381. func (d *Doubler) Load(props []Property) error {
  382. return LoadStruct(d, props)
  383. }
  384. func (d *Doubler) Save() ([]Property, error) {
  385. // Save the default Property slice to an in-memory buffer (a PropertyList).
  386. props, err := SaveStruct(d)
  387. if err != nil {
  388. return nil, err
  389. }
  390. var list PropertyList
  391. if err := list.Load(props); err != nil {
  392. return nil, err
  393. }
  394. // Edit that PropertyList, and send it on.
  395. for i := range list {
  396. switch v := list[i].Value.(type) {
  397. case string:
  398. // + means string concatenation.
  399. list[i].Value = v + v
  400. case int64:
  401. // + means integer addition.
  402. list[i].Value = v + v
  403. }
  404. }
  405. return list.Save()
  406. }
  407. var _ PropertyLoadSaver = (*Doubler)(nil)
  408. type Deriver struct {
  409. S, Derived, Ignored string
  410. }
  411. func (e *Deriver) Load(props []Property) error {
  412. for _, p := range props {
  413. if p.Name != "S" {
  414. continue
  415. }
  416. e.S = p.Value.(string)
  417. e.Derived = "derived+" + e.S
  418. }
  419. return nil
  420. }
  421. func (e *Deriver) Save() ([]Property, error) {
  422. return []Property{
  423. {
  424. Name: "S",
  425. Value: e.S,
  426. },
  427. }, nil
  428. }
  429. var _ PropertyLoadSaver = (*Deriver)(nil)
  430. type BadMultiPropEntity struct{}
  431. func (e *BadMultiPropEntity) Load(props []Property) error {
  432. return errors.New("unimplemented")
  433. }
  434. func (e *BadMultiPropEntity) Save() ([]Property, error) {
  435. // Write multiple properties with the same name "I".
  436. var props []Property
  437. for i := 0; i < 3; i++ {
  438. props = append(props, Property{
  439. Name: "I",
  440. Value: int64(i),
  441. })
  442. }
  443. return props, nil
  444. }
  445. var _ PropertyLoadSaver = (*BadMultiPropEntity)(nil)
  446. type testCase struct {
  447. desc string
  448. src interface{}
  449. want interface{}
  450. putErr string
  451. getErr string
  452. }
  453. var testCases = []testCase{
  454. {
  455. "chan save fails",
  456. &C0{I: -1},
  457. &E{},
  458. "unsupported struct field",
  459. "",
  460. },
  461. {
  462. "*chan save fails",
  463. &C1{I: -1},
  464. &E{},
  465. "unsupported struct field",
  466. "",
  467. },
  468. {
  469. "[]chan save fails",
  470. &C2{I: -1, C: make([]chan int, 8)},
  471. &E{},
  472. "unsupported struct field",
  473. "",
  474. },
  475. {
  476. "chan load fails",
  477. &C3{C: "not a chan"},
  478. &C0{},
  479. "",
  480. "type mismatch",
  481. },
  482. {
  483. "*chan load fails",
  484. &C3{C: "not a *chan"},
  485. &C1{},
  486. "",
  487. "type mismatch",
  488. },
  489. {
  490. "[]chan load fails",
  491. &C3{C: "not a []chan"},
  492. &C2{},
  493. "",
  494. "type mismatch",
  495. },
  496. {
  497. "empty struct",
  498. &E{},
  499. &E{},
  500. "",
  501. "",
  502. },
  503. {
  504. "geopoint",
  505. &G0{G: testGeoPt0},
  506. &G0{G: testGeoPt0},
  507. "",
  508. "",
  509. },
  510. {
  511. "geopoint invalid",
  512. &G0{G: testBadGeoPt},
  513. &G0{},
  514. "invalid GeoPoint value",
  515. "",
  516. },
  517. {
  518. "geopoint as props",
  519. &G0{G: testGeoPt0},
  520. &PropertyList{
  521. Property{Name: "G", Value: testGeoPt0, NoIndex: false},
  522. },
  523. "",
  524. "",
  525. },
  526. {
  527. "geopoint slice",
  528. &G1{G: []GeoPoint{testGeoPt0, testGeoPt1}},
  529. &G1{G: []GeoPoint{testGeoPt0, testGeoPt1}},
  530. "",
  531. "",
  532. },
  533. {
  534. "omit empty, all",
  535. &OmitAll{},
  536. new(PropertyList),
  537. "",
  538. "",
  539. },
  540. {
  541. "omit empty",
  542. &Omit{},
  543. &PropertyList{
  544. Property{Name: "St", Value: "", NoIndex: false},
  545. },
  546. "",
  547. "",
  548. },
  549. {
  550. "omit empty, fields populated",
  551. &Omit{
  552. A: "a",
  553. B: 10,
  554. C: true,
  555. F: []int{11},
  556. },
  557. &PropertyList{
  558. Property{Name: "A", Value: "a", NoIndex: false},
  559. Property{Name: "Bb", Value: int64(10), NoIndex: false},
  560. Property{Name: "C", Value: true, NoIndex: true},
  561. Property{Name: "F", Value: []interface{}{int64(11)}, NoIndex: false},
  562. Property{Name: "St", Value: "", NoIndex: false},
  563. },
  564. "",
  565. "",
  566. },
  567. {
  568. "omit empty, fields populated",
  569. &Omit{
  570. A: "a",
  571. B: 10,
  572. C: true,
  573. F: []int{11},
  574. S: S{St: "string"},
  575. },
  576. &PropertyList{
  577. Property{Name: "A", Value: "a", NoIndex: false},
  578. Property{Name: "Bb", Value: int64(10), NoIndex: false},
  579. Property{Name: "C", Value: true, NoIndex: true},
  580. Property{Name: "F", Value: []interface{}{int64(11)}, NoIndex: false},
  581. Property{Name: "St", Value: "string", NoIndex: false},
  582. },
  583. "",
  584. "",
  585. },
  586. {
  587. "omit empty does not propagate",
  588. &NoOmits{
  589. No: []NoOmit{
  590. {},
  591. },
  592. S: S{},
  593. Ss: S{},
  594. },
  595. &PropertyList{
  596. Property{Name: "No", Value: []interface{}{
  597. &Entity{
  598. Properties: []Property{
  599. {Name: "A", Value: "", NoIndex: false},
  600. {Name: "Bb", Value: int64(0), NoIndex: false},
  601. {Name: "C", Value: false, NoIndex: true},
  602. },
  603. },
  604. }, NoIndex: false},
  605. Property{Name: "Ss", Value: &Entity{
  606. Properties: []Property{
  607. {Name: "St", Value: "", NoIndex: false},
  608. },
  609. }, NoIndex: false},
  610. Property{Name: "St", Value: "", NoIndex: false},
  611. },
  612. "",
  613. "",
  614. },
  615. {
  616. "key",
  617. &K0{K: testKey1a},
  618. &K0{K: testKey1b},
  619. "",
  620. "",
  621. },
  622. {
  623. "key with parent",
  624. &K0{K: testKey2a},
  625. &K0{K: testKey2b},
  626. "",
  627. "",
  628. },
  629. {
  630. "nil key",
  631. &K0{},
  632. &K0{},
  633. "",
  634. "",
  635. },
  636. {
  637. "all nil keys in slice",
  638. &K1{[]*Key{nil, nil}},
  639. &K1{[]*Key{nil, nil}},
  640. "",
  641. "",
  642. },
  643. {
  644. "some nil keys in slice",
  645. &K1{[]*Key{testKey1a, nil, testKey2a}},
  646. &K1{[]*Key{testKey1b, nil, testKey2b}},
  647. "",
  648. "",
  649. },
  650. {
  651. "overflow",
  652. &O0{I: 1 << 48},
  653. &O1{},
  654. "",
  655. "overflow",
  656. },
  657. {
  658. "time",
  659. &T{T: time.Unix(1e9, 0)},
  660. &T{T: time.Unix(1e9, 0)},
  661. "",
  662. "",
  663. },
  664. {
  665. "time as props",
  666. &T{T: time.Unix(1e9, 0)},
  667. &PropertyList{
  668. Property{Name: "T", Value: time.Unix(1e9, 0), NoIndex: false},
  669. },
  670. "",
  671. "",
  672. },
  673. {
  674. "uint save",
  675. &U0{U: 1},
  676. &U0{},
  677. "unsupported struct field",
  678. "",
  679. },
  680. {
  681. "uint load",
  682. &U1{U: "not a uint"},
  683. &U0{},
  684. "",
  685. "type mismatch",
  686. },
  687. {
  688. "zero",
  689. &X0{},
  690. &X0{},
  691. "",
  692. "",
  693. },
  694. {
  695. "basic",
  696. &X0{S: "one", I: 2, i: 3},
  697. &X0{S: "one", I: 2},
  698. "",
  699. "",
  700. },
  701. {
  702. "save string/int load myString/int32",
  703. &X0{S: "one", I: 2, i: 3},
  704. &X1{S: "one", I: 2},
  705. "",
  706. "",
  707. },
  708. {
  709. "missing fields",
  710. &X0{S: "one", I: 2, i: 3},
  711. &X2{},
  712. "",
  713. "no such struct field",
  714. },
  715. {
  716. "save string load bool",
  717. &X0{S: "one", I: 2, i: 3},
  718. &X3{I: 2},
  719. "",
  720. "type mismatch",
  721. },
  722. {
  723. "basic slice",
  724. &Y0{B: true, F: []float64{7, 8, 9}},
  725. &Y0{B: true, F: []float64{7, 8, 9}},
  726. "",
  727. "",
  728. },
  729. {
  730. "save []float64 load float64",
  731. &Y0{B: true, F: []float64{7, 8, 9}},
  732. &Y1{B: true},
  733. "",
  734. "requires a slice",
  735. },
  736. {
  737. "save []float64 load []int64",
  738. &Y0{B: true, F: []float64{7, 8, 9}},
  739. &Y2{B: true},
  740. "",
  741. "type mismatch",
  742. },
  743. {
  744. "single slice is too long",
  745. &Y0{F: make([]float64, maxIndexedProperties+1)},
  746. &Y0{},
  747. "too many indexed properties",
  748. "",
  749. },
  750. {
  751. "two slices are too long",
  752. &Y0{F: make([]float64, maxIndexedProperties), G: make([]float64, maxIndexedProperties)},
  753. &Y0{},
  754. "too many indexed properties",
  755. "",
  756. },
  757. {
  758. "one slice and one scalar are too long",
  759. &Y0{F: make([]float64, maxIndexedProperties), B: true},
  760. &Y0{},
  761. "too many indexed properties",
  762. "",
  763. },
  764. {
  765. "slice of slices of bytes",
  766. &Repeated{
  767. Repeats: []Repeat{
  768. {
  769. Key: "key 1",
  770. Value: []byte("value 1"),
  771. },
  772. {
  773. Key: "key 2",
  774. Value: []byte("value 2"),
  775. },
  776. },
  777. },
  778. &Repeated{
  779. Repeats: []Repeat{
  780. {
  781. Key: "key 1",
  782. Value: []byte("value 1"),
  783. },
  784. {
  785. Key: "key 2",
  786. Value: []byte("value 2"),
  787. },
  788. },
  789. },
  790. "",
  791. "",
  792. },
  793. {
  794. "long blob",
  795. &B0{B: makeUint8Slice(maxIndexedProperties + 1)},
  796. &B0{B: makeUint8Slice(maxIndexedProperties + 1)},
  797. "",
  798. "",
  799. },
  800. {
  801. "long []int8 is too long",
  802. &B1{B: makeInt8Slice(maxIndexedProperties + 1)},
  803. &B1{},
  804. "too many indexed properties",
  805. "",
  806. },
  807. {
  808. "short []int8",
  809. &B1{B: makeInt8Slice(3)},
  810. &B1{B: makeInt8Slice(3)},
  811. "",
  812. "",
  813. },
  814. {
  815. "long myBlob",
  816. &B2{B: makeUint8Slice(maxIndexedProperties + 1)},
  817. &B2{B: makeUint8Slice(maxIndexedProperties + 1)},
  818. "",
  819. "",
  820. },
  821. {
  822. "short myBlob",
  823. &B2{B: makeUint8Slice(3)},
  824. &B2{B: makeUint8Slice(3)},
  825. "",
  826. "",
  827. },
  828. {
  829. "long []myByte",
  830. &B3{B: makeMyByteSlice(maxIndexedProperties + 1)},
  831. &B3{B: makeMyByteSlice(maxIndexedProperties + 1)},
  832. "",
  833. "",
  834. },
  835. {
  836. "short []myByte",
  837. &B3{B: makeMyByteSlice(3)},
  838. &B3{B: makeMyByteSlice(3)},
  839. "",
  840. "",
  841. },
  842. {
  843. "slice of blobs",
  844. &B4{B: [][]byte{
  845. makeUint8Slice(3),
  846. makeUint8Slice(4),
  847. makeUint8Slice(5),
  848. }},
  849. &B4{B: [][]byte{
  850. makeUint8Slice(3),
  851. makeUint8Slice(4),
  852. makeUint8Slice(5),
  853. }},
  854. "",
  855. "",
  856. },
  857. {
  858. "[]byte must be noindex",
  859. &PropertyList{
  860. Property{Name: "B", Value: makeUint8Slice(1501), NoIndex: false},
  861. },
  862. nil,
  863. "[]byte property too long to index",
  864. "",
  865. },
  866. {
  867. "string must be noindex",
  868. &PropertyList{
  869. Property{Name: "B", Value: strings.Repeat("x", 1501), NoIndex: false},
  870. },
  871. nil,
  872. "string property too long to index",
  873. "",
  874. },
  875. {
  876. "slice of []byte must be noindex",
  877. &PropertyList{
  878. Property{Name: "B", Value: []interface{}{
  879. []byte("short"),
  880. makeUint8Slice(1501),
  881. }, NoIndex: false},
  882. },
  883. nil,
  884. "[]byte property too long to index",
  885. "",
  886. },
  887. {
  888. "slice of string must be noindex",
  889. &PropertyList{
  890. Property{Name: "B", Value: []interface{}{
  891. "short",
  892. strings.Repeat("x", 1501),
  893. }, NoIndex: false},
  894. },
  895. nil,
  896. "string property too long to index",
  897. "",
  898. },
  899. {
  900. "save tagged load props",
  901. &Tagged{A: 1, B: []int{21, 22, 23}, C: 3, D: 4, E: 5, I: 6, J: 7},
  902. &PropertyList{
  903. // A and B are renamed to a and b; A and C are noindex, I is ignored.
  904. // Order is sorted as per byName.
  905. Property{Name: "C", Value: int64(3), NoIndex: true},
  906. Property{Name: "D", Value: int64(4), NoIndex: false},
  907. Property{Name: "E", Value: int64(5), NoIndex: false},
  908. Property{Name: "J", Value: int64(7), NoIndex: true},
  909. Property{Name: "a", Value: int64(1), NoIndex: true},
  910. Property{Name: "b", Value: []interface{}{int64(21), int64(22), int64(23)}, NoIndex: false},
  911. },
  912. "",
  913. "",
  914. },
  915. {
  916. "save tagged load tagged",
  917. &Tagged{A: 1, B: []int{21, 22, 23}, C: 3, D: 4, E: 5, I: 6, J: 7},
  918. &Tagged{A: 1, B: []int{21, 22, 23}, C: 3, D: 4, E: 5, J: 7},
  919. "",
  920. "",
  921. },
  922. {
  923. "invalid tagged1",
  924. &InvalidTagged1{I: 1},
  925. &InvalidTagged1{},
  926. "struct tag has invalid property name",
  927. "",
  928. },
  929. {
  930. "invalid tagged2",
  931. &InvalidTagged2{I: 1, J: 2},
  932. &InvalidTagged2{J: 2},
  933. "",
  934. "",
  935. },
  936. {
  937. "invalid tagged3",
  938. &InvalidTagged3{X: "hello"},
  939. &InvalidTagged3{},
  940. "struct tag has invalid property name: \"-\"",
  941. "",
  942. },
  943. {
  944. "invalid tagged4",
  945. &InvalidTagged4{X: "hello"},
  946. &InvalidTagged4{},
  947. "struct tag has invalid option: \"garbage\"",
  948. "",
  949. },
  950. {
  951. "doubler",
  952. &Doubler{S: "s", I: 1, B: true},
  953. &Doubler{S: "ss", I: 2, B: true},
  954. "",
  955. "",
  956. },
  957. {
  958. "save struct load props",
  959. &X0{S: "s", I: 1},
  960. &PropertyList{
  961. Property{Name: "I", Value: int64(1), NoIndex: false},
  962. Property{Name: "S", Value: "s", NoIndex: false},
  963. },
  964. "",
  965. "",
  966. },
  967. {
  968. "save props load struct",
  969. &PropertyList{
  970. Property{Name: "I", Value: int64(1), NoIndex: false},
  971. Property{Name: "S", Value: "s", NoIndex: false},
  972. },
  973. &X0{S: "s", I: 1},
  974. "",
  975. "",
  976. },
  977. {
  978. "nil-value props",
  979. &PropertyList{
  980. Property{Name: "I", Value: nil, NoIndex: false},
  981. Property{Name: "B", Value: nil, NoIndex: false},
  982. Property{Name: "S", Value: nil, NoIndex: false},
  983. Property{Name: "F", Value: nil, NoIndex: false},
  984. Property{Name: "K", Value: nil, NoIndex: false},
  985. Property{Name: "T", Value: nil, NoIndex: false},
  986. Property{Name: "J", Value: []interface{}{nil, int64(7), nil}, NoIndex: false},
  987. },
  988. &struct {
  989. I int64
  990. B bool
  991. S string
  992. F float64
  993. K *Key
  994. T time.Time
  995. J []int64
  996. }{
  997. J: []int64{0, 7, 0},
  998. },
  999. "",
  1000. "",
  1001. },
  1002. {
  1003. "save outer load props flatten",
  1004. &OuterFlatten{
  1005. A: 1,
  1006. I: []Inner1{
  1007. {10, "ten"},
  1008. {20, "twenty"},
  1009. {30, "thirty"},
  1010. },
  1011. J: Inner2{
  1012. Y: 3.14,
  1013. },
  1014. Inner3: Inner3{
  1015. Z: true,
  1016. },
  1017. K: Inner4{
  1018. X: Inner5{
  1019. WW: 12,
  1020. },
  1021. },
  1022. },
  1023. &PropertyList{
  1024. Property{Name: "A", Value: int64(1), NoIndex: false},
  1025. Property{Name: "I.W", Value: []interface{}{int64(10), int64(20), int64(30)}, NoIndex: false},
  1026. Property{Name: "I.X", Value: []interface{}{"ten", "twenty", "thirty"}, NoIndex: false},
  1027. Property{Name: "J.Y", Value: float64(3.14), NoIndex: true},
  1028. Property{Name: "K.X.WW", Value: int64(12), NoIndex: false},
  1029. Property{Name: "Z", Value: true, NoIndex: false},
  1030. },
  1031. "",
  1032. "",
  1033. },
  1034. {
  1035. "load outer props flatten",
  1036. &PropertyList{
  1037. Property{Name: "A", Value: int64(1), NoIndex: false},
  1038. Property{Name: "I.W", Value: []interface{}{int64(10), int64(20), int64(30)}, NoIndex: false},
  1039. Property{Name: "I.X", Value: []interface{}{"ten", "twenty", "thirty"}, NoIndex: false},
  1040. Property{Name: "J.Y", Value: float64(3.14), NoIndex: true},
  1041. Property{Name: "Z", Value: true, NoIndex: false},
  1042. },
  1043. &OuterFlatten{
  1044. A: 1,
  1045. I: []Inner1{
  1046. {10, "ten"},
  1047. {20, "twenty"},
  1048. {30, "thirty"},
  1049. },
  1050. J: Inner2{
  1051. Y: 3.14,
  1052. },
  1053. Inner3: Inner3{
  1054. Z: true,
  1055. },
  1056. },
  1057. "",
  1058. "",
  1059. },
  1060. {
  1061. "save outer load props",
  1062. &Outer{
  1063. A: 1,
  1064. I: []Inner1{
  1065. {10, "ten"},
  1066. {20, "twenty"},
  1067. {30, "thirty"},
  1068. },
  1069. J: Inner2{
  1070. Y: 3.14,
  1071. },
  1072. Inner3: Inner3{
  1073. Z: true,
  1074. },
  1075. },
  1076. &PropertyList{
  1077. Property{Name: "A", Value: int64(1), NoIndex: false},
  1078. Property{Name: "I", Value: []interface{}{
  1079. &Entity{
  1080. Properties: []Property{
  1081. {Name: "W", Value: int64(10), NoIndex: false},
  1082. {Name: "X", Value: "ten", NoIndex: false},
  1083. },
  1084. },
  1085. &Entity{
  1086. Properties: []Property{
  1087. {Name: "W", Value: int64(20), NoIndex: false},
  1088. {Name: "X", Value: "twenty", NoIndex: false},
  1089. },
  1090. },
  1091. &Entity{
  1092. Properties: []Property{
  1093. {Name: "W", Value: int64(30), NoIndex: false},
  1094. {Name: "X", Value: "thirty", NoIndex: false},
  1095. },
  1096. },
  1097. }, NoIndex: false},
  1098. Property{Name: "J", Value: &Entity{
  1099. Properties: []Property{
  1100. {Name: "Y", Value: float64(3.14), NoIndex: false},
  1101. },
  1102. }, NoIndex: false},
  1103. Property{Name: "Z", Value: true, NoIndex: false},
  1104. },
  1105. "",
  1106. "",
  1107. },
  1108. {
  1109. "save props load outer-equivalent",
  1110. &PropertyList{
  1111. Property{Name: "A", Value: int64(1), NoIndex: false},
  1112. Property{Name: "I.W", Value: []interface{}{int64(10), int64(20), int64(30)}, NoIndex: false},
  1113. Property{Name: "I.X", Value: []interface{}{"ten", "twenty", "thirty"}, NoIndex: false},
  1114. Property{Name: "J.Y", Value: float64(3.14), NoIndex: false},
  1115. Property{Name: "Z", Value: true, NoIndex: false},
  1116. },
  1117. &OuterEquivalent{
  1118. A: 1,
  1119. IDotW: []int32{10, 20, 30},
  1120. IDotX: []string{"ten", "twenty", "thirty"},
  1121. JDotY: 3.14,
  1122. Z: true,
  1123. },
  1124. "",
  1125. "",
  1126. },
  1127. {
  1128. "dotted names save",
  1129. &Dotted{A: DottedA{B: DottedB{C: 88}}},
  1130. &PropertyList{
  1131. Property{Name: "A0.A1.A2", Value: &Entity{
  1132. Properties: []Property{
  1133. {Name: "B3", Value: &Entity{
  1134. Properties: []Property{
  1135. {Name: "C4.C5", Value: int64(88), NoIndex: false},
  1136. },
  1137. }, NoIndex: false},
  1138. },
  1139. }, NoIndex: false},
  1140. },
  1141. "",
  1142. "",
  1143. },
  1144. {
  1145. "dotted names load",
  1146. &PropertyList{
  1147. Property{Name: "A0.A1.A2", Value: &Entity{
  1148. Properties: []Property{
  1149. {Name: "B3", Value: &Entity{
  1150. Properties: []Property{
  1151. {Name: "C4.C5", Value: 99, NoIndex: false},
  1152. },
  1153. }, NoIndex: false},
  1154. },
  1155. }, NoIndex: false},
  1156. },
  1157. &Dotted{A: DottedA{B: DottedB{C: 99}}},
  1158. "",
  1159. "",
  1160. },
  1161. {
  1162. "save struct load deriver",
  1163. &X0{S: "s", I: 1},
  1164. &Deriver{S: "s", Derived: "derived+s"},
  1165. "",
  1166. "",
  1167. },
  1168. {
  1169. "save deriver load struct",
  1170. &Deriver{S: "s", Derived: "derived+s", Ignored: "ignored"},
  1171. &X0{S: "s"},
  1172. "",
  1173. "",
  1174. },
  1175. {
  1176. "zero time.Time",
  1177. &T{T: time.Time{}},
  1178. &T{T: time.Time{}},
  1179. "",
  1180. "",
  1181. },
  1182. {
  1183. "time.Time near Unix zero time",
  1184. &T{T: time.Unix(0, 4e3)},
  1185. &T{T: time.Unix(0, 4e3)},
  1186. "",
  1187. "",
  1188. },
  1189. {
  1190. "time.Time, far in the future",
  1191. &T{T: time.Date(99999, 1, 1, 0, 0, 0, 0, time.UTC)},
  1192. &T{T: time.Date(99999, 1, 1, 0, 0, 0, 0, time.UTC)},
  1193. "",
  1194. "",
  1195. },
  1196. {
  1197. "time.Time, very far in the past",
  1198. &T{T: time.Date(-300000, 1, 1, 0, 0, 0, 0, time.UTC)},
  1199. &T{},
  1200. "time value out of range",
  1201. "",
  1202. },
  1203. {
  1204. "time.Time, very far in the future",
  1205. &T{T: time.Date(294248, 1, 1, 0, 0, 0, 0, time.UTC)},
  1206. &T{},
  1207. "time value out of range",
  1208. "",
  1209. },
  1210. {
  1211. "structs",
  1212. &N0{
  1213. X0: X0{S: "one", I: 2, i: 3},
  1214. Nonymous: X0{S: "four", I: 5, i: 6},
  1215. Ignore: "ignore",
  1216. Other: "other",
  1217. },
  1218. &N0{
  1219. X0: X0{S: "one", I: 2},
  1220. Nonymous: X0{S: "four", I: 5},
  1221. Other: "other",
  1222. },
  1223. "",
  1224. "",
  1225. },
  1226. {
  1227. "slice of structs",
  1228. &N1{
  1229. X0: X0{S: "one", I: 2, i: 3},
  1230. Nonymous: []X0{
  1231. {S: "four", I: 5, i: 6},
  1232. {S: "seven", I: 8, i: 9},
  1233. {S: "ten", I: 11, i: 12},
  1234. {S: "thirteen", I: 14, i: 15},
  1235. },
  1236. Ignore: "ignore",
  1237. Other: "other",
  1238. },
  1239. &N1{
  1240. X0: X0{S: "one", I: 2},
  1241. Nonymous: []X0{
  1242. {S: "four", I: 5},
  1243. {S: "seven", I: 8},
  1244. {S: "ten", I: 11},
  1245. {S: "thirteen", I: 14},
  1246. },
  1247. Other: "other",
  1248. },
  1249. "",
  1250. "",
  1251. },
  1252. {
  1253. "structs with slices of structs",
  1254. &N2{
  1255. N1: N1{
  1256. X0: X0{S: "rouge"},
  1257. Nonymous: []X0{
  1258. {S: "rosso0"},
  1259. {S: "rosso1"},
  1260. },
  1261. },
  1262. Green: N1{
  1263. X0: X0{S: "vert"},
  1264. Nonymous: []X0{
  1265. {S: "verde0"},
  1266. {S: "verde1"},
  1267. {S: "verde2"},
  1268. },
  1269. },
  1270. Blue: N1{
  1271. X0: X0{S: "bleu"},
  1272. Nonymous: []X0{
  1273. {S: "blu0"},
  1274. {S: "blu1"},
  1275. {S: "blu2"},
  1276. {S: "blu3"},
  1277. },
  1278. },
  1279. },
  1280. &N2{
  1281. N1: N1{
  1282. X0: X0{S: "rouge"},
  1283. Nonymous: []X0{
  1284. {S: "rosso0"},
  1285. {S: "rosso1"},
  1286. },
  1287. },
  1288. Green: N1{
  1289. X0: X0{S: "vert"},
  1290. Nonymous: []X0{
  1291. {S: "verde0"},
  1292. {S: "verde1"},
  1293. {S: "verde2"},
  1294. },
  1295. },
  1296. Blue: N1{
  1297. X0: X0{S: "bleu"},
  1298. Nonymous: []X0{
  1299. {S: "blu0"},
  1300. {S: "blu1"},
  1301. {S: "blu2"},
  1302. {S: "blu3"},
  1303. },
  1304. },
  1305. },
  1306. "",
  1307. "",
  1308. },
  1309. {
  1310. "save structs load props",
  1311. &N2{
  1312. N1: N1{
  1313. X0: X0{S: "rouge"},
  1314. Nonymous: []X0{
  1315. {S: "rosso0"},
  1316. {S: "rosso1"},
  1317. },
  1318. },
  1319. Green: N1{
  1320. X0: X0{S: "vert"},
  1321. Nonymous: []X0{
  1322. {S: "verde0"},
  1323. {S: "verde1"},
  1324. {S: "verde2"},
  1325. },
  1326. },
  1327. Blue: N1{
  1328. X0: X0{S: "bleu"},
  1329. Nonymous: []X0{
  1330. {S: "blu0"},
  1331. {S: "blu1"},
  1332. {S: "blu2"},
  1333. {S: "blu3"},
  1334. },
  1335. },
  1336. },
  1337. &PropertyList{
  1338. Property{Name: "Blue", Value: &Entity{
  1339. Properties: []Property{
  1340. {Name: "I", Value: int64(0), NoIndex: false},
  1341. {Name: "Nonymous", Value: []interface{}{
  1342. &Entity{
  1343. Properties: []Property{
  1344. {Name: "I", Value: int64(0), NoIndex: false},
  1345. {Name: "S", Value: "blu0", NoIndex: false},
  1346. },
  1347. },
  1348. &Entity{
  1349. Properties: []Property{
  1350. {Name: "I", Value: int64(0), NoIndex: false},
  1351. {Name: "S", Value: "blu1", NoIndex: false},
  1352. },
  1353. },
  1354. &Entity{
  1355. Properties: []Property{
  1356. {Name: "I", Value: int64(0), NoIndex: false},
  1357. {Name: "S", Value: "blu2", NoIndex: false},
  1358. },
  1359. },
  1360. &Entity{
  1361. Properties: []Property{
  1362. {Name: "I", Value: int64(0), NoIndex: false},
  1363. {Name: "S", Value: "blu3", NoIndex: false},
  1364. },
  1365. },
  1366. }, NoIndex: false},
  1367. {Name: "Other", Value: "", NoIndex: false},
  1368. {Name: "S", Value: "bleu", NoIndex: false},
  1369. },
  1370. }, NoIndex: false},
  1371. Property{Name: "green", Value: &Entity{
  1372. Properties: []Property{
  1373. {Name: "I", Value: int64(0), NoIndex: false},
  1374. {Name: "Nonymous", Value: []interface{}{
  1375. &Entity{
  1376. Properties: []Property{
  1377. {Name: "I", Value: int64(0), NoIndex: false},
  1378. {Name: "S", Value: "verde0", NoIndex: false},
  1379. },
  1380. },
  1381. &Entity{
  1382. Properties: []Property{
  1383. {Name: "I", Value: int64(0), NoIndex: false},
  1384. {Name: "S", Value: "verde1", NoIndex: false},
  1385. },
  1386. },
  1387. &Entity{
  1388. Properties: []Property{
  1389. {Name: "I", Value: int64(0), NoIndex: false},
  1390. {Name: "S", Value: "verde2", NoIndex: false},
  1391. },
  1392. },
  1393. }, NoIndex: false},
  1394. {Name: "Other", Value: "", NoIndex: false},
  1395. {Name: "S", Value: "vert", NoIndex: false},
  1396. },
  1397. }, NoIndex: false},
  1398. Property{Name: "red", Value: &Entity{
  1399. Properties: []Property{
  1400. {Name: "I", Value: int64(0), NoIndex: false},
  1401. {Name: "Nonymous", Value: []interface{}{
  1402. &Entity{
  1403. Properties: []Property{
  1404. {Name: "I", Value: int64(0), NoIndex: false},
  1405. {Name: "S", Value: "rosso0", NoIndex: false},
  1406. },
  1407. },
  1408. &Entity{
  1409. Properties: []Property{
  1410. {Name: "I", Value: int64(0), NoIndex: false},
  1411. {Name: "S", Value: "rosso1", NoIndex: false},
  1412. },
  1413. },
  1414. }, NoIndex: false},
  1415. {Name: "Other", Value: "", NoIndex: false},
  1416. {Name: "S", Value: "rouge", NoIndex: false},
  1417. },
  1418. }, NoIndex: false},
  1419. },
  1420. "",
  1421. "",
  1422. },
  1423. {
  1424. "nested entity with key",
  1425. &WithNestedEntityWithKey{
  1426. N: EntityWithKey{
  1427. I: 12,
  1428. S: "abcd",
  1429. K: testKey0,
  1430. },
  1431. },
  1432. &WithNestedEntityWithKey{
  1433. N: EntityWithKey{
  1434. I: 12,
  1435. S: "abcd",
  1436. K: testKey0,
  1437. },
  1438. },
  1439. "",
  1440. "",
  1441. },
  1442. {
  1443. "entity with key at top level",
  1444. &EntityWithKey{
  1445. I: 12,
  1446. S: "abc",
  1447. K: testKey0,
  1448. },
  1449. &EntityWithKey{
  1450. I: 12,
  1451. S: "abc",
  1452. K: testKey0,
  1453. },
  1454. "",
  1455. "",
  1456. },
  1457. {
  1458. "entity with key at top level (key is populated on load)",
  1459. &EntityWithKey{
  1460. I: 12,
  1461. S: "abc",
  1462. },
  1463. &EntityWithKey{
  1464. I: 12,
  1465. S: "abc",
  1466. K: testKey0,
  1467. },
  1468. "",
  1469. "",
  1470. },
  1471. {
  1472. "__key__ field not a *Key",
  1473. &NestedWithNonKeyField{
  1474. N: WithNonKeyField{
  1475. I: 12,
  1476. K: "abcd",
  1477. },
  1478. },
  1479. &NestedWithNonKeyField{
  1480. N: WithNonKeyField{
  1481. I: 12,
  1482. K: "abcd",
  1483. },
  1484. },
  1485. "datastore: __key__ field on struct datastore.WithNonKeyField is not a *datastore.Key",
  1486. "",
  1487. },
  1488. {
  1489. "save struct with ptr to struct fields",
  1490. &PtrToStructField{
  1491. &Basic{
  1492. A: "b",
  1493. },
  1494. &Basic{
  1495. A: "c",
  1496. },
  1497. &Basic{
  1498. A: "anon",
  1499. },
  1500. []*Basic{
  1501. {
  1502. A: "slice0",
  1503. },
  1504. {
  1505. A: "slice1",
  1506. },
  1507. },
  1508. },
  1509. &PropertyList{
  1510. Property{Name: "A", Value: "anon", NoIndex: false},
  1511. Property{Name: "B", Value: &Entity{
  1512. Properties: []Property{
  1513. {Name: "A", Value: "b", NoIndex: false},
  1514. },
  1515. }},
  1516. Property{Name: "D", Value: []interface{}{
  1517. &Entity{
  1518. Properties: []Property{
  1519. {Name: "A", Value: "slice0", NoIndex: false},
  1520. },
  1521. },
  1522. &Entity{
  1523. Properties: []Property{
  1524. {Name: "A", Value: "slice1", NoIndex: false},
  1525. },
  1526. },
  1527. }, NoIndex: false},
  1528. Property{Name: "c", Value: &Entity{
  1529. Properties: []Property{
  1530. {Name: "A", Value: "c", NoIndex: true},
  1531. },
  1532. }, NoIndex: true},
  1533. },
  1534. "",
  1535. "",
  1536. },
  1537. {
  1538. "save and load struct with ptr to struct fields",
  1539. &PtrToStructField{
  1540. &Basic{
  1541. A: "b",
  1542. },
  1543. &Basic{
  1544. A: "c",
  1545. },
  1546. &Basic{
  1547. A: "anon",
  1548. },
  1549. []*Basic{
  1550. {
  1551. A: "slice0",
  1552. },
  1553. {
  1554. A: "slice1",
  1555. },
  1556. },
  1557. },
  1558. &PtrToStructField{
  1559. &Basic{
  1560. A: "b",
  1561. },
  1562. &Basic{
  1563. A: "c",
  1564. },
  1565. &Basic{
  1566. A: "anon",
  1567. },
  1568. []*Basic{
  1569. {
  1570. A: "slice0",
  1571. },
  1572. {
  1573. A: "slice1",
  1574. },
  1575. },
  1576. },
  1577. "",
  1578. "",
  1579. },
  1580. {
  1581. "struct with nil ptr to struct fields",
  1582. &PtrToStructField{
  1583. nil,
  1584. nil,
  1585. nil,
  1586. nil,
  1587. },
  1588. new(PropertyList),
  1589. "",
  1590. "",
  1591. },
  1592. {
  1593. "nested load entity with key",
  1594. &WithNestedEntityWithKey{
  1595. N: EntityWithKey{
  1596. I: 12,
  1597. S: "abcd",
  1598. K: testKey0,
  1599. },
  1600. },
  1601. &PropertyList{
  1602. Property{Name: "N", Value: &Entity{
  1603. Key: testKey0,
  1604. Properties: []Property{
  1605. {Name: "I", Value: int64(12), NoIndex: false},
  1606. {Name: "S", Value: "abcd", NoIndex: false},
  1607. },
  1608. },
  1609. NoIndex: false},
  1610. },
  1611. "",
  1612. "",
  1613. },
  1614. {
  1615. "nested save entity with key",
  1616. &PropertyList{
  1617. Property{Name: "N", Value: &Entity{
  1618. Key: testKey0,
  1619. Properties: []Property{
  1620. {Name: "I", Value: int64(12), NoIndex: false},
  1621. {Name: "S", Value: "abcd", NoIndex: false},
  1622. },
  1623. }, NoIndex: false},
  1624. },
  1625. &WithNestedEntityWithKey{
  1626. N: EntityWithKey{
  1627. I: 12,
  1628. S: "abcd",
  1629. K: testKey0,
  1630. },
  1631. },
  1632. "",
  1633. "",
  1634. },
  1635. {
  1636. "anonymous field with tag",
  1637. &N3{
  1638. C3: C3{C: "s"},
  1639. },
  1640. &PropertyList{
  1641. Property{Name: "red", Value: &Entity{
  1642. Properties: []Property{
  1643. {Name: "C", Value: "s", NoIndex: false},
  1644. },
  1645. }, NoIndex: false},
  1646. },
  1647. "",
  1648. "",
  1649. },
  1650. {
  1651. "unexported anonymous field",
  1652. &N4{
  1653. c4: c4{C: "s"},
  1654. },
  1655. &PropertyList{
  1656. Property{Name: "C", Value: "s", NoIndex: false},
  1657. },
  1658. "",
  1659. "",
  1660. },
  1661. {
  1662. "unexported anonymous field with tag",
  1663. &N5{
  1664. c4: c4{C: "s"},
  1665. },
  1666. new(PropertyList),
  1667. "",
  1668. "",
  1669. },
  1670. {
  1671. "save props load structs with ragged fields",
  1672. &PropertyList{
  1673. Property{Name: "red.S", Value: "rot", NoIndex: false},
  1674. Property{Name: "green.Nonymous.I", Value: []interface{}{int64(10), int64(11), int64(12), int64(13)}, NoIndex: false},
  1675. Property{Name: "Blue.Nonymous.I", Value: []interface{}{int64(20), int64(21)}, NoIndex: false},
  1676. Property{Name: "Blue.Nonymous.S", Value: []interface{}{"blau0", "blau1", "blau2"}, NoIndex: false},
  1677. },
  1678. &N2{
  1679. N1: N1{
  1680. X0: X0{S: "rot"},
  1681. },
  1682. Green: N1{
  1683. Nonymous: []X0{
  1684. {I: 10},
  1685. {I: 11},
  1686. {I: 12},
  1687. {I: 13},
  1688. },
  1689. },
  1690. Blue: N1{
  1691. Nonymous: []X0{
  1692. {S: "blau0", I: 20},
  1693. {S: "blau1", I: 21},
  1694. {S: "blau2"},
  1695. },
  1696. },
  1697. },
  1698. "",
  1699. "",
  1700. },
  1701. {
  1702. "save structs with noindex tags",
  1703. &struct {
  1704. A struct {
  1705. X string `datastore:",noindex"`
  1706. Y string
  1707. } `datastore:",noindex"`
  1708. B struct {
  1709. X string `datastore:",noindex"`
  1710. Y string
  1711. }
  1712. }{},
  1713. &PropertyList{
  1714. Property{Name: "A", Value: &Entity{
  1715. Properties: []Property{
  1716. {Name: "X", Value: "", NoIndex: true},
  1717. {Name: "Y", Value: "", NoIndex: true},
  1718. },
  1719. }, NoIndex: true},
  1720. Property{Name: "B", Value: &Entity{
  1721. Properties: []Property{
  1722. {Name: "X", Value: "", NoIndex: true},
  1723. {Name: "Y", Value: "", NoIndex: false},
  1724. },
  1725. }, NoIndex: false},
  1726. },
  1727. "",
  1728. "",
  1729. },
  1730. {
  1731. "embedded struct with name override",
  1732. &struct {
  1733. Inner1 `datastore:"foo"`
  1734. }{},
  1735. &PropertyList{
  1736. Property{Name: "foo", Value: &Entity{
  1737. Properties: []Property{
  1738. {Name: "W", Value: int64(0), NoIndex: false},
  1739. {Name: "X", Value: "", NoIndex: false},
  1740. },
  1741. }, NoIndex: false},
  1742. },
  1743. "",
  1744. "",
  1745. },
  1746. {
  1747. "slice of slices",
  1748. &SliceOfSlices{},
  1749. nil,
  1750. "flattening nested structs leads to a slice of slices",
  1751. "",
  1752. },
  1753. {
  1754. "recursive struct",
  1755. &Recursive{},
  1756. &Recursive{},
  1757. "",
  1758. "",
  1759. },
  1760. {
  1761. "mutually recursive struct",
  1762. &MutuallyRecursive0{},
  1763. &MutuallyRecursive0{},
  1764. "",
  1765. "",
  1766. },
  1767. {
  1768. "non-exported struct fields",
  1769. &struct {
  1770. i, J int64
  1771. }{i: 1, J: 2},
  1772. &PropertyList{
  1773. Property{Name: "J", Value: int64(2), NoIndex: false},
  1774. },
  1775. "",
  1776. "",
  1777. },
  1778. {
  1779. "json.RawMessage",
  1780. &struct {
  1781. J json.RawMessage
  1782. }{
  1783. J: json.RawMessage("rawr"),
  1784. },
  1785. &PropertyList{
  1786. Property{Name: "J", Value: []byte("rawr"), NoIndex: false},
  1787. },
  1788. "",
  1789. "",
  1790. },
  1791. {
  1792. "json.RawMessage to myBlob",
  1793. &struct {
  1794. B json.RawMessage
  1795. }{
  1796. B: json.RawMessage("rawr"),
  1797. },
  1798. &B2{B: myBlob("rawr")},
  1799. "",
  1800. "",
  1801. },
  1802. {
  1803. "repeated property names",
  1804. &PropertyList{
  1805. Property{Name: "A", Value: ""},
  1806. Property{Name: "A", Value: ""},
  1807. },
  1808. nil,
  1809. "duplicate Property",
  1810. "",
  1811. },
  1812. {
  1813. "embedded time field",
  1814. &SpecialTime{MyTime: EmbeddedTime{ts}},
  1815. &SpecialTime{MyTime: EmbeddedTime{ts}},
  1816. "",
  1817. "",
  1818. },
  1819. {
  1820. "embedded time load",
  1821. &PropertyList{
  1822. Property{Name: "MyTime.Time", Value: ts},
  1823. },
  1824. &SpecialTime{MyTime: EmbeddedTime{ts}},
  1825. "",
  1826. "",
  1827. },
  1828. {
  1829. "pointer fields: nil",
  1830. &Pointers{},
  1831. &Pointers{},
  1832. "",
  1833. "",
  1834. },
  1835. {
  1836. "pointer fields: populated with zeroes",
  1837. populatedPointers(),
  1838. populatedPointers(),
  1839. "",
  1840. "",
  1841. },
  1842. }
  1843. // checkErr returns the empty string if either both want and err are zero,
  1844. // or if want is a non-empty substring of err's string representation.
  1845. func checkErr(want string, err error) string {
  1846. if err != nil {
  1847. got := err.Error()
  1848. if want == "" || !strings.Contains(got, want) {
  1849. return got
  1850. }
  1851. } else if want != "" {
  1852. return fmt.Sprintf("want error %q", want)
  1853. }
  1854. return ""
  1855. }
  1856. func TestRoundTrip(t *testing.T) {
  1857. for _, tc := range testCases {
  1858. p, err := saveEntity(testKey0, tc.src)
  1859. if s := checkErr(tc.putErr, err); s != "" {
  1860. t.Errorf("%s: save: %s", tc.desc, s)
  1861. continue
  1862. }
  1863. if p == nil {
  1864. continue
  1865. }
  1866. var got interface{}
  1867. if _, ok := tc.want.(*PropertyList); ok {
  1868. got = new(PropertyList)
  1869. } else {
  1870. got = reflect.New(reflect.TypeOf(tc.want).Elem()).Interface()
  1871. }
  1872. err = loadEntityProto(got, p)
  1873. if s := checkErr(tc.getErr, err); s != "" {
  1874. t.Errorf("%s: load: %s", tc.desc, s)
  1875. continue
  1876. }
  1877. if pl, ok := got.(*PropertyList); ok {
  1878. // Sort by name to make sure we have a deterministic order.
  1879. sortPL(*pl)
  1880. }
  1881. if !testutil.Equal(got, tc.want, cmp.AllowUnexported(X0{}, X2{})) {
  1882. t.Errorf("%s: compare:\ngot: %+#v\nwant: %+#v", tc.desc, got, tc.want)
  1883. continue
  1884. }
  1885. }
  1886. }
  1887. type aPtrPLS struct {
  1888. Count int
  1889. }
  1890. func (pls *aPtrPLS) Load([]Property) error {
  1891. pls.Count++
  1892. return nil
  1893. }
  1894. func (pls *aPtrPLS) Save() ([]Property, error) {
  1895. return []Property{{Name: "Count", Value: 4}}, nil
  1896. }
  1897. type aValuePLS struct {
  1898. Count int
  1899. }
  1900. func (pls aValuePLS) Load([]Property) error {
  1901. pls.Count += 2
  1902. return nil
  1903. }
  1904. func (pls aValuePLS) Save() ([]Property, error) {
  1905. return []Property{{Name: "Count", Value: 8}}, nil
  1906. }
  1907. type aValuePtrPLS struct {
  1908. Count int
  1909. }
  1910. func (pls *aValuePtrPLS) Load([]Property) error {
  1911. pls.Count = 11
  1912. return nil
  1913. }
  1914. func (pls *aValuePtrPLS) Save() ([]Property, error) {
  1915. return []Property{{Name: "Count", Value: 12}}, nil
  1916. }
  1917. type aNotPLS struct {
  1918. Count int
  1919. }
  1920. type plsString string
  1921. func (s *plsString) Load([]Property) error {
  1922. *s = "LOADED"
  1923. return nil
  1924. }
  1925. func (s *plsString) Save() ([]Property, error) {
  1926. return []Property{{Name: "SS", Value: "SAVED"}}, nil
  1927. }
  1928. func ptrToplsString(s string) *plsString {
  1929. plsStr := plsString(s)
  1930. return &plsStr
  1931. }
  1932. type aSubPLS struct {
  1933. Foo string
  1934. Bar *aPtrPLS
  1935. Baz aValuePtrPLS
  1936. S plsString
  1937. }
  1938. type aSubNotPLS struct {
  1939. Foo string
  1940. Bar *aNotPLS
  1941. }
  1942. type aSubPLSErr struct {
  1943. Foo string
  1944. Bar aValuePLS
  1945. }
  1946. type aSubPLSNoErr struct {
  1947. Foo string
  1948. Bar aPtrPLS
  1949. }
  1950. type GrandparentFlatten struct {
  1951. Parent Parent `datastore:",flatten"`
  1952. }
  1953. type GrandparentOfPtrFlatten struct {
  1954. Parent ParentOfPtr `datastore:",flatten"`
  1955. }
  1956. type GrandparentOfSlice struct {
  1957. Parent ParentOfSlice
  1958. }
  1959. type GrandparentOfSlicePtrs struct {
  1960. Parent ParentOfSlicePtrs
  1961. }
  1962. type GrandparentOfSliceFlatten struct {
  1963. Parent ParentOfSlice `datastore:",flatten"`
  1964. }
  1965. type GrandparentOfSlicePtrsFlatten struct {
  1966. Parent ParentOfSlicePtrs `datastore:",flatten"`
  1967. }
  1968. type Grandparent struct {
  1969. Parent Parent
  1970. }
  1971. type Parent struct {
  1972. Child Child
  1973. String plsString
  1974. }
  1975. type ParentOfPtr struct {
  1976. Child *Child
  1977. String *plsString
  1978. }
  1979. type ParentOfSlice struct {
  1980. Children []Child
  1981. Strings []plsString
  1982. }
  1983. type ParentOfSlicePtrs struct {
  1984. Children []*Child
  1985. Strings []*plsString
  1986. }
  1987. type Child struct {
  1988. I int
  1989. Grandchild Grandchild
  1990. }
  1991. type Grandchild struct {
  1992. S string
  1993. }
  1994. func (c *Child) Load(props []Property) error {
  1995. for _, p := range props {
  1996. if p.Name == "I" {
  1997. c.I++
  1998. } else if p.Name == "Grandchild.S" {
  1999. c.Grandchild.S = "grandchild loaded"
  2000. }
  2001. }
  2002. return nil
  2003. }
  2004. func (c *Child) Save() ([]Property, error) {
  2005. v := c.I + 1
  2006. return []Property{
  2007. {Name: "I", Value: v},
  2008. {Name: "Grandchild.S", Value: fmt.Sprintf("grandchild saved %d", v)},
  2009. }, nil
  2010. }
  2011. func TestLoadSavePLS(t *testing.T) {
  2012. type testCase struct {
  2013. desc string
  2014. src interface{}
  2015. wantSave *pb.Entity
  2016. wantLoad interface{}
  2017. saveErr string
  2018. loadErr string
  2019. }
  2020. testCases := []testCase{
  2021. {
  2022. desc: "non-struct implements PLS (top-level)",
  2023. src: ptrToplsString("hello"),
  2024. wantSave: &pb.Entity{
  2025. Key: keyToProto(testKey0),
  2026. Properties: map[string]*pb.Value{
  2027. "SS": {ValueType: &pb.Value_StringValue{StringValue: "SAVED"}},
  2028. },
  2029. },
  2030. wantLoad: ptrToplsString("LOADED"),
  2031. },
  2032. {
  2033. desc: "substructs do implement PLS",
  2034. src: &aSubPLS{Foo: "foo", Bar: &aPtrPLS{Count: 2}, Baz: aValuePtrPLS{Count: 15}, S: "something"},
  2035. wantSave: &pb.Entity{
  2036. Key: keyToProto(testKey0),
  2037. Properties: map[string]*pb.Value{
  2038. "Foo": {ValueType: &pb.Value_StringValue{StringValue: "foo"}},
  2039. "Bar": {ValueType: &pb.Value_EntityValue{
  2040. EntityValue: &pb.Entity{
  2041. Properties: map[string]*pb.Value{
  2042. "Count": {ValueType: &pb.Value_IntegerValue{IntegerValue: 4}},
  2043. },
  2044. },
  2045. }},
  2046. "Baz": {ValueType: &pb.Value_EntityValue{
  2047. EntityValue: &pb.Entity{
  2048. Properties: map[string]*pb.Value{
  2049. "Count": {ValueType: &pb.Value_IntegerValue{IntegerValue: 12}},
  2050. },
  2051. },
  2052. }},
  2053. "S": {ValueType: &pb.Value_EntityValue{
  2054. EntityValue: &pb.Entity{
  2055. Properties: map[string]*pb.Value{
  2056. "SS": {ValueType: &pb.Value_StringValue{StringValue: "SAVED"}},
  2057. },
  2058. },
  2059. }},
  2060. },
  2061. },
  2062. wantLoad: &aSubPLS{Foo: "foo", Bar: &aPtrPLS{Count: 1}, Baz: aValuePtrPLS{Count: 11}, S: "LOADED"},
  2063. },
  2064. {
  2065. desc: "substruct (ptr) does implement PLS, nil valued substruct",
  2066. src: &aSubPLS{Foo: "foo", S: "something"},
  2067. wantSave: &pb.Entity{
  2068. Key: keyToProto(testKey0),
  2069. Properties: map[string]*pb.Value{
  2070. "Foo": {ValueType: &pb.Value_StringValue{StringValue: "foo"}},
  2071. "Baz": {ValueType: &pb.Value_EntityValue{
  2072. EntityValue: &pb.Entity{
  2073. Properties: map[string]*pb.Value{
  2074. "Count": {ValueType: &pb.Value_IntegerValue{IntegerValue: 12}},
  2075. },
  2076. },
  2077. }},
  2078. "S": {ValueType: &pb.Value_EntityValue{
  2079. EntityValue: &pb.Entity{
  2080. Properties: map[string]*pb.Value{
  2081. "SS": {ValueType: &pb.Value_StringValue{StringValue: "SAVED"}},
  2082. },
  2083. },
  2084. }},
  2085. },
  2086. },
  2087. wantLoad: &aSubPLS{Foo: "foo", Baz: aValuePtrPLS{Count: 11}, S: "LOADED"},
  2088. },
  2089. {
  2090. desc: "substruct (ptr) does not implement PLS",
  2091. src: &aSubNotPLS{Foo: "foo", Bar: &aNotPLS{Count: 2}},
  2092. wantSave: &pb.Entity{
  2093. Key: keyToProto(testKey0),
  2094. Properties: map[string]*pb.Value{
  2095. "Foo": {ValueType: &pb.Value_StringValue{StringValue: "foo"}},
  2096. "Bar": {ValueType: &pb.Value_EntityValue{
  2097. EntityValue: &pb.Entity{
  2098. Properties: map[string]*pb.Value{
  2099. "Count": {ValueType: &pb.Value_IntegerValue{IntegerValue: 2}},
  2100. },
  2101. },
  2102. }},
  2103. },
  2104. },
  2105. wantLoad: &aSubNotPLS{Foo: "foo", Bar: &aNotPLS{Count: 2}},
  2106. },
  2107. {
  2108. desc: "substruct (value) does implement PLS, error on save",
  2109. src: &aSubPLSErr{Foo: "foo", Bar: aValuePLS{Count: 2}},
  2110. wantSave: (*pb.Entity)(nil),
  2111. wantLoad: &aSubPLSErr{},
  2112. saveErr: "PropertyLoadSaver methods must be implemented on a pointer",
  2113. },
  2114. {
  2115. desc: "substruct (value) does implement PLS, error on load",
  2116. src: &aSubPLSNoErr{Foo: "foo", Bar: aPtrPLS{Count: 2}},
  2117. wantSave: &pb.Entity{
  2118. Key: keyToProto(testKey0),
  2119. Properties: map[string]*pb.Value{
  2120. "Foo": {ValueType: &pb.Value_StringValue{StringValue: "foo"}},
  2121. "Bar": {ValueType: &pb.Value_EntityValue{
  2122. EntityValue: &pb.Entity{
  2123. Properties: map[string]*pb.Value{
  2124. "Count": {ValueType: &pb.Value_IntegerValue{IntegerValue: 4}},
  2125. },
  2126. },
  2127. }},
  2128. },
  2129. },
  2130. wantLoad: &aSubPLSErr{},
  2131. loadErr: "PropertyLoadSaver methods must be implemented on a pointer",
  2132. },
  2133. {
  2134. desc: "parent does not have flatten option, child impl PLS",
  2135. src: &Grandparent{
  2136. Parent: Parent{
  2137. Child: Child{
  2138. I: 9,
  2139. Grandchild: Grandchild{
  2140. S: "BAD",
  2141. },
  2142. },
  2143. String: plsString("something"),
  2144. },
  2145. },
  2146. wantSave: &pb.Entity{
  2147. Key: keyToProto(testKey0),
  2148. Properties: map[string]*pb.Value{
  2149. "Parent": {ValueType: &pb.Value_EntityValue{
  2150. EntityValue: &pb.Entity{
  2151. Properties: map[string]*pb.Value{
  2152. "Child": {ValueType: &pb.Value_EntityValue{
  2153. EntityValue: &pb.Entity{
  2154. Properties: map[string]*pb.Value{
  2155. "I": {ValueType: &pb.Value_IntegerValue{IntegerValue: 10}},
  2156. "Grandchild.S": {ValueType: &pb.Value_StringValue{StringValue: "grandchild saved 10"}},
  2157. },
  2158. },
  2159. }},
  2160. "String": {ValueType: &pb.Value_EntityValue{
  2161. EntityValue: &pb.Entity{
  2162. Properties: map[string]*pb.Value{
  2163. "SS": {ValueType: &pb.Value_StringValue{StringValue: "SAVED"}},
  2164. },
  2165. },
  2166. }},
  2167. },
  2168. },
  2169. }},
  2170. },
  2171. },
  2172. wantLoad: &Grandparent{
  2173. Parent: Parent{
  2174. Child: Child{
  2175. I: 1,
  2176. Grandchild: Grandchild{
  2177. S: "grandchild loaded",
  2178. },
  2179. },
  2180. String: "LOADED",
  2181. },
  2182. },
  2183. },
  2184. {
  2185. desc: "parent has flatten option enabled, child impl PLS",
  2186. src: &GrandparentFlatten{
  2187. Parent: Parent{
  2188. Child: Child{
  2189. I: 7,
  2190. Grandchild: Grandchild{
  2191. S: "BAD",
  2192. },
  2193. },
  2194. String: plsString("something"),
  2195. },
  2196. },
  2197. wantSave: &pb.Entity{
  2198. Key: keyToProto(testKey0),
  2199. Properties: map[string]*pb.Value{
  2200. "Parent.Child.I": {ValueType: &pb.Value_IntegerValue{IntegerValue: 8}},
  2201. "Parent.Child.Grandchild.S": {ValueType: &pb.Value_StringValue{StringValue: "grandchild saved 8"}},
  2202. "Parent.String.SS": {ValueType: &pb.Value_StringValue{StringValue: "SAVED"}},
  2203. },
  2204. },
  2205. wantLoad: &GrandparentFlatten{
  2206. Parent: Parent{
  2207. Child: Child{
  2208. I: 1,
  2209. Grandchild: Grandchild{
  2210. S: "grandchild loaded",
  2211. },
  2212. },
  2213. String: "LOADED",
  2214. },
  2215. },
  2216. },
  2217. {
  2218. desc: "parent has flatten option enabled, child (ptr to) impl PLS",
  2219. src: &GrandparentOfPtrFlatten{
  2220. Parent: ParentOfPtr{
  2221. Child: &Child{
  2222. I: 7,
  2223. Grandchild: Grandchild{
  2224. S: "BAD",
  2225. },
  2226. },
  2227. String: ptrToplsString("something"),
  2228. },
  2229. },
  2230. wantSave: &pb.Entity{
  2231. Key: keyToProto(testKey0),
  2232. Properties: map[string]*pb.Value{
  2233. "Parent.Child.I": {ValueType: &pb.Value_IntegerValue{IntegerValue: 8}},
  2234. "Parent.Child.Grandchild.S": {ValueType: &pb.Value_StringValue{StringValue: "grandchild saved 8"}},
  2235. "Parent.String.SS": {ValueType: &pb.Value_StringValue{StringValue: "SAVED"}},
  2236. },
  2237. },
  2238. wantLoad: &GrandparentOfPtrFlatten{
  2239. Parent: ParentOfPtr{
  2240. Child: &Child{
  2241. I: 1,
  2242. Grandchild: Grandchild{
  2243. S: "grandchild loaded",
  2244. },
  2245. },
  2246. String: ptrToplsString("LOADED"),
  2247. },
  2248. },
  2249. },
  2250. {
  2251. desc: "children (slice of) impl PLS",
  2252. src: &GrandparentOfSlice{
  2253. Parent: ParentOfSlice{
  2254. Children: []Child{
  2255. {
  2256. I: 7,
  2257. Grandchild: Grandchild{
  2258. S: "BAD",
  2259. },
  2260. },
  2261. {
  2262. I: 9,
  2263. Grandchild: Grandchild{
  2264. S: "BAD2",
  2265. },
  2266. },
  2267. },
  2268. Strings: []plsString{
  2269. "something1",
  2270. "something2",
  2271. },
  2272. },
  2273. },
  2274. wantSave: &pb.Entity{
  2275. Key: keyToProto(testKey0),
  2276. Properties: map[string]*pb.Value{
  2277. "Parent": {ValueType: &pb.Value_EntityValue{
  2278. EntityValue: &pb.Entity{
  2279. Properties: map[string]*pb.Value{
  2280. "Children": {ValueType: &pb.Value_ArrayValue{
  2281. ArrayValue: &pb.ArrayValue{Values: []*pb.Value{
  2282. {ValueType: &pb.Value_EntityValue{
  2283. EntityValue: &pb.Entity{
  2284. Properties: map[string]*pb.Value{
  2285. "I": {ValueType: &pb.Value_IntegerValue{IntegerValue: 8}},
  2286. "Grandchild.S": {ValueType: &pb.Value_StringValue{StringValue: "grandchild saved 8"}},
  2287. },
  2288. },
  2289. }},
  2290. {ValueType: &pb.Value_EntityValue{
  2291. EntityValue: &pb.Entity{
  2292. Properties: map[string]*pb.Value{
  2293. "I": {ValueType: &pb.Value_IntegerValue{IntegerValue: 10}},
  2294. "Grandchild.S": {ValueType: &pb.Value_StringValue{StringValue: "grandchild saved 10"}},
  2295. },
  2296. },
  2297. }},
  2298. }},
  2299. }},
  2300. "Strings": {ValueType: &pb.Value_ArrayValue{
  2301. ArrayValue: &pb.ArrayValue{Values: []*pb.Value{
  2302. {ValueType: &pb.Value_EntityValue{
  2303. EntityValue: &pb.Entity{
  2304. Properties: map[string]*pb.Value{
  2305. "SS": {ValueType: &pb.Value_StringValue{StringValue: "SAVED"}},
  2306. },
  2307. },
  2308. }},
  2309. {ValueType: &pb.Value_EntityValue{
  2310. EntityValue: &pb.Entity{
  2311. Properties: map[string]*pb.Value{
  2312. "SS": {ValueType: &pb.Value_StringValue{StringValue: "SAVED"}},
  2313. },
  2314. },
  2315. }},
  2316. }},
  2317. }},
  2318. },
  2319. },
  2320. }},
  2321. },
  2322. },
  2323. wantLoad: &GrandparentOfSlice{
  2324. Parent: ParentOfSlice{
  2325. Children: []Child{
  2326. {
  2327. I: 1,
  2328. Grandchild: Grandchild{
  2329. S: "grandchild loaded",
  2330. },
  2331. },
  2332. {
  2333. I: 1,
  2334. Grandchild: Grandchild{
  2335. S: "grandchild loaded",
  2336. },
  2337. },
  2338. },
  2339. Strings: []plsString{
  2340. "LOADED",
  2341. "LOADED",
  2342. },
  2343. },
  2344. },
  2345. },
  2346. {
  2347. desc: "children (slice of ptrs) impl PLS",
  2348. src: &GrandparentOfSlicePtrs{
  2349. Parent: ParentOfSlicePtrs{
  2350. Children: []*Child{
  2351. {
  2352. I: 7,
  2353. Grandchild: Grandchild{
  2354. S: "BAD",
  2355. },
  2356. },
  2357. {
  2358. I: 9,
  2359. Grandchild: Grandchild{
  2360. S: "BAD2",
  2361. },
  2362. },
  2363. },
  2364. Strings: []*plsString{
  2365. ptrToplsString("something1"),
  2366. ptrToplsString("something2"),
  2367. },
  2368. },
  2369. },
  2370. wantSave: &pb.Entity{
  2371. Key: keyToProto(testKey0),
  2372. Properties: map[string]*pb.Value{
  2373. "Parent": {ValueType: &pb.Value_EntityValue{
  2374. EntityValue: &pb.Entity{
  2375. Properties: map[string]*pb.Value{
  2376. "Children": {ValueType: &pb.Value_ArrayValue{
  2377. ArrayValue: &pb.ArrayValue{Values: []*pb.Value{
  2378. {ValueType: &pb.Value_EntityValue{
  2379. EntityValue: &pb.Entity{
  2380. Properties: map[string]*pb.Value{
  2381. "I": {ValueType: &pb.Value_IntegerValue{IntegerValue: 8}},
  2382. "Grandchild.S": {ValueType: &pb.Value_StringValue{StringValue: "grandchild saved 8"}},
  2383. },
  2384. },
  2385. }},
  2386. {ValueType: &pb.Value_EntityValue{
  2387. EntityValue: &pb.Entity{
  2388. Properties: map[string]*pb.Value{
  2389. "I": {ValueType: &pb.Value_IntegerValue{IntegerValue: 10}},
  2390. "Grandchild.S": {ValueType: &pb.Value_StringValue{StringValue: "grandchild saved 10"}},
  2391. },
  2392. },
  2393. }},
  2394. }},
  2395. }},
  2396. "Strings": {ValueType: &pb.Value_ArrayValue{
  2397. ArrayValue: &pb.ArrayValue{Values: []*pb.Value{
  2398. {ValueType: &pb.Value_EntityValue{
  2399. EntityValue: &pb.Entity{
  2400. Properties: map[string]*pb.Value{
  2401. "SS": {ValueType: &pb.Value_StringValue{StringValue: "SAVED"}},
  2402. },
  2403. },
  2404. }},
  2405. {ValueType: &pb.Value_EntityValue{
  2406. EntityValue: &pb.Entity{
  2407. Properties: map[string]*pb.Value{
  2408. "SS": {ValueType: &pb.Value_StringValue{StringValue: "SAVED"}},
  2409. },
  2410. },
  2411. }},
  2412. }},
  2413. }},
  2414. },
  2415. },
  2416. }},
  2417. },
  2418. },
  2419. wantLoad: &GrandparentOfSlicePtrs{
  2420. Parent: ParentOfSlicePtrs{
  2421. Children: []*Child{
  2422. {
  2423. I: 1,
  2424. Grandchild: Grandchild{
  2425. S: "grandchild loaded",
  2426. },
  2427. },
  2428. {
  2429. I: 1,
  2430. Grandchild: Grandchild{
  2431. S: "grandchild loaded",
  2432. },
  2433. },
  2434. },
  2435. Strings: []*plsString{
  2436. ptrToplsString("LOADED"),
  2437. ptrToplsString("LOADED"),
  2438. },
  2439. },
  2440. },
  2441. },
  2442. {
  2443. desc: "parent has flatten option, children (slice of) impl PLS",
  2444. src: &GrandparentOfSliceFlatten{
  2445. Parent: ParentOfSlice{
  2446. Children: []Child{
  2447. {
  2448. I: 7,
  2449. Grandchild: Grandchild{
  2450. S: "BAD",
  2451. },
  2452. },
  2453. {
  2454. I: 9,
  2455. Grandchild: Grandchild{
  2456. S: "BAD2",
  2457. },
  2458. },
  2459. },
  2460. Strings: []plsString{
  2461. "something1",
  2462. "something2",
  2463. },
  2464. },
  2465. },
  2466. wantSave: &pb.Entity{
  2467. Key: keyToProto(testKey0),
  2468. Properties: map[string]*pb.Value{
  2469. "Parent.Children.I": {ValueType: &pb.Value_ArrayValue{ArrayValue: &pb.ArrayValue{
  2470. Values: []*pb.Value{
  2471. {ValueType: &pb.Value_IntegerValue{IntegerValue: 8}},
  2472. {ValueType: &pb.Value_IntegerValue{IntegerValue: 10}},
  2473. },
  2474. },
  2475. }},
  2476. "Parent.Children.Grandchild.S": {ValueType: &pb.Value_ArrayValue{ArrayValue: &pb.ArrayValue{
  2477. Values: []*pb.Value{
  2478. {ValueType: &pb.Value_StringValue{StringValue: "grandchild saved 8"}},
  2479. {ValueType: &pb.Value_StringValue{StringValue: "grandchild saved 10"}},
  2480. },
  2481. },
  2482. }},
  2483. "Parent.Strings.SS": {ValueType: &pb.Value_ArrayValue{ArrayValue: &pb.ArrayValue{
  2484. Values: []*pb.Value{
  2485. {ValueType: &pb.Value_StringValue{StringValue: "SAVED"}},
  2486. {ValueType: &pb.Value_StringValue{StringValue: "SAVED"}},
  2487. },
  2488. },
  2489. }},
  2490. },
  2491. },
  2492. wantLoad: &GrandparentOfSliceFlatten{
  2493. Parent: ParentOfSlice{
  2494. Children: []Child{
  2495. {
  2496. I: 1,
  2497. Grandchild: Grandchild{
  2498. S: "grandchild loaded",
  2499. },
  2500. },
  2501. {
  2502. I: 1,
  2503. Grandchild: Grandchild{
  2504. S: "grandchild loaded",
  2505. },
  2506. },
  2507. },
  2508. Strings: []plsString{
  2509. "LOADED",
  2510. "LOADED",
  2511. },
  2512. },
  2513. },
  2514. },
  2515. {
  2516. desc: "parent has flatten option, children (slice of ptrs) impl PLS",
  2517. src: &GrandparentOfSlicePtrsFlatten{
  2518. Parent: ParentOfSlicePtrs{
  2519. Children: []*Child{
  2520. {
  2521. I: 7,
  2522. Grandchild: Grandchild{
  2523. S: "BAD",
  2524. },
  2525. },
  2526. {
  2527. I: 9,
  2528. Grandchild: Grandchild{
  2529. S: "BAD2",
  2530. },
  2531. },
  2532. },
  2533. Strings: []*plsString{
  2534. ptrToplsString("something1"),
  2535. ptrToplsString("something1"),
  2536. },
  2537. },
  2538. },
  2539. wantSave: &pb.Entity{
  2540. Key: keyToProto(testKey0),
  2541. Properties: map[string]*pb.Value{
  2542. "Parent.Children.I": {ValueType: &pb.Value_ArrayValue{ArrayValue: &pb.ArrayValue{
  2543. Values: []*pb.Value{
  2544. {ValueType: &pb.Value_IntegerValue{IntegerValue: 8}},
  2545. {ValueType: &pb.Value_IntegerValue{IntegerValue: 10}},
  2546. },
  2547. },
  2548. }},
  2549. "Parent.Children.Grandchild.S": {ValueType: &pb.Value_ArrayValue{ArrayValue: &pb.ArrayValue{
  2550. Values: []*pb.Value{
  2551. {ValueType: &pb.Value_StringValue{StringValue: "grandchild saved 8"}},
  2552. {ValueType: &pb.Value_StringValue{StringValue: "grandchild saved 10"}},
  2553. },
  2554. },
  2555. }},
  2556. "Parent.Strings.SS": {ValueType: &pb.Value_ArrayValue{ArrayValue: &pb.ArrayValue{
  2557. Values: []*pb.Value{
  2558. {ValueType: &pb.Value_StringValue{StringValue: "SAVED"}},
  2559. {ValueType: &pb.Value_StringValue{StringValue: "SAVED"}},
  2560. },
  2561. },
  2562. }},
  2563. },
  2564. },
  2565. wantLoad: &GrandparentOfSlicePtrsFlatten{
  2566. Parent: ParentOfSlicePtrs{
  2567. Children: []*Child{
  2568. {
  2569. I: 1,
  2570. Grandchild: Grandchild{
  2571. S: "grandchild loaded",
  2572. },
  2573. },
  2574. {
  2575. I: 1,
  2576. Grandchild: Grandchild{
  2577. S: "grandchild loaded",
  2578. },
  2579. },
  2580. },
  2581. Strings: []*plsString{
  2582. ptrToplsString("LOADED"),
  2583. ptrToplsString("LOADED"),
  2584. },
  2585. },
  2586. },
  2587. },
  2588. }
  2589. for _, tc := range testCases {
  2590. e, err := saveEntity(testKey0, tc.src)
  2591. if tc.saveErr == "" { // Want no error.
  2592. if err != nil {
  2593. t.Errorf("%s: save: %v", tc.desc, err)
  2594. continue
  2595. }
  2596. if !testutil.Equal(e, tc.wantSave) {
  2597. t.Errorf("%s: save: \ngot: %+v\nwant: %+v", tc.desc, e, tc.wantSave)
  2598. continue
  2599. }
  2600. } else { // Want error.
  2601. if err == nil {
  2602. t.Errorf("%s: save: want err", tc.desc)
  2603. continue
  2604. }
  2605. if !strings.Contains(err.Error(), tc.saveErr) {
  2606. t.Errorf("%s: save: \ngot err '%s'\nwant err '%s'", tc.desc, err.Error(), tc.saveErr)
  2607. }
  2608. continue
  2609. }
  2610. gota := reflect.New(reflect.TypeOf(tc.wantLoad).Elem()).Interface()
  2611. err = loadEntityProto(gota, e)
  2612. if tc.loadErr == "" { // Want no error.
  2613. if err != nil {
  2614. t.Errorf("%s: load: %v", tc.desc, err)
  2615. continue
  2616. }
  2617. if !testutil.Equal(gota, tc.wantLoad) {
  2618. t.Errorf("%s: load: \ngot: %+v\nwant: %+v", tc.desc, gota, tc.wantLoad)
  2619. continue
  2620. }
  2621. } else { // Want error.
  2622. if err == nil {
  2623. t.Errorf("%s: load: want err", tc.desc)
  2624. continue
  2625. }
  2626. if !strings.Contains(err.Error(), tc.loadErr) {
  2627. t.Errorf("%s: load: \ngot err '%s'\nwant err '%s'", tc.desc, err.Error(), tc.loadErr)
  2628. }
  2629. }
  2630. }
  2631. }
  2632. func TestQueryConstruction(t *testing.T) {
  2633. tests := []struct {
  2634. q, exp *Query
  2635. err string
  2636. }{
  2637. {
  2638. q: NewQuery("Foo"),
  2639. exp: &Query{
  2640. kind: "Foo",
  2641. limit: -1,
  2642. },
  2643. },
  2644. {
  2645. // Regular filtered query with standard spacing.
  2646. q: NewQuery("Foo").Filter("foo >", 7),
  2647. exp: &Query{
  2648. kind: "Foo",
  2649. filter: []filter{
  2650. {
  2651. FieldName: "foo",
  2652. Op: greaterThan,
  2653. Value: 7,
  2654. },
  2655. },
  2656. limit: -1,
  2657. },
  2658. },
  2659. {
  2660. // Filtered query with no spacing.
  2661. q: NewQuery("Foo").Filter("foo=", 6),
  2662. exp: &Query{
  2663. kind: "Foo",
  2664. filter: []filter{
  2665. {
  2666. FieldName: "foo",
  2667. Op: equal,
  2668. Value: 6,
  2669. },
  2670. },
  2671. limit: -1,
  2672. },
  2673. },
  2674. {
  2675. // Filtered query with funky spacing.
  2676. q: NewQuery("Foo").Filter(" foo< ", 8),
  2677. exp: &Query{
  2678. kind: "Foo",
  2679. filter: []filter{
  2680. {
  2681. FieldName: "foo",
  2682. Op: lessThan,
  2683. Value: 8,
  2684. },
  2685. },
  2686. limit: -1,
  2687. },
  2688. },
  2689. {
  2690. // Filtered query with multicharacter op.
  2691. q: NewQuery("Foo").Filter("foo >=", 9),
  2692. exp: &Query{
  2693. kind: "Foo",
  2694. filter: []filter{
  2695. {
  2696. FieldName: "foo",
  2697. Op: greaterEq,
  2698. Value: 9,
  2699. },
  2700. },
  2701. limit: -1,
  2702. },
  2703. },
  2704. {
  2705. // Query with ordering.
  2706. q: NewQuery("Foo").Order("bar"),
  2707. exp: &Query{
  2708. kind: "Foo",
  2709. order: []order{
  2710. {
  2711. FieldName: "bar",
  2712. Direction: ascending,
  2713. },
  2714. },
  2715. limit: -1,
  2716. },
  2717. },
  2718. {
  2719. // Query with reverse ordering, and funky spacing.
  2720. q: NewQuery("Foo").Order(" - bar"),
  2721. exp: &Query{
  2722. kind: "Foo",
  2723. order: []order{
  2724. {
  2725. FieldName: "bar",
  2726. Direction: descending,
  2727. },
  2728. },
  2729. limit: -1,
  2730. },
  2731. },
  2732. {
  2733. // Query with an empty ordering.
  2734. q: NewQuery("Foo").Order(""),
  2735. err: "empty order",
  2736. },
  2737. {
  2738. // Query with a + ordering.
  2739. q: NewQuery("Foo").Order("+bar"),
  2740. err: "invalid order",
  2741. },
  2742. }
  2743. for i, test := range tests {
  2744. if test.q.err != nil {
  2745. got := test.q.err.Error()
  2746. if !strings.Contains(got, test.err) {
  2747. t.Errorf("%d: error mismatch: got %q want something containing %q", i, got, test.err)
  2748. }
  2749. continue
  2750. }
  2751. if !testutil.Equal(test.q, test.exp, cmp.AllowUnexported(Query{})) {
  2752. t.Errorf("%d: mismatch: got %v want %v", i, test.q, test.exp)
  2753. }
  2754. }
  2755. }
  2756. func TestPutMultiTypes(t *testing.T) {
  2757. ctx := context.Background()
  2758. type S struct {
  2759. A int
  2760. B string
  2761. }
  2762. testCases := []struct {
  2763. desc string
  2764. src interface{}
  2765. wantErr bool
  2766. }{
  2767. // Test cases to check each of the valid input types for src.
  2768. // Each case has the same elements.
  2769. {
  2770. desc: "type []struct",
  2771. src: []S{
  2772. {1, "one"}, {2, "two"},
  2773. },
  2774. },
  2775. {
  2776. desc: "type []*struct",
  2777. src: []*S{
  2778. {1, "one"}, {2, "two"},
  2779. },
  2780. },
  2781. {
  2782. desc: "type []interface{} with PLS elems",
  2783. src: []interface{}{
  2784. &PropertyList{Property{Name: "A", Value: 1}, Property{Name: "B", Value: "one"}},
  2785. &PropertyList{Property{Name: "A", Value: 2}, Property{Name: "B", Value: "two"}},
  2786. },
  2787. },
  2788. {
  2789. desc: "type []interface{} with struct ptr elems",
  2790. src: []interface{}{
  2791. &S{1, "one"}, &S{2, "two"},
  2792. },
  2793. },
  2794. {
  2795. desc: "type []PropertyLoadSaver{}",
  2796. src: []PropertyLoadSaver{
  2797. &PropertyList{Property{Name: "A", Value: 1}, Property{Name: "B", Value: "one"}},
  2798. &PropertyList{Property{Name: "A", Value: 2}, Property{Name: "B", Value: "two"}},
  2799. },
  2800. },
  2801. {
  2802. desc: "type []P (non-pointer, *P implements PropertyLoadSaver)",
  2803. src: []PropertyList{
  2804. {Property{Name: "A", Value: 1}, Property{Name: "B", Value: "one"}},
  2805. {Property{Name: "A", Value: 2}, Property{Name: "B", Value: "two"}},
  2806. },
  2807. },
  2808. // Test some invalid cases.
  2809. {
  2810. desc: "type []interface{} with struct elems",
  2811. src: []interface{}{
  2812. S{1, "one"}, S{2, "two"},
  2813. },
  2814. wantErr: true,
  2815. },
  2816. {
  2817. desc: "PropertyList",
  2818. src: PropertyList{
  2819. Property{Name: "A", Value: 1},
  2820. Property{Name: "B", Value: "one"},
  2821. },
  2822. wantErr: true,
  2823. },
  2824. {
  2825. desc: "type []int",
  2826. src: []int{1, 2},
  2827. wantErr: true,
  2828. },
  2829. {
  2830. desc: "not a slice",
  2831. src: S{1, "one"},
  2832. wantErr: true,
  2833. },
  2834. }
  2835. // Use the same keys and expected entities for all tests.
  2836. keys := []*Key{
  2837. NameKey("testKind", "first", nil),
  2838. NameKey("testKind", "second", nil),
  2839. }
  2840. want := []*pb.Mutation{
  2841. {Operation: &pb.Mutation_Upsert{
  2842. Upsert: &pb.Entity{
  2843. Key: keyToProto(keys[0]),
  2844. Properties: map[string]*pb.Value{
  2845. "A": {ValueType: &pb.Value_IntegerValue{IntegerValue: 1}},
  2846. "B": {ValueType: &pb.Value_StringValue{StringValue: "one"}},
  2847. },
  2848. }}},
  2849. {Operation: &pb.Mutation_Upsert{
  2850. Upsert: &pb.Entity{
  2851. Key: keyToProto(keys[1]),
  2852. Properties: map[string]*pb.Value{
  2853. "A": {ValueType: &pb.Value_IntegerValue{IntegerValue: 2}},
  2854. "B": {ValueType: &pb.Value_StringValue{StringValue: "two"}},
  2855. },
  2856. }}},
  2857. }
  2858. for _, tt := range testCases {
  2859. // Set up a fake client which captures upserts.
  2860. var got []*pb.Mutation
  2861. client := &Client{
  2862. client: &fakeClient{
  2863. commitFn: func(req *pb.CommitRequest) (*pb.CommitResponse, error) {
  2864. got = req.Mutations
  2865. return &pb.CommitResponse{}, nil
  2866. },
  2867. },
  2868. }
  2869. _, err := client.PutMulti(ctx, keys, tt.src)
  2870. if err != nil {
  2871. if !tt.wantErr {
  2872. t.Errorf("%s: error %v", tt.desc, err)
  2873. }
  2874. continue
  2875. }
  2876. if tt.wantErr {
  2877. t.Errorf("%s: wanted error, but none returned", tt.desc)
  2878. continue
  2879. }
  2880. if len(got) != len(want) {
  2881. t.Errorf("%s: got %d entities, want %d", tt.desc, len(got), len(want))
  2882. continue
  2883. }
  2884. for i, e := range got {
  2885. if !proto.Equal(e, want[i]) {
  2886. t.Logf("%s: entity %d doesn't match\ngot: %v\nwant: %v", tt.desc, i, e, want[i])
  2887. }
  2888. }
  2889. }
  2890. }
  2891. func TestNoIndexOnSliceProperties(t *testing.T) {
  2892. // Check that ExcludeFromIndexes is set on the inner elements,
  2893. // rather than the top-level ArrayValue value.
  2894. pl := PropertyList{
  2895. Property{
  2896. Name: "repeated",
  2897. Value: []interface{}{
  2898. 123,
  2899. false,
  2900. "short",
  2901. strings.Repeat("a", 1503),
  2902. },
  2903. NoIndex: true,
  2904. },
  2905. }
  2906. key := NameKey("dummy", "dummy", nil)
  2907. entity, err := saveEntity(key, &pl)
  2908. if err != nil {
  2909. t.Fatalf("saveEntity: %v", err)
  2910. }
  2911. want := &pb.Value{
  2912. ValueType: &pb.Value_ArrayValue{ArrayValue: &pb.ArrayValue{Values: []*pb.Value{
  2913. {ValueType: &pb.Value_IntegerValue{IntegerValue: 123}, ExcludeFromIndexes: true},
  2914. {ValueType: &pb.Value_BooleanValue{BooleanValue: false}, ExcludeFromIndexes: true},
  2915. {ValueType: &pb.Value_StringValue{StringValue: "short"}, ExcludeFromIndexes: true},
  2916. {ValueType: &pb.Value_StringValue{StringValue: strings.Repeat("a", 1503)}, ExcludeFromIndexes: true},
  2917. }}},
  2918. }
  2919. if got := entity.Properties["repeated"]; !proto.Equal(got, want) {
  2920. t.Errorf("Entity proto differs\ngot: %v\nwant: %v", got, want)
  2921. }
  2922. }
  2923. type byName PropertyList
  2924. func (s byName) Len() int { return len(s) }
  2925. func (s byName) Less(i, j int) bool { return s[i].Name < s[j].Name }
  2926. func (s byName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
  2927. // sortPL sorts the property list by property name, and
  2928. // recursively sorts any nested property lists, or nested slices of
  2929. // property lists.
  2930. func sortPL(pl PropertyList) {
  2931. sort.Stable(byName(pl))
  2932. for _, p := range pl {
  2933. switch p.Value.(type) {
  2934. case *Entity:
  2935. sortPL(p.Value.(*Entity).Properties)
  2936. case []interface{}:
  2937. for _, p2 := range p.Value.([]interface{}) {
  2938. if nent, ok := p2.(*Entity); ok {
  2939. sortPL(nent.Properties)
  2940. }
  2941. }
  2942. }
  2943. }
  2944. }
  2945. func TestValidGeoPoint(t *testing.T) {
  2946. testCases := []struct {
  2947. desc string
  2948. pt GeoPoint
  2949. want bool
  2950. }{
  2951. {
  2952. "valid",
  2953. GeoPoint{67.21, 13.37},
  2954. true,
  2955. },
  2956. {
  2957. "high lat",
  2958. GeoPoint{-90.01, 13.37},
  2959. false,
  2960. },
  2961. {
  2962. "low lat",
  2963. GeoPoint{90.01, 13.37},
  2964. false,
  2965. },
  2966. {
  2967. "high lng",
  2968. GeoPoint{67.21, 182},
  2969. false,
  2970. },
  2971. {
  2972. "low lng",
  2973. GeoPoint{67.21, -181},
  2974. false,
  2975. },
  2976. }
  2977. for _, tc := range testCases {
  2978. if got := tc.pt.Valid(); got != tc.want {
  2979. t.Errorf("%s: got %v, want %v", tc.desc, got, tc.want)
  2980. }
  2981. }
  2982. }
  2983. func TestPutInvalidEntity(t *testing.T) {
  2984. // Test that trying to put an invalid entity always returns the correct error
  2985. // type.
  2986. // Fake client that can pretend to start a transaction.
  2987. fakeClient := &fakeDatastoreClient{
  2988. beginTransaction: func(*pb.BeginTransactionRequest) (*pb.BeginTransactionResponse, error) {
  2989. return &pb.BeginTransactionResponse{
  2990. Transaction: []byte("deadbeef"),
  2991. }, nil
  2992. },
  2993. }
  2994. client := &Client{
  2995. client: fakeClient,
  2996. }
  2997. ctx := context.Background()
  2998. key := IncompleteKey("kind", nil)
  2999. _, err := client.Put(ctx, key, "invalid entity")
  3000. if err != ErrInvalidEntityType {
  3001. t.Errorf("client.Put returned err %v, want %v", err, ErrInvalidEntityType)
  3002. }
  3003. _, err = client.PutMulti(ctx, []*Key{key}, []interface{}{"invalid entity"})
  3004. if me, ok := err.(MultiError); !ok {
  3005. t.Errorf("client.PutMulti returned err %v, want MultiError type", err)
  3006. } else if len(me) != 1 || me[0] != ErrInvalidEntityType {
  3007. t.Errorf("client.PutMulti returned err %v, want MulitError{ErrInvalidEntityType}", err)
  3008. }
  3009. client.RunInTransaction(ctx, func(tx *Transaction) error {
  3010. _, err := tx.Put(key, "invalid entity")
  3011. if err != ErrInvalidEntityType {
  3012. t.Errorf("tx.Put returned err %v, want %v", err, ErrInvalidEntityType)
  3013. }
  3014. _, err = tx.PutMulti([]*Key{key}, []interface{}{"invalid entity"})
  3015. if me, ok := err.(MultiError); !ok {
  3016. t.Errorf("tx.PutMulti returned err %v, want MultiError type", err)
  3017. } else if len(me) != 1 || me[0] != ErrInvalidEntityType {
  3018. t.Errorf("tx.PutMulti returned err %v, want MulitError{ErrInvalidEntityType}", err)
  3019. }
  3020. return errors.New("bang") // Return error: we don't actually want to commit.
  3021. })
  3022. }
  3023. func TestDeferred(t *testing.T) {
  3024. type Ent struct {
  3025. A int
  3026. B string
  3027. }
  3028. keys := []*Key{
  3029. NameKey("testKind", "first", nil),
  3030. NameKey("testKind", "second", nil),
  3031. }
  3032. entity1 := &pb.Entity{
  3033. Key: keyToProto(keys[0]),
  3034. Properties: map[string]*pb.Value{
  3035. "A": {ValueType: &pb.Value_IntegerValue{IntegerValue: 1}},
  3036. "B": {ValueType: &pb.Value_StringValue{StringValue: "one"}},
  3037. },
  3038. }
  3039. entity2 := &pb.Entity{
  3040. Key: keyToProto(keys[1]),
  3041. Properties: map[string]*pb.Value{
  3042. "A": {ValueType: &pb.Value_IntegerValue{IntegerValue: 2}},
  3043. "B": {ValueType: &pb.Value_StringValue{StringValue: "two"}},
  3044. },
  3045. }
  3046. // count keeps track of the number of times fakeClient.lookup has been
  3047. // called.
  3048. var count int
  3049. // Fake client that will return Deferred keys in resp on the first call.
  3050. fakeClient := &fakeDatastoreClient{
  3051. lookup: func(*pb.LookupRequest) (*pb.LookupResponse, error) {
  3052. count++
  3053. // On the first call, we return deferred keys.
  3054. if count == 1 {
  3055. return &pb.LookupResponse{
  3056. Found: []*pb.EntityResult{
  3057. {
  3058. Entity: entity1,
  3059. Version: 1,
  3060. },
  3061. },
  3062. Deferred: []*pb.Key{
  3063. keyToProto(keys[1]),
  3064. },
  3065. }, nil
  3066. }
  3067. // On the second call, we do not return any more deferred keys.
  3068. return &pb.LookupResponse{
  3069. Found: []*pb.EntityResult{
  3070. {
  3071. Entity: entity2,
  3072. Version: 1,
  3073. },
  3074. },
  3075. }, nil
  3076. },
  3077. }
  3078. client := &Client{
  3079. client: fakeClient,
  3080. }
  3081. ctx := context.Background()
  3082. dst := make([]Ent, len(keys))
  3083. err := client.GetMulti(ctx, keys, dst)
  3084. if err != nil {
  3085. t.Fatalf("client.Get: %v", err)
  3086. }
  3087. if count != 2 {
  3088. t.Fatalf("expected client.lookup to be called 2 times. Got %d", count)
  3089. }
  3090. if len(dst) != 2 {
  3091. t.Fatalf("expected 2 entities returned, got %d", len(dst))
  3092. }
  3093. for _, e := range dst {
  3094. if e.A == 1 {
  3095. if e.B != "one" {
  3096. t.Fatalf("unexpected entity %+v", e)
  3097. }
  3098. } else if e.A == 2 {
  3099. if e.B != "two" {
  3100. t.Fatalf("unexpected entity %+v", e)
  3101. }
  3102. } else {
  3103. t.Fatalf("unexpected entity %+v", e)
  3104. }
  3105. }
  3106. }
  3107. type KeyLoaderEnt struct {
  3108. A int
  3109. K *Key
  3110. }
  3111. func (e *KeyLoaderEnt) Load(p []Property) error {
  3112. e.A = 2
  3113. return nil
  3114. }
  3115. func (e *KeyLoaderEnt) LoadKey(k *Key) error {
  3116. e.K = k
  3117. return nil
  3118. }
  3119. func (e *KeyLoaderEnt) Save() ([]Property, error) {
  3120. return []Property{{Name: "A", Value: int64(3)}}, nil
  3121. }
  3122. func TestKeyLoaderEndToEnd(t *testing.T) {
  3123. keys := []*Key{
  3124. NameKey("testKind", "first", nil),
  3125. NameKey("testKind", "second", nil),
  3126. }
  3127. entity1 := &pb.Entity{
  3128. Key: keyToProto(keys[0]),
  3129. Properties: map[string]*pb.Value{
  3130. "A": {ValueType: &pb.Value_IntegerValue{IntegerValue: 1}},
  3131. "B": {ValueType: &pb.Value_StringValue{StringValue: "one"}},
  3132. },
  3133. }
  3134. entity2 := &pb.Entity{
  3135. Key: keyToProto(keys[1]),
  3136. Properties: map[string]*pb.Value{
  3137. "A": {ValueType: &pb.Value_IntegerValue{IntegerValue: 2}},
  3138. "B": {ValueType: &pb.Value_StringValue{StringValue: "two"}},
  3139. },
  3140. }
  3141. fakeClient := &fakeDatastoreClient{
  3142. lookup: func(*pb.LookupRequest) (*pb.LookupResponse, error) {
  3143. return &pb.LookupResponse{
  3144. Found: []*pb.EntityResult{
  3145. {
  3146. Entity: entity1,
  3147. Version: 1,
  3148. },
  3149. {
  3150. Entity: entity2,
  3151. Version: 1,
  3152. },
  3153. },
  3154. }, nil
  3155. },
  3156. }
  3157. client := &Client{
  3158. client: fakeClient,
  3159. }
  3160. ctx := context.Background()
  3161. dst := make([]*KeyLoaderEnt, len(keys))
  3162. err := client.GetMulti(ctx, keys, dst)
  3163. if err != nil {
  3164. t.Fatalf("client.Get: %v", err)
  3165. }
  3166. for i := range dst {
  3167. if !testutil.Equal(dst[i].K, keys[i]) {
  3168. t.Fatalf("unexpected entity %d to have key %+v, got %+v", i, keys[i], dst[i].K)
  3169. }
  3170. }
  3171. }
  3172. func TestDeferredMissing(t *testing.T) {
  3173. type Ent struct {
  3174. A int
  3175. B string
  3176. }
  3177. keys := []*Key{
  3178. NameKey("testKind", "first", nil),
  3179. NameKey("testKind", "second", nil),
  3180. }
  3181. entity1 := &pb.Entity{
  3182. Key: keyToProto(keys[0]),
  3183. }
  3184. entity2 := &pb.Entity{
  3185. Key: keyToProto(keys[1]),
  3186. }
  3187. var count int
  3188. fakeClient := &fakeDatastoreClient{
  3189. lookup: func(*pb.LookupRequest) (*pb.LookupResponse, error) {
  3190. count++
  3191. if count == 1 {
  3192. return &pb.LookupResponse{
  3193. Missing: []*pb.EntityResult{
  3194. {
  3195. Entity: entity1,
  3196. Version: 1,
  3197. },
  3198. },
  3199. Deferred: []*pb.Key{
  3200. keyToProto(keys[1]),
  3201. },
  3202. }, nil
  3203. }
  3204. return &pb.LookupResponse{
  3205. Missing: []*pb.EntityResult{
  3206. {
  3207. Entity: entity2,
  3208. Version: 1,
  3209. },
  3210. },
  3211. }, nil
  3212. },
  3213. }
  3214. client := &Client{
  3215. client: fakeClient,
  3216. }
  3217. ctx := context.Background()
  3218. dst := make([]Ent, len(keys))
  3219. err := client.GetMulti(ctx, keys, dst)
  3220. errs, ok := err.(MultiError)
  3221. if !ok {
  3222. t.Fatalf("expected error returns to be MultiError; got %v", err)
  3223. }
  3224. if len(errs) != 2 {
  3225. t.Fatalf("expected 2 errors returns, got %d", len(errs))
  3226. }
  3227. if errs[0] != ErrNoSuchEntity {
  3228. t.Fatalf("expected error to be ErrNoSuchEntity; got %v", errs[0])
  3229. }
  3230. if errs[1] != ErrNoSuchEntity {
  3231. t.Fatalf("expected error to be ErrNoSuchEntity; got %v", errs[1])
  3232. }
  3233. if count != 2 {
  3234. t.Fatalf("expected client.lookup to be called 2 times. Got %d", count)
  3235. }
  3236. if len(dst) != 2 {
  3237. t.Fatalf("expected 2 entities returned, got %d", len(dst))
  3238. }
  3239. for _, e := range dst {
  3240. if e.A != 0 || e.B != "" {
  3241. t.Fatalf("unexpected entity %+v", e)
  3242. }
  3243. }
  3244. }
  3245. func TestGetWithNilKey(t *testing.T) {
  3246. client := &Client{}
  3247. err := client.Get(context.Background(), nil, []Property{})
  3248. if err != ErrInvalidKey {
  3249. t.Fatalf("want ErrInvalidKey, got %v", err)
  3250. }
  3251. }
  3252. func TestGetMultiWithNilKey(t *testing.T) {
  3253. client := &Client{}
  3254. dest := make([]PropertyList, 1)
  3255. err := client.GetMulti(context.Background(), []*Key{nil}, dest)
  3256. if me, ok := err.(MultiError); !ok {
  3257. t.Fatalf("want MultiError, got %v", err)
  3258. } else if len(me) != 1 || me[0] != ErrInvalidKey {
  3259. t.Fatalf("want MultiError{ErrInvalidKey}, got %v", me)
  3260. }
  3261. }
  3262. func TestGetWithIncompleteKey(t *testing.T) {
  3263. client := &Client{}
  3264. err := client.Get(context.Background(), &Key{Kind: "testKind"}, []Property{})
  3265. if err == nil {
  3266. t.Fatalf("want err, got nil")
  3267. }
  3268. }
  3269. func TestGetMultiWithIncompleteKey(t *testing.T) {
  3270. client := &Client{}
  3271. dest := make([]PropertyList, 1)
  3272. err := client.GetMulti(context.Background(), []*Key{{Kind: "testKind"}}, dest)
  3273. if me, ok := err.(MultiError); !ok {
  3274. t.Fatalf("want MultiError, got %v", err)
  3275. } else if len(me) != 1 || me[0] == nil {
  3276. t.Fatalf("want MultiError{err}, got %v", me)
  3277. }
  3278. }
  3279. func TestDeleteWithNilKey(t *testing.T) {
  3280. client := &Client{}
  3281. err := client.Delete(context.Background(), nil)
  3282. if err != ErrInvalidKey {
  3283. t.Fatalf("want ErrInvalidKey, got %v", err)
  3284. }
  3285. }
  3286. func TestDeleteMultiWithNilKey(t *testing.T) {
  3287. client := &Client{}
  3288. err := client.DeleteMulti(context.Background(), []*Key{nil})
  3289. if me, ok := err.(MultiError); !ok {
  3290. t.Fatalf("want MultiError, got %v", err)
  3291. } else if len(me) != 1 || me[0] != ErrInvalidKey {
  3292. t.Fatalf("want MultiError{ErrInvalidKey}, got %v", me)
  3293. }
  3294. }
  3295. func TestDeleteWithIncompleteKey(t *testing.T) {
  3296. client := &Client{}
  3297. err := client.Delete(context.Background(), &Key{Kind: "testKind"})
  3298. if err == nil {
  3299. t.Fatalf("want err, got nil")
  3300. }
  3301. }
  3302. func TestDeleteMultiWithIncompleteKey(t *testing.T) {
  3303. client := &Client{}
  3304. err := client.DeleteMulti(context.Background(), []*Key{{Kind: "testKind"}})
  3305. if me, ok := err.(MultiError); !ok {
  3306. t.Fatalf("want MultiError, got %v", err)
  3307. } else if len(me) != 1 || me[0] == nil {
  3308. t.Fatalf("want MultiError{err}, got %v", me)
  3309. }
  3310. }
  3311. type fakeDatastoreClient struct {
  3312. pb.DatastoreClient
  3313. // Optional handlers for the datastore methods.
  3314. // Any handlers left undefined will return an error.
  3315. lookup func(*pb.LookupRequest) (*pb.LookupResponse, error)
  3316. runQuery func(*pb.RunQueryRequest) (*pb.RunQueryResponse, error)
  3317. beginTransaction func(*pb.BeginTransactionRequest) (*pb.BeginTransactionResponse, error)
  3318. commit func(*pb.CommitRequest) (*pb.CommitResponse, error)
  3319. rollback func(*pb.RollbackRequest) (*pb.RollbackResponse, error)
  3320. allocateIds func(*pb.AllocateIdsRequest) (*pb.AllocateIdsResponse, error)
  3321. }
  3322. func (c *fakeDatastoreClient) Lookup(ctx context.Context, in *pb.LookupRequest, opts ...grpc.CallOption) (*pb.LookupResponse, error) {
  3323. if c.lookup == nil {
  3324. return nil, errors.New("no lookup handler defined")
  3325. }
  3326. return c.lookup(in)
  3327. }
  3328. func (c *fakeDatastoreClient) RunQuery(ctx context.Context, in *pb.RunQueryRequest, opts ...grpc.CallOption) (*pb.RunQueryResponse, error) {
  3329. if c.runQuery == nil {
  3330. return nil, errors.New("no runQuery handler defined")
  3331. }
  3332. return c.runQuery(in)
  3333. }
  3334. func (c *fakeDatastoreClient) BeginTransaction(ctx context.Context, in *pb.BeginTransactionRequest, opts ...grpc.CallOption) (*pb.BeginTransactionResponse, error) {
  3335. if c.beginTransaction == nil {
  3336. return nil, errors.New("no beginTransaction handler defined")
  3337. }
  3338. return c.beginTransaction(in)
  3339. }
  3340. func (c *fakeDatastoreClient) Commit(ctx context.Context, in *pb.CommitRequest, opts ...grpc.CallOption) (*pb.CommitResponse, error) {
  3341. if c.commit == nil {
  3342. return nil, errors.New("no commit handler defined")
  3343. }
  3344. return c.commit(in)
  3345. }
  3346. func (c *fakeDatastoreClient) Rollback(ctx context.Context, in *pb.RollbackRequest, opts ...grpc.CallOption) (*pb.RollbackResponse, error) {
  3347. if c.rollback == nil {
  3348. return nil, errors.New("no rollback handler defined")
  3349. }
  3350. return c.rollback(in)
  3351. }
  3352. func (c *fakeDatastoreClient) AllocateIds(ctx context.Context, in *pb.AllocateIdsRequest, opts ...grpc.CallOption) (*pb.AllocateIdsResponse, error) {
  3353. if c.allocateIds == nil {
  3354. return nil, errors.New("no allocateIds handler defined")
  3355. }
  3356. return c.allocateIds(in)
  3357. }