| OLD | NEW |
| (Empty) |
| 1 # Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 # Use of this source code is governed by a BSD-style license that can be | |
| 3 # found in the LICENSE file. | |
| 4 | |
| 5 from google.appengine.api import datastore_errors | |
| 6 from google.appengine.ext import ndb | |
| 7 | |
| 8 from testing_utils import testing | |
| 9 | |
| 10 from model.versioned_model import VersionedModel | |
| 11 | |
| 12 | |
| 13 class _Entity(VersionedModel): | |
| 14 value = ndb.IntegerProperty(indexed=False) | |
| 15 | |
| 16 | |
| 17 class VersionedModelTest(testing.AppengineTestCase): | |
| 18 | |
| 19 def testGetRootModel(self): | |
| 20 root_model_class = _Entity._GetRootModel() | |
| 21 self.assertEqual('_EntityRoot', root_model_class._get_kind()) | |
| 22 self.assertTrue(issubclass(root_model_class, ndb.Model)) | |
| 23 self.assertEqual(3, root_model_class(current=3).current) | |
| 24 | |
| 25 def testDefaultVersionIsZero(self): | |
| 26 self.assertEqual(0, _Entity.Create().version_number) | |
| 27 self.assertEqual(0, _Entity.Create('m1').version_number) | |
| 28 | |
| 29 def testRootId(self): | |
| 30 self.assertEqual(1, _Entity.Create()._root_id) | |
| 31 self.assertEqual( | |
| 32 1, _Entity(key=ndb.Key('_EntityRoot', 1, '_Entity', 2))._root_id) | |
| 33 self.assertEqual('m1', _Entity.Create('m1')._root_id) | |
| 34 | |
| 35 def testCreate(self): | |
| 36 self.assertEqual(_Entity(key=ndb.Key('_EntityRoot', 'm1', '_Entity', 0)), | |
| 37 _Entity.Create('m1')) | |
| 38 | |
| 39 def testGetMostRecentVersionWhenNoData(self): | |
| 40 self.assertIsNone(_Entity.GetVersion()) | |
| 41 self.assertIsNone(_Entity.GetVersion('m1')) | |
| 42 | |
| 43 def testGetMostRecentVersionWhenDataExists(self): | |
| 44 entity = _Entity.Create() | |
| 45 entity.value = 1 | |
| 46 entity.Save() | |
| 47 entity.value = 2 | |
| 48 entity.Save() | |
| 49 | |
| 50 entity = _Entity.GetVersion() | |
| 51 self.assertEqual(2, entity.version_number) | |
| 52 self.assertEqual(2, entity.value) | |
| 53 | |
| 54 def testGetSpecificVersion(self): | |
| 55 entity = _Entity.Create() | |
| 56 entity.value = 1 | |
| 57 entity.Save() | |
| 58 entity.value = 2 | |
| 59 entity.Save() | |
| 60 | |
| 61 entity_version_2 = _Entity.GetVersion(version=2) | |
| 62 self.assertEqual(2, entity_version_2.version_number) | |
| 63 self.assertEqual(2, entity_version_2.value) | |
| 64 self.assertIsNone(_Entity.GetVersion(version=0)) | |
| 65 self.assertIsNone(_Entity.GetVersion(version=3)) | |
| 66 | |
| 67 def testGetLatestVersionNumber(self): | |
| 68 entity = _Entity.Create() | |
| 69 entity.Save() | |
| 70 self.assertEqual(1, _Entity.GetLatestVersionNumber()) | |
| 71 | |
| 72 def testGetVersionForEntityWithKeyId(self): | |
| 73 entity = _Entity.Create('m1') | |
| 74 entity.value = 1 | |
| 75 entity.Save() | |
| 76 entity.value = 2 | |
| 77 entity.Save() | |
| 78 | |
| 79 self.assertEqual(2, _Entity.GetVersion('m1').version_number) | |
| 80 self.assertEqual(2, _Entity.GetVersion('m1').value) | |
| 81 self.assertIsNone(_Entity.GetVersion('m1', version=0)) | |
| 82 self.assertIsNone(_Entity.GetVersion('m1', version=3)) | |
| 83 | |
| 84 def testGetLatestVersionNumberWhenNoRecordYet(self): | |
| 85 self.assertEqual(-1, _Entity.GetLatestVersionNumber()) | |
| 86 self.assertEqual(-1, _Entity.GetLatestVersionNumber('m1')) | |
| 87 | |
| 88 def testSaveNewVersion(self): | |
| 89 entity = _Entity.Create() | |
| 90 entity.value = 1 | |
| 91 key, saved = entity.Save() | |
| 92 | |
| 93 expected_key = ndb.Key('_EntityRoot', 1, '_Entity', 1) | |
| 94 self.assertEqual(expected_key, key) | |
| 95 self.assertTrue(saved) | |
| 96 | |
| 97 entity = _Entity.GetVersion() | |
| 98 self.assertEqual(1, entity.version_number) | |
| 99 self.assertEqual(1, entity.value) | |
| 100 | |
| 101 def testSaveEntityWithRootId(self): | |
| 102 entity = _Entity.Create('m1') | |
| 103 entity.value = 1 | |
| 104 entity.Save() | |
| 105 entity.value = 3 | |
| 106 entity.Save() | |
| 107 | |
| 108 self.assertEqual(entity.version_number, 2) | |
| 109 self.assertEqual(entity.value, 3) | |
| 110 | |
| 111 def testSaveNewVersionOfEntityWithKeyId(self): | |
| 112 entity = _Entity.Create('m1') | |
| 113 entity.value = 1 | |
| 114 key, saved = entity.Save() | |
| 115 expected_key = ndb.Key('_EntityRoot', 'm1', '_Entity', 1) | |
| 116 self.assertEqual(expected_key, key) | |
| 117 self.assertTrue(saved) | |
| 118 | |
| 119 def testSaveNewVersionWithConflictRetry(self): | |
| 120 original_ndb_transaction = ndb.transaction | |
| 121 | |
| 122 def MockNdbTransaction(func, **options): | |
| 123 _Entity(key=ndb.Key('_EntityRoot', 1, '_Entity', 1), value=1).put() | |
| 124 _Entity(key=ndb.Key('_EntityRoot', 1, '_Entity', 2), value=2).put() | |
| 125 return original_ndb_transaction(func, **options) | |
| 126 self.mock(ndb, 'transaction', MockNdbTransaction) | |
| 127 | |
| 128 entity = _Entity.Create() | |
| 129 key, saved = entity.Save() | |
| 130 expected_key = ndb.Key('_EntityRoot', 1, '_Entity', 3) | |
| 131 self.assertEqual(expected_key, key) | |
| 132 self.assertTrue(saved) | |
| 133 | |
| 134 def testSaveNewVersionWithConflictBeforeTransactionNoRetry(self): | |
| 135 original_ndb_transaction = ndb.transaction | |
| 136 | |
| 137 def MockNdbTransaction(func, **options): | |
| 138 # To simulate another transaction occuring before this one, write a new | |
| 139 # version first before the transaction is called. | |
| 140 _Entity(key=ndb.Key('_EntityRoot', 1, '_Entity', 1), value=1).put() | |
| 141 return original_ndb_transaction(func, **options) | |
| 142 self.mock(ndb, 'transaction', MockNdbTransaction) | |
| 143 | |
| 144 entity = _Entity.Create() | |
| 145 key, saved = entity.Save(retry_on_conflict=False) | |
| 146 expected_key = ndb.Key('_EntityRoot', 1, '_Entity', 1) | |
| 147 self.assertEqual(expected_key, key) | |
| 148 self.assertFalse(saved) | |
| 149 | |
| 150 def testSaveNewVersionConflictBeforeSaving(self): | |
| 151 original_save = VersionedModel.Save | |
| 152 | |
| 153 def MockSave(*args, **kwargs): | |
| 154 # Smulate another transaction beating this call to Save() to creating a | |
| 155 # new entity. | |
| 156 _Entity(key=ndb.Key('_EntityRoot', 1, '_Entity', 1), value=1).put() | |
| 157 return original_save(*args, **kwargs) | |
| 158 self.mock(VersionedModel, 'Save', MockSave) | |
| 159 | |
| 160 entity = _Entity.Create() | |
| 161 key, saved = entity.Save(retry_on_conflict=False) | |
| 162 expected_key = ndb.Key('_EntityRoot', 1, '_Entity', 1) | |
| 163 self.assertEqual(expected_key, key) | |
| 164 self.assertFalse(saved) | |
| 165 | |
| 166 def testLikelyTransactionFailure(self): | |
| 167 original_ndb_transaction = ndb.transaction | |
| 168 | |
| 169 calls = [] | |
| 170 def MockNdbTransaction(func, **options): | |
| 171 if len(calls) < 1: | |
| 172 calls.append(1) | |
| 173 raise datastore_errors.Timeout() | |
| 174 return original_ndb_transaction(func, **options) | |
| 175 self.mock(ndb, 'transaction', MockNdbTransaction) | |
| 176 | |
| 177 entity = _Entity.Create() | |
| 178 key, saved = entity.Save() | |
| 179 expected_key = ndb.Key('_EntityRoot', 1, '_Entity', 1) | |
| 180 self.assertEqual(expected_key, key) | |
| 181 self.assertTrue(saved) | |
| 182 self.assertEqual([1], calls) | |
| 183 | |
| 184 def testTransactionFailure(self): | |
| 185 original_ndb_transaction = ndb.transaction | |
| 186 | |
| 187 calls = [] | |
| 188 def MockNdbTransaction(func, **options): | |
| 189 if len(calls) < 1: | |
| 190 calls.append(1) | |
| 191 raise datastore_errors.BadRequestError() | |
| 192 return original_ndb_transaction(func, **options) | |
| 193 self.mock(ndb, 'transaction', MockNdbTransaction) | |
| 194 | |
| 195 entity = _Entity.Create() | |
| 196 key, saved = entity.Save() | |
| 197 expected_key = ndb.Key('_EntityRoot', 1, '_Entity', 1) | |
| 198 self.assertEqual(expected_key, key) | |
| 199 self.assertEqual([1], calls) | |
| 200 self.assertTrue(saved) | |
| OLD | NEW |