def test_init_validation_raises(some_paramspecbases): (ps1, ps2, ps3, ps4) = some_paramspecbases # First test validation of trees invalid in their own right invalid_trees = ([ps1, ps2], { 'ps1': 'ps2' }, { ps1: 'ps2' }, { ps1: ('ps2', ) }, { ps1: (ps2, ), ps2: (ps1, ) }) causes = ("ParamSpecTree must be a dict", "ParamSpecTree must have ParamSpecs as keys", "ParamSpecTree must have tuple values", "ParamSpecTree can only have tuples " "of ParamSpecs as values", "ParamSpecTree can not have cycles") for tree, cause in zip(invalid_trees, causes): with pytest.raises(ValueError, match='Invalid dependencies') as ei: InterDependencies_(dependencies=tree, inferences={}) assert error_caused_by(ei, cause=cause) for tree, cause in zip(invalid_trees, causes): with pytest.raises(ValueError, match='Invalid inferences') as ei: InterDependencies_(dependencies={}, inferences=tree) assert error_caused_by(ei, cause=cause) with pytest.raises(ValueError, match='Invalid standalones') as ei: InterDependencies_(standalones=('ps1', 'ps2')) assert error_caused_by(ei, cause='Standalones must be a sequence of ' 'ParamSpecs') # Now test trees that are invalid together invalid_trees = [{'deps': {ps1: (ps2, ps3)}, 'inffs': {ps2: (ps4, ps1)}}] for inv in invalid_trees: with pytest.raises(ValueError, match=re.escape("Invalid dependencies/inferences")): InterDependencies_(dependencies=inv['deps'], inferences=inv['inffs'])
def test_metadata(experiment, request): metadata1 = {'number': 1, "string": "Once upon a time..."} metadata2 = {'more': 'meta'} ds1 = DataSet(metadata=metadata1) request.addfinalizer(ds1.conn.close) ds2 = DataSet(metadata=metadata2) request.addfinalizer(ds2.conn.close) assert ds1.run_id == 1 assert ds1.metadata == metadata1 assert ds2.run_id == 2 assert ds2.metadata == metadata2 loaded_ds1 = DataSet(run_id=1) request.addfinalizer(loaded_ds1.conn.close) assert loaded_ds1.metadata == metadata1 loaded_ds2 = DataSet(run_id=2) request.addfinalizer(loaded_ds2.conn.close) assert loaded_ds2.metadata == metadata2 badtag = 'lex luthor' sorry_metadata = {'superman': 1, badtag: None, 'spiderman': 'two'} bad_tag_msg = (f'Tag {badtag} has value None. ' ' That is not a valid metadata value!') with pytest.raises(RuntimeError, match='Rolling back due to unhandled exception') as e: for tag, value in sorry_metadata.items(): ds1.add_metadata(tag, value) assert error_caused_by(e, bad_tag_msg)
def test_perform_actual_upgrade_2_to_3_empty(): v2fixpath = os.path.join(fixturepath, 'db_files', 'version2') dbname_old = os.path.join(v2fixpath, 'empty.db') if not os.path.exists(dbname_old): pytest.skip("No db-file fixtures found. You can generate test db-files" " using the scripts in the " "https://github.com/QCoDeS/qcodes_generate_test_db/ repo") with temporarily_copied_DB(dbname_old, debug=False, version=2) as conn: assert get_user_version(conn) == 2 desc_query = 'SELECT run_description FROM runs' with pytest.raises(RuntimeError) as excinfo: atomic_transaction(conn, desc_query) assert error_caused_by(excinfo, 'no such column: run_description') perform_db_upgrade_2_to_3(conn) assert get_user_version(conn) == 3 c = atomic_transaction(conn, desc_query) assert len(c.fetchall()) == 0
def test_perform_actual_upgrade_0_to_1(): # we cannot use the empty_temp_db, since that has already called connect # and is therefore latest version already v0fixpath = os.path.join(fixturepath, 'db_files', 'version0') dbname_old = os.path.join(v0fixpath, 'empty.db') if not os.path.exists(dbname_old): pytest.skip("No db-file fixtures found. You can generate test db-files" " using the scripts in the " "https://github.com/QCoDeS/qcodes_generate_test_db/ repo") with temporarily_copied_DB(dbname_old, debug=False, version=0) as conn: assert get_user_version(conn) == 0 guid_table_query = "SELECT guid FROM runs" with pytest.raises(RuntimeError) as excinfo: atomic_transaction(conn, guid_table_query) assert error_caused_by(excinfo, 'no such column: guid') perform_db_upgrade_0_to_1(conn) assert get_user_version(conn) == 1 c = atomic_transaction(conn, guid_table_query) assert len(c.fetchall()) == 0
def test_atomic_raises(experiment): conn = experiment.conn bad_sql = '""' with pytest.raises(RuntimeError) as excinfo: with mut_conn.atomic(conn): mut_conn.transaction(conn, bad_sql) assert error_caused_by(excinfo, "syntax error")
def test_atomic_creation(experiment): """" Test that dataset creation is atomic. Test for https://github.com/QCoDeS/Qcodes/issues/1444 """ def just_throw(*args): raise RuntimeError("This breaks adding metadata") # first we patch add_data_to_dynamic_columns to throw an exception # if create_data is not atomic this would create a partial # run in the db. Causing the next create_run to fail with patch("qcodes.dataset.sqlite.queries.add_data_to_dynamic_columns", new=just_throw): x = ParamSpec("x", "numeric") t = ParamSpec("t", "numeric") y = ParamSpec("y", "numeric", depends_on=["x", "t"]) with pytest.raises( RuntimeError, match="Rolling back due to unhandled exception") as e: mut_queries.create_run( experiment.conn, experiment.exp_id, name="testrun", guid=generate_guid(), parameters=[x, t, y], metadata={"a": 1}, ) assert error_caused_by(e, "This breaks adding metadata") # since we are starting from an empty database and the above transaction # should be rolled back there should be no runs in the run table runs = mut_conn.transaction(experiment.conn, 'SELECT run_id FROM runs').fetchall() assert len(runs) == 0 with shadow_conn(experiment.path_to_db) as new_conn: runs = mut_conn.transaction(new_conn, 'SELECT run_id FROM runs').fetchall() assert len(runs) == 0 # if the above was not correctly rolled back we # expect the next creation of a run to fail mut_queries.create_run(experiment.conn, experiment.exp_id, name='testrun', guid=generate_guid(), parameters=[x, t, y], metadata={'a': 1}) runs = mut_conn.transaction(experiment.conn, 'SELECT run_id FROM runs').fetchall() assert len(runs) == 1 with shadow_conn(experiment.path_to_db) as new_conn: runs = mut_conn.transaction(new_conn, 'SELECT run_id FROM runs').fetchall() assert len(runs) == 1
def test_metadata(experiment, request): metadata1 = {'number': 1, "string": "Once upon a time..."} metadata2 = {'more': 'meta'} ds1 = DataSet(metadata=metadata1) request.addfinalizer(ds1.conn.close) ds2 = DataSet(metadata=metadata2) request.addfinalizer(ds2.conn.close) assert ds1.run_id == 1 assert ds1.metadata == metadata1 assert ds2.run_id == 2 assert ds2.metadata == metadata2 loaded_ds1 = DataSet(run_id=1) request.addfinalizer(loaded_ds1.conn.close) assert loaded_ds1.metadata == metadata1 loaded_ds2 = DataSet(run_id=2) request.addfinalizer(loaded_ds2.conn.close) assert loaded_ds2.metadata == metadata2 bad_tag = "lex luthor" bad_tag_msg = (f"Tag {bad_tag} is not a valid tag. " "Use only alphanumeric characters and underscores!") with pytest.raises(RuntimeError, match="Rolling back due to unhandled exception") as e1: ds1.add_metadata(bad_tag, "value") assert error_caused_by(e1, bad_tag_msg) good_tag = "tag" none_value_msg = (f"Tag {good_tag} has value None. " "That is not a valid metadata value!") with pytest.raises(RuntimeError, match="Rolling back due to unhandled exception") as e2: ds1.add_metadata(good_tag, None) assert error_caused_by(e2, none_value_msg)
def test_wrong_address(): wrong_address = 'GPIB::2::INSTR' match_str = re.escape(f'ERROR: resource {wrong_address} not found') with pytest.raises(Exception, match=match_str) as exc_info: _ = Keysight_34465A('keysight_34465A_sim', address=wrong_address, visalib=visalib) assert error_caused_by(exc_info, wrong_address) right_address = 'GPIB::1::INSTR' # from the simulation yaml file _ = Keysight_34465A('keysight_34465A_sim', address=right_address, visalib=visalib)
def test_atomic_with_exception(): sqlite_conn = sqlite3.connect(':memory:') conn_plus = ConnectionPlus(sqlite_conn) sqlite_conn.execute('PRAGMA user_version(25)') sqlite_conn.commit() assert 25 == sqlite_conn.execute('PRAGMA user_version').fetchall()[0][0] with pytest.raises(RuntimeError, match="Rolling back due to unhandled exception") as e: with atomic(conn_plus) as atomic_conn: atomic_conn.execute('PRAGMA user_version(42)') raise Exception('intended exception') assert error_caused_by(e, 'intended exception') assert 25 == sqlite_conn.execute('PRAGMA user_version').fetchall()[0][0]
def test_set_run_timestamp(dataset): assert dataset.run_timestamp_raw is None assert dataset.completed_timestamp_raw is None time_now = time.time() time.sleep(1) # for slower test platforms mut_queries.set_run_timestamp(dataset.conn, dataset.run_id) assert dataset.run_timestamp_raw > time_now assert dataset.completed_timestamp_raw is None with pytest.raises(RuntimeError, match="Rolling back due to unhandled " "exception") as ei: mut_queries.set_run_timestamp(dataset.conn, dataset.run_id) assert error_caused_by(ei, ("Can not set run_timestamp; it has already " "been set"))
def test_set_run_timestamp(experiment): ds = DataSet() assert ds.run_timestamp_raw is None time_now = time.time() time.sleep(1) # for slower test platforms mut_queries.set_run_timestamp(ds.conn, ds.run_id) assert ds.run_timestamp_raw > time_now with pytest.raises(RuntimeError, match="Rolling back due to unhandled " "exception") as ei: mut_queries.set_run_timestamp(ds.conn, ds.run_id) assert error_caused_by(ei, ("Can not set run_timestamp; it has already " "been set")) ds.conn.close()
def test_get_metadata_raises(experiment): with pytest.raises(RuntimeError) as excinfo: mut_queries.get_metadata(experiment.conn, 'something', 'results') assert error_caused_by(excinfo, "no such column: something")
def test_basic_extraction(two_empty_temp_db_connections, some_paramspecs): source_conn, target_conn = two_empty_temp_db_connections source_path = path_to_dbfile(source_conn) target_path = path_to_dbfile(target_conn) type_casters = {'numeric': float, 'array': (lambda x: np.array(x) if hasattr(x, '__iter__') else np.array([x])), 'text': str} source_exp = Experiment(conn=source_conn) source_dataset = DataSet(conn=source_conn, name="basic_copy_paste_name") with pytest.raises(RuntimeError) as excinfo: extract_runs_into_db(source_path, target_path, source_dataset.run_id) assert error_caused_by(excinfo, ('Dataset not completed. An incomplete ' 'dataset can not be copied. The ' 'incomplete dataset has GUID: ' f'{source_dataset.guid} and run_id: ' f'{source_dataset.run_id}')) for ps in some_paramspecs[1].values(): source_dataset.add_parameter(ps) for value in range(10): result = {ps.name: type_casters[ps.type](value) for ps in some_paramspecs[1].values()} source_dataset.add_result(result) source_dataset.add_metadata('goodness', 'fair') source_dataset.add_metadata('test', True) source_dataset.mark_complete() extract_runs_into_db(source_path, target_path, source_dataset.run_id) target_exp = Experiment(conn=target_conn, exp_id=1) length1 = len(target_exp) assert length1 == 1 # trying to insert the same run again should be a NOOP with raise_if_file_changed(target_path): extract_runs_into_db(source_path, target_path, source_dataset.run_id) assert len(target_exp) == length1 target_dataset = DataSet(conn=target_conn, run_id=1) # Now make the interesting comparisons: are the target objects the same as # the source objects? assert source_dataset.the_same_dataset_as(target_dataset) source_data = source_dataset.get_data(*source_dataset.parameters.split(',')) target_data = target_dataset.get_data(*target_dataset.parameters.split(',')) assert source_data == target_data exp_attrs = ['name', 'sample_name', 'format_string', 'started_at', 'finished_at'] for exp_attr in exp_attrs: assert getattr(source_exp, exp_attr) == getattr(target_exp, exp_attr) # trying to insert the same run again should be a NOOP with raise_if_file_changed(target_path): extract_runs_into_db(source_path, target_path, source_dataset.run_id)
def test_get_nonexisting_metadata(dataset): with pytest.raises(RuntimeError) as excinfo: _ = dataset.get_metadata('something') assert error_caused_by(excinfo, "no such column: something")