Explorar el Código

Added more tests + removed duplicate test executions

Randy Paredis hace 3 años
padre
commit
e732c41a7c

+ 4 - 0
.gitignore

@@ -28,3 +28,7 @@ examples/AGV/tuning9/
 doc/_build/
 /src/CBD.egg-info/
 /src/dist/
+
+htmlcov/
+
+.coverage

+ 4 - 0
coverage.sh

@@ -0,0 +1,4 @@
+cd src
+coverage run --source . -m unittest discover -v test "*.py"
+coverage html
+#xdg-open htmlcov/index.html &

+ 4 - 0
examples/SinGen/latex_example.py

@@ -8,6 +8,10 @@ from CBD.converters.latexify import CBD2Latex
 # Create the model
 model = SinGen('model')
 
+# sim = Simulator(model)
+# sim.setVerbose(None)
+# sim.run(20)
+
 # Create the converter (see docs for info on args)
 cbd2latex = CBD2Latex(model, show_steps=True)
 

+ 2 - 17
src/CBD/Core.py

@@ -353,21 +353,6 @@ class WireBlock(BaseBlock):
         self.appendToSignal(self.getInputSignal(curIteration, "IN1").value)
 
 
-class SequenceBlock(BaseBlock):
-    """
-    A simple Sequence block: block initializes signal input with given sequence
-    Use only for the tests please
-    """
-    def __init__(self, block_name, sequence):
-        BaseBlock.__init__(self, block_name, [], ["OUT1"])
-        self.__sequence = sequence
-
-    def compute(self, curIteration):
-        if len(self.__sequence) <= curIteration:
-            raise ValueError("Sequence is not long enough")
-        self.appendToSignal(self.__sequence[curIteration])
-
-
 class CBD(BaseBlock):
     """
     The CBD class, contains an entire Causal Block Diagram
@@ -611,7 +596,7 @@ class CBD(BaseBlock):
             sep (str):  The path separator to use. Defaults to :code:`.`
 
         Returns:
-            The block that corresponds to the given path.
+            The block that corresponds to the given path and the path itself.
 
             .. note::   The block that will be returned has a different path than the path provided
                         in this function call. This is because this function assumes you already have
@@ -667,7 +652,7 @@ class CBD(BaseBlock):
 
     def getSignals(self):
         res = {}
-        for port in super().getSignals().keys():
+        for port in super(self).getSignals().keys():
             res[port] = self.getSignal(port)
         return res
 

+ 64 - 26
src/CBD/lib/std.py

@@ -9,7 +9,7 @@ __all__ = ['ConstantBlock', 'NegatorBlock', 'InverterBlock', 'AdderBlock', 'Prod
            'RootBlock', 'AbsBlock', 'IntBlock', 'ClampBlock', 'GenericBlock', 'MultiplexerBlock', 'LessThanBlock',
            'EqualsBlock', 'LessThanOrEqualsBlock', 'NotBlock', 'OrBlock', 'AndBlock', 'DelayBlock', 'LoggingBlock',
            'AddOneBlock', 'DerivatorBlock', 'IntegratorBlock', 'SplitBlock', 'Clock', 'TimeBlock', 'PowerBlock',
-           'MaxBlock', 'MinBlock', 'DummyClock']
+           'MaxBlock', 'MinBlock', 'DummyClock', 'SequenceBlock']
 
 class ConstantBlock(BaseBlock):
 	"""
@@ -31,7 +31,7 @@ class ConstantBlock(BaseBlock):
 		# TO IMPLEMENT
 		self.appendToSignal(self.getValue())
 
-	def __repr__(self):
+	def __repr__(self):  # pragma: no cover
 		return BaseBlock.__repr__(self) + "  Value = " + str(self.getValue()) + "\n"
 
 
@@ -128,12 +128,16 @@ class RootBlock(BaseBlock):
 	"""
 	A basic block that computes the IN2-th root from IN1
 	"""
-	def __init__(self, block_name):
+	def __init__(self, block_name, tolerance=1e-30):
 		BaseBlock.__init__(self, block_name, ["IN1", "IN2"], ["OUT1"])
+		self._tolerance = tolerance
 
 	def compute(self, curIteration):
 		# TO IMPLEMENT
-		self.appendToSignal(self.getInputSignal(curIteration, "IN1").value ** (1 / self.getInputSignal(curIteration, "IN2").value))
+		input = self.getInputSignal(curIteration, "IN2").value
+		if abs(input) < self._tolerance:
+			raise ZeroDivisionError("RootBlock '{}' received input less than {}.".format(self.getPath(), self._tolerance))
+		self.appendToSignal(self.getInputSignal(curIteration, "IN1").value ** (1 / input))
 
 
 class PowerBlock(BaseBlock):
@@ -185,7 +189,7 @@ class ClampBlock(BaseBlock):
 							respectively.
 	"""
 	def __init__(self, block_name, min=-1, max=1, use_const=True):
-		super().__init__(block_name, ["IN1"] if use_const else ["IN1", "IN2", "IN3"], ["OUT1"])
+		BaseBlock.__init__(self, block_name, ["IN1"] if use_const else ["IN1", "IN2", "IN3"], ["OUT1"])
 		self._use_const = use_const
 		self.min = min
 		self.max = max
@@ -224,7 +228,7 @@ class GenericBlock(BaseBlock):
 		a = self.getInputSignal(curIteration, "IN1").value
 		self.appendToSignal(getattr(math, self.getBlockOperator())(a))
 
-	def __repr__(self):
+	def __repr__(self):  # pragma: no cover
 		repr = BaseBlock.__repr__(self)
 		if self.__block_operator is None:
 			repr += "  No operator given\n"
@@ -448,6 +452,27 @@ class LoggingBlock(BaseBlock):
 				self.__logger.fatal("Time " + str(self.getClock().getTime(curIteration)) + ": " + self.__string)
 
 
+class TimeBlock(BaseBlock):
+	"""
+	Obtains the current time of the simulation.
+
+	Args:
+		block_name (str):   The name of the block.
+
+	Note:
+		When manipulating and reading time values, it may be better to use the
+		:class:`Clock` instead.
+	"""
+	def __init__(self, block_name):
+		BaseBlock.__init__(self, block_name, [], ["OUT1", "relative"])
+
+	def compute(self, curIteration):
+		time = self.getClock().getTime(curIteration)
+		rel_time = self.getClock().getRelativeTime(curIteration)
+		self.appendToSignal(time)
+		self.appendToSignal(rel_time, "relative")
+
+
 class AddOneBlock(CBD):
 	"""
 	Block adds a one to the input (used a lot for mux)
@@ -641,19 +666,34 @@ class Clock(CBD):
 
 class DummyClock(BaseBlock):
 	"""
-	Dummy implementation of the :class:`Clock`, to help for tests.
-	"""
+    Dummy clock to be used in the tests. It contains the exact same
+    functionality as the actual fixed rate :class:`Clock`, but allows for
+    better testing .
+
+    Warning:
+    	Only use this block in the tests!
+
+    Args:
+		block_name (str):   The name of the block.
+		start_time (float): Time at which the simulation starts. Defaults to 0.
+		delta (numeric):    Rate between two clock "ticks".
+
+	:Output Ports:
+		- :code:`time`:     The current simulation time.
+		- :code:`rel_time`: The relative simulation time, ignoring the start time.
+		- :code:`delta`:    The delay between two clock "ticks".
+    """
 	def __init__(self, block_name, start_time=0.0, delta=0.1):
 		BaseBlock.__init__(self, block_name, [], ["time", "rel_time", "delta"])
 		self.__start_time = start_time
 		self.__time = self.__start_time
-		self.__delta = delta
+		self.__delta_t = delta
 
 	def compute(self, curIteration):
 		self.appendToSignal(self.__time, "time")
 		self.appendToSignal(self.__time - self.__start_time, "rel_time")
-		self.appendToSignal(self.__delta, "delta")
-		self.__time += self.__delta
+		self.appendToSignal(self.__delta_t, "delta")
+		self.__time += self.__delta_t
 
 	def getTime(self, curIt):
 		"""
@@ -662,7 +702,7 @@ class DummyClock(BaseBlock):
 		sig = self.getSignal("time")
 		if curIt == 0 or len(sig) == 0:
 			return self.__start_time
-		return sig[curIt - 1].value + self.__delta
+		return sig[curIt - 1].value + self.__delta_t
 
 	def getRelativeTime(self, curIt):
 		"""
@@ -670,23 +710,21 @@ class DummyClock(BaseBlock):
 		"""
 		return self.getTime(curIt) - self.__start_time
 
+	def _rewind(self):
+		self.__start_time -= self.__delta_t
 
-class TimeBlock(BaseBlock):
-	"""
-	Obtains the current time of the simulation.
 
-	Args:
-		block_name (str):   The name of the block.
+class SequenceBlock(BaseBlock):
+	"""
+	A simple sequence block. Will output the sequence iteratively.
+	Especially useful for specific test cases.
 
