@@ -467,6 +467,74 @@ class ObjectWithAttributesGeneTest {
467467 assertFalse(withAttrs.containsSameValueAs(plain))
468468 }
469469
470+ // --- unsafeCopyValueFrom tests ---
471+
472+ @Test
473+ fun testUnsafeCopyValueFrom_copiesAttributeNames () {
474+ val gene1 = ObjectWithAttributesGene (
475+ name = " node" ,
476+ fixedFields = listOf (StringGene (" id" , " 1" ), StringGene (" name" , " Alice" )),
477+ isFixed = true ,
478+ attributeNames = setOf (" id" )
479+ )
480+
481+ val gene2 = ObjectWithAttributesGene (
482+ name = " node" ,
483+ fixedFields = listOf (StringGene (" id" , " 2" ), StringGene (" name" , " Bob" )),
484+ isFixed = true ,
485+ attributeNames = setOf (" name" )
486+ )
487+
488+ // Before copy, they have different attribute names
489+ assertFalse(gene1.containsSameValueAs(gene2))
490+
491+ val result = gene1.unsafeCopyValueFrom(gene2)
492+
493+ assertTrue(result)
494+ // Now gene1 should have the same attribute names as gene2 (and same values)
495+ assertTrue(gene1.containsSameValueAs(gene2))
496+ }
497+
498+ @Test
499+ fun testUnsafeCopyValueFrom_fromPlainObjectGeneClearsAttributes () {
500+ val gene1 = ObjectWithAttributesGene (
501+ name = " node" ,
502+ fixedFields = listOf (StringGene (" id" , " 1" ), StringGene (" name" , " Alice" )),
503+ isFixed = true ,
504+ attributeNames = setOf (" id" )
505+ )
506+
507+ val plain = ObjectGene (" node" , listOf (StringGene (" id" , " 3" ), StringGene (" name" , " Charlie" )))
508+
509+ val result = gene1.unsafeCopyValueFrom(plain)
510+
511+ assertTrue(result)
512+ // gene1 should now have empty attributeNames and match plain ObjectGene
513+ assertTrue(gene1.containsSameValueAs(plain))
514+ }
515+
516+ @Test
517+ fun testUnsafeCopyValueFrom_sameAttributesPreserved () {
518+ val gene1 = ObjectWithAttributesGene (
519+ name = " node" ,
520+ fixedFields = listOf (StringGene (" id" , " 1" ), StringGene (" name" , " Alice" )),
521+ isFixed = true ,
522+ attributeNames = setOf (" id" )
523+ )
524+
525+ val gene2 = ObjectWithAttributesGene (
526+ name = " node" ,
527+ fixedFields = listOf (StringGene (" id" , " 2" ), StringGene (" name" , " Bob" )),
528+ isFixed = true ,
529+ attributeNames = setOf (" id" )
530+ )
531+
532+ val result = gene1.unsafeCopyValueFrom(gene2)
533+
534+ assertTrue(result)
535+ assertTrue(gene1.containsSameValueAs(gene2))
536+ }
537+
470538 @Test
471539 fun testContainsSameValueAs_emptyAttributesVsPlainObjectGene () {
472540 // When attributeNames is empty, ObjectWithAttributesGene produces the same XML as a
0 commit comments