"""The installed-software snapshot table: it must actually accept inserts. This table is rewritten wholesale on every endpoint check-in - delete the asset's rows, insert the current inventory - so its surrogate key climbs at (endpoints x installed apps) per report and never reuses a value. On MySQL a 32-bit key exhausts and inserts stop working permanently. Widening it to BigInteger broke every insert on SQLite, because SQLite only autoincrements a column typed exactly INTEGER PRIMARY KEY. Neither fault was caught by the suite, for the same reason: nothing inserted into this table at all. This does. """ from shopdb.api import db from plugins.endpoints.models.endpoint import EndpointApplication def test_rows_insert_and_the_key_autoincrements(app): with app.app_context(): db.create_all() first = EndpointApplication(assetid=1, displayname='Probe', displayversion='1.0') second = EndpointApplication(assetid=1, displayname='Probe 2', displayversion='2.0') db.session.add_all([first, second]) db.session.commit() assert first.endpointapplicationid is not None assert second.endpointapplicationid is not None assert second.endpointapplicationid != first.endpointapplicationid def test_the_key_is_wide_enough_for_a_table_that_is_rewritten_every_cycle(app): """BIGINT on MySQL, INTEGER on SQLite - both halves matter. Dropping the variant breaks SQLite inserts; dropping the BigInteger breaks MySQL years later, which is worse because it is silent until it is not. """ from sqlalchemy.dialects import mysql, sqlite with app.app_context(): column = EndpointApplication.__table__.c.endpointapplicationid assert 'BIGINT' in str(column.type.compile(dialect=mysql.dialect())) assert 'INTEGER' in str(column.type.compile(dialect=sqlite.dialect())) def test_over_long_registry_values_are_clamped_not_fatal(app): """One malformed Uninstall entry must not cost the whole check-in. On MySQL in strict mode an over-long value raises Data too long and fails the transaction, taking telemetry and events down with it - so that endpoint goes silent until somebody uninstalls the offending program. SQLite does not enforce declared lengths, so the suite would never have shown it. """ from plugins.endpoints.plugin import EndpointsPlugin with app.app_context(): db.create_all() warnings = [] stored = EndpointsPlugin()._replace_applications( assetid=4242, applications=[{ 'displayname': 'A' * 400, 'displayversion': 'V' * 400, 'publisher': 'P' * 400, }], warnings=warnings, ) db.session.commit() assert stored == 1 row = EndpointApplication.query.filter_by(assetid=4242).one() assert len(row.displayname) == 255 assert len(row.displayversion) == 128 assert len(row.publisher) == 255 def test_a_blank_value_becomes_null_rather_than_an_empty_string(app): from plugins.endpoints.plugin import EndpointsPlugin with app.app_context(): db.create_all() EndpointsPlugin()._replace_applications( assetid=4243, applications=[{'displayname': 'Thing', 'publisher': ' '}], warnings=[], ) db.session.commit() row = EndpointApplication.query.filter_by(assetid=4243).one() assert row.publisher is None