-	Note:
-		When manipulating and reading time values, it may be better to use the
-		:class:`Clock` instead.
+	Warning:
+		Do not use this outside of the tests, unless really necessary.
 	"""
-	def __init__(self, block_name):
-		BaseBlock.__init__(self, block_name, [], ["OUT1", "relative"])
+	def __init__(self, block_name, sequence):
+		BaseBlock.__init__(self, block_name, [], ["OUT1"])
+		self.__sequence = sequence
 
 	def compute(self, curIteration):
-		time = self.getClock().getTime(curIteration)
-		rel_time = self.getClock().getRelativeTime(curIteration)
-		self.appendToSignal(time)
-		self.appendToSignal(rel_time, "relative")
+		self.appendToSignal(self.__sequence[curIteration % len(self.__sequence)])

+ 19 - 19
src/CBD/scheduling.py

@@ -30,24 +30,24 @@ class Scheduler:
 		self.rates = {} if rates is None else rates
 		self.__last_schedule = None
 
-	def getNextActionDelta(self, time, dt):
-		"""
-		Helps in identifying if a new action is scheduled in the near future.
-
-		Args:
-			time (float):   The current simulation time.
-			dt (float):     The next delta t as defined/computed by the simulator.
-
-		Returns:
-			The next time when something must happen.
-		"""
-		next = time + dt
-		for rate in self.rates.values():
-			d = ceil(time / rate) * rate
-			if abs(d - time) < 1e-6:
-				continue
-			next = min(next, d)
-		return next - time
+	# def getNextActionDelta(self, time, dt):
+	# 	"""
+	# 	Helps in identifying if a new action is scheduled in the near future.
+	#
+	# 	Args:
+	# 		time (float):   The current simulation time.
+	# 		dt (float):     The next delta t as defined/computed by the simulator.
+	#
+	# 	Returns:
+	# 		The next time when something must happen.
+	# 	"""
+	# 	next = time + dt
+	# 	for rate in self.rates.values():
+	# 		d = ceil(time / rate) * rate
+	# 		if abs(d - time) < 1e-6:
+	# 			continue
+	# 		next = min(next, d)
+	# 	return next - time
 
 	def mustCompute(self, block, time):
 		"""
@@ -106,7 +106,7 @@ class Scheduler:
 			curIt (int):                        The current iteration value.
 			time (float):                       The current simulation time.
 		"""
-		raise NotImplementedError()
+		raise NotImplementedError()  # pragma: no cover
 
 
 class TopologicalScheduler(Scheduler):

+ 7 - 465
src/test/basicCBDTest.py

@@ -1,6 +1,7 @@
 #!/usr/bin/env python
-#
-# Unit tests for all the basic CBD blocks, discrete-time CBD. 
+"""
+Unittest for the basic CBD features
+"""
 
 import unittest
 
@@ -22,331 +23,9 @@ class BasicCBDTestCase(unittest.TestCase):
 		self.sim.run()
 
 	def _getSignal(self, blockname, output_port = None):
