def testTryToConnect(self):
     """try to connect without error"""
     database_path = path_helper.TestDatabasePath()
     file_path = os.path.join(database_path, 'twitter_ios.db')
     execute = sqlite_query_execution.SQLiteQueryExecution(file_path)
     connected = execute.TryToConnect()
     self.assertTrue(connected)
 def testTryToConnectWithError(self):
     """try to connect 2 times resulting in a error"""
     database_path = path_helper.TestDatabasePath()
     file_path = os.path.join(database_path, 'twitter_ios_error.db')
     execute = sqlite_query_execution.SQLiteQueryExecution(file_path)
     connected = execute.TryToConnect()
     self.assertFalse(connected)
  def testGetRequiredTablesWithError(self):
    """get the required tables if anything went wrong"""
    database_path = path_helper.TestDatabasePath()
    file_path = os.path.join(database_path, 'twitter_ios_error.db')
    execute = sqlite_query_execution.SQLiteQueryExecution(file_path)
    connected = execute.TryToConnect()
    database_information = (
        sqlite_database_information.SQLiteDatabaseInformation(execute))
    result = database_information.GetTablesFromDatabase()

    self.assertEqual(result, [])
    self.assertFalse(connected)
 def testGetTableColumnsAndTypeWithNoTables(self):
   """get the columns for the table if the table can not be found."""
   database_path = path_helper.TestDatabasePath()
   file_path = os.path.join(database_path, 'test_database_types.db')
   execute = sqlite_query_execution.SQLiteQueryExecution(file_path)
   connected = execute.TryToConnect()
   database_information = (
       sqlite_database_information.SQLiteDatabaseInformation(execute))
   actual_data = database_information.GetTableColumnsAndType('thisisnot')
   expected_data = {}
   self.assertEqual(len(actual_data), 0)
   self.assertEqual(actual_data, expected_data)
   self.assertTrue(connected)
 def testGetTableColumnsAndTypeWithError(self):
   """get the columns for the table if anything went wrong"""
   database_path = path_helper.TestDatabasePath()
   file_path = os.path.join(database_path, 'test_database_types.db')
   execute = sqlite_query_execution.SQLiteQueryExecution(file_path)
   connected = execute.TryToConnect()
   database_information = (
       sqlite_database_information.SQLiteDatabaseInformation(execute))
   actual_data = database_information.GetTableColumnsAndType(
       "bla);select * from nodata; (")
   expected_data = {}
   self.assertEqual(len(actual_data), 0)
   self.assertEqual(actual_data, expected_data)
   self.assertTrue(connected)
    def setUp(self):
        database_path = path_helper.TestDatabasePath()
        file_path = os.path.join(database_path, 'twitter_ios.db')
        self.execute = sqlite_query_execution.SQLiteQueryExecution(file_path)
        self.execute.TryToConnect()

        file_path_types = os.path.join(database_path, 'test_database_types.db')
        self.execute_types = sqlite_query_execution.SQLiteQueryExecution(
            file_path_types)
        self.execute_types.TryToConnect()

        file_path_names = os.path.join(database_path, 'test_database_names.db')
        self.execute_names = sqlite_query_execution.SQLiteQueryExecution(
            file_path_names)
        self.execute_names.TryToConnect()
  def testGetRequiredTables(self):
    """get the required tables if nothing went wrong"""

    database_path = path_helper.TestDatabasePath()
    file_path = os.path.join(database_path, 'twitter_ios.db')
    execute = sqlite_query_execution.SQLiteQueryExecution(file_path)
    connected = execute.TryToConnect()
    database_information = (
        sqlite_database_information.SQLiteDatabaseInformation(execute))

    result = database_information.GetTablesFromDatabase()
    self.assertEqual(len(result), 7)
    self.assertTrue(connected)
    self.assertEqual(result[0], 'Lists')
    self.assertEqual(result[1], 'ListsShadow')
    self.assertEqual(result[2], 'MyRetweets')
    self.assertEqual(result[3], 'Statuses')
    self.assertEqual(result[4], 'StatusesShadow')
    self.assertEqual(result[5], 'Users')
    self.assertEqual(result[6], 'UsersShadow')
 def testGetTableColumnsAndType(self):
   """get columns for the table nodata with every possible type."""
   database_path = path_helper.TestDatabasePath()
   file_path = os.path.join(database_path, 'test_database_types.db')
   execute = sqlite_query_execution.SQLiteQueryExecution(file_path)
   connected = execute.TryToConnect()
   database_information = (
       sqlite_database_information.SQLiteDatabaseInformation(execute))
   actual_data = database_information.GetTableColumnsAndType('nodata')
   expected_data = {'intval': 'int',
                    'integerval': 'integer',
                    'tinyintval': 'tinyint',
                    'smallintval': 'smallint',
                    'mediuintval': 'mediumint',
                    'bigintval': 'bigint',
                    'unsignedbigintval': 'unsigned big int',
                    'int2val': 'int2',
                    'int8val': 'int8',
                    'characterval': 'character(20)',
                    'varcharval': 'varchar(255)',
                    'varyingcharacterval': 'varying character(255)',
                    'ncharval': 'nchar(55)',
                    'nativecharacterval': 'native character(70)',
                    'nvarcharval': 'nvarchar(100)',
                    'textval': 'text',
                    'clobval': 'clob',
                    'blobval': 'blob',
                    'realval': 'real',
                    'doubleval': 'double',
                    'doubleprecisionval': 'double precision',
                    'floatval': 'float',
                    'numericval': 'numeric',
                    'decimalval': 'decimal(10,5)',
                    'booleanval': 'boolean',
                    'dateval': 'date',
                    'datetimeval': 'datetime'}
   self.assertEqual(len(actual_data), 27)
   self.assertEqual(actual_data, expected_data)
   self.assertTrue(connected)
