Subversion Repository Public Repository

litesoft

Diff Revisions 938 vs 939 for /trunk/Java/GAE/DiscoveryTests/DatastoreServiceTests/src/org/litesoft/gae/datastoreservice/DatastoreServiceTest.java

Diff revisions: vs.
  @@ -1,5 +1,6 @@
1 1 package org.litesoft.gae.datastoreservice;
2 2
3 + import org.litesoft.core.typeutils.Objects;
3 4 import java.util.*;
4 5
5 6 import junit.framework.TestCase;
  @@ -23,748 +24,748 @@
23 24
24 25 public class DatastoreServiceTest extends TestCase
25 26 {
26 - private static final String KIND = "TheFlintstones";
27 + private static final String KIND = "TheFlintstones";
27 28
28 - private final LocalServiceTestHelper mHelper = new LocalServiceTestHelper( new LocalDatastoreServiceTestConfig() );
29 + private final LocalServiceTestHelper mHelper = new LocalServiceTestHelper( new LocalDatastoreServiceTestConfig() );
29 30
30 - public static TestSuite suite()
31 - {
32 - return new TestSuite( DatastoreServiceTest.class );
33 - }
34 -
35 - public DatastoreServiceTest( String name )
36 - {
37 - super( name );
38 - }
39 -
40 - public static void main( String[] args )
41 - {
42 - junit.textui.TestRunner.run( suite() );
43 - }
44 -
45 - @Override
46 - protected void setUp() throws Exception
47 - {
48 - super.setUp();
49 - mHelper.setUp();
50 - mConfig = DatastoreServiceConfig.Builder.withDefaults() // Deadline=null,
51 - // ImplicitTransactionManagementPolicy=NONE,
52 - // ReadPolicy.Consistency=STRONG
53 - .deadline( 5 ); // Deadline=5 secs
54 - mDatastoreService = DatastoreServiceFactory.getDatastoreService( mConfig );
55 - mGOD_Apollo = KeyFactory.createKey( "GODS", "Apollo" );
56 - mGOD_Venus = KeyFactory.createKey( "GODS", "Venus" );
57 -
58 - }
59 -
60 - @Override
61 - public void tearDown()
62 - {
63 - mHelper.tearDown();
64 - }
65 -
66 - private DatastoreServiceConfig mConfig;
67 -
68 - private DatastoreService mDatastoreService;
69 -
70 - private Key mGOD_Apollo, mGOD_Venus;
71 -
72 - private Entity createEntity( Key pGOD, String pName )
73 - {
74 - Entity zEntity = new Entity( KIND, pName, pGOD );
75 - zEntity.setUnindexedProperty( "Version", 1L );
76 -
77 - zEntity.setProperty( "Name", pName );
78 - zEntity.setUnindexedProperty( "Children", 0L );
79 - return zEntity;
80 - }
81 -
82 - private void inc( Entity pEntity, String pProperty )
83 - {
84 - Long zLong = (Long) pEntity.getProperty( pProperty );
85 - pEntity.setUnindexedProperty( pProperty, zLong + 1 );
86 - }
87 -
88 - private Entity updateChildren( Entity pEntity )
89 - {
90 - inc( pEntity, "Version" );
91 - inc( pEntity, "Children" );
92 - return pEntity;
93 - }
94 -
95 - public void test_DataStoreConfig() throws Exception
96 - {
97 - assertEquals( 5.0d, mConfig.getDeadline(), 0.0001 );
98 - assertEquals( ImplicitTransactionManagementPolicy.NONE, mConfig.getImplicitTransactionManagementPolicy() );
99 - assertEquals( Consistency.STRONG, mConfig.getReadPolicy().getConsistency() );
100 - }
101 -
102 - public void test_NonConflictingDifferentGodsOverlapingTransactionsNew() throws Exception
103 - {
104 - Transaction zApolloTransaction = mDatastoreService.beginTransaction();
105 - Transaction zVenusTransaction = mDatastoreService.beginTransaction();
106 -
107 - Entity zEntityFred = createEntity( mGOD_Apollo, "Fred" );
108 - mDatastoreService.put( zApolloTransaction, zEntityFred );
109 - Entity zEntityWilma = createEntity( mGOD_Venus, "Wilma" );
110 - mDatastoreService.put( zVenusTransaction, zEntityWilma );
111 -
112 - Entity zEntityBarney = createEntity( mGOD_Apollo, "Barney" );
113 - mDatastoreService.put( zApolloTransaction, zEntityBarney );
114 - Entity zEntityBetty = createEntity( mGOD_Venus, "Betty" );
115 - mDatastoreService.put( zVenusTransaction, zEntityBetty );
116 -
117 - zApolloTransaction.commit();
118 - zVenusTransaction.commit();
119 -
120 - readAndValidate( null, zEntityFred, "Fred", 1, 0 );
121 - readAndValidate( null, zEntityWilma, "Wilma", 1, 0 );
122 -
123 - readAndValidate( null, zEntityBarney, "Barney", 1, 0 );
124 - readAndValidate( null, zEntityBetty, "Betty", 1, 0 );
125 - }
126 -
127 - public void test_TransactionReadMultiGOD() throws Exception
128 - {
129 - Transaction zApolloTransaction = mDatastoreService.beginTransaction();
130 - Transaction zVenusTransaction = mDatastoreService.beginTransaction();
131 -
132 - Entity zEntityFred = createEntity( mGOD_Apollo, "Fred" );
133 - mDatastoreService.put( zApolloTransaction, zEntityFred );
134 - Entity zEntityWilma = createEntity( mGOD_Venus, "Wilma" );
135 - mDatastoreService.put( zVenusTransaction, zEntityWilma );
136 -
137 - zApolloTransaction.commit();
138 - zVenusTransaction.commit();
139 -
140 - Transaction zTransaction = mDatastoreService.beginTransaction();
141 - mDatastoreService.get( zTransaction, zEntityFred.getKey() ); // will
142 - // succeed!
143 - try
144 - {
145 - mDatastoreService.get( zTransaction, zEntityWilma.getKey() ); // will
146 - // Fail!
147 - fail( "Fred & Wilma - Did NOT Fail with different GODS (Entity Groups)" );
148 - }
149 - catch ( IllegalArgumentException expected )
150 - {
151 - String zMessage = expected.getMessage();
152 - assertTrue( zMessage, zMessage
153 - .startsWith( "can't operate on multiple entity groups in a single transaction." ) );
154 - }
155 - zTransaction.rollback();
156 - }
157 -
158 - public void test_TransactionUpdate() throws Exception
159 - {
160 - Transaction zApolloTransaction = mDatastoreService.beginTransaction();
161 - Transaction zVenusTransaction = mDatastoreService.beginTransaction();
162 -
163 - Entity zEntityFred = createEntity( mGOD_Apollo, "Fred" );
164 - mDatastoreService.put( zApolloTransaction, zEntityFred );
165 - Entity zEntityWilma = createEntity( mGOD_Venus, "Wilma" );
166 - mDatastoreService.put( zVenusTransaction, zEntityWilma );
167 -
168 - Entity zEntityBarney = createEntity( mGOD_Apollo, "Barney" );
169 - mDatastoreService.put( zApolloTransaction, zEntityBarney );
170 - Entity zEntityBetty = createEntity( mGOD_Venus, "Betty" );
171 - mDatastoreService.put( zVenusTransaction, zEntityBetty );
172 -
173 - zApolloTransaction.commit();
174 - zVenusTransaction.commit();
175 -
176 - zVenusTransaction = mDatastoreService.beginTransaction();
177 -
178 - zEntityWilma = updateChildren( readAndValidate( zVenusTransaction, zEntityWilma, "Wilma", 1, 0 ) );
179 - mDatastoreService.put( zVenusTransaction, zEntityWilma );
180 -
181 - Entity zEntityPebbles = createEntity( mGOD_Venus, "Pebbles" );
182 - mDatastoreService.put( zVenusTransaction, zEntityPebbles );
183 -
184 - // Can't Update Fred!
185 -
186 - zVenusTransaction.commit();
187 -
188 - zApolloTransaction = mDatastoreService.beginTransaction();
189 -
190 - zEntityBarney = updateChildren( readAndValidate( zApolloTransaction, zEntityBarney, "Barney", 1, 0 ) );
191 - mDatastoreService.put( zApolloTransaction, zEntityBarney );
192 -
193 - Entity zEntityBammBamm = createEntity( mGOD_Apollo, "BammBamm" );
194 - mDatastoreService.put( zApolloTransaction, zEntityBammBamm );
195 -
196 - // Can't Update Betty!
197 -
198 - zApolloTransaction.commit();
199 -
200 - readAndValidate( null, zEntityFred, "Fred", 1, 0 );
201 - readAndValidate( null, zEntityWilma, "Wilma", 2, 1 );
202 - readAndValidate( null, zEntityPebbles, "Pebbles", 1, 0 );
203 -
204 - readAndValidate( null, zEntityBarney, "Barney", 2, 1 );
205 - readAndValidate( null, zEntityBetty, "Betty", 1, 0 );
206 - readAndValidate( null, zEntityBammBamm, "BammBamm", 1, 0 );
207 - }
208 -
209 - public void test_NonConflictingDifferentGodsOverlapingTransactionsUpdate() throws Exception
210 - {
211 - Transaction zApolloTransaction = mDatastoreService.beginTransaction();
212 - Transaction zVenusTransaction = mDatastoreService.beginTransaction();
213 -
214 - Entity zEntityFred = createEntity( mGOD_Apollo, "Fred" );
215 - mDatastoreService.put( zApolloTransaction, zEntityFred );
216 - Entity zEntityWilma = createEntity( mGOD_Venus, "Wilma" );
217 - mDatastoreService.put( zVenusTransaction, zEntityWilma );
218 -
219 - zApolloTransaction.commit();
220 - zVenusTransaction.commit();
221 -
222 - zApolloTransaction = mDatastoreService.beginTransaction();
223 - zVenusTransaction = mDatastoreService.beginTransaction();
224 -
225 - zEntityWilma = updateChildren( readAndValidate( zVenusTransaction, zEntityWilma, "Wilma", 1, 0 ) );
226 - mDatastoreService.put( zVenusTransaction, zEntityWilma );
227 -
228 - Entity zEntityPebbles = createEntity( mGOD_Venus, "Pebbles" );
229 - mDatastoreService.put( zVenusTransaction, zEntityPebbles );
230 -
231 - zEntityFred = updateChildren( readAndValidate( zApolloTransaction, zEntityFred, "Fred", 1, 0 ) );
232 - mDatastoreService.put( zApolloTransaction, zEntityFred );
233 -
234 - zApolloTransaction.commit();
235 - zVenusTransaction.commit();
236 -
237 - readAndValidate( null, zEntityFred, "Fred", 2, 1 );
238 - readAndValidate( null, zEntityWilma, "Wilma", 2, 1 );
239 -
240 - readAndValidate( null, zEntityPebbles, "Pebbles", 1, 0 );
241 - }
242 -
243 - public void test_ConflictingSameEntityOverlapingTransactionsUpdate() throws Exception
244 - {
245 - Transaction zVenusTransaction = mDatastoreService.beginTransaction();
246 -
247 - Entity zEntityWilma = createEntity( mGOD_Venus, "Wilma" );
248 - mDatastoreService.put( zVenusTransaction, zEntityWilma );
249 -
250 - zVenusTransaction.commit();
251 -
252 - zVenusTransaction = mDatastoreService.beginTransaction();
253 -
254 - zEntityWilma = updateChildren( readAndValidate( zVenusTransaction, zEntityWilma, "Wilma", 1, 0 ) );
255 - mDatastoreService.put( zVenusTransaction, zEntityWilma );
256 -
257 - Entity zEntityPebbles = createEntity( mGOD_Venus, "Pebbles" );
258 - mDatastoreService.put( zVenusTransaction, zEntityPebbles );
259 -
260 - Transaction zVenus2Transaction = mDatastoreService.beginTransaction();
261 -
262 - Entity zEntityWilma2 = updateChildren( readAndValidate2( zVenus2Transaction, zEntityWilma, "Wilma", 1, 0 ) );
263 - mDatastoreService.put( zVenus2Transaction, zEntityWilma2 );
264 -
265 - zVenusTransaction.commit();
266 -
267 - try
268 - {
269 - zVenus2Transaction.commit();
270 - fail( "Two Transaction Wilma Update - Did NOT Fail" );
271 - }
272 - catch ( ConcurrentModificationException expected )
273 - {
274 - String zMessage = expected.getMessage();
275 - assertTrue( zMessage, zMessage.startsWith( "too much contention on these datastore entities. please try again." ) );
276 - }
277 -
278 - readAndValidate( null, zEntityWilma, "Wilma", 2, 1 );
279 - }
280 -
281 - public void test_NonConflictingSameGodDifferentEntityOverlapingTransactionsUpdate() throws Exception
282 - {
283 - Transaction zVenusTransaction = mDatastoreService.beginTransaction();
284 -
285 - Entity zEntityWilma = createEntity( mGOD_Venus, "Wilma" );
286 - mDatastoreService.put( zVenusTransaction, zEntityWilma );
287 -
288 - Entity zEntityBetty = createEntity( mGOD_Venus, "Betty" );
289 - mDatastoreService.put( zVenusTransaction, zEntityBetty );
290 -
291 - zVenusTransaction.commit();
292 -
293 - zVenusTransaction = mDatastoreService.beginTransaction();
294 -
295 - zEntityWilma = updateChildren( readAndValidate( zVenusTransaction, zEntityWilma, "Wilma", 1, 0 ) );
296 - mDatastoreService.put( zVenusTransaction, zEntityWilma );
297 -
298 - Transaction zVenus2Transaction = mDatastoreService.beginTransaction();
299 -
300 - zEntityBetty = updateChildren( readAndValidate( zVenus2Transaction, zEntityBetty, "Betty", 1, 0 ) );
301 - mDatastoreService.put( zVenus2Transaction, zEntityBetty );
302 -
303 - zVenusTransaction.commit();
304 -
305 - try
306 - {
307 - zVenus2Transaction.commit();
308 - fail( "Two Transaction Wilma & Betty Update - Did NOT Fail" );
309 - }
310 - catch ( ConcurrentModificationException expected )
311 - {
312 - String zMessage = expected.getMessage();
313 - assertTrue( zMessage, zMessage.startsWith( "too much contention on these datastore entities. please try again." ) );
314 - }
315 -
316 - readAndValidate( null, zEntityWilma, "Wilma", 2, 1 );
317 - readAndValidate2( null, zEntityBetty, "Betty", 1, 0 );
318 - }
319 -
320 - public void test_QueryAllDifferentGods() throws Exception
321 - {
322 - Transaction zApolloTransaction = mDatastoreService.beginTransaction();
323 - Transaction zVenusTransaction = mDatastoreService.beginTransaction();
324 -
325 - Entity zEntityFred = createEntity( mGOD_Apollo, "Fred" );
326 - mDatastoreService.put( zApolloTransaction, zEntityFred );
327 - Entity zEntityWilma = createEntity( mGOD_Venus, "Wilma" );
328 - mDatastoreService.put( zVenusTransaction, zEntityWilma );
329 -
330 - Entity zEntityBarney = createEntity( mGOD_Apollo, "Barney" );
331 - mDatastoreService.put( zApolloTransaction, zEntityBarney );
332 - Entity zEntityBetty = createEntity( mGOD_Venus, "Betty" );
333 - mDatastoreService.put( zVenusTransaction, zEntityBetty );
334 -
335 - zApolloTransaction.commit();
336 - zVenusTransaction.commit();
337 -
338 - PreparedQuery zQuery = mDatastoreService.prepare( new Query( KIND ).addSort( "Name" ) );
339 -
340 - List<Entity> zList = zQuery.asList( FetchOptions.Builder.withOffset( 0 ) );
341 -
342 - assertEquals( "Entities", 4, zList.size() );
343 -
344 - validate( zList.get( 0 ), "Barney", 1, 0 );
345 - validate( zList.get( 1 ), "Betty", 1, 0 );
346 - validate( zList.get( 2 ), "Fred", 1, 0 );
347 - validate( zList.get( 3 ), "Wilma", 1, 0 );
348 - }
349 -
350 - public void test_QuerySpecificGod() throws Exception
351 - {
352 - Transaction zApolloTransaction = mDatastoreService.beginTransaction();
353 - Transaction zVenusTransaction = mDatastoreService.beginTransaction();
354 -
355 - Entity zEntityFred = createEntity( mGOD_Apollo, "Fred" );
356 - mDatastoreService.put( zApolloTransaction, zEntityFred );
357 - Entity zEntityWilma = createEntity( mGOD_Venus, "Wilma" );
358 - mDatastoreService.put( zVenusTransaction, zEntityWilma );
359 -
360 - Entity zEntityBarney = createEntity( mGOD_Apollo, "Barney" );
361 - mDatastoreService.put( zApolloTransaction, zEntityBarney );
362 - Entity zEntityBetty = createEntity( mGOD_Venus, "Betty" );
363 - mDatastoreService.put( zVenusTransaction, zEntityBetty );
364 -
365 - zApolloTransaction.commit();
366 - zVenusTransaction.commit();
367 -
368 - PreparedQuery zQuery = mDatastoreService.prepare( new Query( KIND, mGOD_Apollo ).addSort( "Name" ) );
369 -
370 - List<Entity> zList = zQuery.asList( FetchOptions.Builder.withOffset( 0 ) );
371 -
372 - assertEquals( "Entities", 2, zList.size() );
373 -
374 - validate( zList.get( 0 ), "Barney", 1, 0 );
375 - validate( zList.get( 1 ), "Fred", 1, 0 );
376 - }
377 -
378 - public void test_QueryEqualsFilter() throws Exception
379 - {
380 - Transaction zApolloTransaction = mDatastoreService.beginTransaction();
381 - Transaction zVenusTransaction = mDatastoreService.beginTransaction();
382 -
383 - Entity zEntityFred = createEntity( mGOD_Apollo, "Fred" );
384 - mDatastoreService.put( zApolloTransaction, zEntityFred );
385 - Entity zEntityWilma = createEntity( mGOD_Venus, "Wilma" );
386 - mDatastoreService.put( zVenusTransaction, zEntityWilma );
387 -
388 - Entity zEntityBarney = createEntity( mGOD_Apollo, "Barney" );
389 - mDatastoreService.put( zApolloTransaction, zEntityBarney );
390 - Entity zEntityBetty = createEntity( mGOD_Venus, "Betty" );
391 - mDatastoreService.put( zVenusTransaction, zEntityBetty );
392 -
393 - zApolloTransaction.commit();
394 - zVenusTransaction.commit();
395 -
396 - PreparedQuery zQuery = mDatastoreService.prepare( new Query( KIND ).addSort( "Name" ).addFilter( "Name", Query.FilterOperator.EQUAL, "Barney") );
397 -
398 - List<Entity> zList = zQuery.asList( FetchOptions.Builder.withOffset( 0 ) );
399 -
400 - assertEquals( "Entities", 1, zList.size() );
401 -
402 - validate( zList.get( 0 ), "Barney", 1, 0 );
403 - }
404 -
405 - public void test_QueryLessThanFilter() throws Exception
406 - {
407 - Transaction zApolloTransaction = mDatastoreService.beginTransaction();
408 - Transaction zVenusTransaction = mDatastoreService.beginTransaction();
409 -
410 - Entity zEntityFred = createEntity( mGOD_Apollo, "Fred" );
411 - mDatastoreService.put( zApolloTransaction, zEntityFred );
412 - Entity zEntityWilma = createEntity( mGOD_Venus, "Wilma" );
413 - mDatastoreService.put( zVenusTransaction, zEntityWilma );
414 -
415 - Entity zEntityBarney = createEntity( mGOD_Apollo, "Barney" );
416 - mDatastoreService.put( zApolloTransaction, zEntityBarney );
417 - Entity zEntityBetty = createEntity( mGOD_Venus, "Betty" );
418 - mDatastoreService.put( zVenusTransaction, zEntityBetty );
419 -
420 - zApolloTransaction.commit();
421 - zVenusTransaction.commit();
422 -
423 - PreparedQuery zQuery = mDatastoreService.prepare( new Query( KIND ).addSort( "Name" ).addFilter( "Name", Query.FilterOperator.LESS_THAN, "C") );
424 -
425 - List<Entity> zList = zQuery.asList( FetchOptions.Builder.withOffset( 0 ) );
426 -
427 - assertEquals( "Entities", 2, zList.size() );
428 -
429 - validate( zList.get( 0 ), "Barney", 1, 0 );
430 - validate( zList.get( 1 ), "Betty", 1, 0 );
431 - }
432 -
433 - public void test_NullKey() throws Exception
434 - {
435 - try
436 - {
437 - KeyFactory.createKey( KIND, null );
438 - fail( "null Key did NOT fail" );
439 - }
440 - catch ( IllegalArgumentException expected )
441 - {
442 - String zMessage = expected.getMessage();
443 - assertTrue( zMessage, zMessage.startsWith( "name cannot be null or empty" ) );
444 - }
445 - // new Entity( KIND, null, pGOD ); // Does Not Fail, but
446 - // implicitly creates a auto-generated id key!!
447 - }
448 -
449 - public void test_EmptyKey() throws Exception
450 - {
451 - try
452 - {
453 - KeyFactory.createKey( KIND, "" );
454 - fail( "empty Key did NOT fail" );
455 - }
456 - catch ( IllegalArgumentException expected )
457 - {
458 - String zMessage = expected.getMessage();
459 - assertTrue( zMessage, zMessage.startsWith( "name cannot be null or empty" ) );
460 - }
461 - }
462 -
463 - public void test_IndexingString() throws Exception
464 - {
465 - Transaction zTransaction = mDatastoreService.beginTransaction();
466 -
467 - String v1, v2;
468 -
469 - mDatastoreService.put( zTransaction, createIndexingEntity( "Strings", null ) );
470 - mDatastoreService.put( zTransaction, createIndexingEntity( "Strings", v1 = "" ) );
471 - mDatastoreService.put( zTransaction, createIndexingEntity( "Strings", v2 = "Fred" ) );
472 -
473 - zTransaction.commit();
474 -
475 - PreparedQuery zQuery = mDatastoreService.prepare( new Query( "Strings" ).addSort( "FieldValue" ) );
476 -
477 - List<Entity> zList = zQuery.asList( FetchOptions.Builder.withOffset( 0 ) );
478 -
479 - assertEquals( "Entities", 3, zList.size() );
480 -
481 - validate( zList.get( 0 ), null );
482 - validate( zList.get( 1 ), v1 );
483 - validate( zList.get( 2 ), v2 );
484 - }
485 -
486 - public void test_IndexingBoolean() throws Exception
487 - {
488 - Transaction zTransaction = mDatastoreService.beginTransaction();
489 -
490 - Boolean v1, v2;
491 -
492 - mDatastoreService.put( zTransaction, createIndexingEntity( "Booleans", null ) );
493 - mDatastoreService.put( zTransaction, createIndexingEntity( "Booleans", v1 = Boolean.FALSE ) );
494 - mDatastoreService.put( zTransaction, createIndexingEntity( "Booleans", v2 = Boolean.TRUE ) );
495 -
496 - zTransaction.commit();
497 -
498 - PreparedQuery zQuery = mDatastoreService.prepare( new Query( "Booleans" ).addSort( "FieldValue" ) );
499 -
500 - List<Entity> zList = zQuery.asList( FetchOptions.Builder.withOffset( 0 ) );
501 -
502 - assertEquals( "Entities", 3, zList.size() );
503 -
504 - validate( zList.get( 0 ), null );
505 - validate( zList.get( 1 ), v1 );
506 - validate( zList.get( 2 ), v2 );
507 - }
508 -
509 - public void test_IndexingLong() throws Exception
510 - {
511 - Transaction zTransaction = mDatastoreService.beginTransaction();
512 -
513 - Long v1, v2;
514 -
515 - mDatastoreService.put( zTransaction, createIndexingEntity( "Longs", null ) );
516 - mDatastoreService.put( zTransaction, createIndexingEntity( "Longs", v1 = 1L ) );
517 - mDatastoreService.put( zTransaction, createIndexingEntity( "Longs", v2 = 100L ) );
518 -
519 - zTransaction.commit();
520 -
521 - PreparedQuery zQuery = mDatastoreService.prepare( new Query( "Longs" ).addSort( "FieldValue" ) );
522 -
523 - List<Entity> zList = zQuery.asList( FetchOptions.Builder.withOffset( 0 ) );
524 -
525 - assertEquals( "Entities", 3, zList.size() );
526 -
527 - validate( zList.get( 0 ), null );
528 - validate( zList.get( 1 ), v1 );
529 - validate( zList.get( 2 ), v2 );
530 - }
531 -
532 - public void test_IndexingDouble() throws Exception
533 - {
534 - Transaction zTransaction = mDatastoreService.beginTransaction();
535 -
536 - Double v1, v2;
537 -
538 - mDatastoreService.put( zTransaction, createIndexingEntity( "Doubles", null ) );
539 - mDatastoreService.put( zTransaction, createIndexingEntity( "Doubles", v1 = 1.1D ) );
540 - mDatastoreService.put( zTransaction, createIndexingEntity( "Doubles", v2 = 11.2D ) );
541 -
542 - zTransaction.commit();
543 -
544 - PreparedQuery zQuery = mDatastoreService.prepare( new Query( "Doubles" ).addSort( "FieldValue" ) );
545 -
546 - List<Entity> zList = zQuery.asList( FetchOptions.Builder.withOffset( 0 ) );
547 -
548 - assertEquals( "Entities", 3, zList.size() );
549 -
550 - validate( zList.get( 0 ), null );
551 - validate( zList.get( 1 ), v1 );
552 - validate( zList.get( 2 ), v2 );
553 - }
554 -
555 - public void test_IndexingDate() throws Exception
556 - {
557 - Transaction zTransaction = mDatastoreService.beginTransaction();
558 -
559 - Date v1, v2;
560 -
561 - mDatastoreService.put( zTransaction, createIndexingEntity( "Dates", null ) );
562 - mDatastoreService.put( zTransaction, createIndexingEntity( "Dates", v1 = createDate( 1957, 1, 4, 11, 12, 13, 14 ) ) );
563 - mDatastoreService.put( zTransaction, createIndexingEntity( "Dates", v2 = createDate( 2000, 2, 29, 0, 0, 0, 0 ) ) );
564 -
565 - zTransaction.commit();
566 -
567 - PreparedQuery zQuery = mDatastoreService.prepare( new Query( "Dates" ).addSort( "FieldValue" ) );
568 -
569 - List<Entity> zList = zQuery.asList( FetchOptions.Builder.withOffset( 0 ) );
570 -
571 - assertEquals( "Entities", 3, zList.size() );
572 -
573 - validate( zList.get( 0 ), null );
574 - validate( zList.get( 1 ), v1 );
575 - validate( zList.get( 2 ), v2 );
576 - }
577 -
578 - public void test_LargeCollections() throws Exception
579 - {
580 - Transaction zTransaction = mDatastoreService.beginTransaction();
581 -
582 - long zMaxLongsThatWork = 62645L;
583 -
584 - Entity zEntity;
585 - Set<Long> zLongs;
586 -
587 - try
588 - {
589 - zLongs = createLongs( zMaxLongsThatWork + 1 ); // Too Big!
590 -
591 - zEntity = new Entity( "LargeCollections", "Test" );
592 - zEntity.setProperty( "FieldValue", "Test" );
593 - zEntity.setUnindexedProperty( "Longs", zLongs );
594 -
595 - mDatastoreService.put( zTransaction, zEntity );
596 -
597 - fail( "Too Many did not fail w/ too large" );
598 - }
599 - catch ( Exception expected )
600 - {
601 - assertNotNull( expected ); // com.google.apphosting.api.ApiProxy$RequestTooLargeException: The request to API call datastore_v3.Put() was too large.
602 - }
603 - zLongs = createLongs( zMaxLongsThatWork ); // Just Small Enough!
604 -
605 - zEntity = new Entity( "LargeCollections", "Test" );
606 - zEntity.setProperty( "FieldValue", "Test" );
607 - zEntity.setUnindexedProperty( "Longs", zLongs );
608 -
609 - mDatastoreService.put( zTransaction, zEntity );
610 -
611 - zTransaction.commit();
612 -
613 - PreparedQuery zQuery = mDatastoreService.prepare( new Query( "LargeCollections" ).addSort( "FieldValue" ) );
614 -
615 - List<Entity> zList = zQuery.asList( FetchOptions.Builder.withOffset( 0 ) );
616 -
617 - assertEquals( "Entities", 1, zList.size() );
618 -
619 - zEntity = zList.get( 0 );
620 -
621 - assertEquals( "FieldValue", "Test", zEntity.getProperty( "FieldValue" ) );
622 -
623 - validate( zLongs, zEntity.getProperty( "Longs" ) );
624 - }
625 -
626 - private Set<Long> createLongs( long pLongsToCreate )
627 - {
628 - HashSet<Long> zSet = new HashSet<Long>();
629 - while ( --pLongsToCreate >= 0 )
630 - {
631 - zSet.add( pLongsToCreate );
632 - }
633 - return zSet;
634 - }
635 -
636 - @SuppressWarnings("unchecked")
637 - private void validate( Set<Long> zExpected, Object pFieldValue )
638 - {
639 - List<Long> zReadList = (List<Long>)pFieldValue;
640 - for (Long zLong : zReadList)
641 - {
642 - if ( !zExpected.remove( zLong ) )
643 - {
644 - fail( "Found value (" + zLong + "), not written" );
645 - }
646 - }
647 - if ( !zExpected.isEmpty() )
648 - {
649 - fail( "Did NOT read: " + zExpected );
650 - }
651 - }
652 -
653 - @SuppressWarnings("deprecation")
654 - private Date createDate( int pYear, int pMonth, int pDay, int pHour, int pMin, int pSec, int pMilliSecs )
655 - {
656 - Date zDate = new Date( pYear - 1900, pMonth - 1, pDay, pHour, pMin, pSec );
657 - if ( pMilliSecs != 0 )
658 - {
659 - zDate = new Date( zDate.getTime() + pMilliSecs );
660 - }
661 - return zDate;
662 - }
663 -
664 - @SuppressWarnings("deprecation")
665 - private String simpleDateToString( Date pDate )
666 - {
667 - int zYear = pDate.getYear() + 1900;
668 - int zMonth = pDate.getMonth() + 1;
669 - int zDay = pDate.getDate();
670 - int zHour = pDate.getHours();
671 - int zMin = pDate.getMinutes();
672 - int zSec = pDate.getSeconds();
673 - int zMilliSecs = (int)(pDate.getTime() - new Date( zYear - 1900, zMonth - 1, zDay, zHour, zMin, zSec ).getTime());
674 - return "" + zYear + "/" + zMonth + "/" + zDay + "-" + zHour + ":" + zMin + ":" + zSec + "." + zMilliSecs;
675 - }
676 -
677 - private String createIndexKey( Object pFieldValue )
678 - {
679 - if ( pFieldValue == null )
680 - {
681 - return " ";
682 - }
683 - if ( pFieldValue instanceof String )
684 - {
685 - return pFieldValue + " ";
686 - }
687 - if ( pFieldValue instanceof Date )
688 - {
689 - return simpleDateToString( (Date)pFieldValue );
690 - }
691 - return pFieldValue.toString();
692 - }
693 -
694 - private Entity createIndexingEntity( String pKind, Object pFieldValue )
695 - {
696 - Entity zEntity = new Entity( pKind, createIndexKey( pFieldValue ), mGOD_Apollo );
697 - zEntity.setProperty( "FieldValue", pFieldValue );
698 - return zEntity;
699 - }
700 -
701 - private void validate( Entity pEntity, Object pExpectedFieldValue )
702 - {
703 - validate( pEntity, createIndexKey( pExpectedFieldValue ), pExpectedFieldValue );
704 - }
705 -
706 - private void validate( Entity pEntity, String pExpectedKey, Object pExpectedFieldValue )
707 - {
708 - assertEquals( "Entity Key", pExpectedKey, pEntity.getKey().getName() );
709 - Object zFieldValue = pEntity.getProperty( "FieldValue" );
710 - if ( pExpectedFieldValue == null )
711 - {
712 - assertNull( "FieldValue", zFieldValue );
713 - }
714 - else
715 - {
716 - assertEquals( "Entity FieldValue", pExpectedFieldValue, zFieldValue );
717 - assertEquals( "Entity FieldValue Class", pExpectedFieldValue.getClass(), zFieldValue.getClass() );
718 - }
719 - }
720 -
721 - private Entity readAndValidate( Transaction pTransaction, Entity pEntity, String pName, long pCurrentVersion, long pCurrentChildren )
722 - throws EntityNotFoundException
723 - {
724 - validate( pEntity, pName, pCurrentVersion, pCurrentChildren );
725 -
726 - return readAndValidate2( pTransaction, pEntity, pName, pCurrentVersion, pCurrentChildren );
727 - }
728 -
729 - private void validate( Entity pEntity, String pName, long pCurrentVersion, long pCurrentChildren )
730 - {
731 - assertEquals( "Current Entity Version", pCurrentVersion, pEntity.getProperty( "Version" ) );
732 - assertEquals( "Current Entity Name", pName, pEntity.getProperty( "Name" ) );
733 - assertEquals( "Current Entity Children", pCurrentChildren, pEntity.getProperty( "Children" ) );
734 - }
735 -
736 - private Entity readAndValidate2( Transaction pTransaction, Entity pEntity, String pName, long pCurrentVersion, long pCurrentChildren )
737 - throws EntityNotFoundException
738 - {
739 - Key zKey = pEntity.getKey();
740 -
741 - return readAndValidate3( pTransaction, zKey, pName, pCurrentVersion, pCurrentChildren );
742 - }
743 -
744 - private Entity readAndValidate3( Transaction pTransaction, Key zKey, String pName, long pCurrentVersion, long pCurrentChildren )
745 - throws EntityNotFoundException
746 - {
747 - assertEquals( "Key Kind", KIND, zKey.getKind() );
748 - assertEquals( "Key Name (Our Key Value)", pName, zKey.getName() );
749 -
750 - Entity zEntity = mDatastoreService.get( pTransaction, zKey );
751 -
752 - if ( pTransaction == null )
753 - {
754 - Object zVersion = zEntity.getProperty( "Version" );
755 - assertNotNull( "Read Entity Version", zVersion );
756 - if ( !zVersion.equals( pCurrentVersion ) )
757 - {
758 - Transaction zTransaction = mDatastoreService.beginTransaction();
759 - zEntity = mDatastoreService.get( zTransaction, zKey );
760 - zTransaction.rollback();
761 - }
762 - }
763 -
764 - assertEquals( "Read Entity Version", pCurrentVersion, zEntity.getProperty( "Version" ) );
765 - assertEquals( "Read Entity Name", pName, zEntity.getProperty( "Name" ) );
766 - assertEquals( "Read Entity Children", pCurrentChildren, zEntity.getProperty( "Children" ) );
31 + public static TestSuite suite()
32 + {
33 + return new TestSuite( DatastoreServiceTest.class );
34 + }
35 +
36 + public DatastoreServiceTest( String name )
37 + {
38 + super( name );
39 + }
40 +
41 + public static void main( String[] args )
42 + {
43 + junit.textui.TestRunner.run( suite() );
44 + }
45 +
46 + @Override
47 + protected void setUp() throws Exception
48 + {
49 + super.setUp();
50 + mHelper.setUp();
51 + mConfig = DatastoreServiceConfig.Builder.withDefaults() // Deadline=null,
52 + // ImplicitTransactionManagementPolicy=NONE,
53 + // ReadPolicy.Consistency=STRONG
54 + .deadline( 5 ); // Deadline=5 secs
55 + mDatastoreService = DatastoreServiceFactory.getDatastoreService( mConfig );
56 + mGOD_Apollo = KeyFactory.createKey( "GODS", "Apollo" );
57 + mGOD_Venus = KeyFactory.createKey( "GODS", "Venus" );
58 +
59 + }
60 +
61 + @Override
62 + public void tearDown()
63 + {
64 + mHelper.tearDown();
65 + }
66 +
67 + private DatastoreServiceConfig mConfig;
68 +
69 + private DatastoreService mDatastoreService;
70 +
71 + private Key mGOD_Apollo, mGOD_Venus;
72 +
73 + private Entity createEntity( Key pGOD, String pName )
74 + {
75 + Entity zEntity = new Entity( KIND, pName, pGOD );
76 + zEntity.setUnindexedProperty( "Version", 1L );
77 +
78 + zEntity.setProperty( "Name", pName );
79 + zEntity.setUnindexedProperty( "Children", 0L );
80 + return zEntity;
81 + }
82 +
83 + private void inc( Entity pEntity, String pProperty )
84 + {
85 + Long zLong = (Long) pEntity.getProperty( pProperty );
86 + pEntity.setUnindexedProperty( pProperty, zLong + 1 );
87 + }
88 +
89 + private Entity updateChildren( Entity pEntity )
90 + {
91 + inc( pEntity, "Version" );
92 + inc( pEntity, "Children" );
93 + return pEntity;
94 + }
95 +
96 + public void test_DataStoreConfig() throws Exception
97 + {
98 + assertEquals( 5.0d, mConfig.getDeadline(), 0.0001 );
99 + assertEquals( ImplicitTransactionManagementPolicy.NONE, mConfig.getImplicitTransactionManagementPolicy() );
100 + assertEquals( Consistency.STRONG, mConfig.getReadPolicy().getConsistency() );
101 + }
102 +
103 + public void test_NonConflictingDifferentGodsOverlapingTransactionsNew() throws Exception
104 + {
105 + Transaction zApolloTransaction = mDatastoreService.beginTransaction();
106 + Transaction zVenusTransaction = mDatastoreService.beginTransaction();
107 +
108 + Entity zEntityFred = createEntity( mGOD_Apollo, "Fred" );
109 + mDatastoreService.put( zApolloTransaction, zEntityFred );
110 + Entity zEntityWilma = createEntity( mGOD_Venus, "Wilma" );
111 + mDatastoreService.put( zVenusTransaction, zEntityWilma );
112 +
113 + Entity zEntityBarney = createEntity( mGOD_Apollo, "Barney" );
114 + mDatastoreService.put( zApolloTransaction, zEntityBarney );
115 + Entity zEntityBetty = createEntity( mGOD_Venus, "Betty" );
116 + mDatastoreService.put( zVenusTransaction, zEntityBetty );
117 +
118 + zApolloTransaction.commit();
119 + zVenusTransaction.commit();
120 +
121 + readAndValidate( null, zEntityFred, "Fred", 1, 0 );
122 + readAndValidate( null, zEntityWilma, "Wilma", 1, 0 );
123 +
124 + readAndValidate( null, zEntityBarney, "Barney", 1, 0 );
125 + readAndValidate( null, zEntityBetty, "Betty", 1, 0 );
126 + }
127 +
128 + public void test_TransactionReadMultiGOD() throws Exception
129 + {
130 + Transaction zApolloTransaction = mDatastoreService.beginTransaction();
131 + Transaction zVenusTransaction = mDatastoreService.beginTransaction();
132 +
133 + Entity zEntityFred = createEntity( mGOD_Apollo, "Fred" );
134 + mDatastoreService.put( zApolloTransaction, zEntityFred );
135 + Entity zEntityWilma = createEntity( mGOD_Venus, "Wilma" );
136 + mDatastoreService.put( zVenusTransaction, zEntityWilma );
137 +
138 + zApolloTransaction.commit();
139 + zVenusTransaction.commit();
140 +
141 + Transaction zTransaction = mDatastoreService.beginTransaction();
142 + mDatastoreService.get( zTransaction, zEntityFred.getKey() ); // will
143 + // succeed!
144 + try
145 + {
146 + mDatastoreService.get( zTransaction, zEntityWilma.getKey() ); // will
147 + // Fail!
148 + fail( "Fred & Wilma - Did NOT Fail with different GODS (Entity Groups)" );
149 + }
150 + catch ( IllegalArgumentException expected )
151 + {
152 + String zMessage = expected.getMessage();
153 + assertTrue( zMessage, zMessage
154 + .startsWith( "can't operate on multiple entity groups in a single transaction." ) );
155 + }
156 + zTransaction.rollback();
157 + }
158 +
159 + public void test_TransactionUpdate() throws Exception
160 + {
161 + Transaction zApolloTransaction = mDatastoreService.beginTransaction();
162 + Transaction zVenusTransaction = mDatastoreService.beginTransaction();
163 +
164 + Entity zEntityFred = createEntity( mGOD_Apollo, "Fred" );
165 + mDatastoreService.put( zApolloTransaction, zEntityFred );
166 + Entity zEntityWilma = createEntity( mGOD_Venus, "Wilma" );
167 + mDatastoreService.put( zVenusTransaction, zEntityWilma );
168 +
169 + Entity zEntityBarney = createEntity( mGOD_Apollo, "Barney" );
170 + mDatastoreService.put( zApolloTransaction, zEntityBarney );
171 + Entity zEntityBetty = createEntity( mGOD_Venus, "Betty" );
172 + mDatastoreService.put( zVenusTransaction, zEntityBetty );
173 +
174 + zApolloTransaction.commit();
175 + zVenusTransaction.commit();
176 +
177 + zVenusTransaction = mDatastoreService.beginTransaction();
178 +
179 + zEntityWilma = updateChildren( readAndValidate( zVenusTransaction, zEntityWilma, "Wilma", 1, 0 ) );
180 + mDatastoreService.put( zVenusTransaction, zEntityWilma );
181 +
182 + Entity zEntityPebbles = createEntity( mGOD_Venus, "Pebbles" );
183 + mDatastoreService.put( zVenusTransaction, zEntityPebbles );
184 +
185 + // Can't Update Fred!
186 +
187 + zVenusTransaction.commit();
188 +
189 + zApolloTransaction = mDatastoreService.beginTransaction();
190 +
191 + zEntityBarney = updateChildren( readAndValidate( zApolloTransaction, zEntityBarney, "Barney", 1, 0 ) );
192 + mDatastoreService.put( zApolloTransaction, zEntityBarney );
193 +
194 + Entity zEntityBammBamm = createEntity( mGOD_Apollo, "BammBamm" );
195 + mDatastoreService.put( zApolloTransaction, zEntityBammBamm );
196 +
197 + // Can't Update Betty!
198 +
199 + zApolloTransaction.commit();
200 +
201 + readAndValidate( null, zEntityFred, "Fred", 1, 0 );
202 + readAndValidate( null, zEntityWilma, "Wilma", 2, 1 );
203 + readAndValidate( null, zEntityPebbles, "Pebbles", 1, 0 );
204 +
205 + readAndValidate( null, zEntityBarney, "Barney", 2, 1 );
206 + readAndValidate( null, zEntityBetty, "Betty", 1, 0 );
207 + readAndValidate( null, zEntityBammBamm, "BammBamm", 1, 0 );
208 + }
209 +
210 + public void test_NonConflictingDifferentGodsOverlapingTransactionsUpdate() throws Exception
211 + {
212 + Transaction zApolloTransaction = mDatastoreService.beginTransaction();
213 + Transaction zVenusTransaction = mDatastoreService.beginTransaction();
214 +
215 + Entity zEntityFred = createEntity( mGOD_Apollo, "Fred" );
216 + mDatastoreService.put( zApolloTransaction, zEntityFred );
217 + Entity zEntityWilma = createEntity( mGOD_Venus, "Wilma" );
218 + mDatastoreService.put( zVenusTransaction, zEntityWilma );
219 +
220 + zApolloTransaction.commit();
221 + zVenusTransaction.commit();
222 +
223 + zApolloTransaction = mDatastoreService.beginTransaction();
224 + zVenusTransaction = mDatastoreService.beginTransaction();
225 +
226 + zEntityWilma = updateChildren( readAndValidate( zVenusTransaction, zEntityWilma, "Wilma", 1, 0 ) );
227 + mDatastoreService.put( zVenusTransaction, zEntityWilma );
228 +
229 + Entity zEntityPebbles = createEntity( mGOD_Venus, "Pebbles" );
230 + mDatastoreService.put( zVenusTransaction, zEntityPebbles );
231 +
232 + zEntityFred = updateChildren( readAndValidate( zApolloTransaction, zEntityFred, "Fred", 1, 0 ) );
233 + mDatastoreService.put( zApolloTransaction, zEntityFred );
234 +
235 + zApolloTransaction.commit();
236 + zVenusTransaction.commit();
237 +
238 + readAndValidate( null, zEntityFred, "Fred", 2, 1 );
239 + readAndValidate( null, zEntityWilma, "Wilma", 2, 1 );
240 +
241 + readAndValidate( null, zEntityPebbles, "Pebbles", 1, 0 );
242 + }
243 +
244 + public void test_ConflictingSameEntityOverlapingTransactionsUpdate() throws Exception
245 + {
246 + Transaction zVenusTransaction = mDatastoreService.beginTransaction();
247 +
248 + Entity zEntityWilma = createEntity( mGOD_Venus, "Wilma" );
249 + mDatastoreService.put( zVenusTransaction, zEntityWilma );
250 +
251 + zVenusTransaction.commit();
252 +
253 + zVenusTransaction = mDatastoreService.beginTransaction();
254 +
255 + zEntityWilma = updateChildren( readAndValidate( zVenusTransaction, zEntityWilma, "Wilma", 1, 0 ) );
256 + mDatastoreService.put( zVenusTransaction, zEntityWilma );
257 +
258 + Entity zEntityPebbles = createEntity( mGOD_Venus, "Pebbles" );
259 + mDatastoreService.put( zVenusTransaction, zEntityPebbles );
260 +
261 + Transaction zVenus2Transaction = mDatastoreService.beginTransaction();
262 +
263 + Entity zEntityWilma2 = updateChildren( readAndValidate2( zVenus2Transaction, zEntityWilma, "Wilma", 1, 0 ) );
264 + mDatastoreService.put( zVenus2Transaction, zEntityWilma2 );
265 +
266 + zVenusTransaction.commit();
267 +
268 + try
269 + {
270 + zVenus2Transaction.commit();
271 + fail( "Two Transaction Wilma Update - Did NOT Fail" );
272 + }
273 + catch ( ConcurrentModificationException expected )
274 + {
275 + String zMessage = expected.getMessage();
276 + assertTrue( zMessage, zMessage.startsWith( "too much contention on these datastore entities. please try again." ) );
277 + }
278 +
279 + readAndValidate( null, zEntityWilma, "Wilma", 2, 1 );
280 + }
281 +
282 + public void test_NonConflictingSameGodDifferentEntityOverlapingTransactionsUpdate() throws Exception
283 + {
284 + Transaction zVenusTransaction = mDatastoreService.beginTransaction();
285 +
286 + Entity zEntityWilma = createEntity( mGOD_Venus, "Wilma" );
287 + mDatastoreService.put( zVenusTransaction, zEntityWilma );
288 +
289 + Entity zEntityBetty = createEntity( mGOD_Venus, "Betty" );
290 + mDatastoreService.put( zVenusTransaction, zEntityBetty );
291 +
292 + zVenusTransaction.commit();
293 +
294 + zVenusTransaction = mDatastoreService.beginTransaction();
295 +
296 + zEntityWilma = updateChildren( readAndValidate( zVenusTransaction, zEntityWilma, "Wilma", 1, 0 ) );
297 + mDatastoreService.put( zVenusTransaction, zEntityWilma );
298 +
299 + Transaction zVenus2Transaction = mDatastoreService.beginTransaction();
300 +
301 + zEntityBetty = updateChildren( readAndValidate( zVenus2Transaction, zEntityBetty, "Betty", 1, 0 ) );
302 + mDatastoreService.put( zVenus2Transaction, zEntityBetty );
303 +
304 + zVenusTransaction.commit();
305 +
306 + try
307 + {
308 + zVenus2Transaction.commit();
309 + fail( "Two Transaction Wilma & Betty Update - Did NOT Fail" );
310 + }
311 + catch ( ConcurrentModificationException expected )
312 + {
313 + String zMessage = expected.getMessage();
314 + assertTrue( zMessage, zMessage.startsWith( "too much contention on these datastore entities. please try again." ) );
315 + }
316 +
317 + readAndValidate( null, zEntityWilma, "Wilma", 2, 1 );
318 + readAndValidate2( null, zEntityBetty, "Betty", 1, 0 );
319 + }
320 +
321 + public void test_QueryAllDifferentGods() throws Exception
322 + {
323 + Transaction zApolloTransaction = mDatastoreService.beginTransaction();
324 + Transaction zVenusTransaction = mDatastoreService.beginTransaction();
325 +
326 + Entity zEntityFred = createEntity( mGOD_Apollo, "Fred" );
327 + mDatastoreService.put( zApolloTransaction, zEntityFred );
328 + Entity zEntityWilma = createEntity( mGOD_Venus, "Wilma" );
329 + mDatastoreService.put( zVenusTransaction, zEntityWilma );
330 +
331 + Entity zEntityBarney = createEntity( mGOD_Apollo, "Barney" );
332 + mDatastoreService.put( zApolloTransaction, zEntityBarney );
333 + Entity zEntityBetty = createEntity( mGOD_Venus, "Betty" );
334 + mDatastoreService.put( zVenusTransaction, zEntityBetty );
335 +
336 + zApolloTransaction.commit();
337 + zVenusTransaction.commit();
338 +
339 + PreparedQuery zQuery = mDatastoreService.prepare( new Query( KIND ).addSort( "Name" ) );
340 +
341 + List<Entity> zList = zQuery.asList( FetchOptions.Builder.withOffset( 0 ) );
342 +
343 + assertEquals( "Entities", 4, zList.size() );
344 +
345 + validate( zList.get( 0 ), "Barney", 1, 0 );
346 + validate( zList.get( 1 ), "Betty", 1, 0 );
347 + validate( zList.get( 2 ), "Fred", 1, 0 );
348 + validate( zList.get( 3 ), "Wilma", 1, 0 );
349 + }
350 +
351 + public void test_QuerySpecificGod() throws Exception
352 + {
353 + Transaction zApolloTransaction = mDatastoreService.beginTransaction();
354 + Transaction zVenusTransaction = mDatastoreService.beginTransaction();
355 +
356 + Entity zEntityFred = createEntity( mGOD_Apollo, "Fred" );
357 + mDatastoreService.put( zApolloTransaction, zEntityFred );
358 + Entity zEntityWilma = createEntity( mGOD_Venus, "Wilma" );
359 + mDatastoreService.put( zVenusTransaction, zEntityWilma );
360 +
361 + Entity zEntityBarney = createEntity( mGOD_Apollo, "Barney" );
362 + mDatastoreService.put( zApolloTransaction, zEntityBarney );
363 + Entity zEntityBetty = createEntity( mGOD_Venus, "Betty" );
364 + mDatastoreService.put( zVenusTransaction, zEntityBetty );
365 +
366 + zApolloTransaction.commit();
367 + zVenusTransaction.commit();
368 +
369 + PreparedQuery zQuery = mDatastoreService.prepare( new Query( KIND, mGOD_Apollo ).addSort( "Name" ) );
370 +
371 + List<Entity> zList = zQuery.asList( FetchOptions.Builder.withOffset( 0 ) );
372 +
373 + assertEquals( "Entities", 2, zList.size() );
374 +
375 + validate( zList.get( 0 ), "Barney", 1, 0 );
376 + validate( zList.get( 1 ), "Fred", 1, 0 );
377 + }
378 +
379 + public void test_QueryEqualsFilter() throws Exception
380 + {
381 + Transaction zApolloTransaction = mDatastoreService.beginTransaction();
382 + Transaction zVenusTransaction = mDatastoreService.beginTransaction();
383 +
384 + Entity zEntityFred = createEntity( mGOD_Apollo, "Fred" );
385 + mDatastoreService.put( zApolloTransaction, zEntityFred );
386 + Entity zEntityWilma = createEntity( mGOD_Venus, "Wilma" );
387 + mDatastoreService.put( zVenusTransaction, zEntityWilma );
388 +
389 + Entity zEntityBarney = createEntity( mGOD_Apollo, "Barney" );
390 + mDatastoreService.put( zApolloTransaction, zEntityBarney );
391 + Entity zEntityBetty = createEntity( mGOD_Venus, "Betty" );
392 + mDatastoreService.put( zVenusTransaction, zEntityBetty );
393 +
394 + zApolloTransaction.commit();
395 + zVenusTransaction.commit();
396 +
397 + PreparedQuery zQuery = mDatastoreService.prepare( new Query( KIND ).addSort( "Name" ).addFilter( "Name", Query.FilterOperator.EQUAL, "Barney") );
398 +
399 + List<Entity> zList = zQuery.asList( FetchOptions.Builder.withOffset( 0 ) );
400 +
401 + assertEquals( "Entities", 1, zList.size() );
402 +
403 + validate( zList.get( 0 ), "Barney", 1, 0 );
404 + }
405 +
406 + public void test_QueryLessThanFilter() throws Exception
407 + {
408 + Transaction zApolloTransaction = mDatastoreService.beginTransaction();
409 + Transaction zVenusTransaction = mDatastoreService.beginTransaction();
410 +
411 + Entity zEntityFred = createEntity( mGOD_Apollo, "Fred" );
412 + mDatastoreService.put( zApolloTransaction, zEntityFred );
413 + Entity zEntityWilma = createEntity( mGOD_Venus, "Wilma" );
414 + mDatastoreService.put( zVenusTransaction, zEntityWilma );
415 +
416 + Entity zEntityBarney = createEntity( mGOD_Apollo, "Barney" );
417 + mDatastoreService.put( zApolloTransaction, zEntityBarney );
418 + Entity zEntityBetty = createEntity( mGOD_Venus, "Betty" );
419 + mDatastoreService.put( zVenusTransaction, zEntityBetty );
420 +
421 + zApolloTransaction.commit();
422 + zVenusTransaction.commit();
423 +
424 + PreparedQuery zQuery = mDatastoreService.prepare( new Query( KIND ).addSort( "Name" ).addFilter( "Name", Query.FilterOperator.LESS_THAN, "C") );
425 +
426 + List<Entity> zList = zQuery.asList( FetchOptions.Builder.withOffset( 0 ) );
427 +
428 + assertEquals( "Entities", 2, zList.size() );
429 +
430 + validate( zList.get( 0 ), "Barney", 1, 0 );
431 + validate( zList.get( 1 ), "Betty", 1, 0 );
432 + }
433 +
434 + public void test_NullKey() throws Exception
435 + {
436 + try
437 + {
438 + KeyFactory.createKey( KIND, null );
439 + fail( "null Key did NOT fail" );
440 + }
441 + catch ( IllegalArgumentException expected )
442 + {
443 + String zMessage = expected.getMessage();
444 + assertTrue( zMessage, zMessage.startsWith( "name cannot be null or empty" ) );
445 + }
446 + // new Entity( KIND, null, pGOD ); // Does Not Fail, but
447 + // implicitly creates a auto-generated id key!!
448 + }
449 +
450 + public void test_EmptyKey() throws Exception
451 + {
452 + try
453 + {
454 + KeyFactory.createKey( KIND, "" );
455 + fail( "empty Key did NOT fail" );
456 + }
457 + catch ( IllegalArgumentException expected )
458 + {
459 + String zMessage = expected.getMessage();
460 + assertTrue( zMessage, zMessage.startsWith( "name cannot be null or empty" ) );
461 + }
462 + }
463 +
464 + public void test_IndexingString() throws Exception
465 + {
466 + Transaction zTransaction = mDatastoreService.beginTransaction();
467 +
468 + String v1, v2;
469 +
470 + mDatastoreService.put( zTransaction, createIndexingEntity( "Strings", null ) );
471 + mDatastoreService.put( zTransaction, createIndexingEntity( "Strings", v1 = "" ) );
472 + mDatastoreService.put( zTransaction, createIndexingEntity( "Strings", v2 = "Fred" ) );
473 +
474 + zTransaction.commit();
475 +
476 + PreparedQuery zQuery = mDatastoreService.prepare( new Query( "Strings" ).addSort( "FieldValue" ) );
477 +
478 + List<Entity> zList = zQuery.asList( FetchOptions.Builder.withOffset( 0 ) );
479 +
480 + assertEquals( "Entities", 3, zList.size() );
481 +
482 + validate( zList.get( 0 ), null );
483 + validate( zList.get( 1 ), v1 );
484 + validate( zList.get( 2 ), v2 );
485 + }
486 +
487 + public void test_IndexingBoolean() throws Exception
488 + {
489 + Transaction zTransaction = mDatastoreService.beginTransaction();
490 +
491 + Boolean v1, v2;
492 +
493 + mDatastoreService.put( zTransaction, createIndexingEntity( "Booleans", null ) );
494 + mDatastoreService.put( zTransaction, createIndexingEntity( "Booleans", v1 = Boolean.FALSE ) );
495 + mDatastoreService.put( zTransaction, createIndexingEntity( "Booleans", v2 = Boolean.TRUE ) );
496 +
497 + zTransaction.commit();
498 +
499 + PreparedQuery zQuery = mDatastoreService.prepare( new Query( "Booleans" ).addSort( "FieldValue" ) );
500 +
501 + List<Entity> zList = zQuery.asList( FetchOptions.Builder.withOffset( 0 ) );
502 +
503 + assertEquals( "Entities", 3, zList.size() );
504 +
505 + validate( zList.get( 0 ), null );
506 + validate( zList.get( 1 ), v1 );
507 + validate( zList.get( 2 ), v2 );
508 + }
509 +
510 + public void test_IndexingLong() throws Exception
511 + {
512 + Transaction zTransaction = mDatastoreService.beginTransaction();
513 +
514 + Long v1, v2;
515 +
516 + mDatastoreService.put( zTransaction, createIndexingEntity( "Longs", null ) );
517 + mDatastoreService.put( zTransaction, createIndexingEntity( "Longs", v1 = 1L ) );
518 + mDatastoreService.put( zTransaction, createIndexingEntity( "Longs", v2 = 100L ) );
519 +
520 + zTransaction.commit();
521 +
522 + PreparedQuery zQuery = mDatastoreService.prepare( new Query( "Longs" ).addSort( "FieldValue" ) );
523 +
524 + List<Entity> zList = zQuery.asList( FetchOptions.Builder.withOffset( 0 ) );
525 +
526 + assertEquals( "Entities", 3, zList.size() );
527 +
528 + validate( zList.get( 0 ), null );
529 + validate( zList.get( 1 ), v1 );
530 + validate( zList.get( 2 ), v2 );
531 + }
532 +
533 + public void test_IndexingDouble() throws Exception
534 + {
535 + Transaction zTransaction = mDatastoreService.beginTransaction();
536 +
537 + Double v1, v2;
538 +
539 + mDatastoreService.put( zTransaction, createIndexingEntity( "Doubles", null ) );
540 + mDatastoreService.put( zTransaction, createIndexingEntity( "Doubles", v1 = 1.1D ) );
541 + mDatastoreService.put( zTransaction, createIndexingEntity( "Doubles", v2 = 11.2D ) );
542 +
543 + zTransaction.commit();
544 +
545 + PreparedQuery zQuery = mDatastoreService.prepare( new Query( "Doubles" ).addSort( "FieldValue" ) );
546 +
547 + List<Entity> zList = zQuery.asList( FetchOptions.Builder.withOffset( 0 ) );
548 +
549 + assertEquals( "Entities", 3, zList.size() );
550 +
551 + validate( zList.get( 0 ), null );
552 + validate( zList.get( 1 ), v1 );
553 + validate( zList.get( 2 ), v2 );
554 + }
555 +
556 + public void test_IndexingDate() throws Exception
557 + {
558 + Transaction zTransaction = mDatastoreService.beginTransaction();
559 +
560 + Date v1, v2;
561 +
562 + mDatastoreService.put( zTransaction, createIndexingEntity( "Dates", null ) );
563 + mDatastoreService.put( zTransaction, createIndexingEntity( "Dates", v1 = createDate( 1957, 1, 4, 11, 12, 13, 14 ) ) );
564 + mDatastoreService.put( zTransaction, createIndexingEntity( "Dates", v2 = createDate( 2000, 2, 29, 0, 0, 0, 0 ) ) );
565 +
566 + zTransaction.commit();
567 +
568 + PreparedQuery zQuery = mDatastoreService.prepare( new Query( "Dates" ).addSort( "FieldValue" ) );
569 +
570 + List<Entity> zList = zQuery.asList( FetchOptions.Builder.withOffset( 0 ) );
571 +
572 + assertEquals( "Entities", 3, zList.size() );
573 +
574 + validate( zList.get( 0 ), null );
575 + validate( zList.get( 1 ), v1 );
576 + validate( zList.get( 2 ), v2 );
577 + }
578 +
579 + public void test_LargeCollections() throws Exception
580 + {
581 + Transaction zTransaction = mDatastoreService.beginTransaction();
582 +
583 + long zMaxLongsThatWork = 62645L;
584 +
585 + Entity zEntity;
586 + Set<Long> zLongs;
587 +
588 + try
589 + {
590 + zLongs = createLongs( zMaxLongsThatWork + 1 ); // Too Big!
591 +
592 + zEntity = new Entity( "LargeCollections", "Test" );
593 + zEntity.setProperty( "FieldValue", "Test" );
594 + zEntity.setUnindexedProperty( "Longs", zLongs );
595 +
596 + mDatastoreService.put( zTransaction, zEntity );
597 +
598 + fail( "Too Many did not fail w/ too large" );
599 + }
600 + catch ( Exception expected )
601 + {
602 + assertNotNull( expected ); // com.google.apphosting.api.ApiProxy$RequestTooLargeException: The request to API call datastore_v3.Put() was too large.
603 + }
604 + zLongs = createLongs( zMaxLongsThatWork ); // Just Small Enough!
605 +
606 + zEntity = new Entity( "LargeCollections", "Test" );
607 + zEntity.setProperty( "FieldValue", "Test" );
608 + zEntity.setUnindexedProperty( "Longs", zLongs );
609 +
610 + mDatastoreService.put( zTransaction, zEntity );
611 +
612 + zTransaction.commit();
613 +
614 + PreparedQuery zQuery = mDatastoreService.prepare( new Query( "LargeCollections" ).addSort( "FieldValue" ) );
615 +
616 + List<Entity> zList = zQuery.asList( FetchOptions.Builder.withOffset( 0 ) );
617 +
618 + assertEquals( "Entities", 1, zList.size() );
619 +
620 + zEntity = zList.get( 0 );
621 +
622 + assertEquals( "FieldValue", "Test", zEntity.getProperty( "FieldValue" ) );
623 +
624 + validate( zLongs, zEntity.getProperty( "Longs" ) );
625 + }
626 +
627 + private Set<Long> createLongs( long pLongsToCreate )
628 + {
629 + HashSet<Long> zSet = new HashSet<Long>();
630 + while ( --pLongsToCreate >= 0 )
631 + {
632 + zSet.add( pLongsToCreate );
633 + }
634 + return zSet;
635 + }
636 +
637 + @SuppressWarnings("unchecked")
638 + private void validate( Set<Long> zExpected, Object pFieldValue )
639 + {
640 + List<Long> zReadList = (List<Long>)pFieldValue;
641 + for (Long zLong : zReadList)
642 + {
643 + if ( !zExpected.remove( zLong ) )
644 + {
645 + fail( "Found value (" + zLong + "), not written" );
646 + }
647 + }
648 + if ( !zExpected.isEmpty() )
649 + {
650 + fail( "Did NOT read: " + zExpected );
651 + }
652 + }
653 +
654 + @SuppressWarnings("deprecation")
655 + private Date createDate( int pYear, int pMonth, int pDay, int pHour, int pMin, int pSec, int pMilliSecs )
656 + {
657 + Date zDate = new Date( pYear - 1900, pMonth - 1, pDay, pHour, pMin, pSec );
658 + if ( pMilliSecs != 0 )
659 + {
660 + zDate = new Date( zDate.getTime() + pMilliSecs );
661 + }
662 + return zDate;
663 + }
664 +
665 + @SuppressWarnings("deprecation")
666 + private String simpleDateToString( Date pDate )
667 + {
668 + int zYear = pDate.getYear() + 1900;
669 + int zMonth = pDate.getMonth() + 1;
670 + int zDay = pDate.getDate();
671 + int zHour = pDate.getHours();
672 + int zMin = pDate.getMinutes();
673 + int zSec = pDate.getSeconds();
674 + int zMilliSecs = (int)(pDate.getTime() - new Date( zYear - 1900, zMonth - 1, zDay, zHour, zMin, zSec ).getTime());
675 + return "" + zYear + "/" + zMonth + "/" + zDay + "-" + zHour + ":" + zMin + ":" + zSec + "." + zMilliSecs;
676 + }
677 +
678 + private String createIndexKey( Object pFieldValue )
679 + {
680 + if ( pFieldValue == null )
681 + {
682 + return " ";
683 + }
684 + if ( pFieldValue instanceof String )
685 + {
686 + return pFieldValue + " ";
687 + }
688 + if ( pFieldValue instanceof Date )
689 + {
690 + return simpleDateToString( (Date)pFieldValue );
691 + }
692 + return pFieldValue.toString();
693 + }
694 +
695 + private Entity createIndexingEntity( String pKind, Object pFieldValue )
696 + {
697 + Entity zEntity = new Entity( pKind, createIndexKey( pFieldValue ), mGOD_Apollo );
698 + zEntity.setProperty( "FieldValue", pFieldValue );
699 + return zEntity;
700 + }
701 +
702 + private void validate( Entity pEntity, Object pExpectedFieldValue )
703 + {
704 + validate( pEntity, createIndexKey( pExpectedFieldValue ), pExpectedFieldValue );
705 + }
706 +
707 + private void validate( Entity pEntity, String pExpectedKey, Object pExpectedFieldValue )
708 + {
709 + assertEquals( "Entity Key", pExpectedKey, pEntity.getKey().getName() );
710 + Object zFieldValue = pEntity.getProperty( "FieldValue" );
711 + if ( pExpectedFieldValue == null )
712 + {
713 + assertNull( "FieldValue", zFieldValue );
714 + }
715 + else
716 + {
717 + assertEquals( "Entity FieldValue", pExpectedFieldValue, zFieldValue );
718 + assertEquals( "Entity FieldValue Class", pExpectedFieldValue.getClass(), zFieldValue.getClass() );
719 + }
720 + }
721 +
722 + private Entity readAndValidate( Transaction pTransaction, Entity pEntity, String pName, long pCurrentVersion, long pCurrentChildren )
723 + throws EntityNotFoundException
724 + {
725 + validate( pEntity, pName, pCurrentVersion, pCurrentChildren );
726 +
727 + return readAndValidate2( pTransaction, pEntity, pName, pCurrentVersion, pCurrentChildren );
728 + }
729 +
730 + private void validate( Entity pEntity, String pName, long pCurrentVersion, long pCurrentChildren )
731 + {
732 + assertEquals( "Current Entity Version", pCurrentVersion, pEntity.getProperty( "Version" ) );
733 + assertEquals( "Current Entity Name", pName, pEntity.getProperty( "Name" ) );
734 + assertEquals( "Current Entity Children", pCurrentChildren, pEntity.getProperty( "Children" ) );
735 + }
736 +
737 + private Entity readAndValidate2( Transaction pTransaction, Entity pEntity, String pName, long pCurrentVersion, long pCurrentChildren )
738 + throws EntityNotFoundException
739 + {
740 + Key zKey = pEntity.getKey();
741 +
742 + return readAndValidate3( pTransaction, zKey, pName, pCurrentVersion, pCurrentChildren );
743 + }
744 +
745 + private Entity readAndValidate3( Transaction pTransaction, Key zKey, String pName, long pCurrentVersion, long pCurrentChildren )
746 + throws EntityNotFoundException
747 + {
748 + assertEquals( "Key Kind", KIND, zKey.getKind() );
749 + assertEquals( "Key Name (Our Key Value)", pName, zKey.getName() );
750 +
751 + Entity zEntity = mDatastoreService.get( pTransaction, zKey );
752 +
753 + if ( pTransaction == null )
754 + {
755 + Object zVersion = zEntity.getProperty( "Version" );
756 + assertNotNull( "Read Entity Version", zVersion );
757 + if ( !zVersion.equals( pCurrentVersion ) )
758 + {
759 + Transaction zTransaction = mDatastoreService.beginTransaction();
760 + zEntity = mDatastoreService.get( zTransaction, zKey );
761 + zTransaction.rollback();
762 + }
763 + }
764 +
765 + assertEquals( "Read Entity Version", pCurrentVersion, zEntity.getProperty( "Version" ) );
766 + assertEquals( "Read Entity Name", pName, zEntity.getProperty( "Name" ) );
767 + assertEquals( "Read Entity Children", pCurrentChildren, zEntity.getProperty( "Children" ) );
767 768
768 - return zEntity;
769 - }
769 + return zEntity;
770 + }
770 771 }