diff --git a/lib/ImportExport/OPML.php b/lib/ImportExport/OPML.php
index fd599a2d..b8711bdd 100644
--- a/lib/ImportExport/OPML.php
+++ b/lib/ImportExport/OPML.php
@@ -146,7 +146,7 @@ class OPML {
throw new Exception("invalidSyntax", ['line' => $err->line, 'column' => $err->column]);
}
$body = $d->getElementsByTagName("body");
- if ($d->documentElement->nodeName !== "opml" || !$body->length || $body->item(0)->parentNode != $d->documentElement) {
+ if ($d->documentElement->nodeName !== "opml" || !$body->length || !$body->item(0)->parentNode->isSameNode($d->documentElement)) {
// not a valid OPML document
throw new Exception("invalidSemantics", ['type' => "OPML"]);
}
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index 59c04a1f..68c7ea8b 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -8,6 +8,7 @@ namespace JKingWeb\Arsse;
const NS_BASE = __NAMESPACE__."\\";
define(NS_BASE."BASE", dirname(__DIR__).DIRECTORY_SEPARATOR);
+const DOCROOT = BASE."tests".DIRECTORY_SEPARATOR."docroot".DIRECTORY_SEPARATOR;
ini_set("memory_limit", "-1");
error_reporting(\E_ALL);
require_once BASE."vendor".DIRECTORY_SEPARATOR."autoload.php";
diff --git a/tests/cases/ImportExport/TestOPML.php b/tests/cases/ImportExport/TestOPML.php
index 2c8d7d29..a17cdaff 100644
--- a/tests/cases/ImportExport/TestOPML.php
+++ b/tests/cases/ImportExport/TestOPML.php
@@ -9,6 +9,7 @@ namespace JKingWeb\Arsse\TestCase\ImportExport;
use JKingWeb\Arsse\Arsse;
use JKingWeb\Arsse\Test\Result;
use JKingWeb\Arsse\ImportExport\OPML;
+use JKingWeb\Arsse\ImportExport\Exception;
/** @covers \JKingWeb\Arsse\ImportExport\OPML */
class TestOPML extends \JKingWeb\Arsse\Test\AbstractTest {
@@ -104,4 +105,25 @@ OPML_EXPORT_SERIALIZATION;
$this->assertException("doesNotExist", "User");
(new OPML)->export("john.doe@example.com");
}
+
+ /** @dataProvider provideParserData */
+ public function testParseOpmlForImport(string $file, bool $flat, $exp) {
+ $data = file_get_contents(\JKingWeb\Arsse\DOCROOT."Import/OPML/$file");
+ $parser = new OPML;
+ if ($exp instanceof \JKingWeb\Arsse\AbstractException) {
+ $this->assertException($exp);
+ $parser->parse($data, $flat);
+ } else {
+ $this->assertSame($exp, $parse->parse($data, $flat));
+ }
+ }
+
+ public function provideParserData() {
+ return [
+ ["BrokenXML.opml", false, new Exception("invalidSyntax")],
+ ["BrokenOPML.1.opml", false, new Exception("invalidSemantics")],
+ ["BrokenOPML.2.opml", false, new Exception("invalidSemantics")],
+ ["BrokenOPML.3.opml", false, new Exception("invalidSemantics")],
+ ];
+ }
}
diff --git a/tests/docroot/Import/OPML/BrokenOPML.1.opml b/tests/docroot/Import/OPML/BrokenOPML.1.opml
new file mode 100644
index 00000000..1f551eab
--- /dev/null
+++ b/tests/docroot/Import/OPML/BrokenOPML.1.opml
@@ -0,0 +1 @@
+
diff --git a/tests/docroot/Import/OPML/BrokenOPML.2.opml b/tests/docroot/Import/OPML/BrokenOPML.2.opml
new file mode 100644
index 00000000..a6c08015
--- /dev/null
+++ b/tests/docroot/Import/OPML/BrokenOPML.2.opml
@@ -0,0 +1 @@
+
diff --git a/tests/docroot/Import/OPML/BrokenOPML.3.opml b/tests/docroot/Import/OPML/BrokenOPML.3.opml
new file mode 100644
index 00000000..466ca0ca
--- /dev/null
+++ b/tests/docroot/Import/OPML/BrokenOPML.3.opml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/tests/docroot/Import/OPML/BrokenXML.opml b/tests/docroot/Import/OPML/BrokenXML.opml
new file mode 100644
index 00000000..95028ac2
--- /dev/null
+++ b/tests/docroot/Import/OPML/BrokenXML.opml
@@ -0,0 +1 @@
+