class EndToEndTestHelper(object):
    """Class defining Variables to be used multiple times in tests"""
    DIR_PATH = os.path.dirname(os.path.realpath(__file__))
    DATABASE_PATH = path_helper.TestDatabasePath()
    MAIN_PATH = os.path.join(os.path.dirname(os.path.dirname(DIR_PATH)),
                             'plasoscaffolder', 'frontend', 'main.py')
    PATH_QUESTION = 'What\'s the path to the plaso project\?\:'
    PATH_WRONG_QUESTION = 'Folder does not exists\. Enter correct one'
    NAME_QUESTION = 'What\'s the name of the plugin\?\:'
    NAME_QUESTION_NOT_VALID = ('Plugin is not in a valid format\. Choose new '
                               'Name \[plugin\_name\_\.\.\.\]')
    NAME_QUESTION_EXISTS = 'Plugin exists\. Choose new Name'

    NAME_ANSWER = 'test'
    TESTFILE_QUESTION = 'What\'s the path to your test file\?\:'
    TESTFILE_QUESTION_NOT_FOUND = "File does not exists\. Choose another\."
    TESTFILE_QUESTION_INVALID = 'Unable to open the database file\. Choose ' \
                                'another\.'
    TESTFILE_ANSWER = os.path.join(DATABASE_PATH, 'twitter_ios.db')
    TESTFILE_ANSWER_ERROR = os.path.join(DATABASE_PATH, 'twitter_ios_error.db')
    TESTFILE_ANSWER_NOT_FOUND = os.path.join(DATABASE_PATH, 'does_not_exist')

    OUTPUT_QUESTION = ('Do you want to have a output example for your '
                       'SQL Query\? \[Y\/n\]\:')
    OUTPUT_ANSWER_NO = 'n'
    OUTPUT_ANSWER_YES = 'y'
    OUTPUT_ADD_QUESTION = 'Do you want to add this query\? \[Y\/n\]\:'
    OUTPUT_ADD_ANSWER_NO = 'n'
    OUTPUT_ADD_ANSWER_YES = 'y'
    OUTPUT_EXAMPLE_FIRST_ROW = 'Your query output could look like this\.'
    OUTPUT_USERS_ID_NAME_EXAMPLE_HEADER = '\[\'id\'\, \'name\'\, ' \
                                          '\'createdDate\'\]'
    OUTPUT_USERS_ID_EXAMPLE_FIRST_ROW = '\(5402612\, \'BBC Breaking News\'\, ' \
                                        '1177252957\.0\)'
    OUTPUT_USERS_ID_EXAMPLE_SECOND_ROW = '\(13334762\, \'GitHub\'\, ' \
                                         '1202704910\.0\)'
    OUTPUT_USERS_ID_EXAMPLE_THIRD_ROW = '\(14388264\, \'Tom Pohl\'\, ' \
                                        '1208195714\.0\)'

    SQL_QUESTION = 'Please write your SQL script for the plugin\:'
    SQL_QUESTION_WITH_ABORT = ('Please write your SQL script for the plugin '
                               '\[\'abort\' to continue\]\:')
    SQL_ANSWER = 'select * from users'
    SQL_ANSWER_ESCAPED = 'select \* from users'
    SQL_ANSWER_2 = 'select * from statuses'
    SQL_ANSWER_ESCAPED_2 = 'select \* from statuses'
    SQL_ANSWER_ID_NAME = 'select id, name, createdDate from users'
    SQL_ANSWER_ESCAPED_ID_NAME = 'select id\, name\, createdDate from users'
    SQL_ANSWER_OK = 'The SQL query was ok.'
    NAME_ROW_QUESTION_USERS = ('Do you want to name the query parse row\: '
                               'Users \? \[Y\/n\]\:')
    NAME_ROW_QUESTION_STATUSES = ('Do you want to name the query parse row\: '
                                  'Statuses \? \[Y\/n\]\:')
    NAME_ROW_QUESTION_USERSSTATUSES = (
        'Do you want to name the query parse row\:'
        ' Usersstatuses \? \[Y\/n\]\:')
    NAME_ROW_QUESTION_INVALID = ('Row name is not in a valid format\. '
                                 'Choose new Name \[RowName\.\.\.\]')
    NAME_ROW_QUESTION_QUERY = 'What row does the SQL Query parse\?\:'
    NAME_ROW_ANSWER_YES = 'Y'
    NAME_ROW_ANSWER_NO = 'N'
    COLUMN_ANSWER_YES = 'Y'
    COLUMN_ANSWER_NO = 'N'
    COLUMN_QUESTION_CREATED_DATE = (
        'Is the column a time event\? createdDate \['
        'Y\/n\]\:')
    COLUMN_QUESTION_UPDATED_AT = ('Is the column a time event\? updatedAt \['
                                  'Y\/n\]\:')
    COLUMN_QUESTION_DATE = ('Is the column a time event\? date \[' 'Y\/n\]\:')
    COLUMN_QUESTION_PROFILE_TIMELINE = ('Is the column a time event\? '
                                        'includeInProfileTimeline \['
                                        'Y\/n\]\:')
    ADDITIONAL_TIMESTAMP = ('Enter \(additional\) timestamp events from '
                            'the query \[columnName,aliasName...\] or \['
                            'abort\]\:')
    ADDITIONAL_TIMESTAMP_INVALID = (
        'Timestamps are not in valid format\. '
        'Reenter them correctly \[name\,name\.\.\.\]')
    MORE_TIMESTAMPS_QUESTION = 'Do you want to add more timestamps\? \[y\/N\]\:'
    MORE_TIMESTAMPS_ANSWER_NO = 'N'
    MORE_TIMESTAMPS_ANSWER_YES = 'Y'
    ADDITIONAL_TIMESTAMP_ABORT = 'abort'
    CUSTOM_QUESTION_USERS = ('Does the event Users need customizing\? \['
                             'y\/N\]\:')
    CUSTOM_QUESTION_USERSSTATUSES = ('Does the event Usersstatuses need '
                                     'customizing\? \[y\/N\]\:')
    CUSTOM_QUESTION_STATUSES = ('Does the event Statuses need customizing\? \['
                                'y\/N\]\:')
    CUSTOM_QUESTION_THEUSER = ('Does the event TheUser need customizing\? \['
                               'y\/N\]\:')
    CUSTOM_ANSWER_NO = 'N'
    CUSTOM_ANSWER_YES = 'Y'
    CUSTOM_ADD_QUESTION = ('Enter columns that are customizable '
                           '\[columnName\,aliasName\.\.\.\] or \[abort\]\:')
    CUSTOM_ADD_INVALID = ('Column names are not in valid format\. '
                          'Reenter them correctly \[name\,name\.\.\.\]')
    CUSTOM_ADD_MORE_QUESTION = ('Do you want to add more columns '
                                'that are customizable\? \[y\/N\]\:')
    CUSTOM_ADD_MORE_ANSWER_NO = 'N'
    CUSTOM_ADD_MORE_ANSWER_YES = 'Y'
    ADD_QUESTION = 'Do you want to add another Query\? \[Y\/n\]\:'
    ADD_ANSWER_NO = 'n'
    ADD_ANSWER_YES = 'Y'
    GENERATE_QUESTION = 'Do you want to Generate the files\? \[Y\/n\]\:'
    GENERATE_ANSWER_YES = 'Y'
    GENERATE_ANSWER_NO = 'N'

    def __init__(self, plaso_dir_path: str, name: str):
        """Initializes the test helper

    Args:
      plaso_dir_path (str): the path of the directory of plaso
      name (str): the name of the plugin.
    """
        self.formatter_path = os.path.join(
            plaso_dir_path, 'plaso/formatters/{0}.py'.format(name))
        self.parser_path = os.path.join(
            plaso_dir_path, 'plaso/parsers/sqlite_plugins/{0}.py'.format(name))
        self.formatter_test_path = os.path.join(
            plaso_dir_path, 'tests/formatters/{0}.py'.format(name))
        self.parser_test_path = os.path.join(
            plaso_dir_path, 'tests/parsers/sqlite_plugins/{0}.py'.format(name))
        self.test_data_path = os.path.join(plaso_dir_path,
                                           'test_data/{0}.db'.format(name))
        self.parsers_init_path = os.path.join(
            plaso_dir_path, 'plaso/parsers/sqlite_plugins/__init__.py')
        self.formatter_init_path = os.path.join(
            plaso_dir_path, 'plaso/formatters/__init__.py')

    def ReadFromFile(self, path: str):
        """read from file helper"""
        with open(path, 'r') as f:
            return f.read()
    def testNormalGenerate(self):
        """Test a normal generation."""
        expected_path = os.path.join(os.path.dirname(__file__),
                                     'expected_files_twitterdb')
        plugin_name = 'the_plugin'
        database_suffix = 'db'
        test_file = os.path.join(path_helper.TestDatabasePath(),
                                 'twitter_ios.db')
        with tempfile.TemporaryDirectory() as tmpdir:
            output_path = os.path.join(tmpdir, "temp")

            file_handler.FileHandler()._CreateFolder(output_path)

            output_console_path = os.path.join(output_path, 'prompts.txt')
            output_handler = output_handler_file.OutputHandlerFile(
                file_path=output_console_path,
                file_handler=file_handler.FileHandler(),
                confirm=True)

            sqlite_path_helper = sqlite_plugin_path_helper.SQLitePluginPathHelper(
                path=output_path,
                plugin_name=plugin_name,
                database_suffix=database_suffix)

            plugin_helper = sqlite_plugin_helper.SQLitePluginHelper()
            controller = sqlite_controller.SQLiteController(
                output_handler=output_handler, plugin_helper=plugin_helper)

            query_execution = sqlite_query_execution.SQLiteQueryExecution(
                test_file)
            query_execution.TryToConnect()

            query_first = 'select * from users'
            query_data_first = plugin_helper.RunSQLQuery(
                query_first, query_execution)
            data_first = plugin_helper.GetColumnsAndTimestampColumn(
                query_data_first.columns, ['createdDate', 'updatedAt'],
                query_data_first.data)
            query_data_first_timestamp = data_first[1]
            query_data_first_normal = data_first[0]
            query_data_first_normal[0].customize = True
            query_data_first_normal[1].customize = True
            query_data_first_normal[2].customize = True

            query_model_first = sql_query_model.SQLQueryModel(
                'select * from users', 'Users', query_data_first_normal,
                query_data_first_timestamp, True, len(query_data_first.data))

            query_second = 'select * from statuses'
            query_data_second = plugin_helper.RunSQLQuery(
                query_second, query_execution)
            data_second = plugin_helper.GetColumnsAndTimestampColumn(
                query_data_second.columns, ['date', 'updatedAt'],
                query_data_second.data)
            query_data_second_timestamp = data_second[1]
            query_data_second_normal = data_second[0]

            query_model_second = sql_query_model.SQLQueryModel(
                'select * from users', 'Statuses',
                query_data_second_normal, query_data_second_timestamp, False,
                len(query_data_second.data))

            sql_query = [query_model_first, query_model_second]

            controller._path = output_path
            controller._name = plugin_name
            controller._testfile = test_file
            controller._sql_query = sql_query
            controller._plugin_helper = plugin_helper
            controller._output_handler = output_handler
            controller._query_execution = query_execution

            controller.Generate(path_helper.TemplatePath(),
                                path_helper.YapfStyleFilePath())

            formatter_init = self._ReadFromFile(
                sqlite_path_helper.formatter_init_file_path)
            formatter = self._ReadFromFile(
                sqlite_path_helper.formatter_file_path)
            formatter_test = self._ReadFromFile(
                sqlite_path_helper.formatter_test_file_path)
            parser_init = self._ReadFromFile(
                sqlite_path_helper.parser_init_file_path)
            parser = self._ReadFromFile(sqlite_path_helper.parser_file_path)
            parser_test = self._ReadFromFile(
                sqlite_path_helper.parser_test_file_path)
            console_output = self._ReadFromFile(
                os.path.join(output_path, 'prompts.txt'))

            expected_formatter_init = self._ReadFromFile(
                os.path.join(expected_path, 'formatters_init.py'))
            expected_formatter = self._ReadFromFile(
                os.path.join(expected_path, 'formatters.py'))
            expected_formatter_test = self._ReadFromFile(
                os.path.join(expected_path, 'formatters_test.py'))
            expected_parser_init = self._ReadFromFile(
                os.path.join(expected_path, 'parsers_init.py'))
            expected_parser = self._ReadFromFile(
                os.path.join(expected_path, 'parsers.py'))
            expected_parser_test = self._ReadFromFile(
                os.path.join(expected_path, 'parsers_test.py'))
            expected_console_output = (
                'Do you want to Generate the files?create '
                '{0}create {1}create {2}create '
                '{3}copy {4}create {5}create {6}'.format(
                    sqlite_path_helper.formatter_file_path,
                    sqlite_path_helper.parser_file_path,
                    sqlite_path_helper.formatter_test_file_path,
                    sqlite_path_helper.parser_test_file_path,
                    sqlite_path_helper.database_path,
                    sqlite_path_helper.parser_init_file_path,
                    sqlite_path_helper.formatter_init_file_path))

            self.assertEqual(formatter_init, expected_formatter_init)
            self.assertEqual(formatter, expected_formatter)
            self.assertEqual(formatter_test, expected_formatter_test)
            self.assertEqual(parser_init, expected_parser_init)
            self.assertEqual(parser, expected_parser)
            self.assertEqual(parser_test, expected_parser_test)
            self.assertEqual(console_output, expected_console_output)
    def testNormalGenerateForAllTypes(self):
        """Test a normal generation."""
        expected_path = os.path.join(os.path.dirname(__file__),
                                     'expected_files_typesdb')
        plugin_name = 'the_plugin'
        database_suffix = 'db'
        test_file = os.path.join(path_helper.TestDatabasePath(),
                                 'test_database_types.db')
        with tempfile.TemporaryDirectory() as tmpdir:
            output_path = os.path.join(tmpdir, "temp")

            file_handler.FileHandler()._CreateFolder(output_path)

            output_console_path = os.path.join(output_path, 'prompts.txt')
            output_handler = output_handler_file.OutputHandlerFile(
                file_path=output_console_path,
                file_handler=file_handler.FileHandler(),
                confirm=True)

            sqlite_path_helper = sqlite_plugin_path_helper.SQLitePluginPathHelper(
                path=output_path,
                plugin_name=plugin_name,
                database_suffix=database_suffix)

            plugin_helper = sqlite_plugin_helper.SQLitePluginHelper()
            controller = sqlite_controller.SQLiteController(
                output_handler=output_handler, plugin_helper=plugin_helper)

            query_execution = sqlite_query_execution.SQLiteQueryExecution(
                test_file)
            query_execution.TryToConnect()

            query_blob = 'select * from blobtypes'
            query_integer = 'select * from integertypes'
            query_numeric = 'select * from numerictypes'
            query_real = 'select * from realtypes'
            query_text = 'select * from texttypes'
            query_no_data = 'select * from nodata'

            query_data_blob = plugin_helper.RunSQLQuery(
                query_blob, query_execution)
            query_data_integer = plugin_helper.RunSQLQuery(
                query_integer, query_execution)
            query_data_numeric = plugin_helper.RunSQLQuery(
                query_numeric, query_execution)
            query_data_real = plugin_helper.RunSQLQuery(
                query_real, query_execution)
            query_data_text = plugin_helper.RunSQLQuery(
                query_text, query_execution)
            query_data_no_data = plugin_helper.RunSQLQuery(
                query_no_data, query_execution)

            query_model_blob = sql_query_model.SQLQueryModel(
                query_blob, 'blobtypes', query_data_blob.columns, [], False, 0)
            query_model_integer = sql_query_model.SQLQueryModel(
                query_integer, 'integertypes', query_data_integer.columns, [],
                False, 0)
            query_model_numeric = sql_query_model.SQLQueryModel(
                query_numeric, 'numerictypes', query_data_numeric.columns, [],
                False, 0)
            query_model_real = sql_query_model.SQLQueryModel(
                query_real, 'realtypes', query_data_real.columns, [], False, 0)
            query_model_text = sql_query_model.SQLQueryModel(
                query_text, 'texttypes', query_data_text.columns, [], False, 0)
            query_model_no_data = sql_query_model.SQLQueryModel(
                query_no_data, 'nodata', query_data_no_data.columns, [], False,
                0)

            sql_query = [
                query_model_blob, query_model_integer, query_model_numeric,
                query_model_real, query_model_text, query_model_no_data
            ]

            controller._path = output_path
            controller._name = plugin_name
            controller._testfile = test_file
            controller._sql_query = sql_query
            controller._plugin_helper = plugin_helper
            controller._output_handler = output_handler
            controller._query_execution = query_execution

            controller.Generate(path_helper.TemplatePath(),
                                path_helper.YapfStyleFilePath())

            formatter_init = self._ReadFromFile(
                sqlite_path_helper.formatter_init_file_path)
            formatter = self._ReadFromFile(
                sqlite_path_helper.formatter_file_path)
            formatter_test = self._ReadFromFile(
                sqlite_path_helper.formatter_test_file_path)
            parser_init = self._ReadFromFile(
                sqlite_path_helper.parser_init_file_path)
            parser = self._ReadFromFile(sqlite_path_helper.parser_file_path)
            parser_test = self._ReadFromFile(
                sqlite_path_helper.parser_test_file_path)
            console_output = self._ReadFromFile(
                os.path.join(output_path, 'prompts.txt'))

            expected_formatter_init = self._ReadFromFile(
                os.path.join(expected_path, 'formatters_init.py'))
            expected_formatter = self._ReadFromFile(
                os.path.join(expected_path, 'formatters.py'))
            expected_formatter_test = self._ReadFromFile(
                os.path.join(expected_path, 'formatters_test.py'))
            expected_parser_init = self._ReadFromFile(
                os.path.join(expected_path, 'parsers_init.py'))
            expected_parser = self._ReadFromFile(
                os.path.join(expected_path, 'parsers.py'))
            expected_parser_test = self._ReadFromFile(
                os.path.join(expected_path, 'parsers_test.py'))
            expected_console_output = (
                'Do you want to Generate the files?create '
                '{0}create {1}create {2}create '
                '{3}copy {4}create {5}create {6}'.format(
                    sqlite_path_helper.formatter_file_path,
                    sqlite_path_helper.parser_file_path,
                    sqlite_path_helper.formatter_test_file_path,
                    sqlite_path_helper.parser_test_file_path,
                    sqlite_path_helper.database_path,
                    sqlite_path_helper.parser_init_file_path,
                    sqlite_path_helper.formatter_init_file_path))

            self.assertEqual(formatter_init, expected_formatter_init)
            self.assertEqual(formatter, expected_formatter)
            self.assertEqual(formatter_test, expected_formatter_test)
            self.assertEqual(parser_init, expected_parser_init)
            self.assertEqual(parser, expected_parser)
            self.assertEqual(parser_test, expected_parser_test)
            self.assertEqual(console_output, expected_console_output)
 def setUp(self):
     database_path = path_helper.TestDatabasePath()
     file_path = os.path.join(database_path, 'twitter_ios.db')
     execute = sqlite_query_execution.SQLiteQueryExecution(file_path)
     execute.TryToConnect()
     self.explain_query_plan = explain_query_plan.ExplainQueryPlan(execute)