# -*- coding: utf-8 -*- # ****************************************************************************** # # Copyright (C) 2009 Olivier Tilloy # # This file is part of the pyexiv2 distribution. # # pyexiv2 is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # pyexiv2 is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with pyexiv2; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA. # # Author: Olivier Tilloy # # ****************************************************************************** import unittest from pyexiv2 import ListenerInterface, NotifyingList import random class SimpleListener(ListenerInterface): def __init__(self): self.changes = 0 def contents_changed(self): self.changes += 1 class TestNotifyingList(unittest.TestCase): def setUp(self): self.values = NotifyingList([5, 7, 9, 14, 57, 3, 2]) def test_no_listener(self): # No listener is registered, nothing should happen. self.values[3] = 13 del self.values[5] self.values.append(17) self.values.extend([11, 22]) self.values.insert(4, 24) self.values.pop() self.values.remove(9) self.values.reverse() self.values.sort() self.values += [8, 4] self.values *= 3 self.values[3:4] = [8, 4] del self.values[3:5] def test_listener_interface(self): self.values.register_listener(ListenerInterface()) self.failUnlessRaises(NotImplementedError, self.values.__setitem__, 3, 13) self.failUnlessRaises(NotImplementedError, self.values.__delitem__, 5) self.failUnlessRaises(NotImplementedError, self.values.append, 17) self.failUnlessRaises(NotImplementedError, self.values.extend, [11, 22]) self.failUnlessRaises(NotImplementedError, self.values.insert, 4, 24) self.failUnlessRaises(NotImplementedError, self.values.pop) self.failUnlessRaises(NotImplementedError, self.values.remove, 9) self.failUnlessRaises(NotImplementedError, self.values.reverse) self.failUnlessRaises(NotImplementedError, self.values.sort) self.failUnlessRaises(NotImplementedError, self.values.__iadd__, [8, 4]) self.failUnlessRaises(NotImplementedError, self.values.__imul__, 3) self.failUnlessRaises(NotImplementedError, self.values.__setslice__, 3, 4, [8, 4]) self.failUnlessRaises(NotImplementedError, self.values.__delslice__, 3, 5) def _register_listeners(self): # Register a random number of listeners listeners = [SimpleListener() for i in xrange(random.randint(3, 20))] for listener in listeners: self.values.register_listener(listener) return listeners def test_setitem(self): listeners = self._register_listeners() self.values[3] = 13 self.failUnlessEqual(self.values, [5, 7, 9, 13, 57, 3, 2]) for listener in listeners: self.failUnlessEqual(listener.changes, 1) self.failUnlessRaises(IndexError, self.values.__setitem__, 9, 27) self.failUnlessEqual(self.values, [5, 7, 9, 13, 57, 3, 2]) for listener in listeners: self.failUnlessEqual(listener.changes, 1) def test_delitem(self): listeners = self._register_listeners() del self.values[5] self.failUnlessEqual(self.values, [5, 7, 9, 14, 57, 2]) for listener in listeners: self.failUnlessEqual(listener.changes, 1) self.failUnlessRaises(IndexError, self.values.__delitem__, 9) self.failUnlessEqual(self.values, [5, 7, 9, 14, 57, 2]) for listener in listeners: self.failUnlessEqual(listener.changes, 1) def test_append(self): listeners = self._register_listeners() self.values.append(17) self.failUnlessEqual(self.values, [5, 7, 9, 14, 57, 3, 2, 17]) for listener in listeners: self.failUnlessEqual(listener.changes, 1) def test_extend(self): listeners = self._register_listeners() self.values.extend([11, 22]) self.failUnlessEqual(self.values, [5, 7, 9, 14, 57, 3, 2, 11, 22]) for listener in listeners: self.failUnlessEqual(listener.changes, 1) self.failUnlessRaises(TypeError, self.values.extend, 26) self.failUnlessEqual(self.values, [5, 7, 9, 14, 57, 3, 2, 11, 22]) for listener in listeners: self.failUnlessEqual(listener.changes, 1) def test_insert(self): listeners = self._register_listeners() self.values.insert(4, 24) self.failUnlessEqual(self.values, [5, 7, 9, 14, 24, 57, 3, 2]) for listener in listeners: self.failUnlessEqual(listener.changes, 1) def test_pop(self): listeners = self._register_listeners() self.values.pop() self.failUnlessEqual(self.values, [5, 7, 9, 14, 57, 3]) for listener in listeners: self.failUnlessEqual(listener.changes, 1) self.values.pop(4) self.failUnlessEqual(self.values, [5, 7, 9, 14, 3]) for listener in listeners: self.failUnlessEqual(listener.changes, 2) self.values.pop(-2) self.failUnlessEqual(self.values, [5, 7, 9, 3]) for listener in listeners: self.failUnlessEqual(listener.changes, 3) self.failUnlessRaises(IndexError, self.values.pop, 33) self.failUnlessEqual(self.values, [5, 7, 9, 3]) for listener in listeners: self.failUnlessEqual(listener.changes, 3) def test_remove(self): listeners = self._register_listeners() self.values.remove(9) self.failUnlessEqual(self.values, [5, 7, 14, 57, 3, 2]) for listener in listeners: self.failUnlessEqual(listener.changes, 1) self.failUnlessRaises(ValueError, self.values.remove, 33) self.failUnlessEqual(self.values, [5, 7, 14, 57, 3, 2]) for listener in listeners: self.failUnlessEqual(listener.changes, 1) def test_reverse(self): listeners = self._register_listeners() self.values.reverse() self.failUnlessEqual(self.values, [2, 3, 57, 14, 9, 7, 5]) for listener in listeners: self.failUnlessEqual(listener.changes, 1) def test_sort(self): listeners = self._register_listeners() self.values.sort() self.failUnlessEqual(self.values, [2, 3, 5, 7, 9, 14, 57]) for listener in listeners: self.failUnlessEqual(listener.changes, 1) self.values.sort(cmp=lambda x, y: y - x) self.failUnlessEqual(self.values, [57, 14, 9, 7, 5, 3, 2]) for listener in listeners: self.failUnlessEqual(listener.changes, 2) self.values.sort(key=lambda x: x * x) self.failUnlessEqual(self.values, [2, 3, 5, 7, 9, 14, 57]) for listener in listeners: self.failUnlessEqual(listener.changes, 3) self.values.sort(reverse=True) self.failUnlessEqual(self.values, [57, 14, 9, 7, 5, 3, 2]) for listener in listeners: self.failUnlessEqual(listener.changes, 4) def test_iadd(self): listeners = self._register_listeners() self.values += [44, 31, 19] self.failUnlessEqual(self.values, [5, 7, 9, 14, 57, 3, 2, 44, 31, 19]) for listener in listeners: self.failUnlessEqual(listener.changes, 1) def test_imul(self): listeners = self._register_listeners() self.values *= 3 self.failUnlessEqual(self.values, [5, 7, 9, 14, 57, 3, 2, 5, 7, 9, 14, 57, 3, 2, 5, 7, 9, 14, 57, 3, 2]) for listener in listeners: self.failUnlessEqual(listener.changes, 1) def test_setslice(self): listeners = self._register_listeners() # Basic slicing (of the form [i:j]): implemented as __setslice__. self.values[2:4] = [3, 4] self.failUnlessEqual(self.values, [5, 7, 3, 4, 57, 3, 2]) for listener in listeners: self.failUnlessEqual(listener.changes, 1) self.values[3:5] = [77, 8, 12] self.failUnlessEqual(self.values, [5, 7, 3, 77, 8, 12, 3, 2]) for listener in listeners: self.failUnlessEqual(listener.changes, 2) self.values[2:5] = [1, 0] self.failUnlessEqual(self.values, [5, 7, 1, 0, 12, 3, 2]) for listener in listeners: self.failUnlessEqual(listener.changes, 3) self.values[0:2] = [] self.failUnlessEqual(self.values, [1, 0, 12, 3, 2]) for listener in listeners: self.failUnlessEqual(listener.changes, 4) self.values[2:2] = [7, 5] self.failUnlessEqual(self.values, [1, 0, 7, 5, 12, 3, 2]) for listener in listeners: self.failUnlessEqual(listener.changes, 5) # With negatives indexes self.values[4:-2] = [9] self.failUnlessEqual(self.values, [1, 0, 7, 5, 9, 3, 2]) for listener in listeners: self.failUnlessEqual(listener.changes, 6) self.values[-2:1] = [6, 4] self.failUnlessEqual(self.values, [1, 0, 7, 5, 9, 6, 4, 3, 2]) for listener in listeners: self.failUnlessEqual(listener.changes, 7) self.values[-5:-2] = [8] self.failUnlessEqual(self.values, [1, 0, 7, 5, 8, 3, 2]) for listener in listeners: self.failUnlessEqual(listener.changes, 8) # With missing (implicit) indexes self.values[:2] = [4] self.failUnlessEqual(self.values, [4, 7, 5, 8, 3, 2]) for listener in listeners: self.failUnlessEqual(listener.changes, 9) self.values[4:] = [1] self.failUnlessEqual(self.values, [4, 7, 5, 8, 1]) for listener in listeners: self.failUnlessEqual(listener.changes, 10) self.values[:] = [5, 7, 9, 14, 57, 3, 2] self.failUnlessEqual(self.values, [5, 7, 9, 14, 57, 3, 2]) for listener in listeners: self.failUnlessEqual(listener.changes, 11) def test_delslice(self): listeners = self._register_listeners() del self.values[2:3] self.failUnlessEqual(self.values, [5, 7, 14, 57, 3, 2]) for listener in listeners: self.failUnlessEqual(listener.changes, 1) del self.values[2:2] self.failUnlessEqual(self.values, [5, 7, 14, 57, 3, 2]) for listener in listeners: self.failUnlessEqual(listener.changes, 1) # With negatives indexes del self.values[4:-1] self.failUnlessEqual(self.values, [5, 7, 14, 57, 2]) for listener in listeners: self.failUnlessEqual(listener.changes, 2) del self.values[-1:5] self.failUnlessEqual(self.values, [5, 7, 14, 57]) for listener in listeners: self.failUnlessEqual(listener.changes, 3) del self.values[-2:-1] self.failUnlessEqual(self.values, [5, 7, 57]) for listener in listeners: self.failUnlessEqual(listener.changes, 4) # With missing (implicit) indexes del self.values[:1] self.failUnlessEqual(self.values, [7, 57]) for listener in listeners: self.failUnlessEqual(listener.changes, 5) del self.values[1:] self.failUnlessEqual(self.values, [7]) for listener in listeners: self.failUnlessEqual(listener.changes, 6) del self.values[:] self.failUnlessEqual(self.values, []) for listener in listeners: self.failUnlessEqual(listener.changes, 7)