def test_repopulate_recent(self, redis=StrictRedis, cassandra=CassandraContext):
        self.init_database(redis=redis, cassandra=cassandra)
        self.register_configurations()

        self.database.redis.flushdb()

        database = ConfigurationContext(redis=self.database.redis, cassandra=self.database.cassandra)
        self.assertEqual(12, len(database.search_for_recent_configuration()))
Example #2
0
    def __init__(self, redis, cassandra, repositories=[], default_ttl_seconds=TTL_YEAR * 5, archive_ttl_seconds=TTL_WEEK * 8, async_processing=False, s3_credentials=None):
        if default_ttl_seconds is not None and default_ttl_seconds < 4 * self.TTL_WEEK:
            raise ValueError('TTL must be at least 4 weeks')
        if archive_ttl_seconds is not None and archive_ttl_seconds < 2 * self.TTL_WEEK:
            raise ValueError('Archive TTL must be at least 2 weeks')
        self.default_ttl_seconds = default_ttl_seconds
        self.archive_ttl_seconds = archive_ttl_seconds or default_ttl_seconds
        self._async_processing = async_processing

        self.redis = redis
        self.cassandra = cassandra

        with self.cassandra:
            self.cassandra.create_table(self.HealthTable)

        self.commit_context = CommitContext(redis, cassandra)
        for repository in repositories:
            self.commit_context.register_repository(repository)
        self.configuration_context = ConfigurationContext(redis, cassandra)
        self.upload_context = UploadContext(
            configuration_context=self.configuration_context,
            commit_context=self.commit_context,
            ttl_seconds=self.default_ttl_seconds,
            async_processing=async_processing,
        )

        self.suite_context = SuiteContext(
            configuration_context=self.configuration_context,
            commit_context=self.commit_context,
            ttl_seconds=self.default_ttl_seconds,
        )
        self.test_context = TestContext(
            configuration_context=self.configuration_context,
            commit_context=self.commit_context,
            ttl_seconds=self.default_ttl_seconds,
        )
        self.failure_context = FailureContext(
            configuration_context=self.configuration_context,
            commit_context=self.commit_context,
            ttl_seconds=self.default_ttl_seconds,
        )
        self.ci_context = CIContext(
            configuration_context=self.configuration_context,
            commit_context=self.commit_context,
            ttl_seconds=self.default_ttl_seconds,
        )

        for context in [self.ci_context, self.failure_context, self.suite_context, self.test_context]:
            self.upload_context.register_upload_callback(context.name, context.register)

        self.archive_context = ArchiveContext(
            configuration_context=self.configuration_context,
            commit_context=self.commit_context,
            ttl_seconds=self.archive_ttl_seconds,
            s3_credentials=s3_credentials,
        )
Example #3
0
    def __init__(self,
                 redis,
                 cassandra,
                 repositories=[],
                 default_ttl_seconds=TTL_YEAR * 5,
                 async_processing=False):
        if default_ttl_seconds is not None and default_ttl_seconds < 4 * self.TTL_WEEK:
            raise ValueError('TTL must be at least 4 weeks')
        self.default_ttl_seconds = default_ttl_seconds
        self._async_processing = async_processing

        self.redis = redis
        self.cassandra = cassandra
        self.commit_context = CommitContext(redis, cassandra)
        for repository in repositories:
            self.commit_context.register_repository(repository)
        self.configuration_context = ConfigurationContext(redis, cassandra)
        self.upload_context = UploadContext(
            configuration_context=self.configuration_context,
            commit_context=self.commit_context,
            ttl_seconds=self.default_ttl_seconds,
            async_processing=async_processing,
        )

        self.suite_context = SuiteContext(
            configuration_context=self.configuration_context,
            commit_context=self.commit_context,
            ttl_seconds=self.default_ttl_seconds,
        )
        self.test_context = TestContext(
            configuration_context=self.configuration_context,
            commit_context=self.commit_context,
            ttl_seconds=self.default_ttl_seconds,
        )
        self.ci_context = CIContext(
            configuration_context=self.configuration_context,
            commit_context=self.commit_context,
            ttl_seconds=self.default_ttl_seconds,
        )

        for context in [
                self.suite_context, self.test_context, self.ci_context
        ]:
            self.upload_context.register_upload_callback(
                context.name, context.register)

        self.archive_context = ArchiveContext(
            configuration_context=self.configuration_context,
            commit_context=self.commit_context,
            ttl_seconds=self.default_ttl_seconds,
        )
 def init_database(self, redis=StrictRedis, cassandra=CassandraContext):
     cassandra.drop_keyspace(keyspace=self.KEYSPACE)
     self.database = ConfigurationContext(
         redis=redis(),
         cassandra=cassandra(keyspace=self.KEYSPACE, create_keyspace=True),
     )
