Throw on canonincalization of paths which do not exists

Per `canonicalize` documentation.
diff --git a/okio/src/jvmMain/kotlin/okio/ZipFileSystem.kt b/okio/src/jvmMain/kotlin/okio/ZipFileSystem.kt
index dcf46b1..f7f98d4 100644
--- a/okio/src/jvmMain/kotlin/okio/ZipFileSystem.kt
+++ b/okio/src/jvmMain/kotlin/okio/ZipFileSystem.kt
@@ -69,8 +69,11 @@
   private val comment: String?
 ) : FileSystem() {
   override fun canonicalize(path: Path): Path {
-    // TODO(jwilson): throw FileNotFoundException if the canonical file doesn't exist.
-    return canonicalizeInternal(path)
+    val canonical = canonicalizeInternal(path)
+    if (canonical !in entries) {
+      throw FileNotFoundException("$path")
+    }
+    return canonical
   }
 
   /** Don't throw [FileNotFoundException] if the path doesn't identify a file. */
diff --git a/okio/src/jvmTest/java/okio/ZipFileSystemTest.kt b/okio/src/jvmTest/java/okio/ZipFileSystemTest.kt
index c2ef186..c9f2d29 100644
--- a/okio/src/jvmTest/java/okio/ZipFileSystemTest.kt
+++ b/okio/src/jvmTest/java/okio/ZipFileSystemTest.kt
@@ -446,6 +446,38 @@
     assertThat(zipFileSystem.list("/".toPath()))
       .containsExactly("/hello.txt".toPath())
   }
+
+  @Test
+  fun canonicalizationValid() {
+    val zipPath = ZipBuilder(base)
+      .addEntry("hello.txt", "Hello World")
+      .addEntry("directory/child.txt", "Another file!")
+      .build()
+    val zipFileSystem = fileSystem.openZip(zipPath)
+
+    assertThat(zipFileSystem.canonicalize("/".toPath())).isEqualTo("/".toPath())
+    assertThat(zipFileSystem.canonicalize(".".toPath())).isEqualTo("/".toPath())
+    assertThat(zipFileSystem.canonicalize("not/a/path/../../..".toPath())).isEqualTo("/".toPath())
+    assertThat(zipFileSystem.canonicalize("hello.txt".toPath())).isEqualTo("/hello.txt".toPath())
+    assertThat(zipFileSystem.canonicalize("stuff/../hello.txt".toPath())).isEqualTo("/hello.txt".toPath())
+    assertThat(zipFileSystem.canonicalize("directory".toPath())).isEqualTo("/directory".toPath())
+    assertThat(zipFileSystem.canonicalize("directory/whevs/..".toPath())).isEqualTo("/directory".toPath())
+    assertThat(zipFileSystem.canonicalize("directory/child.txt".toPath())).isEqualTo("/directory/child.txt".toPath())
+    assertThat(zipFileSystem.canonicalize("directory/whevs/../child.txt".toPath())).isEqualTo("/directory/child.txt".toPath())
+  }
+
+  @Test
+  fun canonicalizationInvalidThrows() {
+    val zipPath = ZipBuilder(base)
+      .addEntry("hello.txt", "Hello World")
+      .addEntry("directory/child.txt", "Another file!")
+      .build()
+    val zipFileSystem = fileSystem.openZip(zipPath)
+
+    assertFailsWith<FileNotFoundException> {
+      zipFileSystem.canonicalize("not/a/path".toPath())
+    }
+  }
 }
 
 private fun ByteString.replaceAll(a: ByteString, b: ByteString): ByteString {