 class TestIndexPathSuper { }
 #endif
 
-class TestIndexPath : TestIndexPathSuper {
-    
-    func testBasics() {
+class TestIndexPath: TestIndexPathSuper {
+    func testEmpty() {
+        let ip = IndexPath()
+        expectEqual(ip.count, 0)
+    }
+    
+    func testSingleIndex() {
         let ip = IndexPath(index: 1)
         expectEqual(ip.count, 1)
+        expectEqual(ip[0], 1)
+        
+        let highValueIp = IndexPath(index: .max)
+        expectEqual(highValueIp.count, 1)
+        expectEqual(highValueIp[0], .max)
+        
+        let lowValueIp = IndexPath(index: .min)
+        expectEqual(lowValueIp.count, 1)
+        expectEqual(lowValueIp[0], .min)
+    }
+    
+    func testTwoIndexes() {
+        let ip = IndexPath(indexes: [0, 1])
+        expectEqual(ip.count, 2)
+        expectEqual(ip[0], 0)
+        expectEqual(ip[1], 1)
+    }
+    
+    func testManyIndexes() {
+        let ip = IndexPath(indexes: [0, 1, 2, 3, 4])
+        expectEqual(ip.count, 5)
+        expectEqual(ip[0], 0)
+        expectEqual(ip[1], 1)
+        expectEqual(ip[2], 2)
+        expectEqual(ip[3], 3)
+        expectEqual(ip[4], 4)
+    }
+    
+    func testCreateFromSequence() {
+        let seq = repeatElement(5, count: 3)
+        let ip = IndexPath(indexes: seq)
+        expectEqual(ip.count, 3)
+        expectEqual(ip[0], 5)
+        expectEqual(ip[1], 5)
+        expectEqual(ip[2], 5)
+    }
+    
+    func testCreateFromLiteral() {
+        let ip: IndexPath = [1, 2, 3, 4]
+        expectEqual(ip.count, 4)
+        expectEqual(ip[0], 1)
+        expectEqual(ip[1], 2)
+        expectEqual(ip[2], 3)
+        expectEqual(ip[3], 4)
+    }
+    
+    func testDropLast() {
+        let ip: IndexPath = [1, 2, 3, 4]
+        let ip2 = ip.dropLast()
+        expectEqual(ip2.count, 3)
+        expectEqual(ip2[0], 1)
+        expectEqual(ip2[1], 2)
+        expectEqual(ip2[2], 3)
+    }
+    
+    func testDropLastFromEmpty() {
+        let ip: IndexPath = []
+        let ip2 = ip.dropLast()
+        expectEqual(ip2.count, 0)
+    }
+    
+    func testDropLastFromSingle() {
+        let ip: IndexPath = [1]
+        let ip2 = ip.dropLast()
+        expectEqual(ip2.count, 0)
+    }
+    
+    func testDropLastFromPair() {
+        let ip: IndexPath = [1, 2]
+        let ip2 = ip.dropLast()
+        expectEqual(ip2.count, 1)
+        expectEqual(ip2[0], 1)
+    }
+    
+    func testDropLastFromTriple() {
+        let ip: IndexPath = [1, 2, 3]
+        let ip2 = ip.dropLast()
+        expectEqual(ip2.count, 2)
+        expectEqual(ip2[0], 1)
+        expectEqual(ip2[1], 2)
+    }
+    
+    func testStartEndIndex() {
+        let ip: IndexPath = [1, 2, 3, 4]
+        expectEqual(ip.startIndex, 0)
+        expectEqual(ip.endIndex, ip.count)
+    }
+    
+    func testIterator() {
+        let ip: IndexPath = [1, 2, 3, 4]
+        var iter = ip.makeIterator()
+        var sum = 0
+        while let index = iter.next() {
+            sum += index
+        }
+        expectEqual(sum, 1 + 2 + 3 + 4)
+    }
+    
+    func testIndexing() {
+        let ip: IndexPath = [1, 2, 3, 4]
+        expectEqual(ip.index(before: 1), 0)
+        expectEqual(ip.index(before: 0), -1) // beyond range!
+        expectEqual(ip.index(after: 1), 2)
+        expectEqual(ip.index(after: 4), 5) // beyond range!
+    }
+    
+    func testCompare() {
+        let ip1: IndexPath = [1, 2]
+        let ip2: IndexPath = [3, 4]
+        let ip3: IndexPath = [5, 1]
+        let ip4: IndexPath = [1, 1, 1]
+        let ip5: IndexPath = [1, 1, 9]
+        
+        expectEqual(ip1.compare(ip1), ComparisonResult.orderedSame)
+        expectEqual(ip1 < ip1, false)
+        expectEqual(ip1 <= ip1, true)
+        expectEqual(ip1 == ip1, true)
+        expectEqual(ip1 >= ip1, true)
+        expectEqual(ip1 > ip1, false)
+        
+        expectEqual(ip1.compare(ip2), ComparisonResult.orderedAscending)
+        expectEqual(ip1 < ip2, true)
+        expectEqual(ip1 <= ip2, true)
+        expectEqual(ip1 == ip2, false)
+        expectEqual(ip1 >= ip2, false)
+        expectEqual(ip1 > ip2, false)
+        
+        expectEqual(ip1.compare(ip3), ComparisonResult.orderedAscending)
+        expectEqual(ip1 < ip3, true)
+        expectEqual(ip1 <= ip3, true)
+        expectEqual(ip1 == ip3, false)
+        expectEqual(ip1 >= ip3, false)
+        expectEqual(ip1 > ip3, false)
+        
+        expectEqual(ip1.compare(ip4), ComparisonResult.orderedDescending)
+        expectEqual(ip1 < ip4, false)
+        expectEqual(ip1 <= ip4, false)
+        expectEqual(ip1 == ip4, false)
+        expectEqual(ip1 >= ip4, true)
+        expectEqual(ip1 > ip4, true)
+        
+        expectEqual(ip1.compare(ip5), ComparisonResult.orderedDescending)
+        expectEqual(ip1 < ip5, false)
+        expectEqual(ip1 <= ip5, false)
+        expectEqual(ip1 == ip5, false)
+        expectEqual(ip1 >= ip5, true)
+        expectEqual(ip1 > ip5, true)
+        
+        expectEqual(ip2.compare(ip1), ComparisonResult.orderedDescending)
+        expectEqual(ip2 < ip1, false)
+        expectEqual(ip2 <= ip1, false)
+        expectEqual(ip2 == ip1, false)
+        expectEqual(ip2 >= ip1, true)
+        expectEqual(ip2 > ip1, true)
+        
+        expectEqual(ip2.compare(ip2), ComparisonResult.orderedSame)
+        expectEqual(ip2 < ip2, false)
+        expectEqual(ip2 <= ip2, true)
+        expectEqual(ip2 == ip2, true)
+        expectEqual(ip2 >= ip2, true)
+        expectEqual(ip2 > ip2, false)
+        
+        expectEqual(ip2.compare(ip3), ComparisonResult.orderedAscending)
+        expectEqual(ip2 < ip3, true)
+        expectEqual(ip2 <= ip3, true)
+        expectEqual(ip2 == ip3, false)
+        expectEqual(ip2 >= ip3, false)
+        expectEqual(ip2 > ip3, false)
+        
+        expectEqual(ip2.compare(ip4), ComparisonResult.orderedDescending)
+        expectEqual(ip2.compare(ip5), ComparisonResult.orderedDescending)
+        expectEqual(ip3.compare(ip1), ComparisonResult.orderedDescending)
+        expectEqual(ip3.compare(ip2), ComparisonResult.orderedDescending)
+        expectEqual(ip3.compare(ip3), ComparisonResult.orderedSame)
+        expectEqual(ip3.compare(ip4), ComparisonResult.orderedDescending)
+        expectEqual(ip3.compare(ip5), ComparisonResult.orderedDescending)
+        expectEqual(ip4.compare(ip1), ComparisonResult.orderedAscending)
+        expectEqual(ip4.compare(ip2), ComparisonResult.orderedAscending)
+        expectEqual(ip4.compare(ip3), ComparisonResult.orderedAscending)
+        expectEqual(ip4.compare(ip4), ComparisonResult.orderedSame)
+        expectEqual(ip4.compare(ip5), ComparisonResult.orderedAscending)
+        expectEqual(ip5.compare(ip1), ComparisonResult.orderedAscending)
+        expectEqual(ip5.compare(ip2), ComparisonResult.orderedAscending)
+        expectEqual(ip5.compare(ip3), ComparisonResult.orderedAscending)
+        expectEqual(ip5.compare(ip4), ComparisonResult.orderedDescending)
+        expectEqual(ip5.compare(ip5), ComparisonResult.orderedSame)
+        
+        let ip6: IndexPath = [1, 1]
+        expectEqual(ip6.compare(ip5), ComparisonResult.orderedAscending)
+        expectEqual(ip5.compare(ip6), ComparisonResult.orderedDescending)
+    }
+    
+    func testHashing() {
+        let ip1: IndexPath = [5, 1]
+        let ip2: IndexPath = [1, 1, 1]
+        
+        expectNotEqual(ip1.hashValue, ip2.hashValue)
+        
+        let nsip1 = ip1._bridgeToObjectiveC()
+        expectEqual(nsip1.hash, ip1.hashValue)
+    }
+    
+    func testEquality() {
+        let ip1: IndexPath = [1, 1]
+        let ip2: IndexPath = [1, 1]
+        let ip3: IndexPath = [1, 1, 1]
+        let ip4: IndexPath = []
+        let ip5: IndexPath = [1]
+        
+        expectTrue(ip1 == ip2)
+        expectFalse(ip1 == ip3)
+        expectFalse(ip1 == ip4)
+        expectFalse(ip4 == ip1)
+        expectFalse(ip5 == ip1)
+        expectFalse(ip5 == ip4)
+        expectTrue(ip4 == ip4)
+        expectTrue(ip5 == ip5)
+    }
+    
+    func testSubscripting() {
+        var ip1: IndexPath = [1]
+        var ip2: IndexPath = [1, 2]
+        var ip3: IndexPath = [1, 2, 3]
+        
+        expectEqual(ip1[0], 1)
+        
+        expectEqual(ip2[0], 1)
+        expectEqual(ip2[1], 2)
+        
+        expectEqual(ip3[0], 1)
+        expectEqual(ip3[1], 2)
+        expectEqual(ip3[2], 3)
+        
+        ip1[0] = 2
+        expectEqual(ip1[0], 2)
+        
+        ip2[0] = 2
+        ip2[1] = 3
+        expectEqual(ip2[0], 2)
+        expectEqual(ip2[1], 3)
+        
+        ip3[0] = 2
+        ip3[1] = 3
+        ip3[2] = 4
+        expectEqual(ip3[0], 2)
+        expectEqual(ip3[1], 3)
+        expectEqual(ip3[2], 4)
+        
+        let ip4 = ip3[0..<2]
+        expectEqual(ip4.count, 2)
+        expectEqual(ip4[0], 2)
+        expectEqual(ip4[1], 3)
     }
     
     func testAppending() {

        let ip2 = IndexPath(indexes: [5, 6, 7])
        
        ip.append(ip2)
        
        expectEqual(ip.count, 7)
        expectEqual(ip[0], 1)

        expectNotEqual(anyHashables[0], anyHashables[1])
        expectEqual(anyHashables[1], anyHashables[2])
    }
}

#if !FOUNDATION_XCTEST
var IndexPathTests = TestSuite("TestIndexPath")
IndexPathTests.test("testEmpty") { TestIndexPath().testEmpty() }
IndexPathTests.test("testSingleIndex") { TestIndexPath().testSingleIndex() }
IndexPathTests.test("testTwoIndexes") { TestIndexPath().testTwoIndexes() }
IndexPathTests.test("testManyIndexes") { TestIndexPath().testManyIndexes() }
IndexPathTests.test("testCreateFromSequence") { TestIndexPath().testCreateFromSequence() }
IndexPathTests.test("testCreateFromLiteral") { TestIndexPath().testCreateFromLiteral() }
IndexPathTests.test("testDropLast") { TestIndexPath().testDropLast() }
IndexPathTests.test("testDropLastFromEmpty") { TestIndexPath().testDropLastFromEmpty() }
IndexPathTests.test("testDropLastFromSingle") { TestIndexPath().testDropLastFromSingle() }
IndexPathTests.test("testDropLastFromPair") { TestIndexPath().testDropLastFromPair() }
IndexPathTests.test("testDropLastFromTriple") { TestIndexPath().testDropLastFromTriple() }
IndexPathTests.test("testStartEndIndex") { TestIndexPath().testStartEndIndex() }
IndexPathTests.test("testIterator") { TestIndexPath().testIterator() }
IndexPathTests.test("testIndexing") { TestIndexPath().testIndexing() }
IndexPathTests.test("testCompare") { TestIndexPath().testCompare() }
IndexPathTests.test("testHashing") { TestIndexPath().testHashing() }
IndexPathTests.test("testEquality") { TestIndexPath().testEquality() }
IndexPathTests.test("testSubscripting") { TestIndexPath().testSubscripting() }
IndexPathTests.test("testAppending") { TestIndexPath().testAppending() }
IndexPathTests.test("testAppendEmpty") { TestIndexPath().testAppendEmpty() }
IndexPathTests.test("testAppendEmptyIndexPath") { TestIndexPath().testAppendEmptyIndexPath() }
IndexPathTests.test("testAppendManyIndexPath") { TestIndexPath().testAppendManyIndexPath() }
IndexPathTests.test("testAppendEmptyIndexPathToSingle") { TestIndexPath().testAppendEmptyIndexPathToSingle() }
IndexPathTests.test("testAppendSingleIndexPath") { TestIndexPath().testAppendSingleIndexPath() }
IndexPathTests.test("testAppendSingleIndexPathToSingle") { TestIndexPath().testAppendSingleIndexPathToSingle() }
IndexPathTests.test("testAppendPairIndexPath") { TestIndexPath().testAppendPairIndexPath() }
IndexPathTests.test("testAppendManyIndexPathToEmpty") { TestIndexPath().testAppendManyIndexPathToEmpty() }
IndexPathTests.test("testAppendByOperator") { TestIndexPath().testAppendByOperator() }
IndexPathTests.test("testAppendArray") { TestIndexPath().testAppendArray() }
IndexPathTests.test("testRanges") { TestIndexPath().testRanges() }
IndexPathTests.test("testRangeFromEmpty") { TestIndexPath().testRangeFromEmpty() }
IndexPathTests.test("testRangeFromSingle") { TestIndexPath().testRangeFromSingle() }
IndexPathTests.test("testRangeFromPair") { TestIndexPath().testRangeFromPair() }
IndexPathTests.test("testRangeFromMany") { TestIndexPath().testRangeFromMany() }
IndexPathTests.test("testRangeReplacementSingle") { TestIndexPath().testRangeReplacementSingle() }
IndexPathTests.test("testRangeReplacementPair") { TestIndexPath().testRangeReplacementPair() }
IndexPathTests.test("testMoreRanges") { TestIndexPath().testMoreRanges() }
IndexPathTests.test("testIteration") { TestIndexPath().testIteration() }
IndexPathTests.test("testDescription") { TestIndexPath().testDescription() }
IndexPathTests.test("testBridgeToObjC") { TestIndexPath().testBridgeToObjC() }
IndexPathTests.test("testForceBridgeFromObjC") { TestIndexPath().testForceBridgeFromObjC() }
IndexPathTests.test("testConditionalBridgeFromObjC") { TestIndexPath().testConditionalBridgeFromObjC() }
IndexPathTests.test("testUnconditionalBridgeFromObjC") { TestIndexPath().testUnconditionalBridgeFromObjC() }
IndexPathTests.test("testObjcBridgeType") { TestIndexPath().testObjcBridgeType() }
IndexPathTests.test("test_AnyHashableContainingIndexPath") { TestIndexPath().test_AnyHashableContainingIndexPath() }
IndexPathTests.test("test_AnyHashableCreatedFromNSIndexPath") { TestIndexPath().test_AnyHashableCreatedFromNSIndexPath() }
runAllTests()
#endif
