import subprocess
import json
import csv
import os
import tempfile
import pytest
from pathlib import Path
PROJECT_ROOT = Path(__file__).parent.parent.parent
SQL_CLI = PROJECT_ROOT / "target" / "release" / "sql-cli"
if not SQL_CLI.exists():
SQL_CLI = PROJECT_ROOT / "target" / "debug" / "sql-cli"
def run_query(csv_file, query):
cmd = [str(SQL_CLI), csv_file, "-q", query, "-o", "json"]
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
raise Exception(f"Query failed: {result.stderr}")
lines = result.stdout.strip().split('\n')
json_lines = [l for l in lines if not l.startswith('#')]
if not json_lines:
return []
return json.loads(''.join(json_lines))
class TestMolecularFormulas:
@classmethod
def setup_class(cls):
cls.temp_dir = tempfile.mkdtemp()
cls.test_file = os.path.join(cls.temp_dir, "test.csv")
with open(cls.test_file, 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow(['id'])
writer.writerow([1])
def test_simple_molecules(self):
result = run_query(self.test_file,
"SELECT ATOMIC_MASS('H2O') as water, "
"ATOMIC_MASS('CO2') as carbon_dioxide, "
"ATOMIC_MASS('NH3') as ammonia FROM test")
assert len(result) == 1
assert abs(result[0]['water'] - 18.016) < 0.01
assert abs(result[0]['carbon_dioxide'] - 44.01) < 0.01
assert abs(result[0]['ammonia'] - 17.034) < 0.01
def test_complex_molecules(self):
result = run_query(self.test_file,
"SELECT ATOMIC_MASS('Ca(OH)2') as calcium_hydroxide, "
"ATOMIC_MASS('Mg(NO3)2') as magnesium_nitrate FROM test")
assert len(result) == 1
assert abs(result[0]['calcium_hydroxide'] - 74.096) < 0.01
assert abs(result[0]['magnesium_nitrate'] - 148.33) < 0.01
def test_organic_molecules(self):
result = run_query(self.test_file,
"SELECT ATOMIC_MASS('C6H12O6') as glucose, "
"ATOMIC_MASS('C2H5OH') as ethanol, "
"ATOMIC_MASS('CH3COOH') as acetic_acid FROM test")
assert len(result) == 1
assert abs(result[0]['glucose'] - 180.156) < 0.01
assert abs(result[0]['ethanol'] - 46.068) < 0.01
assert abs(result[0]['acetic_acid'] - 60.052) < 0.01
def test_compound_aliases(self):
result = run_query(self.test_file,
"SELECT ATOMIC_MASS('water') as water, "
"ATOMIC_MASS('WATER') as water_upper, "
"ATOMIC_MASS('glucose') as glucose, "
"ATOMIC_MASS('salt') as salt, "
"ATOMIC_MASS('ammonia') as ammonia FROM test")
assert len(result) == 1
assert abs(result[0]['water'] - 18.016) < 0.01
assert abs(result[0]['water_upper'] - 18.016) < 0.01
assert abs(result[0]['glucose'] - 180.156) < 0.01
assert abs(result[0]['salt'] - 58.44) < 0.01
assert abs(result[0]['ammonia'] - 17.034) < 0.01
def test_acid_aliases(self):
result = run_query(self.test_file,
"SELECT ATOMIC_MASS('sulfuric acid') as h2so4, "
"ATOMIC_MASS('hydrochloric acid') as hcl, "
"ATOMIC_MASS('nitric acid') as hno3 FROM test")
assert len(result) == 1
assert abs(result[0]['h2so4'] - 98.086) < 0.01
assert abs(result[0]['hcl'] - 36.458) < 0.01
assert abs(result[0]['hno3'] - 63.018) < 0.01
def test_single_elements_still_work(self):
result = run_query(self.test_file,
"SELECT ATOMIC_MASS('H') as hydrogen, "
"ATOMIC_MASS('C') as carbon, "
"ATOMIC_MASS('O') as oxygen, "
"ATOMIC_MASS('Gold') as gold FROM test")
assert len(result) == 1
assert abs(result[0]['hydrogen'] - 1.008) < 0.01
assert abs(result[0]['carbon'] - 12.01) < 0.01
assert abs(result[0]['oxygen'] - 16.00) < 0.01
assert abs(result[0]['gold'] - 196.97) < 0.01
def test_hydrates(self):
pass
class TestMolecularFormulaEdgeCases:
@classmethod
def setup_class(cls):
cls.temp_dir = tempfile.mkdtemp()
cls.test_file = os.path.join(cls.temp_dir, "test.csv")
with open(cls.test_file, 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow(['id'])
writer.writerow([1])
def test_no_number_means_one(self):
result = run_query(self.test_file,
"SELECT ATOMIC_MASS('HCl') as hcl, "
"ATOMIC_MASS('NaCl') as nacl FROM test")
assert len(result) == 1
assert abs(result[0]['hcl'] - 36.458) < 0.01
assert abs(result[0]['nacl'] - 58.44) < 0.01
def test_multi_digit_numbers(self):
result = run_query(self.test_file,
"SELECT ATOMIC_MASS('C12H22O11') as sucrose FROM test")
assert len(result) == 1
assert abs(result[0]['sucrose'] - 342.296) < 0.1
def test_nested_parentheses(self):
pass
if __name__ == "__main__":
pytest.main([__file__, "-v"])