class ConfigurationContextTest(WaitForDockerTestCase):
    KEYSPACE = 'configuration_context_test_keyspace'
    CONFIGURATIONS = [
        Configuration(platform='Mac', version='10.13.0', sdk='17A405', is_simulator=False, architecture='x86_64', style='Debug', flavor='wk1'),
        Configuration(platform='Mac', version='10.13.0', sdk='17A405', is_simulator=False, architecture='x86_64', style='Debug', flavor='wk2'),
        Configuration(platform='Mac', version='10.13.0', sdk='17A405', is_simulator=False, architecture='x86_64', style='Release', flavor='wk1'),
        Configuration(platform='Mac', version='10.13.0', sdk='17A405', is_simulator=False, architecture='x86_64', style='Release', flavor='wk2'),
        Configuration(platform='Mac', version='10.13.0', sdk='17A405', is_simulator=False, architecture='x86_64', style='Asan', flavor='wk1'),
        Configuration(platform='Mac', version='10.13.0', sdk='17A405', is_simulator=False, architecture='x86_64', style='Asan', flavor='wk2'),
        Configuration(platform='Mac', version='10.14.0', sdk='18A391', is_simulator=False, architecture='x86_64', style='Debug', flavor='wk1'),
        Configuration(platform='Mac', version='10.14.0', sdk='18A391', is_simulator=False, architecture='x86_64', style='Debug', flavor='wk2'),
        Configuration(platform='Mac', version='10.14.0', sdk='18A391', is_simulator=False, architecture='x86_64', style='Release', flavor='wk1'),
        Configuration(platform='Mac', version='10.14.0', sdk='18A391', is_simulator=False, architecture='x86_64', style='Release', flavor='wk2'),
        Configuration(platform='Mac', version='10.14.0', sdk='18A391', is_simulator=False, architecture='x86_64', style='Asan', flavor='wk1'),
        Configuration(platform='Mac', version='10.14.0', sdk='18A391', is_simulator=False, architecture='x86_64', style='Asan', flavor='wk2'),
        Configuration(platform='iOS', version='11.0.0', sdk='15A432', is_simulator=True, architecture='x86_64', style='Debug'),
        Configuration(platform='iOS', version='11.0.0', sdk='15A432', is_simulator=True, architecture='x86_64', style='Release'),
        Configuration(platform='iOS', version='11.0.0', sdk='15A432', is_simulator=True, architecture='x86_64', style='Asan'),
        Configuration(platform='iOS', version='11.0.0', sdk='15A432', is_simulator=False, architecture='arm64', model='iPhone 8', style='Debug'),
        Configuration(platform='iOS', version='11.0.0', sdk='15A432', is_simulator=False, architecture='arm64', model='iPhone 8', style='Release'),
        Configuration(platform='iOS', version='11.0.0', sdk='15A432', is_simulator=False, architecture='arm64', model='iPhone 8', style='Asan'),
        Configuration(platform='iOS', version='12.0.0', sdk='16A404', is_simulator=True, architecture='x86_64', style='Debug'),
        Configuration(platform='iOS', version='12.0.0', sdk='16A404', is_simulator=True, architecture='x86_64', style='Release'),
        Configuration(platform='iOS', version='12.0.0', sdk='16A404', is_simulator=True, architecture='x86_64', style='Asan'),
        Configuration(platform='iOS', version='12.0.0', sdk='16A404', is_simulator=False, architecture='arm64', model='iPhone Xs', style='Debug'),
        Configuration(platform='iOS', version='12.0.0', sdk='16A404', is_simulator=False, architecture='arm64', model='iPhone 8', style='Release'),
        Configuration(platform='iOS', version='12.0.0', sdk='16A404', is_simulator=False, architecture='arm64', model='iPhone Xs', style='Asan'),
    ]

    def init_database(self, redis=StrictRedis, cassandra=CassandraContext):
        cassandra.drop_keyspace(keyspace=self.KEYSPACE)
        self.database = ConfigurationContext(
            redis=redis(),
            cassandra=cassandra(keyspace=self.KEYSPACE, create_keyspace=True),
        )

    def register_configurations(self):
        current = time.time()
        old = current - 60 * 60 * 24 * 21

        for configuration in self.CONFIGURATIONS:
            if (configuration.platform == 'Mac' and configuration.version <= Configuration.version_to_integer('10.13')) \
               or (configuration.platform == 'iOS' and configuration.version <= Configuration.version_to_integer('11')):
                self.database.register_configuration(configuration, old)
            else:
                self.database.register_configuration(configuration, current)

    @WaitForDockerTestCase.mock_if_no_docker(mock_redis=FakeStrictRedis, mock_cassandra=MockCassandraContext)
    def test_invalid_configuration(self, redis=StrictRedis, cassandra=CassandraContext):
        self.init_database(redis=redis, cassandra=cassandra)

        with self.assertRaises(TypeError):
            self.database.register_configuration('invalid object')
        with self.assertRaises(TypeError):
            self.database.register_configuration(Configuration(platform='iOS'))

    @WaitForDockerTestCase.mock_if_no_docker(mock_redis=FakeStrictRedis, mock_cassandra=MockCassandraContext)
    def test_no_style_configuration(self, redis=StrictRedis, cassandra=CassandraContext):
        self.init_database(redis=redis, cassandra=cassandra)

        self.database.register_configuration(Configuration(
            platform='Mac', version='10.13.0', sdk='17A405', is_simulator=False, architecture='x86_64',
        ))

    @WaitForDockerTestCase.mock_if_no_docker(mock_redis=FakeStrictRedis, mock_cassandra=MockCassandraContext)
    def test_configuration_by_platform(self, redis=StrictRedis, cassandra=CassandraContext):
        self.init_database(redis=redis, cassandra=cassandra)
        self.register_configurations()

        configuration_to_search_for = Configuration(platform='Mac', style='Debug')
        matching_configurations = self.database.search_for_configuration(configuration_to_search_for)
        self.assertEqual(4, len(matching_configurations))
        for config in matching_configurations:
            self.assertEqual(configuration_to_search_for, config)

    @WaitForDockerTestCase.mock_if_no_docker(mock_redis=FakeStrictRedis, mock_cassandra=MockCassandraContext)
    def test_configuration_by_platform_with_flavor(self, redis=StrictRedis, cassandra=CassandraContext):
        self.init_database(redis=redis, cassandra=cassandra)
        self.register_configurations()

        configuration_to_search_for = Configuration(platform='Mac', style='Debug', flavor='wk1')
        matching_configurations = self.database.search_for_configuration(configuration_to_search_for)
        self.assertEqual(2, len(matching_configurations))
        for config in matching_configurations:
            self.assertEqual(configuration_to_search_for, config)

    @WaitForDockerTestCase.mock_if_no_docker(mock_redis=FakeStrictRedis, mock_cassandra=MockCassandraContext)
    def test_configuration_by_platform_and_version(self, redis=StrictRedis, cassandra=CassandraContext):
        self.init_database(redis=redis, cassandra=cassandra)
        self.register_configurations()

        configuration_to_search_for = Configuration(platform='Mac', version='10.13', style='Release')
        matching_configurations = self.database.search_for_configuration(configuration_to_search_for)
        self.assertEqual(2, len(matching_configurations))
        for config in matching_configurations:
            self.assertEqual(configuration_to_search_for, config)

    @WaitForDockerTestCase.mock_if_no_docker(mock_redis=FakeStrictRedis, mock_cassandra=MockCassandraContext)
    def test_configuration_by_model(self, redis=StrictRedis, cassandra=CassandraContext):
        self.init_database(redis=redis, cassandra=cassandra)
        self.register_configurations()
        configuration_to_search_for = Configuration(model='iPhone 8')
        matching_configurations = self.database.search_for_configuration(configuration_to_search_for)
        self.assertEqual(4, len(matching_configurations))
        for config in matching_configurations:
            self.assertEqual(configuration_to_search_for, config)

    @WaitForDockerTestCase.mock_if_no_docker(mock_redis=FakeStrictRedis, mock_cassandra=MockCassandraContext)
    def test_configuration_by_architecture(self, redis=StrictRedis, cassandra=CassandraContext):
        self.init_database(redis=redis, cassandra=cassandra)
        self.register_configurations()

        configuration_to_search_for = Configuration(architecture='x86_64', style='Release')
        matching_configurations = self.database.search_for_configuration(configuration_to_search_for)
        self.assertEqual(6, len(matching_configurations))
        for config in matching_configurations:
            self.assertEqual(configuration_to_search_for, config)

    @WaitForDockerTestCase.mock_if_no_docker(mock_redis=FakeStrictRedis, mock_cassandra=MockCassandraContext)
    def test_recent_configurations(self, redis=StrictRedis, cassandra=CassandraContext):
        self.init_database(redis=redis, cassandra=cassandra)
        self.register_configurations()

        recent_configurations = self.database.search_for_recent_configuration()
        self.assertEqual(12, len(recent_configurations))

    @WaitForDockerTestCase.mock_if_no_docker(mock_redis=FakeStrictRedis, mock_cassandra=MockCassandraContext)
    def test_recent_configurations_constrained(self, redis=StrictRedis, cassandra=CassandraContext):
        self.init_database(redis=redis, cassandra=cassandra)
        self.register_configurations()

        configuration_to_search_for = Configuration(architecture='arm64', style='Release')
        matching_configurations = self.database.search_for_recent_configuration(configuration_to_search_for)
        self.assertEqual(1, len(matching_configurations))
        self.assertEqual(matching_configurations[0], configuration_to_search_for)

    @WaitForDockerTestCase.mock_if_no_docker(mock_redis=FakeStrictRedis, mock_cassandra=MockCassandraContext)
    def test_recent_configurations_constrained_by_version(self, redis=StrictRedis, cassandra=CassandraContext):
        self.init_database(redis=redis, cassandra=cassandra)
        self.register_configurations()

        configuration_to_search_for = Configuration(version='12', is_simulator=True)
        matching_configurations = self.database.search_for_recent_configuration(configuration_to_search_for)
        self.assertEqual(3, len(matching_configurations))
        for config in matching_configurations:
            self.assertEqual(configuration_to_search_for, config)

    @WaitForDockerTestCase.mock_if_no_docker(mock_redis=FakeStrictRedis, mock_cassandra=MockCassandraContext)
    def test_repopulate_recent(self, redis=StrictRedis, cassandra=CassandraContext):
        self.init_database(redis=redis, cassandra=cassandra)
        self.register_configurations()

        self.database.redis.flushdb()

        database = ConfigurationContext(redis=self.database.redis, cassandra=self.database.cassandra)
        self.assertEqual(12, len(database.search_for_recent_configuration()))

    @WaitForDockerTestCase.mock_if_no_docker(mock_redis=FakeStrictRedis, mock_cassandra=MockCassandraContext)
    def test_partition_by_configuration(self, redis=StrictRedis, cassandra=CassandraContext):
        self.init_database(redis=redis, cassandra=cassandra)
        self.register_configurations()

        class ExampleModel(ClusteredByConfiguration):
            __table_name__ = 'example_table'
            index = columns.Integer(primary_key=True, required=True)
            sdk = columns.Text(primary_key=True, required=True)
            json = columns.Text()

        with self.database:
            self.database.cassandra.create_table(ExampleModel)
            for configuration in self.CONFIGURATIONS:
                for i in range(5):
                    self.database.insert_row_with_configuration(ExampleModel.__table_name__, configuration, index=i, sdk=configuration.sdk, json=configuration.to_json())

            for configuration in self.CONFIGURATIONS:
                result = self.database.select_from_table_with_configurations(ExampleModel.__table_name__, [configuration], index=2).get(configuration, [])
                self.assertEqual(1, len(result), f'Searching by {configuration} failed, found {len(result)} elements and expected 1')
                self.assertEqual(result[0].json, configuration.to_json())

    @WaitForDockerTestCase.mock_if_no_docker(mock_redis=FakeStrictRedis, mock_cassandra=MockCassandraContext)
    def test_partition_by_partial_configuration(self, redis=StrictRedis, cassandra=CassandraContext):
        self.init_database(redis=redis, cassandra=cassandra)
        self.register_configurations()

        class ExampleModel(ClusteredByConfiguration):
            __table_name__ = 'example_table'
            index = columns.Integer(primary_key=True, required=True)
            json = columns.Text()

        with self.database:
            self.database.cassandra.create_table(ExampleModel)
            for configuration in self.CONFIGURATIONS:
                for i in range(5):
                    self.database.insert_row_with_configuration(ExampleModel.__table_name__, configuration, index=i, json=configuration.to_json())

            configuration_to_search_for = Configuration(model='iPhone Xs')
            results = self.database.select_from_table_with_configurations(ExampleModel.__table_name__, [configuration_to_search_for], index=4)
            self.assertEqual(2, len(results), f'Searching by {configuration_to_search_for} failed, found {len(results)} elements and expected 2')
            for key, value in results.items():
                self.assertEqual(Configuration.from_json(value[0].json), Configuration.from_json(key.to_json()))