/** * test_fgla.c - Unit tests for fgla utility functions * * Copyright (C) 2025 https://optics-design.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. */ #include "../test_framework.h" #include "../../include/glautils/fgla.h" // Test string validation int test_search_term_validation() { TEST_START("Search Term Validation"); // Valid search terms TEST_ASSERT(fgla_validate_search_term("BK7"), "BK7 should be valid"); TEST_ASSERT(fgla_validate_search_term("N-SF6"), "N-SF6 should be valid"); TEST_ASSERT(fgla_validate_search_term("517642"), "517642 should be valid"); TEST_ASSERT(fgla_validate_search_term("51x64x"), "51x64x should be valid"); TEST_ASSERT(fgla_validate_search_term("FK51A"), "FK51A should be valid"); // Invalid search terms TEST_ASSERT(!fgla_validate_search_term(NULL), "NULL should be invalid"); TEST_ASSERT(!fgla_validate_search_term(""), "Empty string should be invalid"); TEST_ASSERT(!fgla_validate_search_term("test@#$"), "Special characters should be invalid"); TEST_ASSERT(!fgla_validate_search_term("test|pipe"), "Pipe character should be invalid"); // Test boundary conditions char long_term[300]; memset(long_term, 'A', sizeof(long_term) - 1); long_term[sizeof(long_term) - 1] = '\0'; TEST_ASSERT(!fgla_validate_search_term(long_term), "Overly long term should be invalid"); TEST_END(); } // Test glass code pattern recognition int test_glass_code_pattern() { TEST_START("Glass Code Pattern Recognition"); // Valid glass code patterns TEST_ASSERT(fgla_is_glass_code_pattern("517642"), "517642 should be glass code pattern"); TEST_ASSERT(fgla_is_glass_code_pattern("123456"), "123456 should be glass code pattern"); TEST_ASSERT(fgla_is_glass_code_pattern("51x64x"), "51x64x should be glass code pattern"); TEST_ASSERT(fgla_is_glass_code_pattern("x12345"), "x12345 should be glass code pattern"); TEST_ASSERT(fgla_is_glass_code_pattern("xxxxxx"), "xxxxxx should be glass code pattern"); // Invalid patterns TEST_ASSERT(!fgla_is_glass_code_pattern("51764"), "51764 (5 digits) should not be glass code pattern"); TEST_ASSERT(!fgla_is_glass_code_pattern("5176420"), "5176420 (7 digits) should not be glass code pattern"); TEST_ASSERT(!fgla_is_glass_code_pattern("BK7123"), "BK7123 (letters) should not be glass code pattern"); TEST_ASSERT(!fgla_is_glass_code_pattern("51-642"), "51-642 (dash) should not be glass code pattern"); TEST_ASSERT(!fgla_is_glass_code_pattern(NULL), "NULL should not be glass code pattern"); TEST_END(); } // Test glass code pattern matching int test_glass_code_matching() { TEST_START("Glass Code Pattern Matching"); // Exact matches TEST_ASSERT(fgla_matches_glass_code_pattern_safe("517642", "517642"), "Exact match should work"); // Wildcard matches TEST_ASSERT(fgla_matches_glass_code_pattern_safe("517642", "51x64x"), "Wildcard pattern should match"); TEST_ASSERT(fgla_matches_glass_code_pattern_safe("517642", "x17642"), "Leading wildcard should match"); TEST_ASSERT(fgla_matches_glass_code_pattern_safe("517642", "51764x"), "Trailing wildcard should match"); // Non-matches TEST_ASSERT(!fgla_matches_glass_code_pattern_safe("517642", "518642"), "Different digit should not match"); TEST_ASSERT(!fgla_matches_glass_code_pattern_safe("517642", "51x63x"), "Wrong wildcard pattern should not match"); // Handle longer glass codes (should extract first 6 digits) TEST_ASSERT(fgla_matches_glass_code_pattern_safe("5176420123", "517642"), "Should match first 6 digits of longer code"); // Edge cases TEST_ASSERT(!fgla_matches_glass_code_pattern_safe(NULL, "517642"), "NULL glass code should not match"); TEST_ASSERT(!fgla_matches_glass_code_pattern_safe("517642", NULL), "NULL pattern should not match"); TEST_END(); } // Test string normalization int test_string_normalization() { TEST_START("String Normalization"); char output[100]; // Test basic normalization int result = fgla_normalize_string_safe("N-BK7", output, sizeof(output)); TEST_ASSERT_EQ(0, result, "Normalization should succeed"); TEST_ASSERT_STR_EQ("nbk7", output, "Should remove dash and convert to lowercase"); // Test with multiple dashes result = fgla_normalize_string_safe("N-SF-6", output, sizeof(output)); TEST_ASSERT_EQ(0, result, "Multi-dash normalization should succeed"); TEST_ASSERT_STR_EQ("nsf6", output, "Should remove all dashes"); // Test with no dashes result = fgla_normalize_string_safe("BK7", output, sizeof(output)); TEST_ASSERT_EQ(0, result, "No-dash normalization should succeed"); TEST_ASSERT_STR_EQ("bk7", output, "Should just convert to lowercase"); // Test error conditions result = fgla_normalize_string_safe(NULL, output, sizeof(output)); TEST_ASSERT_EQ(-1, result, "NULL input should return error"); result = fgla_normalize_string_safe("test", NULL, sizeof(output)); TEST_ASSERT_EQ(-1, result, "NULL output should return error"); result = fgla_normalize_string_safe("test", output, 0); TEST_ASSERT_EQ(-1, result, "Zero-size output should return error"); TEST_END(); } // Test substring search int test_substring_search() { TEST_START("Substring Search"); // Case-insensitive search TEST_ASSERT(fgla_contains_substring_safe("N-BK7", "bk"), "Should find 'bk' in 'N-BK7' (case insensitive)"); TEST_ASSERT(fgla_contains_substring_safe("N-BK7", "BK"), "Should find 'BK' in 'N-BK7'"); // Dash-insensitive search TEST_ASSERT(fgla_contains_substring_safe("N-BK7", "nbk"), "Should find 'nbk' in 'N-BK7' (dash insensitive)"); TEST_ASSERT(fgla_contains_substring_safe("NBK7", "n-bk"), "Should find 'n-bk' in 'NBK7' (dash insensitive)"); // Non-matches TEST_ASSERT(!fgla_contains_substring_safe("N-BK7", "sf"), "Should not find 'sf' in 'N-BK7'"); // Edge cases TEST_ASSERT(!fgla_contains_substring_safe(NULL, "test"), "NULL haystack should return false"); TEST_ASSERT(!fgla_contains_substring_safe("test", NULL), "NULL needle should return false"); TEST_ASSERT(!fgla_contains_substring_safe("", "test"), "Empty haystack should return false"); TEST_ASSERT(!fgla_contains_substring_safe("test", ""), "Empty needle should return false"); TEST_END(); } // Test catalog matching int test_catalog_matching() { TEST_START("Catalog Matching"); const char* catalogs[] = {"SCHOTT", "HOYA", "CDGM"}; // Should match TEST_ASSERT(fgla_matches_catalog("SCHOTT", catalogs, 3), "Should match SCHOTT"); TEST_ASSERT(fgla_matches_catalog("schott", catalogs, 3), "Should match schott (case insensitive)"); TEST_ASSERT(fgla_matches_catalog("HOYA", catalogs, 3), "Should match HOYA"); // Should not match TEST_ASSERT(!fgla_matches_catalog("Ohara", catalogs, 3), "Should not match Ohara (not in list)"); // Empty catalog list should match all TEST_ASSERT(fgla_matches_catalog("SCHOTT", NULL, 0), "Empty catalog list should match anything"); TEST_ASSERT(fgla_matches_catalog("Unknown", NULL, 0), "Empty catalog list should match anything"); TEST_END(); } // Test lowercase conversion int test_lowercase_conversion() { TEST_START("Lowercase Conversion"); char test_str[20]; // Test normal case strcpy(test_str, "BK7"); fgla_to_lowercase_safe(test_str, sizeof(test_str)); TEST_ASSERT_STR_EQ("bk7", test_str, "Should convert BK7 to bk7"); // Test mixed case strcpy(test_str, "N-SF6"); fgla_to_lowercase_safe(test_str, sizeof(test_str)); TEST_ASSERT_STR_EQ("n-sf6", test_str, "Should convert N-SF6 to n-sf6"); // Test already lowercase strcpy(test_str, "already"); fgla_to_lowercase_safe(test_str, sizeof(test_str)); TEST_ASSERT_STR_EQ("already", test_str, "Should not change already lowercase"); // Test with NULL (should not crash) fgla_to_lowercase_safe(NULL, 10); // Should not crash TEST_END(); } // Main test runner int main() { printf(BLUE "=== FGLA Utility Unit Tests ===" RESET "\n\n"); RUN_TEST(test_search_term_validation); RUN_TEST(test_glass_code_pattern); RUN_TEST(test_glass_code_matching); RUN_TEST(test_string_normalization); RUN_TEST(test_substring_search); RUN_TEST(test_catalog_matching); RUN_TEST(test_lowercase_conversion); TEST_SUMMARY(); }