""" Unit tests for GOID Generator """ import unittest import sys import os # Add parent directory to path sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from goid_generator import GOIDGenerator, generate_goid, validate_goid, parse_goid class TestGOIDGenerator(unittest.TestCase): """Test cases for GOID generation and validation""" def setUp(self): """Set up test fixtures""" self.gen = GOIDGenerator() def test_generate_basic(self): """Test basic GOID generation""" goid = self.gen.generate('BYG', 'FAC', 'WIN', 'GLA') self.assertTrue(goid.startswith('BYG-FAC-WIN-GLA-')) self.assertEqual(len(goid.split('-')), 5) def test_generate_sequence(self): """Test sequence incrementing""" goid1 = self.gen.generate('BYG', 'FAC', 'WIN', 'GLA') goid2 = self.gen.generate('BYG', 'FAC', 'WIN', 'GLA') seq1 = int(goid1.split('-')[-1]) seq2 = int(goid2.split('-')[-1]) self.assertEqual(seq2, seq1 + 1) def test_generate_with_location(self): """Test GOID generation with location hash""" goid = self.gen.generate('BYG', 'FAC', 'WIN', 'GLA', location_hash='59.3293,18.0686') parts = goid.split('-') self.assertEqual(len(parts), 6) self.assertEqual(len(parts[5]), 4) def test_validate_valid(self): """Test validation of valid GOIDs""" valid_goids = [ 'BYG-FAC-WIN-GLA-0001', 'BYG-FAC-WIN-GLA-9999', 'ENE-EVC-CHA-LED-0001-ABCD', 'TRN-BRG-ABT-CON-0001' ] for goid in valid_goids: is_valid, error = self.gen.validate(goid) self.assertTrue(is_valid, f"Expected {goid} to be valid, got error: {error}") def test_validate_invalid(self): """Test validation of invalid GOIDs""" invalid_goids = [ ('', "empty"), ('BYG', "too few parts"), ('BYG-FAC-WIN-GLA', "missing sequence"), ('BYG-FAC-WIN-GLA-0', "sequence too low"), ('byg-fac-win-gla-0001', "lowercase"), ('BYG-FAC-WIN-GLA-ABC', "non-numeric sequence"), ('BYG-FAC-WIN-GLA-0001-ABCDE', "hash too long"), ('BYG-FAC-WIN-GLA-0001-ABCD-EXTRA', "too many parts"), ] for goid, description in invalid_goids: is_valid, error = self.gen.validate(goid) self.assertFalse(is_valid, f"Expected {description} ({goid}) to be invalid") def test_parse_valid(self): """Test parsing valid GOID""" goid = 'BYG-FAC-WIN-GLA-0001' parsed = self.gen.parse(goid) self.assertEqual(parsed['domain'], 'BYG') self.assertEqual(parsed['system'], 'FAC') self.assertEqual(parsed['subsystem'], 'WIN') self.assertEqual(parsed['obj_type'], 'GLA') self.assertEqual(parsed['sequence'], 1) self.assertIsNone(parsed['location_hash']) def test_parse_with_location(self): """Test parsing GOID with location hash""" goid = 'BYG-FAC-WIN-GLA-0001-ABCD' parsed = self.gen.parse(goid) self.assertEqual(parsed['location_hash'], 'ABCD') def test_parse_invalid(self): """Test parsing invalid GOID raises error""" with self.assertRaises(ValueError): self.gen.parse('INVALID') def test_validate_codes(self): """Test that invalid codes raise errors""" with self.assertRaises(ValueError): self.gen.generate('XXX', 'FAC', 'WIN', 'GLA') with self.assertRaises(ValueError): self.gen.generate('BYG', 'XXX', 'WIN', 'GLA') def test_list_domains(self): """Test listing domains""" domains = self.gen.list_domains() self.assertGreater(len(domains), 0) domain_codes = [d['code'] for d in domains] self.assertIn('BYG', domain_codes) self.assertIn('ENE', domain_codes) def test_list_systems(self): """Test listing systems""" systems = self.gen.list_systems('BYG') self.assertGreater(len(systems), 0) system_codes = [s['code'] for s in systems] self.assertIn('FAC', system_codes) def test_list_objects(self): """Test listing objects""" objects = self.gen.list_objects('BYG', 'FAC') self.assertGreater(len(objects), 0) object_codes = [o['code'] for o in objects] self.assertIn('WIN', object_codes) def test_convenience_functions(self): """Test convenience functions""" goid = generate_goid('BYG', 'FAC', 'WIN', 'GLA') self.assertTrue(goid.startswith('BYG-FAC-WIN-GLA-')) is_valid, error = validate_goid(goid) self.assertTrue(is_valid) parsed = parse_goid(goid) self.assertEqual(parsed['domain'], 'BYG') class TestTaxonomyValidation(unittest.TestCase): """Test taxonomy-specific validation""" def setUp(self): self.gen = GOIDGenerator() def test_all_domains(self): """Test that all domains can generate GOIDs""" domains = self.gen.list_domains() for domain in domains: systems = self.gen.list_systems(domain['code']) for system in systems: objects = self.gen.list_objects(domain['code'], system['code']) for obj in objects: # Generate GOID for first component or object itself obj_type = obj['components'][0] if obj['components'] else obj['code'] goid = self.gen.generate(domain['code'], system['code'], obj['code'], obj_type) is_valid, error = self.gen.validate(goid) self.assertTrue(is_valid, f"Failed for {domain['code']}-{system['code']}-{obj['code']}: {error}") def test_component_types(self): """Test generating GOIDs for component types""" # Window glass goid = self.gen.generate('BYG', 'FAC', 'WIN', 'GLA') self.assertTrue(goid.startswith('BYG-FAC-WIN-GLA-')) # Window frame goid = self.gen.generate('BYG', 'FAC', 'WIN', 'FRM') self.assertTrue(goid.startswith('BYG-FAC-WIN-FRM-')) def test_known_examples(self): """Test known examples from spec""" examples = [ ('BYG', 'FAC', 'WIN', 'GLA', 'BYG-FAC-WIN-GLA-0001'), ('ENE', 'EVC', 'CHA', 'FND', 'ENE-EVC-CHA-FND-0001'), ('TRN', 'BRG', 'ABT', 'FND', 'TRN-BRG-ABT-FND-0001'), ] for domain, system, subsystem, obj_type, expected_prefix in examples: goid = self.gen.generate(domain, system, subsystem, obj_type) self.assertTrue(goid.startswith(expected_prefix.rsplit('-', 1)[0])) if __name__ == '__main__': # Run with verbose output unittest.main(verbosity=2)