def setUp(self): super(APITests, self).setUp() self.section = object() self.a = API(self.section, 'the name', None)
class APITests(SourceMixin, TestCase): def setUp(self): super(APITests, self).setUp() self.section = object() self.a = API(self.section, 'the name', None) called_with = False def _action(self, *args): self.called_with = args def test_repr(self): compare("<API for Section 'the name' at 0x%x>" % id(self.section), repr(self.a)) def test_str(self): compare("<API for Section 'the name' at 0x%x>" % id(self.section), str(self.a)) # set tests def test_set_get_simple(self): # before compare(marker, self.a.get('foo')) compare(None, self.a.get('foo', None)) compare('default', self.a.get('foo', 'default')) compare([], self.a.items()) # set self.a.set('foo', 'value') # after compare(Attribute('foo', 'value', 'set', 'default_source3', 0, None), self.a.get('foo')) compare([Attribute('foo', 'value', 'set', 'default_source3', 0, None)], self.a.items()) compare('default_source3', self.a.source(name='foo')) compare([Attribute('foo', 'value', 'set', 'default_source3', 0, None)], self.a.history(name='foo')) compare([Attribute('foo', 'value', 'set', 'default_source3', 0, None)], self.a.history()) def test_set_get_none_value(self): # set self.a.set('foo', None) # after compare(Attribute('foo', None, 'set', 'default_source3', 0, None), self.a.get('foo')) compare([Attribute('foo', None, 'set', 'default_source3', 0, None)], self.a.items()) compare('default_source3', self.a.source(name='foo')) compare([Attribute('foo', None, 'set', 'default_source3', 0, None)], self.a.history(name='foo')) compare([Attribute('foo', None, 'set', 'default_source3', 0, None)], self.a.history()) def test_set_update_existing(self): # set self.a.set('foo', 'v1', 's1') self.a.set('foo', 'v2', 's2') # after compare(Attribute('foo', 'v2', 'set', 's2', 0, None), self.a.get('foo')) compare([Attribute('foo', 'v2', 'set', 's2', 0, None)], self.a.items()) compare('s2', self.a.source('foo')) compare([ Attribute('foo', 'v1', 'set', 's1', 0, None), Attribute('foo', 'v2', 'set', 's2', 0, None), ], self.a.history('foo')) compare([ Attribute('foo', 'v1', 'set', 's1', 0, None), Attribute('foo', 'v2', 'set', 's2', 0, None), ], self.a.history()) def test_set_set_indexes(self): self.a.set('foo', 'v1', 's1') self.a.set('bar', 'v2', 's2') compare([Attribute('foo', 'v1', 'set', 's1', 0, None), Attribute('bar', 'v2', 'set', 's2', 1, None)], self.a.items()) def test_set_section(self): s = Section() self.a.set('foo', s) self.assertTrue(self.a.get('foo').value is s) def test_set_api(self): s = Section() a = api(s) self.a.set('foo', a) self.assertTrue(self.a.get('foo').value is s) def test_set_section_name(self): s = Section() self.a.set('foo', s) compare('foo', api(s).name) # append tests def test_append(self): # append self.a.append('v1') # after items = self.a.items() compare([Attribute(None, 'v1', 'append', 'default_source3', 0, None)], items) compare('default_source3', items[0].source) compare([ Attribute(None, 'v1', 'append', 'default_source3', 0, None), ], items[0].history()) compare([ Attribute(None, 'v1', 'append', 'default_source3', 0, None), ], self.a.history()) def test_append_append(self): # append self.a.append('v1', 's1') self.a.append('v2', 's2') # after items = self.a.items() compare([ Attribute(None, 'v1', 'append', 's1', 0, None), Attribute(None, 'v2', 'append', 's2', 1, None) ], items) compare('s1', items[0].source) compare('s2', items[1].source) compare([ Attribute(None, 'v1', 'append', 's1', 0, None), ], items[0].history()) compare([ Attribute(None, 'v2', 'append', 's2', 1, None), ], items[1].history()) compare([ Attribute(None, 'v1', 'append', 's1', 0, None), Attribute(None, 'v2', 'append', 's2', 1, None) ], self.a.history()) def test_append_section(self): expected = Section() self.a.append(expected) actual = tuple(self.a.items())[0].value self.assertTrue(expected is actual) def test_append_api(self): expected = Section() a = api(expected) self.a.append(a) actual = tuple(self.a.items())[0].value self.assertTrue(expected is actual) def test_append_section_name(self): s = Section() self.a.append(s) compare(None, api(s).name) # remove tests def test_remove_name(self): # setup self.a.set('foo', 'v1', 's1') # remove self.a.remove('foo') # check compare('default', self.a.get('foo', 'default')) compare([], self.a.items()) compare(None, self.a.source(name='foo')) compare([ Attribute('foo', 'v1', 'set', 's1', 0, None), Attribute('foo', marker, 'remove', 'default_source3', 0, None) ], self.a.history(name='foo')) compare([ Attribute('foo', 'v1', 'set', 's1', 0, None), Attribute('foo', marker, 'remove', 'default_source3', 0, None) ], self.a.history()) def test_remove_name_not_present(self): # we record the remove, handy for merging Sections # remove self.a.remove('foo') # check compare([], self.a.items()) compare(None, self.a.source(name='foo')) compare([ Attribute('foo', marker, 'remove', 'default_source3', 0, None) ], self.a.history(name='foo')) compare([ Attribute('foo', marker, 'remove', 'default_source3', 0, None) ], self.a.history()) def test_remove_value(self): # check that remove by identity works value = object() self.a.set('foo', value) # remove self.a.remove(value=value) # check compare('default', self.a.get('foo', 'default')) compare([], self.a.items()) compare(None, self.a.source(name='foo')) compare([ Attribute('foo', value, 'set', 'default_source3', 0, None), Attribute('foo', marker, 'remove', 'default_source3', 0, None) ], self.a.history(name='foo')) compare([ Attribute('foo', value, 'set', 'default_source3', 0, None), Attribute('foo', marker, 'remove', 'default_source3', 0, None) ], self.a.history()) def test_remove_by_name_previous_remove(self): # setup self.a.set('foo', 'v1') self.a.set('bar', 'v2') # do removes self.a.remove(value='v1') self.a.remove(name='bar') # check (especially history) compare('default', self.a.get('foo', 'default')) compare('default', self.a.get('bar', 'default')) compare([], self.a.items()) compare(None, self.a.source(name='foo')) compare(None, self.a.source(name='bar')) compare([ Attribute('foo', 'v1', 'set', 'default_source3', 0, None), Attribute('foo', marker, 'remove', 'default_source3', 0, None) ], self.a.history(name='foo')) compare([ Attribute('bar', 'v2', 'set', 'default_source3', 1, None), Attribute('bar', marker, 'remove', 'default_source3', 1, None) ], self.a.history(name='bar')) compare([ Attribute('foo', 'v1', 'set', 'default_source3', 0, None), Attribute('bar', 'v2', 'set', 'default_source3', 1, None), Attribute('foo', marker, 'remove', 'default_source3', 0, None), Attribute('bar', marker, 'remove', 'default_source3', 1, None), ], self.a.history()) def test_remove_nothing_specified(self): # just does nothing self.a.remove() compare([], self.a.items()) compare([ ], self.a.history()) def test_double_remove_by_name(self): # setup self.a.set('foo', 'v1') # do removes self.a.remove(name='foo') self.a.remove(name='foo') # check (especially history) compare('default', self.a.get('foo', 'default')) compare([], self.a.items()) compare(None, self.a.source(name='foo')) compare([ Attribute('foo', 'v1', 'set', 'default_source3', 0, None), Attribute('foo', marker, 'remove', 'default_source3', 0, None) ], self.a.history(name='foo')) compare([ Attribute('foo', 'v1', 'set', 'default_source3', 0, None), Attribute('foo', marker, 'remove', 'default_source3', 0, None), ], self.a.history()) def test_double_remove_by_value(self): # setup self.a.set('foo', 'v1') # do removes self.a.remove(value='v1') self.a.remove(value='v1') # check (especially history) compare('default', self.a.get('foo', 'default')) compare([], self.a.items()) compare(None, self.a.source(name='foo')) compare([ Attribute('foo', 'v1', 'set', 'default_source3', 0, None), Attribute('foo', marker, 'remove', 'default_source3', 0, None) ], self.a.history(name='foo')) compare([ Attribute('foo', 'v1', 'set', 'default_source3', 0, None), Attribute('foo', marker, 'remove', 'default_source3', 0, None), ], self.a.history()) def test_remove_value_multiple_match(self): self.a.set('foo', 'v', 's1') self.a.set('bar', 'v', 's2') # remove self.a.remove(value='v', source='s3') # check compare('default', self.a.get('foo', 'default')) compare('default', self.a.get('bar', 'default')) compare([], self.a.items()) compare(None, self.a.source(name='foo')) compare(None, self.a.source(name='bar')) compare([ Attribute('foo', 'v', 'set', 's1', 0, None), Attribute('foo', marker, 'remove', 's3', 0, None) ], self.a.history(name='foo')) compare([ Attribute('bar', 'v', 'set', 's2', 1, None), Attribute('bar', marker, 'remove', 's3', 1, None) ], self.a.history(name='bar')) compare([ Attribute('foo', 'v', 'set', 's1', 0, None), Attribute('bar', 'v', 'set', 's2', 1, None), Attribute('foo', marker, 'remove', 's3', 0, None), Attribute('bar', marker, 'remove', 's3', 1, None) ], self.a.history()) def test_add_append_remove(self): self.a.set('foo', 'v', 's1') self.a.append('v', 's2') # remove self.a.remove(value='v', source='s3') # check compare('default', self.a.get('foo', 'default')) compare([], self.a.items()) compare(None, self.a.source(name='foo')) compare([ Attribute('foo', 'v', 'set', 's1', 0, None), Attribute('foo', marker, 'remove', 's3', 0, None) ], self.a.history(name='foo')) compare([ Attribute('foo', 'v', 'set', 's1', 0, None), Attribute(None, 'v', 'append', 's2', 1, None), Attribute('foo', marker, 'remove', 's3', 0, None), Attribute(None, marker, 'remove', 's3', 1, None) ], self.a.history()) # combined operation tests def test_set_set_append_set_append_remove(self): # a good mix of stuff to exercise history # (all with sources) self.a.set('foo', 'v1', 's1') self.a.set('bar', 'v2', 's2') self.a.append('v3', 's3') self.a.set('bar', 'v4', 's4') self.a.append('v5', 's5') self.a.remove(value='v2', source='s6') # should do nothing self.a.remove(name='foo', source='s7') # check compare('default', self.a.get('foo', 'default')) compare(Attribute('bar', 'v4', 'set', 's4', 1, None), self.a.get('bar', 'default')) compare([ Attribute('bar', 'v4', 'set', 's4', 1, None), Attribute(None, 'v3', 'append', 's3', 2, None), Attribute(None, 'v5', 'append', 's5', 3, None), ], self.a.items()) compare(None, self.a.source(name='foo')) compare('s4', self.a.source(name='bar')) compare([ Attribute('foo', 'v1', 'set', 's1', 0, None), Attribute('foo', marker, 'remove', 's7', 0, None) ], self.a.history(name='foo')) compare([ Attribute('bar', 'v2', 'set', 's2', 1, None), Attribute('bar', 'v4', 'set', 's4', 1, None), ], self.a.history(name='bar')) compare([ Attribute('foo', 'v1', 'set', 's1', 0, None), Attribute('bar', 'v2', 'set', 's2', 1, None), Attribute(None, 'v3', 'append', 's3', 2, None), Attribute('bar', 'v4', 'set', 's4', 1, None), Attribute(None, 'v5', 'append', 's5', 3, None), Attribute('foo', marker, 'remove', 's7', 0, None), ], self.a.history()) # source-only tests def test_source_set_remove_by_name(self): self.a.set('foo', 'v', 's1') # remove self.a.remove(name='foo', source='s3') # check compare('default', self.a.get('foo', 'default')) compare([], self.a.items()) compare(None, self.a.source(name='foo')) compare([ Attribute('foo', 'v', 'set', 's1', 0, None), Attribute('foo', marker, 'remove', 's3', 0, None) ], self.a.history(name='foo')) compare([ Attribute('foo', 'v', 'set', 's1', 0, None), Attribute('foo', marker, 'remove', 's3', 0, None), ], self.a.history()) def test_source_section(self): compare('source', API(None, None, 'source').source()) def test_source_section_empty(self): compare('default_source', self.a.source()) def test_source_name_not_present(self): compare(None, self.a.source('foo')) def test_source_none_specified(self): self.a.set('foo', 'bar') compare('default_source3', self.a.source('foo')) def test_set_source_specified(self): self.a.set('foo', 'bar', 'line 200 - foo.conf') compare('line 200 - foo.conf', self.a.source('foo')) def test_replace_no_source(self): self.a.replace('foo', 'bar') compare( Attribute('foo', 'bar', 'replace', 'default_source3', 0, None), self.a.get('foo')) compare([ Attribute('foo', 'bar', 'replace', 'default_source3', 0, None), ], self.a.items()) compare('default_source3', self.a.source(name='foo')) compare([ Attribute('foo', 'bar', 'replace', 'default_source3', 0, None), ], self.a.history(name='foo')) compare([ Attribute('foo', 'bar', 'replace', 'default_source3', 0, None), ], self.a.history()) def test_replace_source(self): self.a.replace('foo', 'bar', 'the source') compare( Attribute('foo', 'bar', 'replace', 'the source', 0, None), self.a.get('foo')) compare([ Attribute('foo', 'bar', 'replace', 'the source', 0, None), ], self.a.items()) compare('the source', self.a.source(name='foo')) compare([ Attribute('foo', 'bar', 'replace', 'the source', 0, None), ], self.a.history(name='foo')) compare([ Attribute('foo', 'bar', 'replace', 'the source', 0, None), ], self.a.history()) # history only tests def test_history_name_not_present(self): with ShouldRaise(KeyError('foo')): self.a.history('foo') def test_history_empty_section(self): compare([], self.a.history()) # process tests def test_process_empty(self): self.a.process() compare(True, self.a.processed) def test_process_simple(self): self.a.action(self._action) self.a.process() compare(True, self.a.processed) compare(self.called_with, (self.section, self.a)) def test_process_order(self): call_order = [] def action1(section, api): call_order.append('action1') def action2(section, api): call_order.append('action2') self.a.action(action1) self.a.action(action2) self.a.process() compare(True, self.a.processed) compare(['action1', 'action2'], call_order) def test_process_tree(self): call_order = [] def action(section, api): call_order.append(api.get('index').value) a = [self.a] self.a.set('index', 0) self.a.action(action) for i in range(1, 8): si = Section() ai = api(si) ai.set('index', i) a.append(ai) ai.action(action) self.a.set('a1', a[1]) a[1].set('a2', a[2]) a[1].set('a3', a[3]) self.a.set('a4', a[4]) a[4].set('a5', a[5]) a[5].set('a6', a[6]) a[4].set('a7', a[7]) self.a.process() # test leaf-first node traversal compare([2, 3, 1, 6, 5, 7, 4, 0], call_order) # test all sections are processed for ai in a: compare(True, ai.processed) def test_reprocess_strict(self): self.a.action(self._action) self.a.process() self.called_with = False with ShouldRaise(AlreadyProcessed( "Section 'the name' has already been processed" )): self.a.process() self.assertFalse(self.called_with) def test_reprocess_non_strict(self): self.a.action(self._action) self.a.process() self.called_with = False self.a.process(strict=False) self.assertFalse(self.called_with) # clone tests def test_clone_simple(self): # stuff that should be cloned self.a._source = 'foo' self.a.set('x', 1) self.a.set('y', 1) self.a.set('y', 2) self.a.remove('z') def foo(): pass self.a.action(foo) s_ = self.a.clone() self.assertTrue(isinstance(s_, Section)) self.assertFalse(s_ is self.section) a_ = api(s_) self.assertFalse(a_.processed) compare(self.a.name, a_.name) compare(self.a.source(), a_.source()) compare(self.a.by_name, a_.by_name) self.assertFalse(self.a.by_name is a_.by_name) compare(self.a.by_order, a_.by_order) self.assertFalse(self.a.by_order is a_.by_order) compare(self.a.history(), a_.history()) self.assertFalse(self.a._history is a_._history) compare(self.a._actions, a_._actions) self.assertFalse(self.a._actions is a_._actions) def test_clone_nested(self): s1 = Section() s1.x = 1 s2 = Section() s2.y = 2 a2 = api(s2) self.a.set('s1', s1) self.a.set('s2', a2) s_ = self.a.clone() compare(api(s_.s1).history(), api(s1).history()) compare(api(s_.s2).history(), api(s2).history()) self.assertFalse(s_.s1 is s1) self.assertFalse(s_.s2 is s2) def test_clone_already_processed(self): self.a.process() with ShouldRaise(AlreadyProcessed( "Can't clone 'the name' as it has been processed" )): self.a.clone()