Class CharacteristicUtilsUriMigrationTest

java.lang.Object
ubic.gemma.model.common.description.CharacteristicUtilsUriMigrationTest

public class CharacteristicUtilsUriMigrationTest extends Object
Pins the read-time URI canonicaliser — the stand-in for the parked database migration (scripts/sql/term_uri_migration.sql).

The point of these tests is that the shim is not inert. A mapping table that loads to zero rows, or a resource that silently fails to parse, looks exactly like a corpus with no duplicates in it — so "it compiles" is not evidence that anything is being resolved.

  • Constructor Details

    • CharacteristicUtilsUriMigrationTest

      public CharacteristicUtilsUriMigrationTest()
  • Method Details

    • testTheMappingResourceActuallyLoads

      @Test public void testTheMappingResourceActuallyLoads()
    • testCloTwinResolvesToTheKeptTerm

      @Test public void testCloTwinResolvesToTheKeptTerm()
      A CLO twin: the retired spelling resolves to the one we keep, and the label follows.
    • testBareCurieExpandsToAnIri

      @Test public void testBareCurieExpandsToAnIri()
      A bare CURIE is not an IRI; it expands to the OBO form.
    • testColonFormIsRepairedToUnderscore

      @Test public void testColonFormIsRepairedToUnderscore()
      OBO IRIs separate with an underscore; a colon in that position is malformed.
    • testConcatenatedIdIsRepaired

      @Test public void testConcatenatedIdIsRepaired()
      An id concatenated with itself resolves to nothing; the repair was label-verified.
    • testATagEchoedBackInCanonicalFormIsTheSameTag

      @Test public void testATagEchoedBackInCanonicalFormIsTheSameTag()
      🛑 A stored tag and the canonical form the read served it as are the SAME tag.

      A set-replace carries the whole desired set, so a client editing one tag echoes every other one back as it was served — and the read serves canonicalUri. Compared literally, the echoed canonical URI is a different tag from the stored raw one, so the diff would drop the stored row and insert a canonical replacement: the parked migration, applied by accident, one row at a time, under a new id. 634 stored tags carry a URI this shim rewrites (36 experiment tags, 598 biomaterial characteristics, measured against gemd 2026-09-11).

    • testAStatementObjectEchoedBackInCanonicalFormIsTheSameTag

      @Test public void testAStatementObjectEchoedBackInCanonicalFormIsTheSameTag()
      The same rule on a statement's object slot, which the read canonicalizes too.
    • testTwoTermsTheShimDoesNotJoinAreStillDifferentTags

      @Test public void testTwoTermsTheShimDoesNotJoinAreStillDifferentTags()
      And the canonicalization does not make the comparison mushy: two terms the shim does not join are still two tags. KMH-2 / KM-H2 is the pair that made that worth pinning.
    • testAnUnmappedTermIsReturnedUnchanged

      @Test public void testAnUnmappedTermIsReturnedUnchanged()
      The overwhelmingly common case: a term nobody remapped comes back untouched. A canonicaliser that rewrote anything it did not recognise would corrupt the whole corpus to fix 350 rows.
    • testNullIsTolerated

      @Test public void testNullIsTolerated()
      Null in, null out — the VOs call this on nullable columns.
    • testTheMappingHasNoChains

      @Test public void testTheMappingHasNoChains()
      Every mapping must be a fixed point: no from-URI may also be a to-URI, or the resolved answer depends on how many times you resolve.
    • testTwoCellLinesThatMerelyPunctuateAlikeAreNotMerged

      @Test public void testTwoCellLinesThatMerelyPunctuateAlikeAreNotMerged()
      🛑 KMH-2 and KM-H2 are not the same cell line, and the shim used to say they were.

      CLO_0037155 "KMH-2 cell" was mapped onto CLO_0007112 "KM-H2 cell" on the basis of "R5 usage" — a tie-break applied AFTER the twin grouping had already decided the two classes were one, which it does by comparing labels with punctuation and case removed. Both classes are live in CLO, neither carries termReplacedBy, and their asserted parents differ (thyroid-gland-derived versus not). GSE10831's statement 30031645 stored the first and the design endpoint served the second, which is how it surfaced.

      The row is gone from TermUriMigration.tsv and from the parked migration. This test exists because regenerating the table is a script run away, and a re-added row would be invisible until someone compared a stored value with a served one again.

    • testEveryCellLineMergeCitesItsCellosaurusAccession

      @Test public void testEveryCellLineMergeCitesItsCellosaurusAccession() throws Exception
      🛑 Every cell-line merge in the shipped table names the Cellosaurus accession that decided it.

      The twin lane used to be built on label resemblance alone — two CLO classes whose labels match once case and punctuation are stripped — which merged KMH-2 into KM-H2, two different lines, on every read. Cellosaurus arbitrated all 67 rows on 2026-08-29: 61 are one accession carrying both spellings as synonyms, 6 could not be decided by name and are gone. A row without that evidence is a row built the old way, so this reads the resource rather than the parsed map.

      Throws:
      Exception
    • testTheUndecidablePairsAreNotMerged

      @Test public void testTheUndecidablePairsAreNotMerged()
      The six pairs Cellosaurus could not decide by name are not in the table. Each spelling names more than one line — H9 is also the WA09 embryonic stem line, U-373 MG is both the ATCC line and the Uppsala one — so the spelling cannot be what makes them the same.