-		foundBlocks = [ block for block in self.CBD.getBlocks() if block.getBlockName() == blockname ]
-		numFoundBlocks = len(foundBlocks)
-		if numFoundBlocks == 1:
-			signal =  foundBlocks[0].getSignal(name_output = output_port)
-			return [x.value for x in signal]
-		else:
-			raise Exception(str(numFoundBlocks) + " blocks with name " + blockname + " found.\nExpected a single block.")
-
-	def testConstantBlock(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=3.3))
-
-		self._run(NUM_DISCR_TIME_STEPS)
-		self.assertEqual(self._getSignal("c1"), [3.3] * NUM_DISCR_TIME_STEPS)
-
-	def testNegatorBlockPos(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=6.0))
-		self.CBD.addBlock(NegatorBlock(block_name="n"))
-		self.CBD.addConnection("c1", "n")
-
-		self._run(NUM_DISCR_TIME_STEPS)
-		self.assertEqual(self._getSignal("n"), [-6.0] * NUM_DISCR_TIME_STEPS)
-
-	def testNegatorBlockNeg(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=-6.0))
-		self.CBD.addBlock(NegatorBlock(block_name="n"))
-		self.CBD.addConnection("c1", "n")
-
-		self._run(NUM_DISCR_TIME_STEPS)
-		self.assertEqual(self._getSignal("n"), [6.0] * NUM_DISCR_TIME_STEPS)
-
-	def testNegatorBlockZero(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=0.0))
-		self.CBD.addBlock(NegatorBlock(block_name="n"))
-		self.CBD.addConnection("c1", "n")
-
-		self._run(NUM_DISCR_TIME_STEPS)
-		self.assertEqual(self._getSignal("n"), [0.0] * NUM_DISCR_TIME_STEPS)
-
-	def testInverterBlock(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=5.0))
-		self.CBD.addBlock(InverterBlock(block_name="i1"))
-		self.CBD.addBlock(InverterBlock(block_name="i2"))
-
-		self.CBD.addConnection("c1", "i1")
-		self.CBD.addConnection("i1", "i2")
-		self._run(NUM_DISCR_TIME_STEPS)
-		self.assertEqual(self._getSignal("i1"), [0.2] * NUM_DISCR_TIME_STEPS)
-		self.assertEqual(self._getSignal("i2"), [5.0] * NUM_DISCR_TIME_STEPS)
-
-	def testAdderBlock(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=2.0))
-		self.CBD.addBlock(ConstantBlock(block_name="c2", value=6.0))
-		self.CBD.addBlock(AdderBlock(block_name="a"))
-
-		self.CBD.addConnection("c1", "a")
-		self.CBD.addConnection("c2", "a")
-		self._run(NUM_DISCR_TIME_STEPS)
-		self.assertEqual(self._getSignal("a"), [8.0] * NUM_DISCR_TIME_STEPS)
-
-	def testAdderBlock2(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=2.0))
-		self.CBD.addBlock(ConstantBlock(block_name="c2", value=-6.0))
-		self.CBD.addBlock(AdderBlock(block_name="a"))
-
-		self.CBD.addConnection("c1", "a")
-		self.CBD.addConnection("c2", "a")
-		self._run(NUM_DISCR_TIME_STEPS)
-		self.assertEqual(self._getSignal("a"), [-4.0] * NUM_DISCR_TIME_STEPS)
-
-	def testProductBlock(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=2.0))
-		self.CBD.addBlock(ConstantBlock(block_name="c2", value=5.0))
-		self.CBD.addBlock(ProductBlock(block_name="p"))
-
-		self.CBD.addConnection("c1", "p")
-		self.CBD.addConnection("c2", "p")
-		self._run(NUM_DISCR_TIME_STEPS)
-		self.assertEqual(self._getSignal("p"), [10.0] * 5)
-
-	def testProductBlock2(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=1.0/2.0))
-		self.CBD.addBlock(ConstantBlock(block_name="c2", value=4.0))
-		self.CBD.addBlock(ProductBlock(block_name="p"))
-
-		self.CBD.addConnection("c1", "p")
-		self.CBD.addConnection("c2", "p")
-		self._run(NUM_DISCR_TIME_STEPS)
-		self.assertEqual(self._getSignal("p"), [2.0] * 5)
-
-	def testGenericBlock(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=2.2))
-		self.CBD.addBlock(GenericBlock(block_name="g", block_operator="ceil"))
-
-		self.CBD.addConnection("c1", "g")
-		self._run(NUM_DISCR_TIME_STEPS)
-		self.assertEqual(self._getSignal("g"), [3.0] * 5)
-
-	def testRootBlock(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=8.0))
-		self.CBD.addBlock(ConstantBlock(block_name="c2", value=3.0))
-		self.CBD.addBlock(RootBlock(block_name="g"))
-
-		self.CBD.addConnection("c1", "g")
-		self.CBD.addConnection("c2", "g")
-		self._run(1)
-		self.assertEqual(self._getSignal("g"), [2.0])
-
-	def testRootBlock2(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=9.0))
-		self.CBD.addBlock(ConstantBlock(block_name="c2", value=2.0))
-		self.CBD.addBlock(RootBlock(block_name="g"))
-
-		self.CBD.addConnection("c1", "g")
-		self.CBD.addConnection("c2", "g")
-		self._run(1)
-		self.assertEqual(self._getSignal("g"), [3.0])
-
-	def testAbsBlock(self):
-		seq = [1, -1, 2, -6, -9, 7]
-		self.CBD.addBlock(SequenceBlock(block_name="seq", sequence=seq))
-		self.CBD.addBlock(AbsBlock(block_name="abs"))
-
-		self.CBD.addConnection("seq", "abs")
-		self._run(len(seq))
-		self.assertEqual(self._getSignal("abs"), [abs(x) for x in seq])
-
-	def testMultiplexerBlock(self):
-		a = list(range(10))
-		b = list(range(100, 90, -1))
-		s = [0, 1, 1, 0, 0, 0, 1, 1, 1, 0]
-		self.CBD.addBlock(SequenceBlock(block_name="c1", sequence=a))
-		self.CBD.addBlock(SequenceBlock(block_name="c2", sequence=b))
-		self.CBD.addBlock(SequenceBlock(block_name="c3", sequence=s))
-		self.CBD.addBlock(MultiplexerBlock(block_name="mux"))
-
-		self.CBD.addConnection("c1", "mux")
-		self.CBD.addConnection("c2", "mux")
-		self.CBD.addConnection("c3", "mux", input_port_name="select")
-		self._run(10)
-		self.assertEqual(self._getSignal("mux"), [0, 99, 98, 3, 4, 5, 94, 93, 92, 9])
-
-	def testIntBlock(self):
-		seq = [1.2, 2.2, 3.8, 4.7, 2.3, 6.6666]
-		self.CBD.addBlock(SequenceBlock(block_name="seq", sequence=seq))
-		self.CBD.addBlock(IntBlock(block_name="int"))
-
-		self.CBD.addConnection("seq", "int")
-		self._run(len(seq))
-		self.assertEqual(self._getSignal("int"), [int(x) for x in seq])
-
-	def testLessThanBlock1(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=2))
-		self.CBD.addBlock(ConstantBlock(block_name="c2", value=6))
-		self.CBD.addBlock(LessThanBlock(block_name="lt"))
-
-		self.CBD.addConnection("c1", "lt")
-		self.CBD.addConnection("c2", "lt")
-		self._run(1)
-		self.assertEqual(self._getSignal("lt"), [1])
-
-	def testLessThanBlock2(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=9))
-		self.CBD.addBlock(ConstantBlock(block_name="c2", value=7))
-		self.CBD.addBlock(LessThanBlock(block_name="lt"))
-
-		self.CBD.addConnection("c1", "lt")
-		self.CBD.addConnection("c2", "lt")
-		self._run(1)
-		self.assertEqual(self._getSignal("lt"), [0])
-
-	def testLessThanBlock3(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=5))
-		self.CBD.addBlock(ConstantBlock(block_name="c2", value=5))
-		self.CBD.addBlock(LessThanBlock(block_name="lt"))
-
-		self.CBD.addConnection("c1", "lt")
-		self.CBD.addConnection("c2", "lt")
-		self._run(1)
-		self.assertEqual(self._getSignal("lt"), [0])
-
-	def testLessThanOrEqualsBlock1(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=2))
-		self.CBD.addBlock(ConstantBlock(block_name="c2", value=6))
-		self.CBD.addBlock(LessThanOrEqualsBlock(block_name="leq"))
-
-		self.CBD.addConnection("c1", "leq")
-		self.CBD.addConnection("c2", "leq")
-		self._run(1)
-		self.assertEqual(self._getSignal("leq"), [1])
-
-	def testLessThanOrEqualsBlock2(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=9))
-		self.CBD.addBlock(ConstantBlock(block_name="c2", value=7))
-		self.CBD.addBlock(LessThanOrEqualsBlock(block_name="leq"))
-
-		self.CBD.addConnection("c1", "leq")
-		self.CBD.addConnection("c2", "leq")
-		self._run(1)
-		self.assertEqual(self._getSignal("leq"), [0])
-
-	def testLessThanOrEqualsBlock3(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=5))
-		self.CBD.addBlock(ConstantBlock(block_name="c2", value=5))
-		self.CBD.addBlock(LessThanOrEqualsBlock(block_name="leq"))
-
-		self.CBD.addConnection("c1", "leq")
-		self.CBD.addConnection("c2", "leq")
-		self._run(1)
-		self.assertEqual(self._getSignal("leq"), [1])
-
-	def testEqualsBlock1(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=5))
-		self.CBD.addBlock(ConstantBlock(block_name="c2", value=5))
-		self.CBD.addBlock(EqualsBlock(block_name="eq"))
-
-		self.CBD.addConnection("c1", "eq")
-		self.CBD.addConnection("c2", "eq")
-		self._run(1)
-		self.assertEqual(self._getSignal("eq"), [1])
-
-	def testEqualsBlock2(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=4))
-		self.CBD.addBlock(ConstantBlock(block_name="c2", value=7))
-		self.CBD.addBlock(EqualsBlock(block_name="eq"))
-
-		self.CBD.addConnection("c1", "eq")
-		self.CBD.addConnection("c2", "eq")
-		self._run(1)
-		self.assertEqual(self._getSignal("eq"), [0])
-
-	def testNotBlock1(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c", value=0))
-		self.CBD.addBlock(NotBlock(block_name="not"))
-
-		self.CBD.addConnection("c", "not")
-		self._run(1)
-		self.assertEqual(self._getSignal("not"), [1])
-
-	def testNotBlock2(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c", value=1))
-		self.CBD.addBlock(NotBlock(block_name="not"))
-
-		self.CBD.addConnection("c", "not")
-		self._run(1)
-		self.assertEqual(self._getSignal("not"), [0])
-
-	def testNotBlock3(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c", value=17))
-		self.CBD.addBlock(NotBlock(block_name="not"))
-
-		self.CBD.addConnection("c", "not")
-		self._run(1)
-		self.assertEqual(self._getSignal("not"), [0])
-
-	def testAndBlock(self):
-		self.CBD.addBlock(SequenceBlock(block_name="c1", sequence=[0, 0, 1, 1]))
-		self.CBD.addBlock(SequenceBlock(block_name="c2", sequence=[0, 1, 0, 1]))
-		self.CBD.addBlock(AndBlock(block_name="and"))
-
-		self.CBD.addConnection("c1", "and")
-		self.CBD.addConnection("c2", "and")
-		self._run(4)
-		self.assertEqual(self._getSignal("and"), [0, 0, 0, 1])
-
-	def testOrBlock(self):
-		self.CBD.addBlock(SequenceBlock(block_name="c1", sequence=[0, 0, 1, 1]))
-		self.CBD.addBlock(SequenceBlock(block_name="c2", sequence=[0, 1, 0, 1]))
-		self.CBD.addBlock(OrBlock(block_name="or"))
-
-		self.CBD.addConnection("c1", "or")
-		self.CBD.addConnection("c2", "or")
-		self._run(4)
-		self.assertEqual(self._getSignal("or"), [0, 1, 1, 1])
-
-	def testModuloBlock(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=8.0))
-		self.CBD.addBlock(ConstantBlock(block_name="c2", value=3.0))
-		self.CBD.addBlock(ModuloBlock(block_name="g"))
-
-		self.CBD.addConnection("c1", "g")
-		self.CBD.addConnection("c2", "g")
-		self._run(1)
-		self.assertEqual(self._getSignal("g"), [2.0])
-
-	def testModuloBlock2(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=8.0))
-		self.CBD.addBlock(ConstantBlock(block_name="c2", value=8.0))
-		self.CBD.addBlock(ModuloBlock(block_name="g"))
-
-		self.CBD.addConnection("c1", "g")
-		self.CBD.addConnection("c2", "g")
-		self._run(1)
-		self.assertEqual(self._getSignal("g"), [0.0])
-
-	def testPreviousValueDelayBlock(self):
-		self.CBD.addBlock(ConstantBlock(block_name="ZeroConstant", value=0.0))
-		self.CBD.addBlock(SequenceBlock(block_name="seq", sequence=[0, 2, 4, 6, 8, 10, 12]))
-		self.CBD.addBlock(DelayBlock(block_name="d"))
-
-		self.CBD.addConnection("ZeroConstant", "d", input_port_name="IC")
-		self.CBD.addConnection("seq", "d")
-
-		self._run(7, 0.5)
-		self.assertEqual(self._getSignal("d"), [0, 0, 2, 4, 6, 8, 10])
-
-	def testPreviousValueDelayBlock2(self):
-		self.CBD.addBlock(SequenceBlock(block_name="FirstSeq", sequence=[2, 12, 22, 23, 32, 11, 91]))
-		self.CBD.addBlock(SequenceBlock(block_name="SecSeq", sequence=[5, 5, 5, 5, 3, 3, 3]))
-		self.CBD.addBlock(DelayBlock(block_name="prev"))
-		self.CBD.addConnection(self.CBD.getBlockByName("FirstSeq"), "prev")
-		self.CBD.addConnection(self.CBD.getBlockByName("SecSeq"), "prev", input_port_name="IC")
-		self._run(7)
-		self.assertEqual(self._getSignal("prev"), [5, 2, 12, 22, 23, 32, 11])
-
-	def testSequenceBlock(self):
-		self.CBD.addBlock(SequenceBlock(block_name="FirstSeq", sequence=[2, 2, 2, 3, 2, 1, 1]))
-		self._run(7)
-		self.assertEqual(self._getSignal("FirstSeq"), [2, 2, 2, 3, 2, 1, 1])
-
-	def testLoggingBlock(self):
-		self.CBD.addBlock(ConstantBlock(block_name="One", value=1))
-		self.CBD.addBlock(LoggingBlock("Test", "Logging block test with level is error", level.ERROR))
-		self.CBD.addConnection("One", "Test")
-		self._run(1)
-
+		block = self.CBD.getBlockByName(blockname)
+		signal =  block.getSignal(name_output = output_port)
+		return [x.value for x in signal]
 
 	def testLinearStrongComponent(self):
 		self.CBD.addBlock(ConstantBlock(block_name="c2", value=5.5))
@@ -479,136 +158,6 @@ class BasicCBDTestCase(unittest.TestCase):
 		self.CBD.addConnection("c1", "a2")
 		self.assertRaises(SystemExit, self._run, 5)
 
-	def initializeFuncDerBas(self):
-		#f(t) = 5*t
-		CBDFunc = CBD("function", output_ports = ["OUT1"])
-		CBDFunc.addBlock(TimeBlock(block_name="t"))
-		CBDFunc.addBlock(ProductBlock(block_name="p"))
-		CBDFunc.addBlock(ConstantBlock(block_name="c", value=5.0))
-		CBDFunc.addConnection("t", "p")
-		CBDFunc.addConnection("c", "p")
-		CBDFunc.addConnection("p", "OUT1")
-		return CBDFunc
-
-	def initializeFunc(self):
-		#f(t) = (t-2)^3
-		CBDFunc = CBD("function", output_ports = ["OUT1"])
-		CBDFunc.addBlock(TimeBlock(block_name="t"))
-		CBDFunc.addBlock(ProductBlock(block_name="p"))
-		CBDFunc.addBlock(ProductBlock(block_name="p2"))
-		CBDFunc.addBlock(AdderBlock(block_name="a"))
-		CBDFunc.addBlock(ConstantBlock(block_name="c", value=-2.0))
-		CBDFunc.addConnection("t", "a")
-		CBDFunc.addConnection("c", "a")
-		CBDFunc.addConnection("a", "p")
-		CBDFunc.addConnection("a", "p")
-		CBDFunc.addConnection("p", "p2")
-		CBDFunc.addConnection("a", "p2")
-		CBDFunc.addConnection("p2", "OUT1")
-		return CBDFunc
-
-	def initializeFunc2(self):
-		#f(t) = (t-2)^4
-		CBDFunc = CBD("function", output_ports = ["OUT1"])
-		CBDFunc.addBlock(TimeBlock(block_name="t"))
-		CBDFunc.addBlock(ProductBlock(block_name="p"))
-		CBDFunc.addBlock(ProductBlock(block_name="p2"))
-		CBDFunc.addBlock(ProductBlock(block_name="p3"))
-		CBDFunc.addBlock(AdderBlock(block_name="a"))
-		CBDFunc.addBlock(ConstantBlock(block_name="c", value=-2.0))
-		CBDFunc.addConnection("t", "a")
-		CBDFunc.addConnection("c", "a")
-		CBDFunc.addConnection("a", "p")
-		CBDFunc.addConnection("a", "p")
-		CBDFunc.addConnection("p", "p2")
-		CBDFunc.addConnection("a", "p2")
-		CBDFunc.addConnection("p2", "p3")
-		CBDFunc.addConnection("a", "p3")
-		CBDFunc.addConnection("p3", "OUT1")
-		return CBDFunc
-
-	def initializeFuncInt(self):
-		#f(t) = 2*t
-		CBDFunc = CBD("function", output_ports = ["OUT1"])
-		CBDFunc.addBlock(TimeBlock(block_name="t"))
-		CBDFunc.addBlock(ProductBlock(block_name="p"))
-		CBDFunc.addBlock(ConstantBlock(block_name="c", value=2.0))
-		CBDFunc.addConnection("t", "p")
-		CBDFunc.addConnection("c", "p")
-		CBDFunc.addConnection("p", "OUT1")
-		return CBDFunc
-
-	def testDerivatorBlock(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c3", value=1.0))
-		self.CBD.addBlock(ConstantBlock(block_name="zero", value=0.0))
-		CBDFunc = self.initializeFuncDerBas()
-		self.CBD.addBlock(CBDFunc)
-		self.CBD.addBlock(DerivatorBlock(block_name="der"))
-
-		self.CBD.addConnection("c3", "der", input_port_name="delta_t")
-		self.CBD.addConnection("zero", "der", input_port_name="IC")
-		self.CBD.addConnection("function", "der")
-		self._run(5)
-		self.assertEqual(self._getSignal("der"), [0.0]+[5.0]*4)
-
-
-	def testIntegratorBlock(self):
-		# Function: f(t) = 6 + f(t - dt), where f(0) = 6
-		dt = 0.0001
-		epsilon = 0.002
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=6.0))
-		self.CBD.addBlock(ConstantBlock(block_name="c2", value=0.0))
-		self.CBD.addBlock(ConstantBlock(block_name="c3", value=dt))
-		self.CBD.addBlock(AdderBlock(block_name="a"))
-		self.CBD.addBlock(DelayBlock(block_name="d"))
-
-		self.CBD.addBlock(IntegratorBlock(block_name="int"))
-		self.CBD.addConnection("c3", "int", input_port_name="delta_t")
-		self.CBD.addConnection("a", "int")
-		self.CBD.addConnection("c2", "int", input_port_name="IC")
-
-		self.CBD.addConnection("c1", "a")
-		self.CBD.addConnection("d", "a")
-		self.CBD.addConnection("a", "d")
-		self.CBD.addConnection("c2", "d", input_port_name="IC")
-		self._run(NUM_DISCR_TIME_STEPS, dt)
-		actual = [x*dt for x in [0.0, 9.0, 24.0, 45.0, 72.0]]
-		measured = self._getSignal("int")
-		error = [abs(measured[i] - actual[i]) for i in range(NUM_DISCR_TIME_STEPS)]
-		self.assertFalse(any([x > epsilon for x in error]), "Error too large.\n\tExpected: {}\n\tActual: {}"
-		                                                    "\n\tErrors: {}".format(actual, measured, error))
-
-	def testDelayBlock(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=5.0))
-		self.CBD.addBlock(ConstantBlock(block_name="c2", value=3.0))
-		self.CBD.addBlock(DelayBlock(block_name="d"))
-
-		self.CBD.addConnection("c2", "d")
-		self.CBD.addConnection("c1", "d", input_port_name="IC")
-		self._run(4)
-		self.assertEqual(self._getSignal("d"), [5.0, 3.0, 3.0, 3.0])
-
-	def testDelayBlock2(self):
-		self.CBD.addBlock(ConstantBlock(block_name="c1", value=1.0))
-		self.CBD.addBlock(ConstantBlock(block_name="c2", value=5.0))
-		self.CBD.addBlock(DelayBlock(block_name="d"))
-		self.CBD.addBlock(AdderBlock(block_name="a"))
-
-		self.CBD.addConnection("c2", "a")
-		self.CBD.addConnection("d", "a")
-		self.CBD.addConnection("c1", "d", input_port_name="IC")
-		self.CBD.addConnection("a", "d")
-		self._run(5)
-		self.assertEqual(self._getSignal("d"), [1.0, 6.0, 11.0, 16.0, 21.0])
-
-	def testAddOneBlock(self):
-		self.CBD.addBlock(SequenceBlock(block_name="c", sequence=[1, 2, 5, 7, 3]))
-		self.CBD.addBlock(AddOneBlock(block_name="add1"))
-
-		self.CBD.addConnection("c", "add1")
-		self._run(5)
-		self.assertEqual(self._getSignal("add1"), [2, 3, 6, 8, 4])
-
 	def testFlatten(self):
 		child = CBD("child", ["IN1"], ["OUT1"])
 		child.addBlock(AddOneBlock(block_name="add1"))
