// Path: src/main/java/com/github/rschmitt/dynamicobject/DynamicObject.java
// static <T> T deserialize(String edn, Class<T> type) {
//     return EdnSerialization.deserialize(edn, type);
// }
// 
// Path: src/main/java/com/github/rschmitt/dynamicobject/DynamicObject.java
// static <T> T fromFressianByteArray(byte[] bytes) {
//     return FressianSerialization.fromFressianByteArray(bytes);
// }
// 
// Path: src/main/java/com/github/rschmitt/dynamicobject/DynamicObject.java
// static <D extends DynamicObject<D>> D newInstance(Class<D> type) {
//     return Instances.newInstance(type);
// }
// 
// Path: src/main/java/com/github/rschmitt/dynamicobject/DynamicObject.java
// static String serialize(Object o) {
//     return EdnSerialization.serialize(o);
// }
// 
// Path: src/main/java/com/github/rschmitt/dynamicobject/DynamicObject.java
// static byte[] toFressianByteArray(Object o) {
//     return FressianSerialization.toFressianByteArray(o);
// }
// 
// Path: src/test/java/com/github/rschmitt/dynamicobject/TestUtils.java
// public static void assertEquivalent(String expected, String actual) {
//     assertEquals(genericRead(expected), genericRead(actual));
// }


import static com.github.rschmitt.dynamicobject.DynamicObject.deserialize;
import static com.github.rschmitt.dynamicobject.DynamicObject.fromFressianByteArray;
import static com.github.rschmitt.dynamicobject.DynamicObject.newInstance;
import static com.github.rschmitt.dynamicobject.DynamicObject.serialize;
import static com.github.rschmitt.dynamicobject.DynamicObject.toFressianByteArray;
import static com.github.rschmitt.dynamicobject.TestUtils.assertEquivalent;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

        roundTrip(tail, true);
        roundTrip(middle, true);
        roundTrip(head, true);
        assertEquivalent("#LinkedList{:value 3}", serialize(tail));
        assertEquivalent("#LinkedList{:next #LinkedList{:value 3}, :value 2}", serialize(middle));
        assertEquivalent("#LinkedList{:next #LinkedList{:next #LinkedList{:value 3}, :value 2}, :value 1}", serialize(head));
    }

    @Test
    public void deregisteringTheTagRemovesItFromSerializedOutput() {
        DynamicObject.registerTag(LinkedList.class, "LinkedList");

        LinkedList tail = newInstance(LinkedList.class).value(3);
        LinkedList middle = newInstance(LinkedList.class).value(2).next(tail);
        LinkedList head = newInstance(LinkedList.class).value(1).next(middle);

        DynamicObject.deregisterTag(LinkedList.class);

        roundTrip(tail, false);
        roundTrip(middle, false);
        roundTrip(head, false);

        assertEquivalent("{:next {:next {:value 3}, :value 2}, :value 1}", serialize(head));
        assertEquivalent("{:next {:value 3}, :value 2}", serialize(middle));
        assertEquivalent("{:value 3}", serialize(tail));
    }

    @Test
    public void registeringTheTagDoesNotAffectEqualityOfDeserializedInstances() {
// Path: src/main/java/com/github/rschmitt/dynamicobject/DynamicObject.java
// static <T> T deserialize(String edn, Class<T> type) {
//     return EdnSerialization.deserialize(edn, type);
// }
// 
// Path: src/main/java/com/github/rschmitt/dynamicobject/DynamicObject.java
// static <T> T fromFressianByteArray(byte[] bytes) {
//     return FressianSerialization.fromFressianByteArray(bytes);
// }
// 
// Path: src/main/java/com/github/rschmitt/dynamicobject/DynamicObject.java
// static <D extends DynamicObject<D>> D newInstance(Class<D> type) {
//     return Instances.newInstance(type);
// }
// 
// Path: src/main/java/com/github/rschmitt/dynamicobject/DynamicObject.java
// static String serialize(Object o) {
//     return EdnSerialization.serialize(o);
// }
// 
// Path: src/main/java/com/github/rschmitt/dynamicobject/DynamicObject.java
// static byte[] toFressianByteArray(Object o) {
//     return FressianSerialization.toFressianByteArray(o);
// }
// 
// Path: src/test/java/com/github/rschmitt/dynamicobject/TestUtils.java
// public static void assertEquivalent(String expected, String actual) {
//     assertEquals(genericRead(expected), genericRead(actual));
// }


// Path: src/test/java/com/github/rschmitt/dynamicobject/RecursionTest.java
import static com.github.rschmitt.dynamicobject.DynamicObject.deserialize;
import static com.github.rschmitt.dynamicobject.DynamicObject.fromFressianByteArray;
import static com.github.rschmitt.dynamicobject.DynamicObject.newInstance;
import static com.github.rschmitt.dynamicobject.DynamicObject.serialize;
import static com.github.rschmitt.dynamicobject.DynamicObject.toFressianByteArray;
import static com.github.rschmitt.dynamicobject.TestUtils.assertEquivalent;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;


        roundTrip(tail, true);
        roundTrip(middle, true);
        roundTrip(head, true);
        assertEquivalent("#LinkedList{:value 3}", serialize(tail));
        assertEquivalent("#LinkedList{:next #LinkedList{:value 3}, :value 2}", serialize(middle));
        assertEquivalent("#LinkedList{:next #LinkedList{:next #LinkedList{:value 3}, :value 2}, :value 1}", serialize(head));
    }

    @Test
    public void deregisteringTheTagRemovesItFromSerializedOutput() {
        DynamicObject.registerTag(LinkedList.class, "LinkedList");

        LinkedList tail = newInstance(LinkedList.class).value(3);
        LinkedList middle = newInstance(LinkedList.class).value(2).next(tail);
        LinkedList head = newInstance(LinkedList.class).value(1).next(middle);

        DynamicObject.deregisterTag(LinkedList.class);

        roundTrip(tail, false);
        roundTrip(middle, false);
        roundTrip(head, false);

        assertEquivalent("{:next {:next {:value 3}, :value 2}, :value 1}", serialize(head));
        assertEquivalent("{:next {:value 3}, :value 2}", serialize(middle));
        assertEquivalent("{:value 3}", serialize(tail));
    }

    @Test
    public void registeringTheTagDoesNotAffectEqualityOfDeserializedInstances() {
        LinkedList obj1 = DynamicObject.deserialize("{:value 1, :next {:value 2, :next {:value 3}}}", LinkedList.class);