def test_dsl_factory(self):
        factory = DSLFactory()
        factory2 = DSLFactory()
        # test of singleton factory behavior
        self.assertIs(factory, factory2)

        a = factory.from_file(
            "/home/robolab/robocomp/components/euroage-tv/components/tvGames/gamestatemachine.smdsl"
        )
        # test for cached query
        b = factory.from_file(
            "/home/robolab/robocomp/components/euroage-tv/components/tvGames/gamestatemachine.smdsl"
        )
        self.assertIs(a, b)

        c = factory.from_file(
            "/home/robolab/robocomp/interfaces/IDSLs/JointMotor.idsl")
        # test for cached query
        d = factory.from_file(
            "/home/robolab/robocomp/interfaces/IDSLs/JointMotor.idsl")
        self.assertIs(c, d)

        e = factory.from_file(
            "/home/robolab/robocomp/tools/robocompdsl/component_generation_test/customStateMachinePython/test.cdsl"
        )
        # test for cached query
        f = factory.from_file(
            "/home/robolab/robocomp/tools/robocompdsl/component_generation_test/customStateMachinePython/test.cdsl"
        )
        self.assertIs(e, f)
示例#2
0
class DSLFactoryTestCase(unittest.TestCase):

    def setUp(self):
        self.maxDiff = None
        self.factory = DSLFactory()

    def assertNestedDictEqual(self, first, second, ignored_keys=None, msg=None):
        if ignored_keys is not None:
            first = copy.deepcopy(first)
            second = copy.deepcopy(second)
            for key in ignored_keys:
                if key in first:
                    del first[key]
                if key in second:
                    del second[key]
        j1 = json.dumps(first, sort_keys=True, indent=4)
        j2 = json.dumps(second, sort_keys=True, indent=4)


        self.maxDiff = None
        # with open('last_json1.txt', 'w') as outfile:
        #     json.dump(first, outfile, sort_keys=True, indent=4)
        # with open('last_json2.txt', 'w') as outfile:
        #     json.dump(second, outfile, sort_keys=True, indent=4)
        self.assertEqual(j1, j2, msg)

    def test_factory_singleton(self):
        factory2 = DSLFactory()
        self.assertIs(self.factory, factory2)

    def test_factory_smdsl(self):
        a = self.factory.from_file(os.path.join(RESOURCES_DIR, "gamestatemachine.smdsl"))
        self.assertDictEqual(a, {
            'machine': {
                'name': 'application_machine',
                'default': False,
                'contents': {
                    'states': None,
                    'finalstate': 'app_end',
                    'initialstate': 'game_machine',
                    'transitions': [
                        {'src': 'game_machine', 'dests': ['app_end']}]
                }
            },
            'substates': [
                {
                    'parallel': False,
                    'parent': 'game_machine',
                    'contents': {
                        'states': [
                            'session_init',
                            'game_start_wait',
                            'game_init',
                            'game_loop',
                            'game_pause',
                            'game_resume',
                            'game_reset',
                            'game_end',
                            'game_won',
                            'game_lost',
                            'session_end'],
                        'finalstate': None,
                        'initialstate': 'session_start_wait',
                        'transitions': [
                            {'src': 'session_start_wait', 'dests': ['session_init']},
                            {'src': 'session_init', 'dests': ['game_start_wait']},
                            {'src': 'game_start_wait', 'dests': ['game_start_wait']},
                            {'src': 'game_start_wait', 'dests': ['game_init']},
                            {'src': 'game_start_wait', 'dests': ['session_end']},
                            {'src': 'session_end', 'dests': ['session_start_wait']},
                            {'src': 'game_init', 'dests': ['game_loop']},
                            {'src': 'game_loop', 'dests': ['game_loop', 'game_pause', 'game_won', 'game_lost', 'game_end']},
                            {'src': 'game_pause', 'dests': ['game_loop']},
                            {'src': 'game_pause', 'dests': ['game_reset']},
                            {'src': 'game_pause', 'dests': ['game_resume']},
                            {'src': 'game_pause', 'dests': ['game_end']},
                            {'src': 'game_resume', 'dests': ['game_loop']},
                            {'src': 'game_end', 'dests': ['game_lost']},
                            {'src': 'game_end', 'dests': ['game_won']},
                            {'src': 'game_lost', 'dests': ['game_start_wait']},
                            {'src': 'game_won', 'dests': ['game_start_wait']},
                            {'src': 'game_reset', 'dests': ['game_start_wait']}
                        ]
                    }
                },
                {
                    'parallel': False,
                    'parent': 'session_init',
                    'contents': {
                        'states': [
                            'player_acquisition_loop'],
                        'finalstate': 'player_acquisition_ended',
                        'initialstate': 'player_acquisition_init',
                        'transitions': [
                            {'src': 'player_acquisition_init', 'dests': ['player_acquisition_loop']},
                            {'src': 'player_acquisition_loop', 'dests': ['player_acquisition_loop']},
                            {'src': 'player_acquisition_loop', 'dests': ['player_acquisition_ended']}
                        ]
                    }
                }
            ],
            'filename': os.path.join(RESOURCES_DIR, "gamestatemachine.smdsl")
        })
        # Test for cached query
        b = self.factory.from_file(os.path.join(RESOURCES_DIR, "gamestatemachine.smdsl"))
        self.assertIs(a, b)

    def test_factory_idsl(self):
        c = self.factory.from_file("JointMotor.idsl")
        ref = OrderedDict({
            'name': 'RoboCompJointMotor',
            'imports': [],
            'recursive_imports': [],
            'interfaces':[
                    {'name': 'JointMotor',
                     'methods':
                         OrderedDict([
                             ('getAllMotorParams',{'name': 'getAllMotorParams', 'decorator': '', 'return': 'MotorParamsList', 'params': [], 'throws': 'nothing'}),
                             ('getAllMotorState', {'name': 'getAllMotorState', 'decorator': '', 'return': 'void', 'params': [{'decorator': 'out', 'type': 'MotorStateMap', 'name': 'mstateMap'}], 'throws': ['UnknownMotorException']}),
                             ('getBusParams', {'name': 'getBusParams', 'decorator': '', 'return': 'BusParams', 'params': [], 'throws': 'nothing'}),
                             ('getMotorParams', {'name': 'getMotorParams', 'decorator': '', 'return': 'MotorParams', 'params': [{'decorator': 'none', 'type': 'string', 'name': 'motor'}], 'throws': ['UnknownMotorException']}),
                             ('getMotorState', {'name': 'getMotorState', 'decorator': '', 'return': 'MotorState', 'params': [{'decorator': 'none', 'type': 'string', 'name': 'motor'}], 'throws': ['UnknownMotorException']}),
                             ('getMotorStateMap', {'name': 'getMotorStateMap', 'decorator': '', 'return': 'MotorStateMap', 'params': [{'decorator': 'none', 'type': 'MotorList', 'name': 'mList'}], 'throws': ['UnknownMotorException']}),
                             ('setPosition', {'name': 'setPosition', 'decorator': '', 'return': 'void', 'params': [{'decorator': 'none', 'type': 'MotorGoalPosition', 'name': 'goal'}], 'throws': ['UnknownMotorException', ',', 'HardwareFailedException', ',', 'CollisionException']}),
                             ('setSyncPosition', {'name': 'setSyncPosition', 'decorator': '', 'return': 'void', 'params': [{'decorator': 'none', 'type': 'MotorGoalPositionList', 'name': 'listGoals'}], 'throws': ['UnknownMotorException', ',', 'HardwareFailedException']}),
                             ('setSyncVelocity', {'name': 'setSyncVelocity', 'decorator': '', 'return': 'void', 'params': [{'decorator': 'none', 'type': 'MotorGoalVelocityList', 'name': 'listGoals'}], 'throws': ['UnknownMotorException', ',', 'HardwareFailedException']}),
                             ('setSyncZeroPos', {'name': 'setSyncZeroPos', 'decorator': '', 'return': 'void', 'params': [], 'throws': ['UnknownMotorException', ',', 'HardwareFailedException']}),
                             ('setVelocity', {'name': 'setVelocity', 'decorator': '', 'return': 'void', 'params': [{'decorator': 'none', 'type': 'MotorGoalVelocity', 'name': 'goal'}], 'throws': ['UnknownMotorException', ',', 'HardwareFailedException']}),
                             ('setZeroPos', {'name': 'setZeroPos', 'decorator': '', 'return': 'void', 'params': [{'decorator': 'none', 'type': 'string', 'name': 'name'}], 'throws': ['UnknownMotorException', ',', 'HardwareFailedException']})])},
                    {'name': 'JointMotorPublish',
                     'methods':
                         OrderedDict([
                             ('motorStates', {'name': 'motorStates',
                                              'decorator': '',
                                              'return': 'void',
                                              'params': [
                                                  {'decorator': 'none',
                                                   'type': 'MotorStateMap',
                                                   'name': 'mstateMap'}
                                              ],
                                              'throws': 'nothing'
                                              })
                         ])
                     }
                ],
            'types': [
                {'type': 'exception',
                 'name': 'HardwareFailedException',
                 'content': '\n                string  what;\n        '},
                {'type': 'exception',
                 'name': 'OutOfRangeException',
                 'content': '\n                string  what;\n        '},
                {'type': 'exception',
                 'name': 'UnknownMotorException',
                 'content': '\n                string  what;\n        '},
                {'type': 'exception',
                 'name': 'CollisionException',
                 'content': '\n                string what;\n        '},
                {'type': 'struct',
                 'name': 'MotorState',
                 'structIdentifiers': [{'type': 'float', 'identifier': 'pos'},
                                       {'type': 'float', 'identifier': 'vel'},
                                       {'type': 'float', 'identifier': 'power'},
                                       {'type': 'string', 'identifier': 'timeStamp'},
                                       {'type': 'int', 'identifier': 'p'},
                                       {'type': 'int', 'identifier': 'v'},
                                       {'type': 'bool', 'identifier': 'isMoving'},
                                       {'type': 'int', 'identifier': 'temperature'}]},
                {'type': 'dictionary',
                 'content': 'string,MotorState',
                 'name': 'MotorStateMap'},
                {'type': 'struct',
                 'name': 'MotorParams',
                 'structIdentifiers': [{'type': 'string', 'identifier': 'name'},
                                       {'type': 'byte', 'identifier': 'busId'},
                                       {'type': 'float', 'identifier': 'minPos'},
                                       {'type': 'float', 'identifier': 'maxPos'},
                                       {'type': 'float', 'identifier': 'maxVelocity'},
                                       {'type': 'float', 'identifier': 'zeroPos'},
                                       {'type': 'float', 'identifier': 'stepsRange'},
                                       {'type': 'float', 'identifier': 'maxDegrees'},
                                       {'type': 'bool', 'identifier': 'invertedSign'},
                                       {'type': 'float', 'identifier': 'offset'},
                                       {'type': 'float', 'identifier': 'unitsRange'}]},
                {'type': 'sequence',
                 'typeSequence': 'MotorParams',
                 'name': 'MotorParamsList'},
                {'type': 'struct',
                 'name': 'BusParams',
                 'structIdentifiers': [{'type': 'string', 'identifier': 'handler'},
                                       {'type': 'string', 'identifier': 'device'},
                                       {'type': 'int', 'identifier': 'numMotors'},
                                       {'type': 'int', 'identifier': 'baudRate'},
                                       {'type': 'int', 'identifier': 'basicPeriod'}]},
                {'type': 'struct',
                 'name': 'MotorGoalPosition',
                 'structIdentifiers': [{'type': 'string', 'identifier': 'name'},
                                       {'type': 'float', 'identifier': 'position'},
                                       {'type': 'float', 'identifier': 'maxSpeed'}]},
                {'type': 'sequence',
                 'typeSequence': 'MotorGoalPosition',
                 'name': 'MotorGoalPositionList'},
                {'type': 'struct',
                 'name': 'MotorGoalVelocity',
                 'structIdentifiers': [{'type': 'string', 'identifier': 'name'},
                                       {'type': 'float', 'identifier': 'velocity'},
                                       {'type': 'float', 'identifier': 'maxAcc'}]},
                {'type': 'sequence',
                 'typeSequence': 'MotorGoalVelocity',
                 'name': 'MotorGoalVelocityList'},
                {'type': 'sequence',
                 'typeSequence': 'string',
                 'name': 'MotorList'}],
            'sequences': [
                {'name': 'RoboCompJointMotor/MotorParamsList',
                 'type': 'sequence',
                 'typeSequence': 'MotorParams'},
                {'name': 'RoboCompJointMotor/MotorGoalPositionList',
                 'type': 'sequence',
                 'typeSequence': 'MotorGoalPosition'},
                {'name': 'RoboCompJointMotor/MotorGoalVelocityList',
                 'type': 'sequence',
                 'typeSequence': 'MotorGoalVelocity'},
                {'name': 'RoboCompJointMotor/MotorList',
                 'type': 'sequence',
                 'typeSequence': 'string'}
            ],
            'simpleSequences': [
                {'name': 'RoboCompJointMotor',
                 'strName': 'MotorParamsList'},
                {'name': 'RoboCompJointMotor',
                 'strName': 'MotorGoalPositionList'},
                {'name': 'RoboCompJointMotor',
                 'strName': 'MotorGoalVelocityList'},
                {'name': 'RoboCompJointMotor',
                 'strName': 'MotorList'}
            ],
            'structs': [
                {'name': 'RoboCompJointMotor/MotorState',
                 'type': 'struct',
                 'structIdentifiers': [
                     ['float', 'pos'],
                     ['float', 'vel'],
                     ['float', 'power'],
                     ['string', 'timeStamp'],
                     ['int', 'p'],
                     ['int', 'v'],
                     ['bool', 'isMoving'],
                     ['int', 'temperature']
                 ]
                 },
                {'name': 'RoboCompJointMotor/MotorParams',
                 'type': 'struct',
                 'structIdentifiers': [
                     ['string', 'name'],
                     ['byte', 'busId'],
                     ['float', 'minPos'],
                     ['float', 'maxPos'],
                     ['float', 'maxVelocity'],
                     ['float', 'zeroPos'],
                     ['float', 'stepsRange'],
                     ['float', 'maxDegrees'],
                     ['bool', 'invertedSign'],
                     ['float', 'offset'],
                     ['float', 'unitsRange']
                 ]
                 },
                {'name': 'RoboCompJointMotor/BusParams',
                 'type': 'struct',
                 'structIdentifiers': [
                     ['string', 'handler'],
                     ['string', 'device'],
                     ['int', 'numMotors'],
                     ['int', 'baudRate'],
                     ['int', 'basicPeriod']
                 ]
                 },
                {'name': 'RoboCompJointMotor/MotorGoalPosition',
                 'type': 'struct',
                 'structIdentifiers': [
                     ['string', 'name'],
                     ['float', 'position'],
                     ['float', 'maxSpeed']
                 ]
                 },
                {'name': 'RoboCompJointMotor/MotorGoalVelocity',
                 'type': 'struct',
                 'structIdentifiers': [
                     ['string', 'name'],
                     ['float', 'velocity'],
                     ['float', 'maxAcc']
                 ]
                 }
            ],
            'simpleStructs': [
                {'name': 'RoboCompJointMotor',
                 'strName': 'MotorState'},
                {'name': 'RoboCompJointMotor',
                 'strName': 'MotorParams'},
                {'name': 'RoboCompJointMotor',
                 'strName': 'BusParams'},
                {'name': 'RoboCompJointMotor',
                 'strName': 'MotorGoalPosition'},
                {'name': 'RoboCompJointMotor',
                 'strName': 'MotorGoalVelocity'}
            ],
            'filename': '/opt/robocomp/interfaces/IDSLs/JointMotor.idsl'
        })
        self.assertNestedDictEqual(c, ref, ignored_keys=['filename'])
        # test for cached query
        d = self.factory.from_file("JointMotor.idsl")
        self.assertIs(c, d)

    def test_factory_cdsl(self):
        # TODO: Use a better cdsl example than this
        g = self.factory.from_file(os.path.join(RESOURCES_DIR, "customstatemachinecpp.cdsl"))
        ref = cf.ComponentFacade({
            'options': [],
            'name': 'testcomp',
            'imports': [],
            'recursiveImports': [],
            'language': 'cpp',
            'statemachine_path': 'gamestatemachine.smdsl',
            'statemachine_visual': False,
            'innermodelviewer': False,
            'gui': ['Qt', 'QWidget'],
            'rosInterfaces': [],
            'iceInterfaces': [],
            'implements': [],
            'requires': [],
            'publishes': [],
            'subscribesTo': [],
            'usingROS': False,
            'dsr': False,
            'filename': os.path.join(RESOURCES_DIR, "customstatemachinecpp.cdsl")})
        self.assertEqual(g, ref)
        # test for cached query
        h = self.factory.from_file(os.path.join(RESOURCES_DIR, "customstatemachinecpp.cdsl"))
        self.assertIs(g, h)

    def test_factory_cdsl_with_options(self):
        # TODO: Use a better cdsl example than this
        g = self.factory.from_file(os.path.join(RESOURCES_DIR, "componentwithoptions.cdsl"))
        ref = cf.ComponentFacade({
            'options': ['agmagent', 'innermodelviewer'],
            'name': 'testcomp',
            'imports': ['AGMCommonBehavior.idsl',
                        'AGMExecutive.idsl',
                        'AGMExecutiveTopic.idsl',
                        'AGMWorldModel.idsl'],
            'recursiveImports': ['Planning.idsl'],
            'language': 'cpp',
            'statemachine_path': None,
            'statemachine_visual': False,
            'innermodelviewer': True,
            'gui': ['Qt', 'QWidget'],
            'rosInterfaces': [],
            'iceInterfaces': [['AGMCommonBehavior', 'ice'],
                              ['AGMExecutive', 'ice'],
                              ['AGMExecutiveTopic', 'ice'],
                              ['AGMWorldModel', 'ice']],
            'implements': [['AGMCommonBehavior','ice']],
            'requires': [['AGMExecutive', 'ice']],
            'publishes': [],
            'subscribesTo': [['AGMExecutiveTopic', 'ice']],
            'usingROS': False,
            'dsr': False,
            'filename': os.path.join(RESOURCES_DIR, "componentwithoptions.cdsl")})
        self.assertEqual(g, ref)

        # test for cached query
        h = self.factory.from_file(os.path.join(RESOURCES_DIR, "componentwithoptions.cdsl"))
        self.assertIs(g, h)


    # def test_factory_jcdsl(self):
    #     # TODO: Use a better cdsl example than this
    #     g = self.factory.from_file(os.path.join(RESOURCES_DIR, "jsoncomp.jcdsl"))
    #     self.assertCountEqual(g, {
    #         'options': ['agmagent', 'innermodelviewer'],
    #         'name': 'testcomp',
    #         'imports': ['AGMCommonBehavior.idsl',
    #                     'AGMExecutive.idsl',
    #                     'AGMExecutiveTopic.idsl',
    #                     'AGMWorldModel.idsl'],
    #         'recursiveImports': ['Planning.idsl'],
    #         'language': 'cpp',
    #         'statemachine': None,
    #         'statemachine_visual': False,
    #         'innermodelviewer': True,
    #         'gui': ['Qt', 'QWidget'],
    #         'rosInterfaces': [],
    #         'iceInterfaces': ['AGMCommonBehavior',
    #                           'AGMExecutive',
    #                           'AGMExecutiveTopic',
    #                           'AGMWorldModel'],
    #         'implements': ['AGMCommonBehavior'],
    #         'requires': ['AGMExecutive'],
    #         'publishes': [],
    #         'subscribesTo': ['AGMExecutiveTopic'],
    #         'usingROS': False,
    #         'filename': os.path.join(RESOURCES_DIR, "jsoncomp.jcdsl")})
    #     # test for cached query
    #     h = self.factory.from_file(os.path.join(RESOURCES_DIR, "jsoncomp.jcdsl"))
    #     self.assertIs(g, h)

    def test_factory_special_cases(self):
        # valid idsl without path
        a = self.factory.from_file("JointMotor.idsl")
        b = self.factory.from_file("JointMotor.idsl")
        self.assertEqual(a,b)

        # Not valid idsl without path
        self.assertRaises(IOError, self.factory.from_file,"NotAnIdsl.idsl")

        # None as path
        self.assertEqual(self.factory.from_file(None), None)

        # invalid dsl type from file extension
        self.assertRaises(ValueError, self.factory.from_string,"asdafafsdfasfsdfasdff", "ppsl")

        # invalid dsl type from file extension
        self.assertRaises(ParseException, self.factory.from_string, "this is not a valid string for the parser", "idsl")



    def assertFilesSame(self, sFName1, sFName2):
        text1 = open(os.path.join(self.tempdir, sFName1), 'rb').read()
        text2 = open(os.path.join(self.tempdir, sFName2), 'rb').read()
        self.assertEqual(text1, text2)