@@ -619,14 +168,7 @@ class BasicCBDTestCase(unittest.TestCase):
 		self.assertEqual(set([x.getBlockName() for x in child.getBlocks()]),
 		                 {'add1.OneConstant', 'add1.PlusOne', 'add1.IN1', 'add1.OUT1', 'IN1', 'OUT1'})
 
-
-def suite():
-	"""Returns a test suite containing all the test cases in this module."""
-	suite = unittest.makeSuite(BasicCBDTestCase)
-
-	return unittest.TestSuite((suite))
-
-if __name__ == '__main__':
+if __name__ == '__main__':  # pragma: no cover
 	# When this module is executed from the command-line, run all its tests
 	unittest.main(verbosity=2)
 

+ 6 - 19
src/test/flattenCBDTest.py

@@ -6,7 +6,6 @@ import unittest
 from CBD.Core import *
 from CBD.lib.std import *
 from CBD.simulator import Simulator
-from test.basicCBDTest import BasicCBDTestCase
 
 class FlattenCBDTest(unittest.TestCase):
 	def setUp(self):
@@ -17,16 +16,11 @@ class FlattenCBDTest(unittest.TestCase):
 		self.sim.setDeltaT(step)
 		self.sim.setTerminationTime(num_steps * step)
 		self.sim.run()
