class CxxdConfigParserWithNoConfigFileAndNoCompilationDbOrTxtCompileFlagsConfigTest(
        unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.project_root_directory = tempfile.gettempdir()

    @classmethod
    def tearDownClass(cls):
        pass

    def setUp(self):
        self.parser = CxxdConfigParser('inexisting_cxxd_config_filename',
                                       self.project_root_directory)

    def test_if_cxxd_config_parser_returns_auto_discovery_try_harder_mode(
            self):
        self.assertEqual(self.parser.get_configuration_type(),
                         'auto-discovery-try-harder')

    def test_if_cxxd_config_parser_returns_none_because_no_configuration_could_be_found(
            self):
        self.assertEqual(self.parser.get_configuration_for_target(''), None)

    def test_if_cxxd_config_parser_returns_empty_blacklisted_dir_list(self):
        self.assertEqual(self.parser.get_blacklisted_directories(), [])

    def test_if_cxxd_config_parser_returns_clang_tidy_binary(self):
        self.assertNotEqual(self.parser.get_clang_tidy_binary_path(), None)

    def test_if_cxxd_config_parser_returns_empty_extra_file_extensions_list(
            self):
        self.assertEqual(self.parser.get_extra_file_extensions(), [])

    def test_if_cxxd_config_parser_returns_empty_clang_tidy_arg_list(self):
        self.assertEqual(self.parser.get_clang_tidy_args(), [])

    def test_if_cxxd_config_parser_returns_clang_format_binary(self):
        self.assertNotEqual(self.parser.get_clang_format_binary_path(), None)

    def test_if_cxxd_config_parser_returns_empty_clang_format_arg_list(self):
        self.assertEqual(self.parser.get_clang_format_args(), [])

    def test_if_cxxd_config_parser_returns_empty_project_builder_arg_list(
            self):
        self.assertEqual(self.parser.get_project_builder_args(), [])
class CxxdConfigParserWithConfigFileButWithNoCompilationDbOrTxtCompileFlagsConfigTest(
        unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.target = 'debug'
        cls.cxxd_config = FileGenerator.gen_cxxd_config_filename(
            cls.target, 'inexisting_path')
        cls.project_root_directory = tempfile.gettempdir()

    @classmethod
    def tearDownClass(cls):
        FileGenerator.close_gen_file(cls.cxxd_config)

    def setUp(self):
        self.parser = CxxdConfigParser(self.cxxd_config.name,
                                       self.project_root_directory)

    def test_if_cxxd_config_parser_returns_compilation_database_type(self):
        self.assertEqual(self.parser.get_configuration_type(),
                         'compilation-database')

    def test_if_cxxd_config_parser_returns_none_because_no_configuration_file_could_be_found(
            self):
        self.assertEqual(self.parser.get_configuration_for_target(''), None)
Beispiel #3
0
class Server():
    class ServiceHandler():
        def __init__(self, service):
            self.service = service
            self.process = None

        def start_listening(self):
            if self.is_started():
                logging.warning("Service process already started!")
            else:
                from service import service_listener
                self.process = Process(target=service_listener,
                                       args=(self.service, ),
                                       name=self.service.__class__.__name__)
                self.process.daemon = False
                self.process.start()

        def stop_listening(self):
            if self.is_started():
                self.process.join()
                self.process = None
            else:
                logging.warning("Service process already stopped!")

        def is_started(self):
            return self.process is not None

        def startup_request(self, payload):
            if self.is_started():
                self.service.send_startup_request(payload)
            else:
                logging.warning(
                    "Service process must be started before issuing any kind of requests!"
                )

        def shutdown_request(self, payload):
            if self.is_started():
                self.service.send_shutdown_request(payload)
            else:
                logging.warning(
                    "Service process must be started before issuing any kind of requests!"
                )

        def request(self, payload):
            if self.is_started():
                self.service.send_request(payload)
            else:
                logging.warning(
                    "Service process must be started before issuing any kind of requests!"
                )

    def __init__(self, handle, project_root_directory, target,
                 source_code_model_plugin, project_builder_plugin,
                 clang_format_plugin, clang_tidy_plugin):
        self.handle = handle
        self.cxxd_config_filename = '.cxxd_config.json'
        self.cxxd_config_parser = CxxdConfigParser(
            os.path.join(project_root_directory, self.cxxd_config_filename),
            project_root_directory)
        self.action = {
            ServerRequestId.START_ALL_SERVICES: self.__start_all_services,
            ServerRequestId.START_SERVICE: self.__start_service,
            ServerRequestId.SEND_SERVICE: self.__send_service_request,
            ServerRequestId.SHUTDOWN_ALL_SERVICES:
            self.__shutdown_all_services,
            ServerRequestId.SHUTDOWN_SERVICE: self.__shutdown_service,
            ServerRequestId.SHUTDOWN_AND_EXIT: self.__shutdown_and_exit
            # TODO add runtime debugging switch action
        }
        self.service = {}
        self.started_up = True
        self.configuration = self.cxxd_config_parser.get_configuration_for_target(
            target)
        if self.configuration:
            self.service = {
                ServiceId.SOURCE_CODE_MODEL:
                self.ServiceHandler(
                    SourceCodeModel(project_root_directory,
                                    self.cxxd_config_parser, target,
                                    source_code_model_plugin)),
                ServiceId.PROJECT_BUILDER:
                self.ServiceHandler(
                    ProjectBuilder(project_root_directory,
                                   self.cxxd_config_parser,
                                   project_builder_plugin)),
                ServiceId.CLANG_FORMAT:
                self.ServiceHandler(
                    ClangFormat(project_root_directory,
                                self.cxxd_config_parser, clang_format_plugin)),
                ServiceId.CLANG_TIDY:
                self.ServiceHandler(
                    ClangTidy(project_root_directory, self.cxxd_config_parser,
                              target, clang_tidy_plugin)),
            }
            logging.info("Registered services: {0}".format(self.service))
            logging.info("Actions: {0}".format(self.action))
        else:
            logging.fatal(
                'Unable to find proper configuration for given target: {0}. Please check entries in your .cxxd_config.json.'
                .format(target))
            logging.fatal('Bailing out ...')
            self.__shutdown_and_exit(0, [])

    def __start_all_services(self, dummyServiceId, dummyPayload):
        logging.info("Starting all registered services ... {0}".format(
            self.service))
        for serviceId, svc_handler in self.service.iteritems():
            svc_handler.start_listening()
            svc_handler.startup_request(dummyPayload)
            logging.info("id={0}, service='{1}', payload={2}".format(
                serviceId, svc_handler.service.__class__.__name__,
                dummyPayload))
        return self.started_up

    def __start_service(self, serviceId, payload):
        svc_handler = self.service.get(serviceId, None)
        if svc_handler is not None:
            logging.info("id={0}, service='{1}', payload={2}".format(
                serviceId, svc_handler.service.__class__.__name__, payload))
            svc_handler.start_listening()
            svc_handler.startup_request(payload)
        else:
            logging.error(
                "Starting the service not possible. No service found under id={0}."
                .format(serviceId))
        return self.started_up

    def __shutdown_all_services(self, dummyServiceId, payload):
        logging.info("Shutting down all registered services ... {0}".format(
            self.service))
        for serviceId, svc_handler in self.service.iteritems():
            svc_handler.shutdown_request(payload)
            logging.info("id={0}, service='{1}', payload={2}".format(
                serviceId, svc_handler.service.__class__.__name__, payload))
        for svc_handler in self.service.itervalues():
            svc_handler.stop_listening()
        return self.started_up

    def __shutdown_service(self, serviceId, payload):
        svc_handler = self.service.get(serviceId, None)
        if svc_handler is not None:
            logging.info("id={0}, service='{1}', payload={2}".format(
                serviceId, svc_handler.service.__class__.__name__, payload))
            svc_handler.shutdown_request(payload)
            svc_handler.stop_listening()
        else:
            logging.error(
                "Shutting down the service not possible. No service found under id={0}."
                .format(serviceId))
        return self.started_up

    def __shutdown_and_exit(self, dummyServiceId, payload):
        logging.info("Shutting down the server ...")
        self.__shutdown_all_services(dummyServiceId, payload)
        self.started_up = False
        return self.started_up

    def __send_service_request(self, serviceId, payload):
        svc_handler = self.service.get(serviceId, None)
        if svc_handler is not None:
            logging.info("id={0}, service='{1}', Payload={2}".format(
                serviceId, svc_handler.service.__class__.__name__, payload))
            svc_handler.request(payload)
        else:
            logging.error(
                "Sending a request to the service not possible. No service found under id={0}."
                .format(serviceId))
        return self.started_up

    def __unknown_action(self, serviceId, payload):
        logging.error(
            "Unknown action triggered! Valid actions are: {0}".format(
                self.action))
        return self.started_up

    def process_request(self):
        payload = self.handle.get()
        still_running = self.action.get(int(payload[0]),
                                        self.__unknown_action)(int(payload[1]),
                                                               payload[2])
        return still_running

    def is_started_up(self):
        return self.started_up
class CxxdConfigParserWithNonEmptyConfigFileAndCompilationDb(
        unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.target = 'debug'
        cls.json_compilation_database = FileGenerator.gen_json_compilation_database(
            'doesnt_matter.cpp')
        cls.cxxd_config = FileGenerator.gen_cxxd_config_filename(
            cls.target, os.path.dirname(cls.json_compilation_database.name))
        cls.project_root_directory = tempfile.gettempdir()

    @classmethod
    def tearDownClass(cls):
        FileGenerator.close_gen_file(cls.json_compilation_database)
        FileGenerator.close_gen_file(cls.cxxd_config)

    def setUp(self):
        self.parser = CxxdConfigParser(self.cxxd_config.name,
                                       self.project_root_directory)

    def test_if_cxxd_config_parser_returns_compilation_database_type(self):
        self.assertEqual(self.parser.get_configuration_type(),
                         'compilation-database')

    def test_if_cxxd_config_parser_returns_configuration_for_given_target(
            self):
        self.assertEqual(
            os.path.normpath(
                self.parser.get_configuration_for_target(self.target)),
            self.json_compilation_database.name)

    def test_if_cxxd_config_parser_returns_none_for_inexisting_target(self):
        self.assertEqual(
            self.parser.get_configuration_for_target('inexisting_target'),
            None)

    def test_if_cxxd_config_parser_returns_non_empty_blacklisted_dir_list(
            self):
        self.assertNotEqual(self.parser.get_blacklisted_directories(), [])

    def test_if_cxxd_config_parser_returns_non_empty_extra_file_extensions_list(
            self):
        self.assertNotEqual(self.parser.get_extra_file_extensions(), [])

    def test_if_cxxd_config_parser_returns_clang_tidy_binary(self):
        self.assertNotEqual(self.parser.get_clang_tidy_binary_path(), None)

    def test_if_cxxd_config_parser_returns_non_empty_clang_tidy_arg_list(self):
        self.assertNotEqual(self.parser.get_clang_tidy_args(), [])

    def test_if_cxxd_config_parser_returns_clang_format_binary(self):
        self.assertNotEqual(self.parser.get_clang_format_binary_path(), None)

    def test_if_cxxd_config_parser_returns_non_empty_clang_format_arg_list(
            self):
        self.assertNotEqual(self.parser.get_clang_format_args(), [])

    def test_if_cxxd_config_parser_returns_non_empty_project_builder_arg_list(
            self):
        self.assertNotEqual(self.parser.get_project_builder_args(), [])

    def test_if_is_file_blacklisted_handles_files_from_blacklisted_dirs_correctly(
            self):
        directory_list = ['/tmp']
        filename = '/tmp/filename.cpp'
        self.assertEqual(
            CxxdConfigParser.is_file_blacklisted(directory_list, filename),
            True)

    def test_if_is_file_blacklisted_handles_files_not_in_blacklisted_dirs_correctly(
            self):
        directory_list = ['/tmp']
        filename = '/home/filename.cpp'
        self.assertEqual(
            CxxdConfigParser.is_file_blacklisted(directory_list, filename),
            False)

    def test_if_is_file_blacklisted_handles_file_for_given_dir_recursively(
            self):
        directory_list = ['/tmp']
        filename = '/tmp/dir1/dir2/dir3/filename.cpp'
        self.assertEqual(
            CxxdConfigParser.is_file_blacklisted(directory_list, filename),
            True)
class CxxdConfigParserWithCornerCaseConfigEntriesTest(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.target = 'debug'
        cls.json_compilation_database = FileGenerator.gen_json_compilation_database(
            'doesnt_matter.cpp')
        cls.project_root_directory = tempfile.gettempdir()

    @classmethod
    def tearDownClass(cls):
        FileGenerator.close_gen_file(cls.json_compilation_database)

    def test_if_cxxd_config_parser_returns_auto_discovery_try_harder_when_configuration_is_missing(
            self):
        self.cxxd_config = FileGenerator.gen_cxxd_config_filename_with_invalid_section(
            [
                '\
{                                               \n\
}                                               \n\
        '
            ])
        self.cxxd_config_parser = CxxdConfigParser(self.cxxd_config.name,
                                                   self.project_root_directory)
        self.assertEqual(self.cxxd_config_parser.get_configuration_type(),
                         'auto-discovery-try-harder')
        FileGenerator.close_gen_file(self.cxxd_config)

    def test_if_cxxd_config_parser_returns_auto_discovery_try_harder_when_configuration_is_misspelled(
            self):
        self.cxxd_config = FileGenerator.gen_cxxd_config_filename_with_invalid_section(
            [
                '\
{                                               \n\
    "configurations" : {                        \n\
    }                                           \n\
}                                               \n\
        '
            ])
        self.cxxd_config_parser = CxxdConfigParser(self.cxxd_config.name,
                                                   self.project_root_directory)
        self.assertEqual(self.cxxd_config_parser.get_configuration_type(),
                         'auto-discovery-try-harder')
        FileGenerator.close_gen_file(self.cxxd_config)

    def test_if_cxxd_config_parser_returns_auto_discovery_try_harder_when_type_is_missing(
            self):
        self.cxxd_config = FileGenerator.gen_cxxd_config_filename_with_invalid_section(
            [
                '\
{                                               \n\
    "configuration" : {                         \n\
    }                                           \n\
}                                               \n\
        '
            ])
        self.cxxd_config_parser = CxxdConfigParser(self.cxxd_config.name,
                                                   self.project_root_directory)
        self.assertEqual(self.cxxd_config_parser.get_configuration_type(),
                         'auto-discovery-try-harder')
        FileGenerator.close_gen_file(self.cxxd_config)

    def test_if_cxxd_config_parser_returns_none_when_type_is_not_one_of_valid_values(
            self):
        self.cxxd_config = FileGenerator.gen_cxxd_config_filename_with_invalid_section(
            [
                '\
{                                               \n\
    "configuration" : {                         \n\
        "type": "something-unsupported"         \n\
    }                                           \n\
}                                               \n\
        '
            ])
        self.cxxd_config_parser = CxxdConfigParser(self.cxxd_config.name,
                                                   self.project_root_directory)
        self.assertEqual(self.cxxd_config_parser.get_configuration_type(),
                         None)
        FileGenerator.close_gen_file(self.cxxd_config)

    def test_if_cxxd_config_parser_returns_compilation_database_for_type(self):
        self.cxxd_config = FileGenerator.gen_cxxd_config_filename_with_invalid_section(
            [
                '\
{                                               \n\
    "configuration" : {                         \n\
        "type": "compilation-database"          \n\
    }                                           \n\
}                                               \n\
        '
            ])
        self.cxxd_config_parser = CxxdConfigParser(self.cxxd_config.name,
                                                   self.project_root_directory)
        self.assertEqual(self.cxxd_config_parser.get_configuration_type(),
                         'compilation-database')
        FileGenerator.close_gen_file(self.cxxd_config)

    def test_if_cxxd_config_parser_returns_compile_flags_for_type(self):
        self.cxxd_config = FileGenerator.gen_cxxd_config_filename_with_invalid_section(
            [
                '\
{                                               \n\
    "configuration" : {                         \n\
        "type": "compile-flags"                 \n\
    }                                           \n\
}                                               \n\
        '
            ])
        self.cxxd_config_parser = CxxdConfigParser(self.cxxd_config.name,
                                                   self.project_root_directory)
        self.assertEqual(self.cxxd_config_parser.get_configuration_type(),
                         'compile-flags')
        FileGenerator.close_gen_file(self.cxxd_config)

    def test_if_cxxd_config_parser_returns_auto_discovery_for_type(self):
        self.cxxd_config = FileGenerator.gen_cxxd_config_filename_with_invalid_section(
            [
                '\
{                                               \n\
    "configuration" : {                         \n\
        "type": "auto-discovery"                \n\
    }                                           \n\
}                                               \n\
        '
            ])
        self.cxxd_config_parser = CxxdConfigParser(self.cxxd_config.name,
                                                   self.project_root_directory)
        self.assertEqual(self.cxxd_config_parser.get_configuration_type(),
                         'auto-discovery')
        FileGenerator.close_gen_file(self.cxxd_config)

    def test_if_cxxd_config_parser_returns_none_when_for_inexisting_target_section(
            self):
        self.cxxd_config = FileGenerator.gen_cxxd_config_filename_with_invalid_section(
            [
                '\
{                                               \n\
    "configuration" : {                         \n\
        "type": "compilation-database",         \n\
        "compilation-database" : {              \n\
        }                                       \n\
     }                                          \n\
}                                               \n\
        '
            ])
        self.cxxd_config_parser = CxxdConfigParser(self.cxxd_config.name,
                                                   self.project_root_directory)
        self.assertEqual(
            self.cxxd_config_parser.get_configuration_for_target('whatever'),
            None)
        FileGenerator.close_gen_file(self.cxxd_config)

    def test_if_cxxd_config_parser_returns_none_when_for_misspelled_target_section(
            self):
        self.cxxd_config = FileGenerator.gen_cxxd_config_filename_with_invalid_section(
            [
                '\
{                                               \n\
    "configuration" : {                         \n\
        "type": "compilation-database",         \n\
        "compilation-database" : {              \n\
            "targetsss" : {                     \n\
            }                                   \n\
        }                                       \n\
     }                                          \n\
}                                               \n\
        '
            ])
        self.cxxd_config_parser = CxxdConfigParser(self.cxxd_config.name,
                                                   self.project_root_directory)
        self.assertEqual(
            self.cxxd_config_parser.get_configuration_for_target('whatever'),
            None)
        FileGenerator.close_gen_file(self.cxxd_config)

    def test_if_cxxd_config_parser_returns_none_for_inexisting_target(self):
        self.cxxd_config = FileGenerator.gen_cxxd_config_filename_with_invalid_section(
            [
                '\
{                                               \n\
    "configuration" : {                         \n\
        "type": "compilation-database",         \n\
        "compilation-database" : {              \n\
            "target" : {                        \n\
            }                                   \n\
        }                                       \n\
     }                                          \n\
}                                               \n\
        '
            ])
        self.cxxd_config_parser = CxxdConfigParser(self.cxxd_config.name,
                                                   self.project_root_directory)
        self.assertEqual(
            self.cxxd_config_parser.get_configuration_for_target('whatever'),
            None)
        FileGenerator.close_gen_file(self.cxxd_config)

    def test_if_cxxd_config_parser_returns_none_when_auto_discovery_does_not_contain_any_search_paths(
            self):
        self.cxxd_config = FileGenerator.gen_cxxd_config_filename_with_invalid_section(
            [
                '\
{                                               \n\
    "configuration" : {                         \n\
        "type": "auto-discovery",               \n\
        "auto-discovery" : {                    \n\
        }                                       \n\
     }                                          \n\
}                                               \n\
        '
            ])
        self.cxxd_config_parser = CxxdConfigParser(self.cxxd_config.name,
                                                   self.project_root_directory)
        self.assertEqual(self.cxxd_config_parser.get_configuration_type(),
                         'auto-discovery')
        self.assertEqual(
            self.cxxd_config_parser.get_configuration_for_target('whatever'),
            None)
        FileGenerator.close_gen_file(self.cxxd_config)

    def test_if_cxxd_config_parser_returns_none_when_auto_discovery_search_path_is_misspelled(
            self):
        self.cxxd_config = FileGenerator.gen_cxxd_config_filename_with_invalid_section(
            [
                '\
{                                               \n\
    "configuration" : {                         \n\
        "type": "auto-discovery",               \n\
        "auto-discovery" : {                    \n\
            "search-pathssss" : [               \n\
            ]                                   \n\
        }                                       \n\
     }                                          \n\
}                                               \n\
        '
            ])
        self.cxxd_config_parser = CxxdConfigParser(self.cxxd_config.name,
                                                   self.project_root_directory)
        self.assertEqual(self.cxxd_config_parser.get_configuration_type(),
                         'auto-discovery')
        self.assertEqual(
            self.cxxd_config_parser.get_configuration_for_target('whatever'),
            None)
        FileGenerator.close_gen_file(self.cxxd_config)

    def test_if_cxxd_config_parser_returns_none_when_config_is_not_found_in_auto_discovery_search_paths(
            self):
        self.cxxd_config = FileGenerator.gen_cxxd_config_filename_with_invalid_section(
            [
                '\
{                                               \n\
    "configuration" : {                         \n\
        "type": "auto-discovery",               \n\
        "auto-discovery" : {                    \n\
            "search-paths" : ["/some_path"]     \n\
        }                                       \n\
     }                                          \n\
}                                               \n\
        '
            ])
        self.cxxd_config_parser = CxxdConfigParser(self.cxxd_config.name,
                                                   self.project_root_directory)
        self.assertEqual(self.cxxd_config_parser.get_configuration_type(),
                         'auto-discovery')
        self.assertEqual(
            self.cxxd_config_parser.get_configuration_for_target('whatever'),
            None)
        FileGenerator.close_gen_file(self.cxxd_config)

    def test_if_cxxd_config_parser_returns_config_found_in_auto_discovery_search_path(
            self):
        self.cxxd_config = FileGenerator.gen_cxxd_config_filename_with_invalid_section(
            [
                '\
{                                               \n\
    "configuration" : {                         \n\
        "type": "auto-discovery",               \n\
        "auto-discovery" : {                    \n\
            "search-paths" : ["/tmp"]           \n\
        }                                       \n\
     }                                          \n\
}                                               \n\
        '
            ])
        self.cxxd_config_parser = CxxdConfigParser(self.cxxd_config.name,
                                                   self.project_root_directory)
        self.assertEqual(self.cxxd_config_parser.get_configuration_type(),
                         'auto-discovery')
        self.assertEqual(
            self.cxxd_config_parser.get_configuration_for_target('whatever'),
            self.json_compilation_database.name)
        FileGenerator.close_gen_file(self.cxxd_config)

    def test_if_cxxd_config_parser_returns_none_configuration_when_config_for_selected_type_is_missing(
            self):
        self.cxxd_config = FileGenerator.gen_cxxd_config_filename_with_invalid_section(
            [
                '\
{                                               \n\
    "configuration" : {                         \n\
        "type" : "compilation-database",        \n\
        "compile-flags" : {                     \n\
            "target" : {                        \n\
                "rel" : "/rel"                  \n\
            }                                   \n\
        }                                       \n\
     }                                          \n\
}                                               \n\
        '
            ])
        self.cxxd_config_parser = CxxdConfigParser(self.cxxd_config.name,
                                                   self.project_root_directory)
        self.assertEqual(self.cxxd_config_parser.get_configuration_type(),
                         'compilation-database')
        self.assertEqual(
            self.cxxd_config_parser.get_configuration_for_target('rel'), None)
        FileGenerator.close_gen_file(self.cxxd_config)

    def test_if_cxxd_config_parser_returns_valid_configuration_when_there_are_multiple_configs_existing(
            self):
        self.cxxd_config = FileGenerator.gen_cxxd_config_filename_with_invalid_section(
            [
                '\
{                                               \n\
    "configuration" : {                         \n\
        "type" : "compilation-database",        \n\
        "compilation-database" : {              \n\
            "target" : {                        \n\
                "rel" : "/tmp"                  \n\
            }                                   \n\
        },                                      \n\
        "compile-flags" : {                     \n\
            "target" : {                        \n\
                "rel" : "/tmp"                  \n\
            }                                   \n\
        }                                       \n\
     }                                          \n\
}                                               \n\
        '
            ])
        self.cxxd_config_parser = CxxdConfigParser(self.cxxd_config.name,
                                                   self.project_root_directory)
        self.assertEqual(self.cxxd_config_parser.get_configuration_type(),
                         'compilation-database')
        self.assertEqual(
            self.cxxd_config_parser.get_configuration_for_target('rel'),
            self.json_compilation_database.name)
        FileGenerator.close_gen_file(self.cxxd_config)