def test_complex_spec(self):
        # Create a sdram just to set max chip size
        SDRAM(1000)
        temp_spec = mktemp()
        spec = DataSpecificationGenerator(io.FileIO(temp_spec, "w"))
        spec.reserve_memory_region(0, 44)
        spec.switch_write_focus(0)
        spec.set_register_value(3, 0x31323341)
        spec.write_value_from_register(3)
        spec.set_register_value(3, 0x31323342)
        spec.write_value_from_register(3)
        spec.set_register_value(3, 0x31323344)
        spec.write_value_from_register(3)
        spec.set_register_value(3, 0x31323347)
        spec.write_value_from_register(3)
        spec.set_register_value(3, 0x3132334B)
        spec.write_value_from_register(3)
        spec.set_register_value(2, 24)
        spec.set_write_pointer(2, address_is_register=True)
        spec.write_array([0x61, 0x62, 0x63, 0x64], data_type=DataType.UINT8)
        spec.set_register_value(5, 4)
        spec.write_repeated_value(0x70,
                                  5,
                                  repeats_is_register=True,
                                  data_type=DataType.UINT8)
        spec.write_value(0x7d, data_type=DataType.INT64)
        spec.end_specification()

        executor = DataSpecificationExecutor(io.FileIO(temp_spec, "r"), 400)
        executor.execute()
        r = executor.get_region(0)
        self.assertEqual(r.allocated_size, 44)
        self.assertEqual(r.max_write_pointer, 40)
        self.assertFalse(r.unfilled)
        self.assertEqual(
            r.region_data,
            bytearray("A321"
                      "B321"
                      "D321"
                      "G321"
                      "K321"
                      "\0\0\0\0"
                      "abcd"
                      "pppp"
                      "}\0\0\0"
                      "\0\0\0\0"
                      "\0\0\0\0".encode("ISO 8859-1")))
    def test_simple_spec(self):

        # Create a sdram just to set max chip size
        SDRAM(1000)
        # Write a data spec to execute
        temp_spec = mktemp()
        spec_writer = io.FileIO(temp_spec, "w")
        spec = DataSpecificationGenerator(spec_writer)
        spec.reserve_memory_region(0, 100)
        spec.reserve_memory_region(1, 200, empty=True)
        spec.reserve_memory_region(2, 4)
        spec.reserve_memory_region(3, 12, reference=1)
        spec.reference_memory_region(4, 2)
        spec.switch_write_focus(0)
        spec.write_array([0, 1, 2])
        spec.set_write_pointer(20)
        spec.write_value(4)
        spec.switch_write_focus(2)
        spec.write_value(3)
        spec.set_write_pointer(0)
        spec.write_value(10)
        spec.end_specification()

        # Execute the spec
        spec_reader = io.FileIO(temp_spec, "r")
        executor = DataSpecificationExecutor(spec_reader, 400)
        executor.execute()

        # Test the size
        header_and_table_size = (constants.MAX_MEM_REGIONS + 2) * 4
        self.assertEqual(executor.get_constructed_data_size(),
                         header_and_table_size + 100 + 200 + 4 + 12)

        # Test the unused regions
        for region in range(5, constants.MAX_MEM_REGIONS):
            self.assertIsNone(executor.get_region(region))

        # Test region 0
        region_0 = executor.get_region(0)
        self.assertEqual(region_0.allocated_size, 100)
        self.assertEqual(region_0.max_write_pointer, 24)
        self.assertFalse(region_0.unfilled)
        self.assertIsNone(region_0.reference)
        self.assertEqual(region_0.region_data[:region_0.max_write_pointer],
                         struct.pack("<IIIIII", 0, 1, 2, 0, 0, 4))

        # Test region 1
        region_1 = executor.get_region(1)
        self.assertIsInstance(region_1, MemoryRegionReal)
        self.assertEqual(region_1.allocated_size, 200)
        self.assertTrue(region_1.unfilled)
        self.assertIsNone(region_1.reference)

        # Test region 2
        region_2 = executor.get_region(2)
        self.assertIsInstance(region_2, MemoryRegionReal)
        self.assertEqual(region_2.allocated_size, 4)
        self.assertIsNone(region_2.reference)
        self.assertEqual(region_2.region_data, struct.pack("<I", 10))

        # Test region 3
        region_3 = executor.get_region(3)
        self.assertIsInstance(region_3, MemoryRegionReal)
        self.assertEqual(region_3.allocated_size, 12)
        self.assertEqual(region_3.reference, 1)
        self.assertEqual(executor.referenceable_regions, [3])

        # Test region 4
        region_4 = executor.get_region(4)
        self.assertIsInstance(region_4, MemoryRegionReference)
        self.assertEqual(region_4.ref, 2)
        self.assertEqual(executor.references_to_fill, [4])

        # Test the pointer table
        table = executor.get_pointer_table(0)
        self.assertEqual(len(table), constants.MAX_MEM_REGIONS)
        self.assertEqual(table[0], header_and_table_size)
        self.assertEqual(table[1], header_and_table_size + 100)
        self.assertEqual(table[2], header_and_table_size + 300)
        self.assertEqual(table[3], header_and_table_size + 304)
        # 4 is also 0 because it is a reference
        for region in range(4, constants.MAX_MEM_REGIONS):
            self.assertEqual(table[region], 0)

        # Test the header
        header = executor.get_header()
        self.assertEqual(len(header), 2)
        self.assertEqual(header[0], constants.APPDATA_MAGIC_NUM)
        self.assertEqual(header[1], constants.DSE_VERSION)