import os
import filecmp
import unittest
import numpy as np
from openql import openql as ql
from utils import file_compare

curdir = os.path.dirname(os.path.realpath(__file__))
output_dir = os.path.join(curdir, 'test_output')

class Test_bugs(unittest.TestCase):
    @classmethod
    def setUp(self):
        ql.initialize()
        ql.set_option('output_dir', output_dir)
        ql.set_option('use_default_gates', 'yes')
        ql.set_option('log_level', 'LOG_WARNING')

    # @unittest.expectedFailure
    # @unittest.skip
    def test_typecast(self):
        sweep_points = [1,2]
        num_circuits = 1
        num_qubits = 2
        platf = ql.Platform("starmon", 'cc_light')
        p = ql.Program('test_bug', platf, num_qubits)
        p.set_sweep_points(sweep_points)
        k = ql.Kernel('kernel1', platf, num_qubits)

        qubit = 1

        k.identity(np.int(qubit))
        k.identity(np.int32(qubit))
        k.identity(np.int64(qubit))

        k.identity(np.uint(qubit))
        k.identity(np.uint32(qubit))
        k.identity(np.uint64(qubit))

        # add the kernel to the program
        p.add_kernel(k)


    # relates to https://github.com/QE-Lab/OpenQL/issues/171
    # various runs of compiles were generating different results or in the best
    # case strange errors. So multiple (NCOMPILES) runs of compile are executed
    # to make sure there is no error and output generated in all these runs is same
    # JvS: more likely, it also had to do with the classical register allocator
    # depending on stuff like Python's garbage collection to free a register.
    # The register numbers have to be hardcoded now for that reason.
    def test_stateful_behavior(self):
        ql.set_option('optimize', 'no')
        ql.set_option('scheduler', 'ALAP')

        platform = ql.Platform("myPlatform", 'cc_light')

        sweep_points = [1]
        nqubits = 3
        nregs = 3

        p = ql.Program("statelessProgram", platform, nqubits, nregs)
        p.set_sweep_points(sweep_points)
        k = ql.Kernel("aKernel", platform, nqubits, nregs)

        k.prepz(0)
        k.gate('rx180', [0])
        k.measure(0)

        rd = ql.CReg(0)
        rs1 = ql.CReg(1)
        rs2 = ql.CReg(2)

        k.classical(rs1, ql.Operation(3))
        k.classical(rs1, ql.Operation(4))
        k.classical(rd, ql.Operation(rs1, '+', rs2))

        p.add_kernel(k)

        NCOMPILES=50
        QISA_fn = os.path.join(output_dir, p.name+'_last.qasm')
        for i in range(NCOMPILES):
            p.compile()
            self.setUpClass()
            QISA_fn_i = os.path.join(output_dir, p.name+'_'+str(i)+'_last.qasm')
            os.rename(QISA_fn,QISA_fn_i)

        for i in range(NCOMPILES-1):
            QISA_fn_1 = os.path.join(output_dir, p.name+'_'+str(i)+'_last.qasm')
            QISA_fn_2 = os.path.join(output_dir, p.name+'_'+str(i+1)+'_last.qasm')
            self.assertTrue( file_compare(QISA_fn_1, QISA_fn_2))

# Unclear how this test works.
# When clear, enable it again.
# Now it fails, not clear how to repair, so it is disabled.
#    def test_empty_infinite_loop(self):
#        name = 'empty_infinite_loop'
#        in_fn = 'test_' + name + '.cq'
#        out_fn = 'test_output/' + name + '_out.cq'
#        gold_fn = 'golden/' + name + '_out.cq'
#        ql.initialize()
#        #ql.set_option('log_level', 'LOG_DEBUG')
#        ql.compile(in_fn)
#        self.assertTrue(file_compare(out_fn, gold_fn))

if __name__ == '__main__':
    unittest.main()

