from datetime import datetime from unittest.mock import Mock from fpcapture.connectors import db from fpcapture.connectors import mysql from fpcapture.logic import codegen from fpcapture.model.codegen_error import CodegenError from fpcapture.model.track_fp import TrackFp from utils import db_ops TEST_FILENAME = '\\10.10.1.2\path\to\audio.wav' TEST_TUID = 1234 TEST_UPC = 123456123456 TEST_UPLOAD_TIME = 1450454181 TEST_CORRELATION_ID = 'CORRELATION-ID-FOO' TEST_TRACK_SOURCE = 'direct_delivery' TEST_SAMPLE_RATE = 44100 TEST_DURATION = 192 TEST_SAMPLES_DECODED = 2121210 TEST_GIVEN_DURATION = 0 TEST_START_OFFSET = 0 TEST_CODEGEN_VERSION = 4.12 TEST_CODEGEN_TIME = 0.346359 TEST_DECODE_TIME = 0.519938 TEST_CODE_COUNT = 4932 TEST_CODE = "THE_REAL_CODE_WOULD_BE_A_LOT_LONGER" TEST_CODEGEN_SUCCESS = [{ "metadata": { "artist": "", "release": "", "title": "", "genre": "", "bitrate": 1411, "sample_rate": TEST_SAMPLE_RATE, "duration": TEST_DURATION, "filename": "020286121428_1_9.wav", "samples_decoded": TEST_SAMPLES_DECODED, "given_duration": 0, "start_offset": TEST_START_OFFSET, "version": TEST_CODEGEN_VERSION, "codegen_time": TEST_CODEGEN_TIME, "decode_time": TEST_DECODE_TIME }, "code_count": TEST_CODE_COUNT, "code": TEST_CODE, "tag": 0}] TEST_CODEGEN_ERROR = [{ "error": "could not decode", "tag": 0, "metadata": {"filename": TEST_FILENAME} }] def mock_run_codegen(monkeypatch, output=TEST_CODEGEN_SUCCESS): run_codegen = Mock(return_value=output) monkeypatch.setattr(codegen, 'run_codegen', run_codegen) return run_codegen def utc_upload_time(timestamp=TEST_UPLOAD_TIME): return datetime.utcfromtimestamp(timestamp) def existing_track_fp(db_session): created_dt = datetime(year=1947, month=1, day=8) fp = TrackFp() fp.tuid = TEST_TUID fp.upc = 111111111111 fp.sample_rate_hertz = 22500 fp.duration_seconds = 70 fp.filename = '\\1.2.3.4\here\is\where\the\file\goes.wav' fp.samples_decoded = 33434 fp.given_duration_seconds = 332 fp.start_offset_seconds = 999 fp.codegen_version = 'a really old version' fp.codegen_time_seconds = 1.12 fp.decode_time_seconds = 9.2 fp.code_count = 6004 fp.fingerprint = 'This is not a real fingerprint. Not at all.' fp.datetime_added_utc = created_dt fp.datetime_updated_utc = created_dt fp.created_by = 'someone@foo.theorchard.com' fp.updated_by = 'someone@foo.theorchard.com' fp.file_upload_time_utc = utc_upload_time(1418918181) fp.correlation_id = 'an-old-correlation-id' db_session.add(fp) db_session.commit() return fp def existing_codegen_error(db_session): created_dt = datetime(year=1947, month=1, day=8) ce = CodegenError() ce.tuid = TEST_TUID ce.upc = '222222333333' ce.filename = '\\1.2.3.4\something\was\wrong\with\this\file.wav' ce.error_message = 'something went horribly wrong' ce.datetime_added_utc = created_dt ce.datetime_updated_utc = created_dt ce.created_by = 'user@someone@bar.theorchard.com' ce.updated_by = 'user@someone@bar.theorchard.com' ce.file_upload_time_utc = utc_upload_time(1418831781) ce.correlation_id = 'also-an-old-correlation-id' db_session.add(ce) db_session.commit() return ce def test_encode_success(monkeypatch): """Test that encode creates a new track_fp record for the given tuid when the codegen binary runs successfully and there is no existing record with that tuid """ db_ops.create_tables() mock_run_codegen(monkeypatch) session = mysql.fpc_session() start_dt = datetime.utcnow() codegen.encode( db_session=session, filename=TEST_FILENAME, tuid=TEST_TUID, upc=TEST_UPC, file_upload_time=TEST_UPLOAD_TIME, correlation_id=TEST_CORRELATION_ID, track_source=TEST_TRACK_SOURCE) end_dt = datetime.utcnow() fp = session.query(TrackFp).first() session.close() assert fp.tuid == TEST_TUID assert fp.upc == TEST_UPC assert fp.sample_rate_hertz == TEST_SAMPLE_RATE assert fp.duration_seconds == TEST_DURATION assert fp.filename == TEST_FILENAME assert fp.samples_decoded == TEST_SAMPLES_DECODED assert fp.given_duration_seconds == TEST_GIVEN_DURATION assert fp.start_offset_seconds == TEST_START_OFFSET assert fp.codegen_version == str(TEST_CODEGEN_VERSION) assert fp.codegen_time_seconds == TEST_CODEGEN_TIME assert fp.decode_time_seconds == TEST_DECODE_TIME assert fp.code_count == TEST_CODE_COUNT assert fp.fingerprint == TEST_CODE assert start_dt <= fp.datetime_added_utc <= end_dt assert fp.created_by == db.current_user() assert start_dt <= fp.datetime_updated_utc <= end_dt assert fp.updated_by == db.current_user() assert fp.file_upload_time_utc == utc_upload_time() assert fp.correlation_id == TEST_CORRELATION_ID def test_encode_success_update(monkeypatch): """Test that codegen updates the existing track_fp when the codegen binary runs successfully and a record already exists with the given tuid """ db_ops.create_tables() mock_run_codegen(monkeypatch) session = mysql.fpc_session() existing_fp = existing_track_fp(session) start_dt = datetime.utcnow() codegen.encode( db_session=session, filename=TEST_FILENAME, tuid=TEST_TUID, upc=TEST_UPC, file_upload_time=TEST_UPLOAD_TIME, correlation_id=TEST_CORRELATION_ID, track_source=TEST_TRACK_SOURCE) end_dt = datetime.utcnow() fp = session.query(TrackFp).filter_by(tuid=TEST_TUID).first() assert fp.id == existing_fp.id assert start_dt <= fp.datetime_updated_utc <= end_dt assert fp.upc == TEST_UPC assert fp.sample_rate_hertz == TEST_SAMPLE_RATE assert fp.duration_seconds == TEST_DURATION assert fp.filename == TEST_FILENAME assert fp.samples_decoded == TEST_SAMPLES_DECODED assert fp.given_duration_seconds == TEST_GIVEN_DURATION assert fp.start_offset_seconds == TEST_START_OFFSET assert fp.codegen_version == TEST_CODEGEN_VERSION assert fp.codegen_time_seconds == TEST_CODEGEN_TIME assert fp.decode_time_seconds == TEST_DECODE_TIME assert fp.code_count == TEST_CODE_COUNT assert fp.fingerprint == TEST_CODE assert fp.updated_by == db.current_user() assert fp.file_upload_time_utc == utc_upload_time() assert fp.correlation_id == TEST_CORRELATION_ID def test_encode_error(monkeypatch): """Test that codegen creates a new codegen_error for the given tuid when the codegen binary returns an error and there is no existing record with that tuid """ db_ops.create_tables() mock_run_codegen(monkeypatch, TEST_CODEGEN_ERROR) session = mysql.fpc_session() start_dt = datetime.utcnow() codegen.encode( db_session=session, filename=TEST_FILENAME, tuid=TEST_TUID, upc=TEST_UPC, file_upload_time=TEST_UPLOAD_TIME, correlation_id=TEST_CORRELATION_ID, track_source=TEST_TRACK_SOURCE) end_dt = datetime.utcnow() ce = session.query(CodegenError).first() session.close() assert ce.tuid == TEST_TUID assert start_dt <= ce.datetime_added_utc <= end_dt assert ce.created_by == db.current_user() assert start_dt <= ce.datetime_updated_utc <= end_dt assert ce.updated_by == db.current_user() assert ce.upc == TEST_UPC assert ce.filename == TEST_FILENAME assert ce.file_upload_time_utc == utc_upload_time() assert ce.error_message == TEST_CODEGEN_ERROR[0].get('error') assert ce.correlation_id == TEST_CORRELATION_ID def test_encode_error_update(monkeypatch): """Test that codegen updates the existing codegen_error record when the codegen binary returns an error and a record already exists with that tuid """ db_ops.create_tables() mock_run_codegen(monkeypatch, TEST_CODEGEN_ERROR) session = mysql.fpc_session() existing_error = existing_codegen_error(session) start_dt = datetime.utcnow() codegen.encode( db_session=session, filename=TEST_FILENAME, tuid=TEST_TUID, upc=TEST_UPC, file_upload_time=TEST_UPLOAD_TIME, correlation_id=TEST_CORRELATION_ID, track_source=TEST_TRACK_SOURCE) end_dt = datetime.utcnow() ce = session.query(CodegenError).filter_by(tuid=TEST_TUID).first() assert ce.id == existing_error.id assert start_dt <= ce.datetime_updated_utc <= end_dt assert ce.upc == TEST_UPC assert ce.filename == TEST_FILENAME assert ce.error_message == TEST_CODEGEN_ERROR[0].get('error') assert ce.updated_by == db.current_user() assert ce.file_upload_time_utc == utc_upload_time() assert ce.correlation_id == TEST_CORRELATION_ID def test_encode_success_upc_string(monkeypatch): """Test that codegen successfully saves a UPC string to track_fp """ db_ops.create_tables() mock_run_codegen(monkeypatch) session = mysql.fpc_session() start_dt = datetime.utcnow() codegen.encode( db_session=session, filename=TEST_FILENAME, tuid=TEST_TUID, upc=str(TEST_UPC), file_upload_time=TEST_UPLOAD_TIME, correlation_id=TEST_CORRELATION_ID, track_source=TEST_TRACK_SOURCE) end_dt = datetime.utcnow() fp = session.query(TrackFp).first() session.close() assert fp.upc == TEST_UPC def test_encode_error_upc_string(monkeypatch): """Test that codegen successfully saves a UPC string to codegen_error. """ db_ops.create_tables() mock_run_codegen(monkeypatch, TEST_CODEGEN_ERROR) session = mysql.fpc_session() start_dt = datetime.utcnow() codegen.encode( db_session=session, filename=TEST_FILENAME, tuid=TEST_TUID, upc=str(TEST_UPC), file_upload_time=TEST_UPLOAD_TIME, correlation_id=TEST_CORRELATION_ID, track_source=TEST_TRACK_SOURCE) end_dt = datetime.utcnow() ce = session.query(CodegenError).first() session.close() assert ce.upc == TEST_UPC