def testStronglyConsistentCommits(self):
    created_by = users.User('*****@*****.**')

    # Microversions use FinalizeAssociatedPaths so the Commit() path should use
    # the always strongly-consistent GetFiles(), rather than a query. Verify
    # this behavior by simulating a never-consistent HR datastore.
    policy = datastore_stub_util.PseudoRandomHRConsistencyPolicy(probability=0)
    self.testbed.init_datastore_v3_stub(consistency_policy=policy)

    final_changeset = microversions._CommitMicroversion(
        created_by=created_by, write=True, path='/foo', content='foo')
    self.assertEqual(2, final_changeset.num)
    file_obj = files.Get('/foo', changeset=final_changeset.linked_changeset)
    self.assertEqual('foo', file_obj.content)
  def testCommitMicroversion(self):
    created_by = users.User('*****@*****.**')

    # Write.
    final_changeset = microversions._CommitMicroversion(
        created_by=created_by, write=True, path='/foo', content='foo')
    self.assertEqual(2, final_changeset.num)
    file_obj = files.Get('/foo', changeset=final_changeset.linked_changeset)
    self.assertEqual('foo', file_obj.content)

    # Verify the final changeset's created_by.
    self.assertEqual('*****@*****.**', str(final_changeset.created_by))

    # Write with an existing root file (which should be copied to the version).
    files.Write('/foo', 'new foo', disabled_services=True)
    final_changeset = microversions._CommitMicroversion(
        created_by=created_by, write=True, path='/foo', meta={'color': 'blue'})
    self.assertEqual(4, final_changeset.num)
    file_obj = files.Get('/foo', changeset=final_changeset.linked_changeset)
    self.assertEqual('new foo', file_obj.content)
    self.assertEqual('blue', file_obj.color)

    # Touch.
    final_changeset = microversions._CommitMicroversion(
        created_by=created_by, touch=True, paths='/foo')
    self.assertEqual(6, final_changeset.num)
    file_obj = files.Get('/foo', changeset=final_changeset.linked_changeset)
    self.assertEqual('new foo', file_obj.content)

    # Delete. In the real code path, the delete of the root file will often
    # complete before the task is started, so we delete /foo to verify that
    # deletes don't rely on presence of the root file.
    files.Delete('/foo', disabled_services=True)
    final_changeset = microversions._CommitMicroversion(
        created_by=created_by, delete=True, paths='/foo')
    self.assertEqual(8, final_changeset.num)
    file_obj = files.Get('/foo', changeset=final_changeset.linked_changeset)
    self.assertEqual('', file_obj.content)

    # Check file versions.
    file_versions = self.vcs.GetFileVersions('/foo')
    self.assertEqual(8, file_versions[0].changeset.num)
    self.assertEqual(6, file_versions[1].changeset.num)
    self.assertEqual(4, file_versions[2].changeset.num)
    self.assertEqual(2, file_versions[3].changeset.num)
    self.assertEqual(versions.FILE_DELETED, file_versions[0].status)
    self.assertEqual(versions.FILE_EDITED, file_versions[1].status)
    self.assertEqual(versions.FILE_EDITED, file_versions[2].status)
    self.assertEqual(versions.FILE_CREATED, file_versions[3].status)

    # Touch multi.
    final_changeset = microversions._CommitMicroversion(
        created_by=created_by, touch=True, paths=['/foo', '/bar'])
    self.assertEqual(10, final_changeset.num)
    file_objs = files.Get(['/foo', '/bar'],
                          changeset=final_changeset.linked_changeset)
    self.assertEqual(2, len(file_objs))

    # Delete multi.
    final_changeset = microversions._CommitMicroversion(
        created_by=created_by, delete=True, paths=['/foo', '/bar'])
    self.assertEqual(12, final_changeset.num)
    file_objs = files.Get(['/foo', '/bar'],
                          changeset=final_changeset.linked_changeset)
    self.assertEqual(versions.FILE_DELETED, file_objs['/foo'].status)
    self.assertEqual(versions.FILE_DELETED, file_objs['/bar'].status)