__copyright__ = "Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved."
__license__ = """
NVIDIA CORPORATION and its licensors retain all intellectual property
and proprietary rights in and to this software, related documentation
and any modifications thereto. Any use, reproduction, disclosure or
distribution of this software and related documentation without an express
license agreement from NVIDIA CORPORATION is strictly prohibited.
"""


# Copyright 2017 Pixar
#
# Licensed under the Apache License, Version 2.0 (the "Apache License")
# with the following modification; you may not use this file except in
# compliance with the Apache License and the following modification to it:
# Section 6. Trademarks. is deleted and replaced with:
#
# 6. Trademarks. This License does not grant permission to use the trade
#    names, trademarks, service marks, or product names of the Licensor
#    and its affiliates, except as required to comply with Section 4(c) of
#    the License and to reproduce the content of the NOTICE file.
#
# You may obtain a copy of the Apache License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the Apache License with the above modification is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the Apache License for the specific
# language governing permissions and limitations under the Apache License.

import os
import pathlib
import platform
import sys
import time
import unittest

from . import tc_logger


def setUpModule():
    # pre-load USD before anything else to prevent crash
    # from weird carb conflict
    # FIXME ^^^
    try:
        from . import update_path_and_load_usd

        update_path_and_load_usd()
    except ImportError:
        # not needed in Kit
        pass


try:
    import omni.kit.test

    TestClass = omni.kit.test.AsyncTestCase
    TEST_DIR = str(pathlib.Path(__file__).parent.parent.parent.parent)
except ImportError:
    from . import TestRtScenegraph

    TestClass = TestRtScenegraph
    TEST_DIR = "."


def get_path_parts():
    from usdrt import Sdf

    parts = [
        Sdf.Path("/Cornell_Box"),
        Sdf.Path("/Cornell_Box/Root"),
        Sdf.Path("/Cornell_Box/Root/Cornell_Box1_LP"),
        Sdf.Path("/Cornell_Box/Root/Cornell_Box1_LP/Green_Wall"),
        Sdf.Path("/Cornell_Box/Root/Cornell_Box1_LP/Green_Wall/Green1SG"),
        Sdf.Path("/Cornell_Box/Root/Cornell_Box1_LP/Green_Wall/Green1SG.indices"),
    ]

    return parts