[((190, 225), 'os.path.join', 'os.path.join', (['curdir', '"""test_output"""'], {}), "(curdir, 'test_output')\n", (202, 225), False, 'import os\n'), ((149, 175), 'os.path.realpath', 'os.path.realpath', (['__file__'], {}), '(__file__)\n', (165, 175), False, 'import os\n'), ((3485, 3500), 'unittest.main', 'unittest.main', ([], {}), '()\n', (3498, 3500), False, 'import unittest\n'), ((309, 324), 'openql.openql.initialize', 'ql.initialize', ([], {}), '()\n', (322, 324), True, 'from openql import openql as ql\n'), ((333, 372), 'openql.openql.set_option', 'ql.set_option', (['"""output_dir"""', 'output_dir'], {}), "('output_dir', output_dir)\n", (346, 372), True, 'from openql import openql as ql\n'), ((381, 422), 'openql.openql.set_option', 'ql.set_option', (['"""use_default_gates"""', '"""yes"""'], {}), "('use_default_gates', 'yes')\n", (394, 422), True, 'from openql import openql as ql\n'), ((431, 472), 'openql.openql.set_option', 'ql.set_option', (['"""log_level"""', '"""LOG_WARNING"""'], {}), "('log_level', 'LOG_WARNING')\n", (444, 472), True, 'from openql import openql as ql\n'), ((649, 683), 'openql.openql.Platform', 'ql.Platform', (['"""starmon"""', '"""cc_light"""'], {}), "('starmon', 'cc_light')\n", (660, 683), True, 'from openql import openql as ql\n'), ((696, 737), 'openql.openql.Program', 'ql.Program', (['"""test_bug"""', 'platf', 'num_qubits'], {}), "('test_bug', platf, num_qubits)\n", (706, 737), True, 'from openql import openql as ql\n'), ((791, 830), 'openql.openql.Kernel', 'ql.Kernel', (['"""kernel1"""', 'platf', 'num_qubits'], {}), "('kernel1', platf, num_qubits)\n", (800, 830), True, 'from openql import openql as ql\n'), ((1712, 1743), 'openql.openql.set_option', 'ql.set_option', (['"""optimize"""', '"""no"""'], {}), "('optimize', 'no')\n", (1725, 1743), True, 'from openql import openql as ql\n'), ((1752, 1786), 'openql.openql.set_option', 'ql.set_option', (['"""scheduler"""', '"""ALAP"""'], {}), "('scheduler', 'ALAP')\n", (1765, 1786), True, 'from openql import openql as ql\n'), ((1807, 1844), 'openql.openql.Platform', 'ql.Platform', (['"""myPlatform"""', '"""cc_light"""'], {}), "('myPlatform', 'cc_light')\n", (1818, 1844), True, 'from openql import openql as ql\n'), ((1924, 1980), 'openql.openql.Program', 'ql.Program', (['"""statelessProgram"""', 'platform', 'nqubits', 'nregs'], {}), "('statelessProgram', platform, nqubits, nregs)\n", (1934, 1980), True, 'from openql import openql as ql\n'), ((2034, 2080), 'openql.openql.Kernel', 'ql.Kernel', (['"""aKernel"""', 'platform', 'nqubits', 'nregs'], {}), "('aKernel', platform, nqubits, nregs)\n", (2043, 2080), True, 'from openql import openql as ql\n'), ((2165, 2175), 'openql.openql.CReg', 'ql.CReg', (['(0)'], {}), '(0)\n', (2172, 2175), True, 'from openql import openql as ql\n'), ((2190, 2200), 'openql.openql.CReg', 'ql.CReg', (['(1)'], {}), '(1)\n', (2197, 2200), True, 'from openql import openql as ql\n'), ((2215, 2225), 'openql.openql.CReg', 'ql.CReg', (['(2)'], {}), '(2)\n', (2222, 2225), True, 'from openql import openql as ql\n'), ((2429, 2476), 'os.path.join', 'os.path.join', (['output_dir', "(p.name + '_last.qasm')"], {}), "(output_dir, p.name + '_last.qasm')\n", (2441, 2476), False, 'import os\n'), ((870, 883), 'numpy.int', 'np.int', (['qubit'], {}), '(qubit)\n', (876, 883), True, 'import numpy as np\n'), ((904, 919), 'numpy.int32', 'np.int32', (['qubit'], {}), '(qubit)\n', (912, 919), True, 'import numpy as np\n'), ((940, 955), 'numpy.int64', 'np.int64', (['qubit'], {}), '(qubit)\n', (948, 955), True, 'import numpy as np\n'), ((977, 991), 'numpy.uint', 'np.uint', (['qubit'], {}), '(qubit)\n', (984, 991), True, 'import numpy as np\n'), ((1012, 1028), 'numpy.uint32', 'np.uint32', (['qubit'], {}), '(qubit)\n', (1021, 1028), True, 'import numpy as np\n'), ((1049, 1065), 'numpy.uint64', 'np.uint64', (['qubit'], {}), '(qubit)\n', (1058, 1065), True, 'import numpy as np\n'), ((2252, 2267), 'openql.openql.Operation', 'ql.Operation', (['(3)'], {}), '(3)\n', (2264, 2267), True, 'from openql import openql as ql\n'), ((2294, 2309), 'openql.openql.Operation', 'ql.Operation', (['(4)'], {}), '(4)\n', (2306, 2309), True, 'from openql import openql as ql\n'), ((2335, 2362), 'openql.openql.Operation', 'ql.Operation', (['rs1', '"""+"""', 'rs2'], {}), "(rs1, '+', rs2)\n", (2347, 2362), True, 'from openql import openql as ql\n'), ((2657, 2686), 'os.rename', 'os.rename', (['QISA_fn', 'QISA_fn_i'], {}), '(QISA_fn, QISA_fn_i)\n', (2666, 2686), False, 'import os\n'), ((2917, 2951), 'utils.file_compare', 'file_compare', (['QISA_fn_1', 'QISA_fn_2'], {}), '(QISA_fn_1, QISA_fn_2)\n', (2929, 2951), False, 'from utils import file_compare\n')]