-			
+
 	def _getSignal(self, blockname, output_port = None):
-		foundBlocks = [ block for block in self.CBD.getBlocks() if block.getBlockName() == blockname ]
-		
-		signal =  foundBlocks[0].getSignal(name_output = output_port)
-		
-		if len(foundBlocks) == 1:
-			return [x.value for x in signal]
-		else:
-			raise Exception("No single block with name " + blockname + " found")
+		block = self.CBD.getBlockByName(blockname)
+		signal =  block.getSignal(name_output = output_port)
+		return [x.value for x in signal]
 							
 	def testInterCBD(self):
 		CBDLittle1 = CBD("first_child", output_ports = ["outCBD1"])
@@ -184,16 +178,9 @@ class FlattenCBDTest(unittest.TestCase):
 		self.assertEqual(self._getSignal("first_child.in1CBD1"), [2.0]*5)
 		self.assertEqual(self._getSignal("first_child.a"), [-12.0]*5)
 		self.assertEqual(self._getSignal("a2"), [0.0]*5)
-		
-		
-def suite():
-    """Returns a suite containing all the test cases in this module."""
-    suite1 = unittest.makeSuite(BasicCBDTestCase)
-    
-    return unittest.TestSuite((suite1))
 
-if __name__ == '__main__':
-    # When this module is executed from the command-line, run all its tests
+if __name__ == '__main__':  # pragma: no cover
+	# When this module is executed from the command-line, run all its tests
     unittest.main()
 
 	

+ 5 - 17
src/test/hierarchyCBDTest.py

@@ -6,7 +6,6 @@ import unittest
 from CBD.Core import *
 from CBD.lib.std import *
 from CBD.simulator import Simulator
-from test.basicCBDTest import BasicCBDTestCase
 
 class HierarchyCBDTest(unittest.TestCase):
 	def setUp(self):
@@ -19,14 +18,9 @@ class HierarchyCBDTest(unittest.TestCase):
 		self.sim.run()
 
 	def _getSignal(self, blockname, output_port = None):
-		foundBlocks = [ block for block in self.CBD.getBlocks() if block.getBlockName() == blockname ]
-		
-		signal =  foundBlocks[0].getSignal(name_output = output_port)
-		
-		if len(foundBlocks) == 1:
-			return [x.value for x in signal]
-		else:
-			raise Exception("No single block with name " + blockname + " found")			
+		block = self.CBD.getBlockByName(blockname)
+		signal =  block.getSignal(name_output = output_port)
+		return [x.value for x in signal]
 		
 	def testInterCBD(self):		
 		CBDLittle1 = CBD("first_child", output_ports = ["outCBD1"])
@@ -185,15 +179,9 @@ class HierarchyCBDTest(unittest.TestCase):
 		self.assertEqual(self._getSignal("first_child", output_port = "in1CBD1"), [2.0]*5)
 		self.assertEqual(self._getSignal("first_child", output_port = "a"), [-12.0]*5)
 		self.assertEqual(self._getSignal("a2"), [0.0]*5)
-		
-def suite():
-    """Returns a suite containing all the test cases in this module."""
-    suite1 = unittest.makeSuite(BasicCBDTestCase)
-    
-    return unittest.TestSuite((suite1))
 
-if __name__ == '__main__':
-    # When this module is executed from the command-line, run all its tests
+if __name__ == '__main__':  # pragma: no cover
+	# When this module is executed from the command-line, run all its tests
     unittest.main()
 
 	

+ 4 - 15
src/test/ioCBDTest.py

@@ -21,13 +21,9 @@ class IOCBDTestCase(unittest.TestCase):
 		self.sim.run()
 
 	def _getSignal(self, blockname, output_port = None):
-		foundBlocks = [ block for block in self.CBD.getBlocks() if block.getBlockName() == blockname ]
-		numFoundBlocks = len(foundBlocks)
-		if numFoundBlocks == 1:
-			signal =  foundBlocks[0].getSignal(name_output = output_port)
-			return [x.value for x in signal]
-		else:
-			raise Exception(str(numFoundBlocks) + " blocks with name " + blockname + " found.\nExpected a single block.")
+		block = self.CBD.getBlockByName(blockname)
+		signal =  block.getSignal(name_output = output_port)
+		return [x.value for x in signal]
 
 	def testCSVReaderNormal(self):
 		self.CBD.addBlock(ReadCSV("seq", self.file, Interpolation.LINEAR, repeat=False))
@@ -42,14 +38,7 @@ class IOCBDTestCase(unittest.TestCase):
 		self.assertEqual([10.0, 6.0, 2.0, 1.0, 0.0, -1.0, -2.0, -1.0, 0.0, 5.0, -5.0, 17.0] * 4,
 		                 self._getSignal("seq", "y"))
 
-
-def suite():
-	"""Returns a test suite containing all the test cases in this module."""
-	suite = unittest.makeSuite(IOCBDTestCase)
-
-	return unittest.TestSuite((suite))
-
-if __name__ == '__main__':
+if __name__ == '__main__':  # pragma: no cover
 	# When this module is executed from the command-line, run all its tests
 	unittest.main(verbosity=2)
 

+ 4 - 15
src/test/otherCBDTest.py

@@ -19,13 +19,9 @@ class OtherCBDTestCase(unittest.TestCase):
 		self.sim.run()
 
 	def _getSignal(self, blockname, output_port = None):
-		foundBlocks = [ block for block in self.CBD.getBlocks() if block.getBlockName() == blockname ]
-		numFoundBlocks = len(foundBlocks)
-		if numFoundBlocks == 1:
-			signal =  foundBlocks[0].getSignal(name_output = output_port)
-			return [x.value for x in signal]
-		else:
-			raise Exception(str(numFoundBlocks) + " blocks with name " + blockname + " found.\nExpected a single block.")
+		block = self.CBD.getBlockByName(blockname)
+		signal =  block.getSignal(name_output = output_port)
+		return [x.value for x in signal]
 
 	def testMultiRate(self):
 		self.CBD.addBlock(TimeBlock("time"))
@@ -41,13 +37,6 @@ class OtherCBDTestCase(unittest.TestCase):
 
 		self.assertEqual([0.0, 4.0, 8.0, 12.0, 16.0], self._getSignal("mult"))
 
-
-def suite():
-	"""Returns a test suite containing all the test cases in this module."""
-	suite = unittest.makeSuite(IOCBDTestCase)
-
-	return unittest.TestSuite((suite))
-
-if __name__ == '__main__':
+if __name__ == '__main__':  # pragma: no cover
 	# When this module is executed from the command-line, run all its tests
 	unittest.main(verbosity=2)

+ 13 - 17
src/test/sortedGraphCBDTest.py

@@ -8,17 +8,12 @@ from CBD.lib.std import *
 from CBD.depGraph import createDepGraph
 from CBD.simulator import Simulator
 from CBD.scheduling import TopologicalScheduler
-from test.basicCBDTest import BasicCBDTestCase
 
 class SortedGraphCBDTest(unittest.TestCase):
 	def setUp(self):
 		self.CBD = CBD("block_under_test")
 		self.sim = Simulator(self.CBD)
 		self.scheduler = TopologicalScheduler()
-		
-	def _run(self, num_steps=1):
-		self.sim.setTerminationTime(num_steps)
-		self.sim.run()
 
 	def testSortedGraph(self):
 		CBDNegator = CBD("negatorCBD", input_ports = ["inNegator"], output_ports = ["outNegator"])
@@ -36,7 +31,7 @@ class SortedGraphCBDTest(unittest.TestCase):
 		self.CBD.addConnection("c", "negatorCBD", input_port_name = "inNegator")
 		
 		depGraph = createDepGraph(self.CBD, 0)
-		sortedGraph = self.scheduler.schedule(depGraph, 1, 0.0)
+		sortedGraph = self.scheduler.obtain(depGraph, 1, 0.0)
 		
 		self.assertEqual(len(sortedGraph), 5)
 		self.assertEqual(sortedGraph[0][0], const)
@@ -63,7 +58,7 @@ class SortedGraphCBDTest(unittest.TestCase):
 		self.CBD.addConnection("c2", "adderCBD", input_port_name = "in2")
 		
 		depGraph = createDepGraph(self.CBD, 0)
-		sortedGraph = self.scheduler.schedule(depGraph, 1, 0.0)
+		sortedGraph = self.scheduler.obtain(depGraph, 1, 0.0)
 		comps = [ x[0] for x in sortedGraph ]
 		
 		tester = self
