def test_handle_init1(self):
    self.service.access_mode = 'r'
    memcache.set(self.memcache_prefix + 'update_' + '1',
        {'path': ['a'], 'new_value': '["v1"]'})
    memcache.set(self.memcache_prefix + 'state', {
      'token': 'state_token_1',
      'version': 1,
      'last_transaction': [
        {'path': ['b'], 'new_value': '["v2"]', 'version': 2},
      ],
      'clients': set(['1'])
    })

    yield self.service._DatasourceService__handle_init({'init': [None, 'abc']})
    self.assertEquals({'1': {'service1': [{'init_success': [
      'abc',
      'state_token_1',
      0,
      {},
      [
        ['a', ["v1"], 1],
        ['b', ["v2"], 2],
      ]
    ]}]}}, mcchannel._outgoing_messages)

    mcchannel._outgoing_messages = defaultdict(lambda: defaultdict(list))
    datasource._Version(parent=self.datasource_key, id=1, version=1).put()
    datasource._Value(parent=self.datasource_key, id='a',
        value='["v3"]').put()
    yield self.service._DatasourceService__handle_init({'init': [None, 'abc']})
    self.assertEquals({'1': {'service1': [{'init_success': [
      'abc',
      'state_token_1',
      1,
      {'a': {'.': ["v3"]}},
      [
        ['b', ["v2"], 2],
      ]
    ]}]}}, mcchannel._outgoing_messages)

    mcchannel._outgoing_messages = defaultdict(lambda: defaultdict(list))
    datasource._Version(parent=self.datasource_key, id=1, version=2).put()
    datasource._Value(parent=self.datasource_key, id='b',
        value='["v4"]').put()
    yield self.service._DatasourceService__handle_init({'init': [None, 'abc']})
    self.assertEquals({'1': {'service1': [{'init_success': [
      'abc',
      'state_token_1',
      2,
      {
        'a': {'.': ["v3"]},
        'b': {'.': ["v4"]}
      },
      []
    ]}]}}, mcchannel._outgoing_messages)
 def test_get_disk_state(self):
   disk_state = yield self.service._DatasourceService__get_disk_state()
   self.assertEquals((0, {}), disk_state)
   datasource._Version(parent=self.datasource_key, id=1, version=3).put()
   datasource._Value(parent=self.datasource_key, id='/',
       value='["v1"]').put()
   datasource._Value(parent=self.datasource_key, id='a0/a1',
       value='["v2"]').put()
   disk_state = yield self.service._DatasourceService__get_disk_state()
   self.assertEquals((3, {
     '.': ["v1"],
     'a0': {'a1': {'.': ["v2"]}}
   }), disk_state)
  def test_save_handler(self):
    update_saving_status_after_saving_calls = []
    original_update_saving_status_after_saving = (
        datasource._update_saving_status_after_saving)
    datasource._update_saving_status_after_saving = (lambda *args:
        update_saving_status_after_saving_calls.append(args))
    try:
      memcache.set(self.memcache_prefix + 'update_' + '1',
          {'path': [], 'new_value': '["v1"]'})
      memcache.set(self.memcache_prefix + 'state', {
        'token': 'state_token_1',
        'version': 1,
        'last_transaction': [
          {'path': ['b'], 'new_value': '["v2"]', 'version': 2},
        ],
        'clients': set(['1'])
      })

      query = urllib.urlencode({
        'datasource_key': self.datasource_key.urlsafe(),
        'service': 'service1'
      })
      self.testapp.post(
          datasource._config.BASE_URL_PATH + '/random?' + query)
      self.assertEquals(2, ndb.Key(datasource._Version, 1,
          parent=self.datasource_key).get().version)
      self.assertEquals('["v1"]', ndb.Key(datasource._Value, '/',
          parent=self.datasource_key).get().value)
      self.assertEquals('["v2"]', ndb.Key(datasource._Value, 'b',
          parent=self.datasource_key).get().value)
      self.assertEquals([('service1', self.datasource_key)],
          update_saving_status_after_saving_calls)
      update_saving_status_after_saving_calls = []
      self.assertEquals({'1': {'service1': [{'saved': [
        'state_token_1',
        2
      ]}]}}, mcchannel._outgoing_messages)
      mcchannel._outgoing_messages = defaultdict(lambda: defaultdict(list))

      # Modify what is stored on disk for paths '' and 'b' to make sure
      # the first two updates do not get saved again.
      datasource._Value(parent=self.datasource_key, id='/',
          value='["other_v1"]').put()
      datasource._Value(parent=self.datasource_key, id='b',
          value='["other_v2"]').put()
      datasource._Value(parent=self.datasource_key, id='c',
          value='["other_v3"]').put()
      memcache.set(self.memcache_prefix + 'update_' + '3',
          {'path': ['c'], 'new_value': 'null'})
      memcache.set(self.memcache_prefix + 'state', {
        'token': 'state_token_1',
        'version': 3,
        'clients': set(['1'])
      })
      self.testapp.post(
          datasource._config.BASE_URL_PATH + '/random?' + query)
      self.assertEquals(3, ndb.Key(datasource._Version, 1,
          parent=self.datasource_key).get().version)
      self.assertEquals('["other_v1"]', ndb.Key(datasource._Value, '/',
          parent=self.datasource_key).get().value)
      self.assertEquals('["other_v2"]', ndb.Key(datasource._Value, 'b',
          parent=self.datasource_key).get().value)
      self.assertIs(None, ndb.Key(datasource._Value, 'c',
          parent=self.datasource_key).get())
      self.assertEquals([('service1', self.datasource_key)],
          update_saving_status_after_saving_calls)
      update_saving_status_after_saving_calls = []
      self.assertEquals({'1': {'service1': [{'saved': [
        'state_token_1',
        3
      ]}]}}, mcchannel._outgoing_messages)
      mcchannel._outgoing_messages = defaultdict(lambda: defaultdict(list))

    finally:
      datasource._update_saving_status_after_saving = (
          original_update_saving_status_after_saving)