class TestSdfPath(TestClass):
    @tc_logger
    def test_get_prefixes(self):
        from usdrt import Sdf

        path = Sdf.Path("/Cornell_Box/Root/Cornell_Box1_LP/Green_Wall/Green1SG.indices")

        expected = get_path_parts()

        prefixes = path.GetPrefixes()

        self.assertEqual(prefixes, expected)

    @tc_logger
    def test_repr_representation(self):
        from usdrt import Sdf

        path = Sdf.Path("/Cornell_Box/Root/Cornell_Box1_LP/Green_Wall/Green1SG.indices")
        expected = "Sdf.Path('/Cornell_Box/Root/Cornell_Box1_LP/Green_Wall/Green1SG.indices')"

        self.assertEqual(repr(path), expected)

    @tc_logger
    def test_str_representation(self):
        from usdrt import Sdf

        path = Sdf.Path("/Cornell_Box/Root/Cornell_Box1_LP/Green_Wall/Green1SG.indices")
        expected = "/Cornell_Box/Root/Cornell_Box1_LP/Green_Wall/Green1SG.indices"

        self.assertEqual(str(path), expected)

    @tc_logger
    def test_implicit_string_conversion(self):
        from usdrt import Sdf, Usd

        stage = Usd.Stage.Open(TEST_DIR + "/data/usd/tests/cornell.usda")
        self.assertTrue(stage)

        prim = stage.GetPrimAtPath(Sdf.Path("/Cornell_Box"))
        self.assertTrue(prim)

        primFromString = stage.GetPrimAtPath("/Cornell_Box")
        self.assertTrue(primFromString)

    @tc_logger
    def test_get_string(self):
        from usdrt import Sdf

        path = Sdf.Path("/Cornell_Box/Root/Cornell_Box1_LP/Green_Wall/Green1SG.indices")
        expected = "/Cornell_Box/Root/Cornell_Box1_LP/Green_Wall/Green1SG.indices"

        self.assertEqual(path.GetString(), expected)
        self.assertEqual(path.pathString, expected)

    @tc_logger
    def test_get_text(self):
        from usdrt import Sdf

        path = Sdf.Path("/Cornell_Box/Root/Cornell_Box1_LP/Green_Wall/Green1SG.indices")
        expected = "/Cornell_Box/Root/Cornell_Box1_LP/Green_Wall/Green1SG.indices"

        self.assertEqual(path.GetText(), expected)

    @tc_logger
    def test_get_name_token(self):
        from usdrt import Sdf

        self.assertEqual(Sdf.Path("/foo/bar/baz").name, "baz")
        self.assertEqual(Sdf.Path("/foo").name, "foo")
        self.assertEqual(Sdf.Path.emptyPath.name, "")
        self.assertEqual(Sdf.Path("/foo/bar/baz.prop").name, "prop")
        self.assertEqual(Sdf.Path("/foo/bar/baz.prop:argle:bargle").name, "prop:argle:bargle")
        self.assertEqual(Sdf.Path("foo/bar/baz").name, "baz")
        self.assertEqual(Sdf.Path("foo").name, "foo")
        self.assertEqual(Sdf.Path("foo/bar/baz.prop").name, "prop")
        self.assertEqual(Sdf.Path("foo/bar/baz.prop:argle:bargle").name, "prop:argle:bargle")

    @tc_logger
    def test_get_prim_path(self):
        from usdrt import Sdf, Usd

        path = Sdf.Path("/Cornell_Box/Root/Cornell_Box1_LP/Green_Wall/Green1SG.indices")
        expected = Sdf.Path("/Cornell_Box/Root/Cornell_Box1_LP/Green_Wall/Green1SG")

        self.assertEqual(path.GetPrimPath(), expected)

    @tc_logger
    def test_path_element_count(self):
        from usdrt import Sdf

        self.assertEqual(Sdf.Path("/").pathElementCount, 0)
        self.assertEqual(Sdf.Path("/abc").pathElementCount, 1)
        self.assertEqual(Sdf.Path("/abc/xyz").pathElementCount, 2)

    @tc_logger
    def test_get_name(self):
        from usdrt import Sdf

        self.assertEqual(Sdf.Path("/foo/bar/baz").name, "baz")
        self.assertEqual(Sdf.Path("/foo").name, "foo")
        self.assertEqual(Sdf.Path.emptyPath.name, "")
        self.assertEqual(Sdf.Path("/foo/bar/baz.prop").name, "prop")
        self.assertEqual(Sdf.Path("/foo/bar/baz.prop:argle:bargle").name, "prop:argle:bargle")
        self.assertEqual(Sdf.Path("foo/bar/baz").name, "baz")
        self.assertEqual(Sdf.Path("foo").name, "foo")
        self.assertEqual(Sdf.Path("foo/bar/baz.prop").name, "prop")
        self.assertEqual(Sdf.Path("foo/bar/baz.prop:argle:bargle").name, "prop:argle:bargle")

    @tc_logger
    def test_path_queries(self):
        from usdrt import Sdf

        absRoot = Sdf.Path("/")
        absolute = Sdf.Path("/absolute/path/test")
        relative = Sdf.Path("../relative/path/test")
        prim = Sdf.Path("/this/is/a/prim/path")
        rootPrim = Sdf.Path("/root")
        propPath = Sdf.Path("/this/path/has.propPart")
        namespaceProp = Sdf.Path("/this/path/has.namespaced(self):propPart")

        self.assertTrue(absolute.IsAbsolutePath())
        self.assertFalse(relative.IsAbsolutePath())

        self.assertTrue(absRoot.IsAbsoluteRootPath())
        self.assertFalse(absolute.IsAbsoluteRootPath())
        self.assertFalse(Sdf.Path.emptyPath.IsAbsoluteRootPath())

        self.assertTrue(prim.IsPrimPath())
        self.assertFalse(propPath.IsPrimPath())
        self.assertFalse(Sdf.Path.emptyPath.IsPrimPath())

        self.assertTrue(absolute.IsAbsoluteRootOrPrimPath())
        self.assertTrue(prim.IsAbsoluteRootOrPrimPath())
        self.assertFalse(relative.IsAbsoluteRootOrPrimPath())
        self.assertFalse(propPath.IsAbsoluteRootOrPrimPath())
        self.assertFalse(Sdf.Path.emptyPath.IsAbsoluteRootOrPrimPath())

        self.assertTrue(rootPrim.IsRootPrimPath())
        self.assertFalse(prim.IsRootPrimPath())
        self.assertFalse(Sdf.Path.emptyPath.IsRootPrimPath())

        self.assertTrue(propPath.IsPropertyPath())
        self.assertFalse(prim.IsPropertyPath())
        self.assertFalse(Sdf.Path.emptyPath.IsPropertyPath())

        self.assertTrue(propPath.IsPrimPropertyPath())
        self.assertFalse(prim.IsPrimPropertyPath())
        self.assertFalse(Sdf.Path.emptyPath.IsPrimPropertyPath())

        self.assertTrue(namespaceProp.IsNamespacedPropertyPath())
        self.assertFalse(propPath.IsNamespacedPropertyPath())
        self.assertFalse(prim.IsNamespacedPropertyPath())
        self.assertFalse(Sdf.Path.emptyPath.IsNamespacedPropertyPath())

        self.assertTrue(Sdf.Path.emptyPath.IsEmpty())
        self.assertFalse(propPath.IsEmpty())
        self.assertFalse(prim.IsEmpty())

    @tc_logger
    def test_operators(self):
        from usdrt import Sdf

        # Test lessthan
        self.assertTrue(Sdf.Path("aaa") < Sdf.Path("aab"))
        self.assertTrue(not Sdf.Path("aaa") < Sdf.Path())
        self.assertTrue(Sdf.Path("/") < Sdf.Path("/a"))

        # string conversion
        self.assertEqual(Sdf.Path("foo"), "foo")
        self.assertEqual("foo", Sdf.Path("foo"))

        self.assertNotEqual(Sdf.Path("foo"), "bar")
        self.assertNotEqual("bar", Sdf.Path("foo"))

    @tc_logger
    def test_contains_property_elements(self):
        from usdrt import Sdf

        path = Sdf.Path("/Cornell_Box/Root/Cornell_Box1_LP/Green_Wall/Green1SG.indices")
        self.assertTrue(path.ContainsPropertyElements())

        path = Sdf.Path("/Cornell_Box/Root/Cornell_Box1_LP/Green_Wall/Green1SG")
        self.assertFalse(path.ContainsPropertyElements())

    @tc_logger
    def test_get_parent_path(self):
        from usdrt import Sdf

        self.assertEqual(Sdf.Path("/foo/bar/baz").GetParentPath(), Sdf.Path("/foo/bar"))
        self.assertEqual(Sdf.Path("/foo").GetParentPath(), Sdf.Path("/"))
        self.assertEqual(Sdf.Path.emptyPath.GetParentPath(), Sdf.Path.emptyPath)
        self.assertEqual(Sdf.Path("/foo/bar/baz.prop").GetParentPath(), Sdf.Path("/foo/bar/baz"))
        self.assertEqual(Sdf.Path("foo/bar/baz").GetParentPath(), Sdf.Path("foo/bar"))
        # self.assertEqual(Sdf.Path("foo").GetParentPath(), Sdf.Path("."))
        self.assertEqual(Sdf.Path("foo/bar/baz.prop").GetParentPath(), Sdf.Path("foo/bar/baz"))

    @tc_logger
    def test_get_prim_path(self):
        from usdrt import Sdf

        primPath = Sdf.Path("/A/B/C").GetPrimPath()
        self.assertEqual(primPath, Sdf.Path("/A/B/C"))

        primPath = Sdf.Path("/A/B/C.foo").GetPrimPath()
        self.assertEqual(primPath, Sdf.Path("/A/B/C"))
        primPath = Sdf.Path("/A/B/C.foo:bar:baz").GetPrimPath()
        self.assertEqual(primPath, Sdf.Path("/A/B/C"))

    @tc_logger
    def test_get_absolute_root_or_prim_path(self):
        from usdrt import Sdf

        self.assertTrue(Sdf.Path.absoluteRootPath, Sdf.Path("/"))

    @tc_logger
    def test_append_path(self):
        from usdrt import Sdf

        # append to empty path -> empty path
        # with self.assertRaises(Tf.ErrorException):
        #    Sdf.Path().AppendPath( Sdf.Path() )
        # with self.assertRaises(Tf.ErrorException):
        #    Sdf.Path().AppendPath( Sdf.Path('A') )
        # append to root/prim path
        self.assertEqual(Sdf.Path("/").AppendPath(Sdf.Path("A")), Sdf.Path("/A"))
        self.assertEqual(Sdf.Path("/A").AppendPath(Sdf.Path("B")), Sdf.Path("/A/B"))

        # append empty to root/prim path -> no change
        # with self.assertRaises(Tf.ErrorException):
        #    Sdf.Path('/').AppendPath( Sdf.Path() )

        # with self.assertRaises(Tf.ErrorException):
        #    Sdf.Path('/A').AppendPath( Sdf.Path() )

    @tc_logger
    def test_append_child(self):
        from usdrt import Sdf

        aPath = Sdf.Path("/foo")
        self.assertEqual(aPath.AppendChild("bar"), Sdf.Path("/foo/bar"))
        aPath = Sdf.Path("foo")
        self.assertEqual(aPath.AppendChild("bar"), Sdf.Path("foo/bar"))

        aPath = Sdf.Path("/foo.prop")
        self.assertEqual(aPath.AppendChild("bar"), Sdf.Path.emptyPath)

    @tc_logger
    def test_append_property(self):
        from usdrt import Sdf

        aPath = Sdf.Path("/foo")
        self.assertEqual(aPath.AppendProperty("prop"), Sdf.Path("/foo.prop"))
        self.assertEqual(aPath.AppendProperty("prop:foo:bar"), Sdf.Path("/foo.prop:foo:bar"))

        aPath = Sdf.Path("/foo.prop")
        self.assertEqual(aPath.AppendProperty("prop2"), Sdf.Path.emptyPath)
        self.assertEqual(aPath.AppendProperty("prop2:foo:bar"), Sdf.Path.emptyPath)

    @tc_logger
    def test_replace_prefix(self):
        from usdrt import Sdf

        # Test HasPrefix
        self.assertFalse(Sdf.Path.emptyPath.HasPrefix("A"))
        self.assertFalse(Sdf.Path("A").HasPrefix(Sdf.Path.emptyPath))
        aPath = Sdf.Path("/Chars/Buzz_1/LArm.FB")
        self.assertEqual(aPath.HasPrefix("/Chars/Buzz_1"), True)
        self.assertEqual(aPath.HasPrefix("Buzz_1"), False)

        # Replace aPath's prefix and get a new path
        bPath = aPath.ReplacePrefix("/Chars/Buzz_1", "/Chars/Buzz_2")
        self.assertEqual(bPath, Sdf.Path("/Chars/Buzz_2/LArm.FB"))

        # Specify a bogus prefix to replace and get an empty path
        cPath = bPath.ReplacePrefix("/BadPrefix/Buzz_2", "/ReleasedChars/Buzz_2")
        self.assertEqual(cPath, bPath)

        # ReplacePrefix with an empty old or new prefix returns an empty path.
        self.assertEqual(Sdf.Path("/A/B").ReplacePrefix(Sdf.Path.emptyPath, "/C"), Sdf.Path.emptyPath)
        self.assertEqual(Sdf.Path("/A/B").ReplacePrefix("/A", Sdf.Path.emptyPath), Sdf.Path.emptyPath)

        self.assertEqual(Sdf.Path.emptyPath.ReplacePrefix(Sdf.Path.emptyPath, "/C"), Sdf.Path.emptyPath)
        self.assertEqual(Sdf.Path.emptyPath.ReplacePrefix("/A", Sdf.Path.emptyPath), Sdf.Path.emptyPath)
        self.assertEqual(Sdf.Path.emptyPath.ReplacePrefix("/A", "/B"), Sdf.Path.emptyPath)

        self.assertEqual(
            Sdf.Path("/Cone").ReplacePrefix(Sdf.Path.absoluteRootPath, Sdf.Path("/World")), Sdf.Path("/World/Cone")
        )

    @tc_logger
    def test_get_common_prefix(self):
        from usdrt import Sdf

        # prefix exists
        self.assertEqual(
            Sdf.Path("/prefix/is/common/one").GetCommonPrefix(Sdf.Path("/prefix/is/common/two")),
            Sdf.Path("/prefix/is/common"),
        )
        self.assertEqual(
            Sdf.Path("/prefix/is/common.one").GetCommonPrefix(Sdf.Path("/prefix/is/common.two")),
            Sdf.Path("/prefix/is/common"),
        )

        self.assertEqual(
            Sdf.Path("/prefix/is/common.oneone").GetCommonPrefix(Sdf.Path("/prefix/is/common.one")),
            Sdf.Path("/prefix/is/common"),
        )

        # paths are the same
        self.assertEqual(
            Sdf.Path("/paths/are/the/same").GetCommonPrefix(Sdf.Path("/paths/are/the/same")),
            Sdf.Path("/paths/are/the/same"),
        )

        # empty path, both parts
        self.assertEqual(Sdf.Path.emptyPath.GetCommonPrefix(Sdf.Path("/foo/bar")), Sdf.Path.emptyPath)
        self.assertEqual(Sdf.Path("/foo/bar").GetCommonPrefix(Sdf.Path.emptyPath), Sdf.Path.emptyPath)

        # no common prefix
        self.assertEqual(Sdf.Path("/a/b/c").GetCommonPrefix(Sdf.Path("/d/e/f")), Sdf.Path.absoluteRootPath)

        # absolute root path
        self.assertEqual(Sdf.Path.GetCommonPrefix(Sdf.Path("/"), Sdf.Path("/World")), Sdf.Path.absoluteRootPath)

        # make sure its valid
        self.assertEqual(Sdf.Path.GetCommonPrefix(Sdf.Path("/W"), Sdf.Path("/World/Cube")), Sdf.Path.absoluteRootPath)
        self.assertEqual(Sdf.Path.GetCommonPrefix(Sdf.Path("/A"), Sdf.Path("/B")), Sdf.Path.absoluteRootPath)

    @tc_logger
    def test_remove_common_suffix(self):
        from usdrt import Sdf

        aPath = Sdf.Path("/A/B/C")
        bPath = Sdf.Path("/X/Y/Z")
        (r1, r2) = aPath.RemoveCommonSuffix(bPath)
        self.assertEqual(r1, Sdf.Path("/A/B/C"))
        self.assertEqual(r2, Sdf.Path("/X/Y/Z"))
        (r1, r2) = aPath.RemoveCommonSuffix(bPath, stopAtRootPrim=True)
        self.assertEqual(r1, Sdf.Path("/A/B/C"))
        self.assertEqual(r2, Sdf.Path("/X/Y/Z"))

        aPath = Sdf.Path("A/B/C")
        bPath = Sdf.Path("X/Y/Z")
        (r1, r2) = aPath.RemoveCommonSuffix(bPath)
        self.assertEqual(r1, Sdf.Path("A/B/C"))
        self.assertEqual(r2, Sdf.Path("X/Y/Z"))
        (r1, r2) = aPath.RemoveCommonSuffix(bPath, stopAtRootPrim=True)
        self.assertEqual(r1, Sdf.Path("A/B/C"))
        self.assertEqual(r2, Sdf.Path("X/Y/Z"))

        aPath = Sdf.Path("/A/B/C")
        bPath = Sdf.Path("/X/Y/C")
        (r1, r2) = aPath.RemoveCommonSuffix(bPath)
        self.assertEqual(r1, Sdf.Path("/A/B"))
        self.assertEqual(r2, Sdf.Path("/X/Y"))
        (r1, r2) = aPath.RemoveCommonSuffix(bPath, stopAtRootPrim=True)
        self.assertEqual(r1, Sdf.Path("/A/B"))
        self.assertEqual(r2, Sdf.Path("/X/Y"))

        aPath = Sdf.Path("A/B/C")
        bPath = Sdf.Path("X/Y/C")
        (r1, r2) = aPath.RemoveCommonSuffix(bPath)
        self.assertEqual(r1, Sdf.Path("A/B"))
        self.assertEqual(r2, Sdf.Path("X/Y"))
        (r1, r2) = aPath.RemoveCommonSuffix(bPath, stopAtRootPrim=True)
        self.assertEqual(r1, Sdf.Path("A/B"))
        self.assertEqual(r2, Sdf.Path("X/Y"))

        aPath = Sdf.Path("A/B/C")
        bPath = Sdf.Path("/X/Y/C")
        (r1, r2) = aPath.RemoveCommonSuffix(bPath)
        self.assertEqual(r1, Sdf.Path("A/B"))
        self.assertEqual(r2, Sdf.Path("/X/Y"))
        (r1, r2) = aPath.RemoveCommonSuffix(bPath, stopAtRootPrim=True)
        self.assertEqual(r1, Sdf.Path("A/B"))
        self.assertEqual(r2, Sdf.Path("/X/Y"))

        aPath = Sdf.Path("/A/B/C")
        bPath = Sdf.Path("/X/B/C")
        (r1, r2) = aPath.RemoveCommonSuffix(bPath)
        self.assertEqual(r1, Sdf.Path("/A"))
        self.assertEqual(r2, Sdf.Path("/X"))
        (r1, r2) = aPath.RemoveCommonSuffix(bPath, stopAtRootPrim=True)
        self.assertEqual(r1, Sdf.Path("/A"))
        self.assertEqual(r2, Sdf.Path("/X"))

        aPath = Sdf.Path("A/B/C")
        bPath = Sdf.Path("X/B/C")
        (r1, r2) = aPath.RemoveCommonSuffix(bPath)
        self.assertEqual(r1, Sdf.Path("A"))
        self.assertEqual(r2, Sdf.Path("X"))
        (r1, r2) = aPath.RemoveCommonSuffix(bPath, stopAtRootPrim=True)
        self.assertEqual(r1, Sdf.Path("A"))
        self.assertEqual(r2, Sdf.Path("X"))

        aPath = Sdf.Path("A/B/C")
        bPath = Sdf.Path("/X/B/C")
        (r1, r2) = aPath.RemoveCommonSuffix(bPath)
        self.assertEqual(r1, Sdf.Path("A"))
        self.assertEqual(r2, Sdf.Path("/X"))
        (r1, r2) = aPath.RemoveCommonSuffix(bPath, stopAtRootPrim=True)
        self.assertEqual(r1, Sdf.Path("A"))
        self.assertEqual(r2, Sdf.Path("/X"))

        aPath = Sdf.Path("/A/B/C")
        bPath = Sdf.Path("/A/B/C")
        (r1, r2) = aPath.RemoveCommonSuffix(bPath)
        self.assertEqual(r1, Sdf.Path("/"))
        self.assertEqual(r2, Sdf.Path("/"))
        (r1, r2) = aPath.RemoveCommonSuffix(bPath, stopAtRootPrim=True)
        self.assertEqual(r1, Sdf.Path("/A"))
        self.assertEqual(r2, Sdf.Path("/A"))

        aPath = Sdf.Path("A/B/C")
        bPath = Sdf.Path("A/B/C")
        # (r1, r2) = aPath.RemoveCommonSuffix(bPath)
        # self.assertEqual(r1, Sdf.Path('.'))
        # self.assertEqual(r2, Sdf.Path('.'))
        (r1, r2) = aPath.RemoveCommonSuffix(bPath, stopAtRootPrim=True)
        self.assertEqual(r1, Sdf.Path("A"))
        self.assertEqual(r2, Sdf.Path("A"))

        aPath = Sdf.Path("A/B/C")
        bPath = Sdf.Path("/A/B/C")
        # (r1, r2) = aPath.RemoveCommonSuffix(bPath)
        # self.assertEqual(r1, Sdf.Path('.'))
        # self.assertEqual(r2, Sdf.Path('/'))
        (r1, r2) = aPath.RemoveCommonSuffix(bPath, stopAtRootPrim=True)
        self.assertEqual(r1, Sdf.Path("A"))
        self.assertEqual(r2, Sdf.Path("/A"))

        aPath = Sdf.Path("/A/B/C")
        bPath = Sdf.Path("/X/C")
        (r1, r2) = aPath.RemoveCommonSuffix(bPath)
        self.assertEqual(r1, Sdf.Path("/A/B"))
        self.assertEqual(r2, Sdf.Path("/X"))
        (r1, r2) = aPath.RemoveCommonSuffix(bPath, stopAtRootPrim=True)
        self.assertEqual(r1, Sdf.Path("/A/B"))
        self.assertEqual(r2, Sdf.Path("/X"))

        aPath = Sdf.Path("A/B/C")
        bPath = Sdf.Path("X/C")
        (r1, r2) = aPath.RemoveCommonSuffix(bPath)
        self.assertEqual(r1, Sdf.Path("A/B"))
        self.assertEqual(r2, Sdf.Path("X"))
        (r1, r2) = aPath.RemoveCommonSuffix(bPath, stopAtRootPrim=True)
        self.assertEqual(r1, Sdf.Path("A/B"))
        self.assertEqual(r2, Sdf.Path("X"))

        aPath = Sdf.Path("/A/B/C")
        bPath = Sdf.Path("/B/C")
        (r1, r2) = aPath.RemoveCommonSuffix(bPath)
        self.assertEqual(r1, Sdf.Path("/A"))
        self.assertEqual(r2, Sdf.Path("/"))
        (r1, r2) = aPath.RemoveCommonSuffix(bPath, stopAtRootPrim=True)
        self.assertEqual(r1, Sdf.Path("/A/B"))
        self.assertEqual(r2, Sdf.Path("/B"))

        aPath = Sdf.Path("A/B/C")
        bPath = Sdf.Path("B/C")
        # (r1, r2) = aPath.RemoveCommonSuffix(bPath)
        # self.assertEqual(r1, Sdf.Path('A'))
        # self.assertEqual(r2, Sdf.Path('.'))
        (r1, r2) = aPath.RemoveCommonSuffix(bPath, stopAtRootPrim=True)
        self.assertEqual(r1, Sdf.Path("A/B"))
        self.assertEqual(r2, Sdf.Path("B"))

        aPath = Sdf.Path("/A/B/C")
        bPath = Sdf.Path("/C")
        (r1, r2) = aPath.RemoveCommonSuffix(bPath)
        self.assertEqual(r1, Sdf.Path("/A/B"))
        self.assertEqual(r2, Sdf.Path("/"))
        (r1, r2) = aPath.RemoveCommonSuffix(bPath, stopAtRootPrim=True)
        self.assertEqual(r1, Sdf.Path("/A/B/C"))
        self.assertEqual(r2, Sdf.Path("/C"))

        aPath = Sdf.Path("A/B/C")
        bPath = Sdf.Path("C")
        # (r1, r2) = aPath.RemoveCommonSuffix(bPath)
        # self.assertEqual(r1, Sdf.Path('A/B'))
        # self.assertEqual(r2, Sdf.Path('.'))
        (r1, r2) = aPath.RemoveCommonSuffix(bPath, stopAtRootPrim=True)
        self.assertEqual(r1, Sdf.Path("A/B/C"))
        self.assertEqual(r2, Sdf.Path("C"))

        aPath = Sdf.Path("A/B/C")
        bPath = Sdf.Path("/C")
        (r1, r2) = aPath.RemoveCommonSuffix(bPath)
        self.assertEqual(r1, Sdf.Path("A/B"))
        self.assertEqual(r2, Sdf.Path("/"))
        (r1, r2) = aPath.RemoveCommonSuffix(bPath, stopAtRootPrim=True)
        self.assertEqual(r1, Sdf.Path("A/B/C"))
        self.assertEqual(r2, Sdf.Path("/C"))

    @tc_logger
    def test_replace_name(self):
        from usdrt import Sdf

        self.assertEqual(Sdf.Path("/foo/bar/baz").ReplaceName("foo"), Sdf.Path("/foo/bar/foo"))
        self.assertEqual(Sdf.Path("/foo").ReplaceName("bar"), Sdf.Path("/bar"))
        self.assertEqual(Sdf.Path("/foo/bar/baz.prop").ReplaceName("attr"), Sdf.Path("/foo/bar/baz.attr"))
        self.assertEqual(
            Sdf.Path("/foo/bar/baz.prop").ReplaceName("attr:argle:bargle"), Sdf.Path("/foo/bar/baz.attr:argle:bargle")
        )
        self.assertEqual(Sdf.Path("/foo/bar/baz.prop:argle:bargle").ReplaceName("attr"), Sdf.Path("/foo/bar/baz.attr"))
        self.assertEqual(
            Sdf.Path("/foo/bar/baz.prop:argle:bargle").ReplaceName("attr:foo:fa:raw"),
            Sdf.Path("/foo/bar/baz.attr:foo:fa:raw"),
        )
        self.assertEqual(Sdf.Path("foo/bar/baz").ReplaceName("foo"), Sdf.Path("foo/bar/foo"))
        self.assertEqual(Sdf.Path("foo").ReplaceName("bar"), Sdf.Path("bar"))
        self.assertEqual(Sdf.Path("foo/bar/baz.prop").ReplaceName("attr"), Sdf.Path("foo/bar/baz.attr"))
        self.assertEqual(
            Sdf.Path("foo/bar/baz.prop").ReplaceName("attr:argle:bargle"), Sdf.Path("foo/bar/baz.attr:argle:bargle")
        )

    # STATIC TESTS
    @tc_logger
    def test_empty_path(self):
        from usdrt import Sdf

        self.assertEqual(Sdf.Path.emptyPath, Sdf.Path(""))
        self.assertEqual(Sdf.Path.emptyPath, Sdf.Path())

    @tc_logger
    def test_absolute_root_path(self):
        from usdrt import Sdf

        self.assertEqual(Sdf.Path.absoluteRootPath, Sdf.Path("/"))

    @tc_logger
    def test_hashing(self):
        from usdrt import Sdf

        test_paths = get_path_parts()

        d = {}
        for i in enumerate(test_paths):
            d[i[1]] = i[0]
        for i in enumerate(test_paths):
            self.assertEqual(d[i[1]], i[0])


class TestSdfPathAncestorsRange(TestClass):
    @tc_logger
    def test_iterator(self):
        from usdrt import Sdf

        path = Sdf.Path("/Cornell_Box/Root/Cornell_Box1_LP/Green_Wall/Green1SG.indices")

        expected = get_path_parts()
        expected.reverse()

        i = 0
        for ancestor in path.GetAncestorsRange():
            self.assertEqual(ancestor, expected[i])
            i += 1

    @tc_logger
    def test_get_path(self):
        from usdrt import Sdf

        path = Sdf.Path("/Cornell_Box/Root/Cornell_Box1_LP/Green_Wall/Green1SG.indices")

        expected = get_path_parts()
        expected.reverse()

        ar = path.GetAncestorsRange()
        self.assertEqual(ar.GetPath(), path)