@@ -95,7 +90,7 @@ class SortedGraphCBDTest(unittest.TestCase):
 		self.CBD.addConnection("c", "negatorCBD", input_port_name = "inNegator")
 		
 		depGraph = createDepGraph(self.CBD, 0)
-		sortedGraph = self.scheduler.schedule(depGraph, 1, 0.0)
+		sortedGraph = self.scheduler.obtain(depGraph, 1, 0.0)
 		comps = [ x[0] for x in sortedGraph ]
 		
 		tester = self
@@ -126,7 +121,7 @@ class SortedGraphCBDTest(unittest.TestCase):
 		self.CBD.addConnection("c2", "strongCBD", input_port_name = "inC2")
 		
 		depGraph = createDepGraph(self.CBD, 0)
-		sortedGraph = self.scheduler.schedule(depGraph, 1, 0.0)
+		sortedGraph = self.scheduler.obtain(depGraph, 1, 0.0)
 				
 		self.assertEqual(len(sortedGraph), 5)
 		self.assertEqual(len(sortedGraph[4]), 3)
@@ -153,19 +148,20 @@ class SortedGraphCBDTest(unittest.TestCase):
 		self.CBD.addConnection("strongCBD", "a3", output_port_name = "out2")
 		
 		depGraph = createDepGraph(self.CBD, 0)
-		sortedGraph = self.scheduler.schedule(depGraph, 1, 0.0)
+		sortedGraph = self.scheduler.obtain(depGraph, 1, 0.0)
 				
 		self.assertEqual(len(sortedGraph), 5)
 		self.assertEqual(len(sortedGraph[4]), 6)
-		
-		
-def suite():
-	"""Returns a suite containing all the test cases in this module."""
-	suite1 = unittest.makeSuite(BasicCBDTestCase)
 
-	return unittest.TestSuite((suite1))
+	def testAlwaysRecomputeSchedule(self):
+		self.scheduler.recompte_at = True
+		self.testSortedGraph()
+
+	def testSometimesRecomputeSchedule(self):
+		self.scheduler.recompte_at = [0, 4]
+		self.testSortedGraph()
 
-if __name__ == '__main__':
+if __name__ == '__main__':  # pragma: no cover
 	# When this module is executed from the command-line, run all its tests
 	unittest.main()
 

+ 555 - 0
src/test/stdCBDTest.py

