Repository: LovetheFrogs/PyCircTools (language: python)

Issue:
Tested 8 to 1 Multiplexer
Implemented the test fot 8-to-1 Multiplexer


Discussion / hints:

Fix patch:
diff --git a/CTools/Multiplexers/Mux4to1.py b/CTools/Multiplexers/Mux4to1.py
index 063c9fc..9473b88 100644
--- a/CTools/Multiplexers/Mux4to1.py
+++ b/CTools/Multiplexers/Mux4to1.py
@@ -46,7 +46,7 @@ def get_set(self, setNum):
 
     def get_output(self):
         """
-        Method get_output gets the output of the 2 to 1 Multiplexer.
+        Method get_output gets the output of the 4 to 1 Multiplexer.
 
         :return: Value of the output.
         :rtype: bool
diff --git a/CTools/Multiplexers/Mux8to1.py b/CTools/Multiplexers/Mux8to1.py
new file mode 100644
index 0000000..115a226
--- /dev/null
+++ b/CTools/Multiplexers/Mux8to1.py
@@ -0,0 +1,114 @@
+from CTools.Exceptions.MultiplexersExceptions import NonExistingInput, NonExistingControlSignal
+from CTools.Exceptions.CircuitToolsExceptions import NotTruthValue
+
+
+class Mux8to1:
+    """
+    8 to 1 Multiplexeer. Takes three bits as Set input.
+    """
+    def __init__(self):
+        """
+        Mux8to1 class constructor method.
+        """
+        self.input = [False] * 8
+        self.set = [False] * 3
+        self.output = self.__calculate_output()
+
+    def get_input(self, num):
+        """
+        Method get_input is used to get the value of input[num]
+
+        :param num: Number of the input you want to get. It is a number from 0 to 7.
+        :type num: int
+        :raises NonExistingInput: Raised when a Multiplexer/Demultiplexer doesn't have the input asked for.
+        :return: Value of the desired input (num).
+        :rtype: bool
+        """
+        if num >= len(self.input) or num < 0:
+            raise NonExistingInput(num)
+
+        return self.input[num]
+
+    def get_set(self, setNum):
+        """
+        Method get_set gets the value of the set[setNum] control signal.
+
+        :param setNum: Number of the set control signal you want to get, ranges from 0 to 3.
+        :type setNum: int
+        :raises NonExistingControlSignal: Raised when a Multiplexer/Demultiplexer doesn't have setNum control signal.
+        :return: Value of the desired set control signal (setNum).
+        :rtype: bool
+        """
+        if setNum >= len(self.set) or setNum < 0:
+            raise NonExistingControlSignal
+
+        return self.set[setNum]
+
+    def get_output(self):
+        """
+        Method get_output gets the output of the 8 to 1 Multiplexer.
+
+        :return: Value of the output.
+        :rtype: bool
+        """
+        return self.output
+
+    def set_input(self, num, value):
+        """
+        Method set_input sets a certain input to the desired value, either True or False.
+
+        :param num: Number of the input selected.
+        :type num: int
+        :param value: Desired value of the input.
+        :type value: bool
+        :raises NonExistingInput: raised when a Multiplexer/Demultiplexer doesn't have the input asked for.
+        :raises NotTruthValue: Raised when value's type is not bool.
+        """
+        if num >= len(self.input) or num < 0:
+            raise NonExistingInput(num)
+
+        if type(value) is not bool:
+            raise NotTruthValue
+
+        self.input[num] = value
+        self.output = self.__calculate_output()
+        return self
+
+    def set_set(self, setNum, value):
+        """
+        Method set_set sets the value of the set control signal to the desired truth value.
+
+        :param setNum: Number of the set control signal selected.
+        :type setNum: int
+        :param value: Desired value of the set control signal.
+        :type value: bool
+        :raises NonExistingControlSignal: Raised when a Multiplexer/Demultiplexer doesn't have setNum control signal.
+        :raises NotTruthValue: Raised when value's type is not bool.
+        """
+        if setNum >= len(self.set) or setNum < 0:
+            raise NonExistingControlSignal(setNum)
+
+        if type(value) is not bool:
+            raise NotTruthValue
+
+        self.set[setNum] = value
+        self.output = self.__calculate_output()
+        return self
+
+    def __calculate_output(self):
+        """
+        Private method __calculate_output calculates the output signal using the 8-to-1 mux formula.
+
+        :return: Value of the output signal.
+        :rtype: bool
+        """
+        first = not self.set[2] and not self.set[1] and not self.set[0] and self.input[0]
+        second = not self.set[2] and not self.set[1] and self.set[0] and self.input[1]
+        third = not self.set[2] and self.set[1] and not self.set[0] and self.input[2]
+        fourth = not self.set[2] and self.set[1] and self.set[0] and self.input[3]
+        fifth = self.set[2] and not self.set[1] and not self.set[0] and self.input[4]
+        sixth = self.set[2] and not self.set[1] and self.set[0] and self.input[5]
+        seventh = self.set[2] and self.set[1] and not self.set[0] and self.input[6]
+        eight = self.set[2] and self.set[1] and self.set[0] and self.input[7]
+
+        return first or second or third or fourth or fifth or sixth or seventh or eight
diff --git a/CTools/Multiplexers/__init__.py b/CTools/Multiplexers/__init__.py
index 695961b..1404323 100644
--- a/CTools/Multiplexers/__init__.py
+++ b/CTools/Multiplexers/__init__.py
@@ -6,3 +6,4 @@
 
 from CTools.Multiplexers.Mux2to1 import *
 from CTools.Multiplexers.Mux4to1 import *
+from CTools.Multiplexers.Mux8to1 import *


Test patch:
diff --git a/tests/Multiplexers_tests/test_Mux8to1.py b/tests/Multiplexers_tests/test_Mux8to1.py
new file mode 100644
index 0000000..84d9e1c
--- /dev/null
+++ b/tests/Multiplexers_tests/test_Mux8to1.py
@@ -0,0 +1,76 @@
+import itertools
+
+from CTools import NotTruthValue, NonExistingControlSignal, NonExistingInput
+from CTools.Multiplexers import Mux8to1
+
+
+def generate_inputs(num):
+    vals = []
+    for i in itertools.product([False, True], repeat=num):
+        vals.append(i)
+
+    return vals
+
+
+def get_expected(val):
+    if val[0] == 0 and val[1] == 0 and val[2] == 0:
+        return 7
+    if val[0] == 0 and val[1] == 0 and val[2] == 1:
+        return 6
+    if val[0] == 0 and val[1] == 1 and val[2] == 0:
+        return 5
+    if val[0] == 0 and val[1] == 1 and val[2] == 1:
+        return 4
+    if val[0] == 1 and val[1] == 0 and val[2] == 0:
+        return 3
+    if val[0] == 1 and val[1] == 0 and val[2] == 1:
+        return 2
+    if val[0] == 1 and val[1] == 1 and val[2] == 0:
+        return 1
+    if val[0] == 1 and val[1] == 1 and val[2] == 1:
+        return 0
+
+
+def test_Mux8to1():
+    errors = []
+    mux = Mux8to1()
+    inputs = generate_inputs(8)
+    set_inputs = generate_inputs(3)
+
+    for val in inputs:
+        mux.set_input(0, val[7]).set_input(1, val[6]).set_input(2, val[5]).set_input(3, val[4]).set_input(4, val[3])\
+            .set_input(5, val[2]).set_input(6, val[1]).set_input(7, val[0])
+
+        for set_val in set_inputs:
+            mux.set_set(0, set_val[2]).set_set(1, set_val[1]).set_set(2, set_val[0])
+            expected = val[get_expected(set_val)]
+            output = mux.get_output()
+
+            if output != expected:
+                to_append = "{}".format(str(val[7])) + ", {}".format(str(val[6])) + ", {}".format(str(val[5])) + \
+                            ", {}".format(str(val[4])) + ", {}".format(str(val[3])) + ", {}".format(str(val[2])) + \
+                            ", {}".format(str(val[1])) + ", {}".format(str(val[0])) +\
+                            ", set signals {}".format(str(set_val[2])) + ", {}".format(str(set_val[1])) + \
+                            ", {}".format(str(set_val[0])) + \
+                            " test not passed!"
+                errors.append(to_append)
+
+    try:
+        mux.set_set(5, False)
+        errors.append("Not existing set input test not passed!")
+    except NonExistingControlSignal:
+        pass
+
+    try:
+        mux.set_set(0, 5)
+        errors.append("Not truth value to set test not passed!")
+    except NotTruthValue:
+        pass
+
+    try:
+        mux.set_input(16, False)
+        errors.append("Not existing input test not passed!")
+    except NonExistingInput:
+        pass
+
+    assert not errors, "errors occurred:\n{}".format("\n".join(errors))