@@ -0,0 +1,555 @@
+#!/usr/bin/env python
+"""
+Unit tests for all the basic CBD blocks in the std library.
+"""
+
+import unittest
+
+from CBD.Core import *
+from CBD.lib.std import *
+from CBD.simulator import Simulator
+
+NUM_DISCR_TIME_STEPS = 5
+
+class StdCBDTestCase(unittest.TestCase):
+	def setUp(self):
+		self.CBD = CBD("CBD_for_block_under_test")
+		self.sim = Simulator(self.CBD)
+
+	def _run(self, num_steps=1, delta_t = 1.0):
+		self.sim.setDeltaT(delta_t)
+		self.sim.setTerminationTime(num_steps * delta_t)
+		self.CBD.addBlock(DummyClock("clock", delta=delta_t))
+		self.sim.run()
+
+	def _getSignal(self, blockname, output_port = None):
+		block = self.CBD.getBlockByName(blockname)
+		signal =  block.getSignal(name_output = output_port)
+		return [x.value for x in signal]
+
+	def testConstantBlock(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=3.3))
+
+		self._run(NUM_DISCR_TIME_STEPS)
+		self.assertEqual(self._getSignal("c1"), [3.3] * NUM_DISCR_TIME_STEPS)
+
+		self.CBD.getBlockByName("c1").setValue(5)
+		self.assertEqual(self.CBD.getBlockByName("c1").getValue(), 5)
+
+	def testNegatorBlockPos(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=6.0))
+		self.CBD.addBlock(NegatorBlock(block_name="n"))
+		self.CBD.addConnection("c1", "n")
+
+		self._run(NUM_DISCR_TIME_STEPS)
+		self.assertEqual(self._getSignal("n"), [-6.0] * NUM_DISCR_TIME_STEPS)
+
+	def testNegatorBlockNeg(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=-6.0))
+		self.CBD.addBlock(NegatorBlock(block_name="n"))
+		self.CBD.addConnection("c1", "n")
+
+		self._run(NUM_DISCR_TIME_STEPS)
+		self.assertEqual(self._getSignal("n"), [6.0] * NUM_DISCR_TIME_STEPS)
+
+	def testNegatorBlockZero(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=0.0))
+		self.CBD.addBlock(NegatorBlock(block_name="n"))
+		self.CBD.addConnection("c1", "n")
+
+		self._run(NUM_DISCR_TIME_STEPS)
+		self.assertEqual(self._getSignal("n"), [0.0] * NUM_DISCR_TIME_STEPS)
+
+	def testInverterBlock(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=5.0))
+		self.CBD.addBlock(InverterBlock(block_name="i1"))
+		self.CBD.addBlock(InverterBlock(block_name="i2"))
+
+		self.CBD.addConnection("c1", "i1")
+		self.CBD.addConnection("i1", "i2")
+		self._run(NUM_DISCR_TIME_STEPS)
+		self.assertEqual(self._getSignal("i1"), [0.2] * NUM_DISCR_TIME_STEPS)
+		self.assertEqual(self._getSignal("i2"), [5.0] * NUM_DISCR_TIME_STEPS)
+
+	def testInverterBlockDivByZero(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=0))
+		self.CBD.addBlock(InverterBlock(block_name="inv"))
+
+		self.CBD.addConnection("c1", "inv")
+		self.assertRaises(ZeroDivisionError, self._run, NUM_DISCR_TIME_STEPS)
+
+	def testAdderBlock(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=2.0))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=6.0))
+		self.CBD.addBlock(AdderBlock(block_name="a"))
+
+		self.CBD.addConnection("c1", "a")
+		self.CBD.addConnection("c2", "a")
+		self._run(NUM_DISCR_TIME_STEPS)
+		self.assertEqual(self._getSignal("a"), [8.0] * NUM_DISCR_TIME_STEPS)
+
+	def testAdderBlock2(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=2.0))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=-6.0))
+		self.CBD.addBlock(AdderBlock(block_name="a", numberOfInputs=5))
+
+		self.assertEqual(self.CBD.getBlockByName("a").getNumberOfInputs(), 5)
+
+		self.CBD.addConnection("c1", "a")
+		self.CBD.addConnection("c2", "a")
+		self.CBD.addConnection("c1", "a")
+		self.CBD.addConnection("c2", "a")
+		self.CBD.addConnection("c1", "a")
+		self._run(NUM_DISCR_TIME_STEPS)
+		self.assertEqual(self._getSignal("a"), [-6.0] * NUM_DISCR_TIME_STEPS)
+
+	def testProductBlock(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=2.0))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=5.0))
+		self.CBD.addBlock(ProductBlock(block_name="p"))
+
+		self.CBD.addConnection("c1", "p")
+		self.CBD.addConnection("c2", "p")
+		self._run(NUM_DISCR_TIME_STEPS)
+		self.assertEqual(self._getSignal("p"), [10.0] * 5)
+
+	def testProductBlock2(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=0.5))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=4.0))
+		self.CBD.addBlock(ProductBlock(block_name="p", numberOfInputs=4))
+
+		self.assertEqual(self.CBD.getBlockByName("p").getNumberOfInputs(), 4)
+
+		self.CBD.addConnection("c1", "p")
+		self.CBD.addConnection("c2", "p")
+		self.CBD.addConnection("c1", "p")
+		self.CBD.addConnection("c2", "p")
+		self._run(NUM_DISCR_TIME_STEPS)
+		self.assertEqual(self._getSignal("p"), [4.0] * 5)
+
+	def testGenericBlock(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=2.2))
+		self.CBD.addBlock(GenericBlock(block_name="g", block_operator="ceil"))
+
+		self.CBD.addConnection("c1", "g")
+		self._run(NUM_DISCR_TIME_STEPS)
+		self.assertEqual(self._getSignal("g"), [3.0] * 5)
+
+	def testRootBlock(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=8.0))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=3.0))
+		self.CBD.addBlock(RootBlock(block_name="g"))
+
+		self.CBD.addConnection("c1", "g")
+		self.CBD.addConnection("c2", "g")
+		self._run(1)
+		self.assertEqual(self._getSignal("g"), [2.0])
+
+	def testRootBlock2(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=9.0))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=2.0))
+		self.CBD.addBlock(RootBlock(block_name="g"))
+
+		self.CBD.addConnection("c1", "g")
+		self.CBD.addConnection("c2", "g")
+		self._run(1)
+		self.assertEqual(self._getSignal("g"), [3.0])
+
+	def testRootBlockDivByZero(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=0))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=2.0))
+		self.CBD.addBlock(RootBlock(block_name="root"))
+
+		self.CBD.addConnection("c2", "root")
+		self.CBD.addConnection("c1", "root")
+		self.assertRaises(ZeroDivisionError, self._run, NUM_DISCR_TIME_STEPS)
+
+	def testPowerBlock(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=8.0))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=3.0))
+		self.CBD.addBlock(PowerBlock(block_name="g"))
+
+		self.CBD.addConnection("c1", "g")
+		self.CBD.addConnection("c2", "g")
+		self._run(1)
+		self.assertEqual(self._getSignal("g"), [512.0])
+
+	def testAbsBlock(self):
+		seq = [1, -1, 2, -6, -9, 7]
+		self.CBD.addBlock(SequenceBlock(block_name="seq", sequence=seq))
+		self.CBD.addBlock(AbsBlock(block_name="abs"))
+
+		self.CBD.addConnection("seq", "abs")
+		self._run(len(seq))
+		self.assertEqual(self._getSignal("abs"), [abs(x) for x in seq])
+
+	def testMaxBlock(self):
+		self.CBD.addBlock(TimeBlock("time"))
+		self.CBD.addBlock(ConstantBlock("c1", -2))
+		self.CBD.addBlock(ConstantBlock("c2", 3.0))
+		self.CBD.addBlock(AdderBlock("sum"))
+
+		self.CBD.addBlock(MaxBlock(block_name="max", numberOfInputs=3))
+
+		self.assertEqual(self.CBD.getBlockByName("max").getNumberOfInputs(), 3)
+
+		self.CBD.addConnection("time", "sum")
+		self.CBD.addConnection("c1", "sum")
+		self.CBD.addConnection("sum", "max")
+		self.CBD.addConnection("c2", "max")
+		self.CBD.addConnection("time", "max")
+		self._run(5)
+		self.assertEqual(self._getSignal("max"), [max(float(x), 3.0, x + 2.0) for x in range(-2, 3)])
+
+	def testMinBlock(self):
+		self.CBD.addBlock(TimeBlock("time"))
+		self.CBD.addBlock(ConstantBlock("c1", -2))
+		self.CBD.addBlock(ConstantBlock("c2", 3.0))
+		self.CBD.addBlock(AdderBlock("sum"))
+
+		self.CBD.addBlock(MinBlock(block_name="min", numberOfInputs=3))
+
+		self.assertEqual(self.CBD.getBlockByName("min").getNumberOfInputs(), 3)
+
+		self.CBD.addConnection("time", "sum")
+		self.CBD.addConnection("c1", "sum")
+		self.CBD.addConnection("sum", "min")
+		self.CBD.addConnection("c2", "min")
+		self.CBD.addConnection("time", "min")
+		self._run(5)
+		self.assertEqual(self._getSignal("min"), [min(float(x), 3.0, x + 2.0) for x in range(-2, 3)])
+
+	def testClampBlock(self):
+		self.CBD.addBlock(TimeBlock("time"))
+		self.CBD.addBlock(ConstantBlock("c1", -2))
+		self.CBD.addBlock(AdderBlock("sum"))
+
+		self.CBD.addBlock(ClampBlock(block_name="clamp", min=-1.0, max=2.0))
+
+		self.CBD.addConnection("time", "sum")
+		self.CBD.addConnection("c1", "sum")
+		self.CBD.addConnection("sum", "clamp")
+		self._run(5)
+		self.assertEqual(self._getSignal("clamp"), [max(min(float(x), 2.0), -1.0) for x in range(-2, 3)])
+
+	def testClampBlock2(self):
+		self.CBD.addBlock(TimeBlock("time"))
+		self.CBD.addBlock(ConstantBlock("c1", -2))
+		self.CBD.addBlock(ConstantBlock("c2", -1.0))
+		self.CBD.addBlock(ConstantBlock("c3", 2.0))
+		self.CBD.addBlock(AdderBlock("sum"))
+
+		self.CBD.addBlock(ClampBlock(block_name="clamp", use_const=False))
+
+		self.CBD.addConnection("time", "sum")
+		self.CBD.addConnection("c1", "sum")
+		self.CBD.addConnection("sum", "clamp")
+		self.CBD.addConnection("c2", "clamp")
+		self.CBD.addConnection("c3", "clamp")
+		self._run(5)
+		self.assertEqual(self._getSignal("clamp"), [max(min(float(x), 2.0), -1.0) for x in range(-2, 3)])
+
+	def testMultiplexerBlock(self):
+		a = list(range(10))
+		b = list(range(100, 90, -1))
+		s = [0, 1, 1, 0, 0, 0, 1, 1, 1, 0]
+		self.CBD.addBlock(SequenceBlock(block_name="c1", sequence=a))
+		self.CBD.addBlock(SequenceBlock(block_name="c2", sequence=b))
+		self.CBD.addBlock(SequenceBlock(block_name="c3", sequence=s))
+		self.CBD.addBlock(MultiplexerBlock(block_name="mux"))
+
+		self.CBD.addConnection("c1", "mux")
+		self.CBD.addConnection("c2", "mux")
+		self.CBD.addConnection("c3", "mux", input_port_name="select")
+		self._run(10)
+		self.assertEqual(self._getSignal("mux"), [0, 99, 98, 3, 4, 5, 94, 93, 92, 9])
+
+	def testIntBlock(self):
+		seq = [1.2, 2.2, 3.8, 4.7, 2.3, 6.6666]
+		self.CBD.addBlock(SequenceBlock(block_name="seq", sequence=seq))
+		self.CBD.addBlock(IntBlock(block_name="int"))
+
+		self.CBD.addConnection("seq", "int")
+		self._run(len(seq))
+		self.assertEqual(self._getSignal("int"), [int(x) for x in seq])
+
+	def testLessThanBlock1(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=2))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=6))
+		self.CBD.addBlock(LessThanBlock(block_name="lt"))
+
+		self.CBD.addConnection("c1", "lt")
+		self.CBD.addConnection("c2", "lt")
+		self._run(1)
+		self.assertEqual(self._getSignal("lt"), [1])
+
+	def testLessThanBlock2(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=9))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=7))
+		self.CBD.addBlock(LessThanBlock(block_name="lt"))
+
+		self.CBD.addConnection("c1", "lt")
+		self.CBD.addConnection("c2", "lt")
+		self._run(1)
+		self.assertEqual(self._getSignal("lt"), [0])
+
+	def testLessThanBlock3(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=5))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=5))
+		self.CBD.addBlock(LessThanBlock(block_name="lt"))
+
+		self.CBD.addConnection("c1", "lt")
+		self.CBD.addConnection("c2", "lt")
+		self._run(1)
+		self.assertEqual(self._getSignal("lt"), [0])
+
+	def testLessThanOrEqualsBlock1(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=2))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=6))
+		self.CBD.addBlock(LessThanOrEqualsBlock(block_name="leq"))
+
+		self.CBD.addConnection("c1", "leq")
+		self.CBD.addConnection("c2", "leq")
+		self._run(1)
+		self.assertEqual(self._getSignal("leq"), [1])
+
+	def testLessThanOrEqualsBlock2(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=9))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=7))
+		self.CBD.addBlock(LessThanOrEqualsBlock(block_name="leq"))
+
+		self.CBD.addConnection("c1", "leq")
+		self.CBD.addConnection("c2", "leq")
+		self._run(1)
+		self.assertEqual(self._getSignal("leq"), [0])
+
+	def testLessThanOrEqualsBlock3(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=5))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=5))
+		self.CBD.addBlock(LessThanOrEqualsBlock(block_name="leq"))
+
+		self.CBD.addConnection("c1", "leq")
+		self.CBD.addConnection("c2", "leq")
+		self._run(1)
+		self.assertEqual(self._getSignal("leq"), [1])
+
+	def testEqualsBlock1(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=5))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=5))
+		self.CBD.addBlock(EqualsBlock(block_name="eq"))
+
+		self.CBD.addConnection("c1", "eq")
+		self.CBD.addConnection("c2", "eq")
+		self._run(1)
+		self.assertEqual(self._getSignal("eq"), [1])
+
+	def testEqualsBlock2(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=4))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=7))
+		self.CBD.addBlock(EqualsBlock(block_name="eq"))
+
+		self.CBD.addConnection("c1", "eq")
+		self.CBD.addConnection("c2", "eq")
+		self._run(1)
+		self.assertEqual(self._getSignal("eq"), [0])
+
+	def testNotBlock1(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c", value=0))
+		self.CBD.addBlock(NotBlock(block_name="not"))
+
+		self.CBD.addConnection("c", "not")
+		self._run(1)
+		self.assertEqual(self._getSignal("not"), [1])
+
+	def testNotBlock2(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c", value=1))
+		self.CBD.addBlock(NotBlock(block_name="not"))
+
+		self.CBD.addConnection("c", "not")
+		self._run(1)
+		self.assertEqual(self._getSignal("not"), [0])
+
+	def testNotBlock3(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c", value=17))
+		self.CBD.addBlock(NotBlock(block_name="not"))
+
+		self.CBD.addConnection("c", "not")
+		self._run(1)
+		self.assertEqual(self._getSignal("not"), [0])
+
+	def testAndBlock(self):
+		self.CBD.addBlock(SequenceBlock(block_name="c1", sequence=[0, 0, 1, 1]))
+		self.CBD.addBlock(SequenceBlock(block_name="c2", sequence=[0, 1, 0, 1]))
+		self.CBD.addBlock(AndBlock(block_name="and"))
+
+		self.CBD.addConnection("c1", "and")
+		self.CBD.addConnection("c2", "and")
+		self._run(4)
+		self.assertEqual(self._getSignal("and"), [0, 0, 0, 1])
+
+	def testOrBlock(self):
+		self.CBD.addBlock(SequenceBlock(block_name="c1", sequence=[0, 0, 1, 1]))
+		self.CBD.addBlock(SequenceBlock(block_name="c2", sequence=[0, 1, 0, 1]))
+		self.CBD.addBlock(OrBlock(block_name="or"))
+
+		self.CBD.addConnection("c1", "or")
+		self.CBD.addConnection("c2", "or")
+		self._run(4)
+		self.assertEqual(self._getSignal("or"), [0, 1, 1, 1])
+
+	def testModuloBlock(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=8.0))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=3.0))
+		self.CBD.addBlock(ModuloBlock(block_name="g"))
+
+		self.CBD.addConnection("c1", "g")
+		self.CBD.addConnection("c2", "g")
+		self._run(1)
+		self.assertEqual(self._getSignal("g"), [2.0])
+
+	def testModuloBlock2(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=8.0))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=8.0))
+		self.CBD.addBlock(ModuloBlock(block_name="g"))
+
+		self.CBD.addConnection("c1", "g")
+		self.CBD.addConnection("c2", "g")
+		self._run(1)
+		self.assertEqual(self._getSignal("g"), [0.0])
+
+	def testPreviousValueDelayBlock(self):
+		self.CBD.addBlock(ConstantBlock(block_name="ZeroConstant", value=0.0))
+		self.CBD.addBlock(SequenceBlock(block_name="seq", sequence=[0, 2, 4, 6, 8, 10, 12]))
+		self.CBD.addBlock(DelayBlock(block_name="d"))
+
+		self.CBD.addConnection("ZeroConstant", "d", input_port_name="IC")
+		self.CBD.addConnection("seq", "d")
+
+		self._run(7, 0.5)
+		self.assertEqual(self._getSignal("d"), [0, 0, 2, 4, 6, 8, 10])
+
+	def testPreviousValueDelayBlock2(self):
+		self.CBD.addBlock(SequenceBlock(block_name="FirstSeq", sequence=[2, 12, 22, 23, 32, 11, 91]))
+		self.CBD.addBlock(SequenceBlock(block_name="SecSeq", sequence=[5, 5, 5, 5, 3, 3, 3]))
+		self.CBD.addBlock(DelayBlock(block_name="prev"))
+		self.CBD.addConnection(self.CBD.getBlockByName("FirstSeq"), "prev")
+		self.CBD.addConnection(self.CBD.getBlockByName("SecSeq"), "prev", input_port_name="IC")
+		self._run(7)
+		self.assertEqual(self._getSignal("prev"), [5, 2, 12, 22, 23, 32, 11])
+
+	def testSequenceBlock(self):
+		self.CBD.addBlock(SequenceBlock(block_name="FirstSeq", sequence=[2, 2, 2, 3, 2, 1, 1]))
+		self._run(7)
+		self.assertEqual(self._getSignal("FirstSeq"), [2, 2, 2, 3, 2, 1, 1])
+
+	def testLoggingBlockError(self):
+		self.CBD.addBlock(ConstantBlock(block_name="One", value=1))
+		self.CBD.addBlock(LoggingBlock("L1", "Logging block test were level is error", level.ERROR))
+		self.CBD.addConnection("One", "L1")
+		self._run(1)
+
+	def testLoggingBlockWarning(self):
+		self.CBD.addBlock(ConstantBlock(block_name="One", value=1))
+		self.CBD.addBlock(LoggingBlock("L1", "Logging block test were level is warning", level.WARNING))
+		self.CBD.addConnection("One", "L1")
+		self._run(1)
+
+	def testLoggingBlockFatal(self):
+		self.CBD.addBlock(ConstantBlock(block_name="One", value=1))
+		self.CBD.addBlock(LoggingBlock("L1", "Logging block test were level is fatal", level.FATAL))
+		self.CBD.addConnection("One", "L1")
+		self.assertRaises(SystemExit, self._run, 1)
+
+	def initializeFuncDerBas(self):
+		#f(t) = 5*t
+		CBDFunc = CBD("function", output_ports = ["OUT1"])
+		CBDFunc.addBlock(TimeBlock(block_name="t"))
+		CBDFunc.addBlock(ProductBlock(block_name="p"))
+		CBDFunc.addBlock(ConstantBlock(block_name="c", value=5.0))
+		CBDFunc.addConnection("t", "p")
+		CBDFunc.addConnection("c", "p")
+		CBDFunc.addConnection("p", "OUT1")
+		return CBDFunc
+
+	def testDerivatorBlock(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c3", value=1.0))
+		self.CBD.addBlock(ConstantBlock(block_name="zero", value=0.0))
+		CBDFunc = self.initializeFuncDerBas()
+		self.CBD.addBlock(CBDFunc)
+		self.CBD.addBlock(DerivatorBlock(block_name="der"))
+
+		self.CBD.addConnection("c3", "der", input_port_name="delta_t")
+		self.CBD.addConnection("zero", "der", input_port_name="IC")
+		self.CBD.addConnection("function", "der")
+		self._run(5)
+		self.assertEqual(self._getSignal("der"), [0.0]+[5.0]*4)
+
+	def testIntegratorBlock(self):
+		# Function: f(t) = 6 + f(t - dt), where f(0) = 6
+		dt = 0.0001
+		epsilon = 0.002
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=6.0))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=0.0))
+		self.CBD.addBlock(ConstantBlock(block_name="c3", value=dt))
+		self.CBD.addBlock(AdderBlock(block_name="a"))
+		self.CBD.addBlock(DelayBlock(block_name="d"))
+
+		self.CBD.addBlock(IntegratorBlock(block_name="int"))
+		self.CBD.addConnection("c3", "int", input_port_name="delta_t")
+		self.CBD.addConnection("a", "int")
+		self.CBD.addConnection("c2", "int", input_port_name="IC")
+
+		self.CBD.addConnection("c1", "a")
+		self.CBD.addConnection("d", "a")
+		self.CBD.addConnection("a", "d")
+		self.CBD.addConnection("c2", "d", input_port_name="IC")
+		self._run(NUM_DISCR_TIME_STEPS, dt)
+		actual = [x*dt for x in [0.0, 9.0, 24.0, 45.0, 72.0]]
+		measured = self._getSignal("int")
+		error = [abs(measured[i] - actual[i]) for i in range(NUM_DISCR_TIME_STEPS)]
+		self.assertFalse(any([x > epsilon for x in error]), "Error too large.\n\tExpected: {}\n\tActual: {}"
+		                                                    "\n\tErrors: {}".format(actual, measured, error))
+
+	def testDelayBlock(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=5.0))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=3.0))
+		self.CBD.addBlock(DelayBlock(block_name="d"))
+
+		self.CBD.addConnection("c2", "d")
+		self.CBD.addConnection("c1", "d", input_port_name="IC")
+		self._run(4)
+		self.assertEqual(self._getSignal("d"), [5.0, 3.0, 3.0, 3.0])
+
+	def testDelayBlock2(self):
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=1.0))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=5.0))
+		self.CBD.addBlock(DelayBlock(block_name="d"))
+		self.CBD.addBlock(AdderBlock(block_name="a"))
+
+		self.CBD.addConnection("c2", "a")
+		self.CBD.addConnection("d", "a")
+		self.CBD.addConnection("c1", "d", input_port_name="IC")
+		self.CBD.addConnection("a", "d")
+		self._run(5)
+		self.assertEqual(self._getSignal("d"), [1.0, 6.0, 11.0, 16.0, 21.0])
+
+	def testAddOneBlock(self):
+		self.CBD.addBlock(SequenceBlock(block_name="c", sequence=[1, 2, 5, 7, 3]))
+		self.CBD.addBlock(AddOneBlock(block_name="add1"))
+
+		self.CBD.addConnection("c", "add1")
+		self._run(5)
+		self.assertEqual(self._getSignal("add1"), [2, 3, 6, 8, 4])
+
+if __name__ == '__main__':  # pragma: no cover
+	# When this module is executed from the command-line, run all its tests
+	unittest.main(verbosity=2)
+
+  
+  
+  
+  
+  
+  
+  
+