Code

Fixed svg-path (and display/curve) tests to properly handle closepath and made a...
authorjaspervdg <jaspervdg@users.sourceforge.net>
Fri, 8 Aug 2008 14:18:02 +0000 (14:18 +0000)
committerjaspervdg <jaspervdg@users.sourceforge.net>
Fri, 8 Aug 2008 14:18:02 +0000 (14:18 +0000)
buildtool.cpp
src/display/curve-test.h
src/svg/svg-path-geom-test.h
src/svg/svg-path-nr-test.h

index 3a3f2ff65f608db0f38f1d9396dc097780cce3c2..1de8d68bce7c7f18aef8e0f2654e9e913b3070b6 100644 (file)
@@ -2765,6 +2765,75 @@ static void removeFromStatCache(const String f) {
     statCache.erase(f);
 }
 
+//########################################################################
+//# Dir cache to speed up dir requests
+//########################################################################
+/*struct DirListing {
+    bool available;
+    std::vector<String> files;
+    std::vector<String> dirs;
+};
+typedef std::map<String, DirListing > dirCacheType;
+static dirCacheType dirCache;
+static const DirListing &cachedDir(String fullDir)
+{
+    String dirNative = getNativePath(fullDir);
+    std::pair<dirCacheType::iterator,bool> result = dirCache.insert(dirCacheType::value_type(dirNative, DirListing()));
+    if (result.second) {
+        DIR *dir = opendir(dirNative.c_str());
+        if (!dir)
+            {
+            error("Could not open directory %s : %s",
+                dirNative.c_str(), strerror(errno));
+            result.first->second.available = false;
+            }
+        else
+            {
+            result.first->second.available = true;
+            while (true)
+                {
+                struct dirent *de = readdir(dir);
+                if (!de)
+                    break;
+
+                //Get the directory member name
+                String s = de->d_name;
+                if (s.size() == 0 || s[0] == '.')
+                    continue;
+                String childName;
+                if (dirName.size()>0)
+                    {
+                    childName.append(dirName);
+                    childName.append("/");
+                    }
+                childName.append(s);
+                String fullChild = baseDir;
+                fullChild.append("/");
+                fullChild.append(childName);
+                
+                if (isDirectory(fullChild))
+                    {
+                    //trace("directory: %s", childName.c_str());
+                    if (!listFiles(baseDir, childName, res))
+                        return false;
+                    continue;
+                    }
+                else if (!isRegularFile(fullChild))
+                    {
+                    error("unknown file:%s", childName.c_str());
+                    return false;
+                    }
+
+            //all done!
+                res.push_back(childName);
+
+                }
+            closedir(dir);
+            }
+    }
+    return result.first->second;
+}*/
+
 //########################################################################
 //# F I L E S E T
 //########################################################################
@@ -3962,13 +4031,18 @@ bool MakeBase::executeCommand(const String &command,
         return false;
         } 
     SetHandleInformation(stdoutRead, HANDLE_FLAG_INHERIT, 0);
-    if (!CreatePipe(&stderrRead, &stderrWrite, &saAttr, 0))
-        {
-        error("executeProgram: could not create pipe");
-        delete[] paramBuf;
-        return false;
-        } 
-    SetHandleInformation(stderrRead, HANDLE_FLAG_INHERIT, 0);
+    if (&outbuf != &errbuf) {
+        if (!CreatePipe(&stderrRead, &stderrWrite, &saAttr, 0))
+            {
+            error("executeProgram: could not create pipe");
+            delete[] paramBuf;
+            return false;
+            } 
+        SetHandleInformation(stderrRead, HANDLE_FLAG_INHERIT, 0);
+    } else {
+        stderrRead = stdoutRead;
+        stderrWrite = stdoutWrite;
+    }
 
     // Create the process
     STARTUPINFO siStartupInfo;
@@ -4010,7 +4084,7 @@ bool MakeBase::executeCommand(const String &command,
         error("executeCommand: could not close read pipe");
         return false;
         }
-    if (!CloseHandle(stderrWrite))
+    if (stdoutWrite != stderrWrite && !CloseHandle(stderrWrite))
         {
         error("executeCommand: could not close read pipe");
         return false;
@@ -4068,7 +4142,7 @@ bool MakeBase::executeCommand(const String &command,
         error("executeCommand: could not close read pipe");
         return false;
         }
-    if (!CloseHandle(stderrRead))
+    if (stdoutRead != stderrRead && !CloseHandle(stderrRead))
         {
         error("executeCommand: could not close read pipe");
         return false;
@@ -6490,6 +6564,7 @@ public:
         TASK_COPY,
         TASK_CXXTEST_PART,
         TASK_CXXTEST_ROOT,
+        TASK_CXXTEST_RUN,
         TASK_DELETE,
         TASK_ECHO,
         TASK_JAR,
@@ -7401,6 +7476,97 @@ private:
 };
 
 
+/**
+ * Execute the CxxTest test executable
+ */
+class TaskCxxTestRun: public Task
+{
+public:
+
+    TaskCxxTestRun(MakeBase &par) : Task(par)
+         {
+         type    = TASK_CXXTEST_RUN;
+         name    = "cxxtestrun";
+         }
+
+    virtual ~TaskCxxTestRun()
+        {}
+
+    virtual bool execute()
+        {
+        unsigned int newFiles = 0;
+                
+        String workingDir = parent.resolve(parent.eval(workingDirOpt, "inkscape"));
+        String rawCmd = parent.eval(commandOpt, "build/cxxtests");
+
+        String cmdExe;
+        if (fileExists(rawCmd)) {
+            cmdExe = rawCmd;
+        } else if (fileExists(rawCmd + ".exe")) {
+            cmdExe = rawCmd + ".exe";
+        } else {
+            error("<cxxtestrun> problem: cxxtests executable not found! (command=\"%s\")", rawCmd.c_str());
+        }
+        // Note that the log file names are based on the exact name used to call cxxtests (it uses argv[0] + ".log"/".xml")
+        if (isNewerThan(cmdExe, rawCmd + ".log") || isNewerThan(cmdExe, rawCmd + ".xml")) newFiles++;
+
+        // Prepend the necessary ../'s
+        String cmd = rawCmd;
+        unsigned int workingDirDepth = 0;
+        bool wasSlash = true;
+        for(size_t i=0; i<workingDir.size(); i++) {
+            // This assumes no . and .. parts
+            if (wasSlash && workingDir[i]!='/') workingDirDepth++;
+            wasSlash = workingDir[i] == '/';
+        }
+        for(size_t i=0; i<workingDirDepth; i++) {
+            cmd = "../" + cmd;
+        }
+        
+        if (newFiles>0) {
+            char olddir[1024];
+            if (workingDir.size()>0) {
+                // TODO: Double-check usage of getcwd and handle chdir errors
+                getcwd(olddir, 1024);
+                chdir(workingDir.c_str());
+            }
+
+            String outString;
+            if (!executeCommand(cmd.c_str(), "", outString, outString))
+                {
+                error("<cxxtestrun> problem: %s", outString.c_str());
+                return false;
+                }
+
+            if (workingDir.size()>0) {
+                // TODO: Handle errors?
+                chdir(olddir);
+            }
+
+            removeFromStatCache(getNativePath(cmd + ".log"));
+            removeFromStatCache(getNativePath(cmd + ".xml"));
+        }
+
+        return true;
+        }
+
+    virtual bool parse(Element *elem)
+        {
+        if (!parent.getAttribute(elem, "command", commandOpt))
+            return false;
+        if (!parent.getAttribute(elem, "workingdir", workingDirOpt))
+            return false;
+        return true;
+        }
+
+private:
+
+    String  commandOpt;
+    String  workingDirOpt;
+
+};
+
+
 /**
  *
  */
@@ -8801,6 +8967,8 @@ Task *Task::createTask(Element *elem, int lineNr)
         task = new TaskCxxTestPart(parent);
     else if (tagName == "cxxtestroot")
         task = new TaskCxxTestRoot(parent);
+    else if (tagName == "cxxtestrun")
+        task = new TaskCxxTestRun(parent);
     else if (tagName == "delete")
         task = new TaskDelete(parent);
     else if (tagName == "echo")
index cca77e06391dadfe41369f594877edb07521dd5a..a45f01afdcc05e50398238574d4dbe88b4696ca3 100644 (file)
@@ -15,11 +15,11 @@ private:
 public:
     CurveTest() : path4(Geom::Point(3,5)) // Just a moveto
     {
-        // Closed path which needs a closing segment
+        // Closed path
         path1.append(Geom::HLineSegment(Geom::Point(0,0),1));
         path1.append(Geom::VLineSegment(Geom::Point(1,0),1));
         path1.close();
-        // Closed path that doesn't need a closing segment
+        // Closed path (ClosingSegment is zero length)
         path2.append(Geom::LineSegment(Geom::Point(2,0),Geom::Point(3,0)));
         path2.append(Geom::BezierCurve<3>(Geom::Point(3,0),Geom::Point(2,1),Geom::Point(1,1),Geom::Point(2,0)));
         path2.close();
@@ -53,11 +53,13 @@ public:
             pv[0] = path1;
             TS_ASSERT_EQUALS(SPCurve(pv).get_segment_count() , 3u);
             pv[0] = path2;
-            TS_ASSERT_EQUALS(SPCurve(pv).get_segment_count() , 2u);
+            TS_ASSERT_EQUALS(SPCurve(pv).get_segment_count() , 3u);
             pv[0] = path3;
             TS_ASSERT_EQUALS(SPCurve(pv).get_segment_count() , 4u);
             pv[0] = path4;
             TS_ASSERT_EQUALS(SPCurve(pv).get_segment_count() , 0u);
+            pv[0].close();
+            TS_ASSERT_EQUALS(SPCurve(pv).get_segment_count() , 1u);
         }
         { // Combination
             Geom::PathVector pv;
@@ -66,7 +68,7 @@ public:
             pv.push_back(path3);
             pv.push_back(path4);
             SPCurve curve(pv);
-            TS_ASSERT_EQUALS(curve.get_segment_count() , 9u);
+            TS_ASSERT_EQUALS(curve.get_segment_count() , 10u);
         }
     }
 
@@ -88,11 +90,13 @@ public:
             pv[0] = path1;
             TS_ASSERT_EQUALS(SPCurve(pv).nodes_in_path() , 3u);
             pv[0] = path2;
-            TS_ASSERT_EQUALS(SPCurve(pv).nodes_in_path() , 2u);
+            TS_ASSERT_EQUALS(SPCurve(pv).nodes_in_path() , 3u);
             pv[0] = path3;
             TS_ASSERT_EQUALS(SPCurve(pv).nodes_in_path() , 5u);
             pv[0] = path4;
             TS_ASSERT_EQUALS(SPCurve(pv).nodes_in_path() , 1u);
+            pv[0].close();
+            TS_ASSERT_EQUALS(SPCurve(pv).nodes_in_path() , 1u);
         }
         { // Combination
             Geom::PathVector pv;
@@ -101,7 +105,7 @@ public:
             pv.push_back(path3);
             pv.push_back(path4);
             SPCurve curve(pv);
-            TS_ASSERT_EQUALS(curve.nodes_in_path() , 11u);
+            TS_ASSERT_EQUALS(curve.nodes_in_path() , 12u);
         }
     }
 
index 1bcc5fb17de6d35d578ba91b9c410cc19f54a8ac..32a2ed2319d6162262da7246fbaf85ca0095b091 100644 (file)
@@ -17,11 +17,14 @@ private:
     std::vector<std::string> rectanglesRelativeClosed;\r
     std::vector<std::string> rectanglesAbsoluteOpen;\r
     std::vector<std::string> rectanglesRelativeOpen;\r
-    Geom::PathVector rectanglepv;\r
+    std::vector<std::string> rectanglesAbsoluteClosed2;\r
+    std::vector<std::string> rectanglesRelativeClosed2;\r
+    Geom::PathVector rectanglepvopen;\r
+    Geom::PathVector rectanglepvclosed;\r
+    Geom::PathVector rectanglepvclosed2;\r
 public:\r
     SvgPathGeomTest() {\r
         // Lots of ways to define the same rectangle\r
-        rectanglesAbsoluteClosed.push_back("M 1,2 L 4,2 L 4,8 L 1,8 L 1,2 Z");\r
         rectanglesAbsoluteClosed.push_back("M 1,2 L 4,2 L 4,8 L 1,8 z");\r
         rectanglesAbsoluteClosed.push_back("M 1,2 4,2 4,8 1,8 z");\r
         rectanglesAbsoluteClosed.push_back("M 1,2 H 4 V 8 H 1 z");\r
@@ -34,12 +37,31 @@ public:
         rectanglesRelativeOpen.push_back("m 1,2 l 3,0 l 0,6 l -3,0 l 0,-6");\r
         rectanglesRelativeOpen.push_back("m 1,2 3,0 0,6 -3,0 0,-6");\r
         rectanglesRelativeOpen.push_back("m 1,2 h 3 v 6 h -3 v -6");\r
-        rectanglepv.push_back(Geom::Path(Geom::Point(1,2)));\r
-        rectanglepv.back().append(Geom::LineSegment(Geom::Point(1,2),Geom::Point(4,2)));\r
-        rectanglepv.back().append(Geom::LineSegment(Geom::Point(4,2),Geom::Point(4,8)));\r
-        rectanglepv.back().append(Geom::LineSegment(Geom::Point(4,8),Geom::Point(1,8)));\r
-        rectanglepv.back().append(Geom::LineSegment(Geom::Point(1,8),Geom::Point(1,2)));\r
+        rectanglesAbsoluteClosed2.push_back("M 1,2 L 4,2 L 4,8 L 1,8 L 1,2 z");\r
+        rectanglesAbsoluteClosed2.push_back("M 1,2 4,2 4,8 1,8 1,2 z");\r
+        rectanglesAbsoluteClosed2.push_back("M 1,2 H 4 V 8 H 1 V 2 z");\r
+        rectanglesRelativeClosed2.push_back("m 1,2 l 3,0 l 0,6 l -3,0 l 0,-6 z");\r
+        rectanglesRelativeClosed2.push_back("m 1,2 3,0 0,6 -3,0 0,-6 z");\r
+        rectanglesRelativeClosed2.push_back("m 1,2 h 3 v 6 h -3 v -6 z");\r
+        rectanglepvopen.push_back(Geom::Path(Geom::Point(1,2)));\r
+        rectanglepvopen.back().append(Geom::LineSegment(Geom::Point(1,2),Geom::Point(4,2)));\r
+        rectanglepvopen.back().append(Geom::LineSegment(Geom::Point(4,2),Geom::Point(4,8)));\r
+        rectanglepvopen.back().append(Geom::LineSegment(Geom::Point(4,8),Geom::Point(1,8)));\r
+        rectanglepvopen.back().append(Geom::LineSegment(Geom::Point(1,8),Geom::Point(1,2)));\r
+        rectanglepvclosed.push_back(Geom::Path(Geom::Point(1,2)));\r
+        rectanglepvclosed.back().append(Geom::LineSegment(Geom::Point(1,2),Geom::Point(4,2)));\r
+        rectanglepvclosed.back().append(Geom::LineSegment(Geom::Point(4,2),Geom::Point(4,8)));\r
+        rectanglepvclosed.back().append(Geom::LineSegment(Geom::Point(4,8),Geom::Point(1,8)));\r
+        rectanglepvclosed.back().close();\r
+        rectanglepvclosed2.push_back(Geom::Path(Geom::Point(1,2)));\r
+        rectanglepvclosed2.back().append(Geom::LineSegment(Geom::Point(1,2),Geom::Point(4,2)));\r
+        rectanglepvclosed2.back().append(Geom::LineSegment(Geom::Point(4,2),Geom::Point(4,8)));\r
+        rectanglepvclosed2.back().append(Geom::LineSegment(Geom::Point(4,8),Geom::Point(1,8)));\r
+        rectanglepvclosed2.back().append(Geom::LineSegment(Geom::Point(1,8),Geom::Point(1,2)));\r
+        rectanglepvclosed2.back().close();\r
         // TODO: Also test some (smooth) cubic/quadratic beziers and elliptical arcs\r
+        // TODO: Should we make it mandatory that h/v in the path data results in a H/VLineSegment?\r
+        //       If so, the tests should be modified to reflect this.\r
     }\r
 \r
 // createSuite and destroySuite get us per-suite setup and teardown\r
@@ -49,47 +71,60 @@ public:
 \r
     void testReadRectanglesAbsoluteClosed()\r
     {\r
-        rectanglepv.back().close();\r
         for(size_t i=0; i<rectanglesAbsoluteClosed.size(); i++) {\r
             Geom::PathVector pv = sp_svg_read_pathv(rectanglesAbsoluteClosed[i].c_str());\r
-            TSM_ASSERT(rectanglesAbsoluteClosed[i].c_str(), bpathEqual(pv,rectanglepv));\r
+            TSM_ASSERT(rectanglesAbsoluteClosed[i].c_str(), bpathEqual(pv,rectanglepvclosed));\r
         }\r
     }\r
 \r
     void testReadRectanglesRelativeClosed()\r
     {\r
-        rectanglepv.back().close();\r
         for(size_t i=0; i<rectanglesRelativeClosed.size(); i++) {\r
             Geom::PathVector pv = sp_svg_read_pathv(rectanglesRelativeClosed[i].c_str());\r
-            TSM_ASSERT(rectanglesRelativeClosed[i].c_str(), bpathEqual(pv,rectanglepv));\r
+            TSM_ASSERT(rectanglesRelativeClosed[i].c_str(), bpathEqual(pv,rectanglepvclosed));\r
         }\r
     }\r
 \r
     void testReadRectanglesAbsoluteOpen()\r
     {\r
-        rectanglepv.back().close(false);\r
         for(size_t i=0; i<rectanglesAbsoluteOpen.size(); i++) {\r
             Geom::PathVector pv = sp_svg_read_pathv(rectanglesAbsoluteOpen[i].c_str());\r
-            TSM_ASSERT(rectanglesAbsoluteOpen[i].c_str(), bpathEqual(pv,rectanglepv));\r
+            TSM_ASSERT(rectanglesAbsoluteOpen[i].c_str(), bpathEqual(pv,rectanglepvopen));\r
         }\r
     }\r
 \r
     void testReadRectanglesRelativeOpen()\r
     {\r
-        rectanglepv.back().close(false);\r
         for(size_t i=0; i<rectanglesRelativeOpen.size(); i++) {\r
             Geom::PathVector pv = sp_svg_read_pathv(rectanglesRelativeOpen[i].c_str());\r
-            TSM_ASSERT(rectanglesRelativeOpen[i].c_str(), bpathEqual(pv,rectanglepv));\r
+            TSM_ASSERT(rectanglesRelativeOpen[i].c_str(), bpathEqual(pv,rectanglepvopen));\r
+        }\r
+    }\r
+\r
+    void testReadRectanglesAbsoluteClosed2()\r
+    {\r
+        for(size_t i=0; i<rectanglesAbsoluteClosed2.size(); i++) {\r
+            Geom::PathVector pv = sp_svg_read_pathv(rectanglesAbsoluteClosed2[i].c_str());\r
+            TSM_ASSERT(rectanglesAbsoluteClosed2[i].c_str(), bpathEqual(pv,rectanglepvclosed2));\r
+        }\r
+    }\r
+\r
+    void testReadRectanglesRelativeClosed2()\r
+    {\r
+        for(size_t i=0; i<rectanglesRelativeClosed2.size(); i++) {\r
+            Geom::PathVector pv = sp_svg_read_pathv(rectanglesRelativeClosed2[i].c_str());\r
+            TSM_ASSERT(rectanglesRelativeClosed2[i].c_str(), bpathEqual(pv,rectanglepvclosed2));\r
         }\r
     }\r
 \r
     void testReadConcatenatedPaths()\r
     {\r
+        // Note that finalPoint doesn't actually return the final point of the path, just the last given point... (but since this might be intentional and we're not testing lib2geom here, we just specify the final point explicitly\r
         Geom::PathVector pv_good;\r
-        pv_good.push_back(rectanglepv.back());\r
-        pv_good.push_back(rectanglepv.back()*Geom::Translate(pv_good[0].finalPoint()));\r
-        pv_good.push_back(rectanglepv.back()*Geom::Translate(pv_good[1].finalPoint()));\r
-        pv_good.push_back(rectanglepv.back());\r
+        pv_good.push_back(rectanglepvclosed.back());\r
+        pv_good.push_back(rectanglepvopen.back() * Geom::Translate(1,2)/* * Geom::Translate(pv_good[0].finalPoint())*/);\r
+        pv_good.push_back(rectanglepvclosed.back() * Geom::Translate(2,4)/* *Geom::Translate(pv_good[1].finalPoint())*/);\r
+        pv_good.push_back(rectanglepvopen.back());\r
         pv_good[0].close();\r
         pv_good[1].close(false);\r
         pv_good[2].close();\r
@@ -124,6 +159,7 @@ public:
     }\r
 \r
     void testReadImplicitMoveto() {\r
+        TS_WARN("Currently lib2geom (/libnr) has no way of specifying the difference between '... z M 0,0 L 1,0' and '... z L 1,0', the SVG specification does state that these should be handled differently with respect to markers however, see the description of the 'orient' attribute of the 'marker' element.");\r
         Geom::PathVector pv_good;\r
         pv_good.push_back(Geom::Path(Geom::Point(1,1)));\r
         pv_good.back().append(Geom::LineSegment(Geom::Point(1,1),Geom::Point(2,2)));\r
@@ -144,21 +180,28 @@ public:
     }\r
 \r
     void testReadFloatingPoint() {\r
-        Geom::PathVector pv_good;\r
-        pv_good.push_back(Geom::Path(Geom::Point(.01,.02)));\r
-        pv_good.back().append(Geom::LineSegment(Geom::Point(.01,.02),Geom::Point(.04,.02)));\r
-        pv_good.back().append(Geom::LineSegment(Geom::Point(.04,.02),Geom::Point(1.5,1.6)));\r
-        pv_good.back().append(Geom::LineSegment(Geom::Point(1.5,1.6),Geom::Point(.01,.08)));\r
-        pv_good.back().close();\r
+        Geom::PathVector pv_good1;\r
+        pv_good1.push_back(Geom::Path(Geom::Point(.01,.02)));\r
+        pv_good1.back().append(Geom::LineSegment(Geom::Point(.01,.02),Geom::Point(.04,.02)));\r
+        pv_good1.back().append(Geom::LineSegment(Geom::Point(.04,.02),Geom::Point(1.5,1.6)));\r
+        pv_good1.back().append(Geom::LineSegment(Geom::Point(1.5,1.6),Geom::Point(.01,.08)));\r
+        pv_good1.back().append(Geom::LineSegment(Geom::Point(.01,.08),Geom::Point(.01,.02)));\r
+        pv_good1.back().close();\r
         {   // Test decimals\r
             char const * path_str = "M .01,.02 L.04.02 L1.5,1.6L0.01,0.08 .01.02 z";\r
             Geom::PathVector pv = sp_svg_read_pathv(path_str);\r
-            TSM_ASSERT(path_str, bpathEqual(pv,pv_good));\r
+            TSM_ASSERT(path_str, bpathEqual(pv,pv_good1));\r
         }\r
+        Geom::PathVector pv_good2;\r
+        pv_good2.push_back(Geom::Path(Geom::Point(.01,.02)));\r
+        pv_good2.back().append(Geom::LineSegment(Geom::Point(.01,.02),Geom::Point(.04,.02)));\r
+        pv_good2.back().append(Geom::LineSegment(Geom::Point(.04,.02),Geom::Point(1.5,1.6)));\r
+        pv_good2.back().append(Geom::LineSegment(Geom::Point(1.5,1.6),Geom::Point(.01,.08)));\r
+        pv_good2.back().close();\r
         {   // Test exponent\r
             char const * path_str = "M 1e-2,.2e-1 L 0.004e1,0.0002e+2 L0150E-2,1.6e0L1.0e-2,80e-3 z";\r
             Geom::PathVector pv = sp_svg_read_pathv(path_str);\r
-            TSM_ASSERT(path_str, bpathEqual(pv,pv_good));\r
+            TSM_ASSERT(path_str, bpathEqual(pv,pv_good2));\r
         }\r
     }\r
 \r
@@ -185,129 +228,121 @@ public:
     void testReadErrorMisplacedCharacter() {\r
         char const * path_str;\r
         Geom::PathVector pv;\r
-        rectanglepv.back().close();\r
         // Comma in the wrong place (commas may only appear between parameters)\r
         path_str = "M 1,2 4,2 4,8 1,8 z , m 13,15";\r
         pv = sp_svg_read_pathv(path_str);\r
-        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepv));\r
+        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepvclosed));\r
         // Comma in the wrong place (commas may only appear between parameters)\r
         path_str = "M 1,2 4,2 4,8 1,8 z m,13,15";\r
         pv = sp_svg_read_pathv(path_str);\r
-        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepv));\r
+        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepvclosed));\r
         // Period in the wrong place (no numbers after a 'z')\r
         path_str = "M 1,2 4,2 4,8 1,8 z . m 13,15";\r
         pv = sp_svg_read_pathv(path_str);\r
-        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepv));\r
+        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepvclosed));\r
         // Sign in the wrong place (no numbers after a 'z')\r
         path_str = "M 1,2 4,2 4,8 1,8 z + - m 13,15";\r
         pv = sp_svg_read_pathv(path_str);\r
-        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepv));\r
+        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepvclosed));\r
         // Digit in the wrong place (no numbers after a 'z')\r
         path_str = "M 1,2 4,2 4,8 1,8 z 9809 m 13,15";\r
         pv = sp_svg_read_pathv(path_str);\r
-        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepv));\r
+        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepvclosed));\r
         // Digit in the wrong place (no numbers after a 'z')\r
         path_str = "M 1,2 4,2 4,8 1,8 z 9809 876 m 13,15";\r
         pv = sp_svg_read_pathv(path_str);\r
-        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepv));\r
+        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepvclosed));\r
     }\r
 \r
     void testReadErrorUnrecognizedCharacter() {\r
         char const * path_str;\r
         Geom::PathVector pv;\r
-        rectanglepv.back().close();\r
         // Unrecognized character\r
         path_str = "M 1,2 4,2 4,8 1,8 z&m 13,15";\r
         pv = sp_svg_read_pathv(path_str);\r
-        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepv));\r
+        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepvclosed));\r
         // Unrecognized character\r
         path_str = "M 1,2 4,2 4,8 1,8 z m &13,15";\r
         pv = sp_svg_read_pathv(path_str);\r
-        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepv));\r
+        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepvclosed));\r
     }\r
 \r
     void testReadErrorTypo() {\r
         char const * path_str;\r
         Geom::PathVector pv;\r
-        rectanglepv.back().close();\r
         // Typo\r
         path_str = "M 1,2 4,2 4,8 1,8 z j 13,15";\r
         pv = sp_svg_read_pathv(path_str);\r
-        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepv));\r
+        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepvclosed));\r
 \r
-        rectanglepv.back().close(false);\r
         // Typo\r
         path_str = "M 1,2 4,2 4,8 1,8 L 1,2 x m 13,15";\r
         pv = sp_svg_read_pathv(path_str);\r
-        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepv));\r
+        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepvopen));\r
     }\r
 \r
     void testReadErrorIllformedNumbers() {\r
         char const * path_str;\r
         Geom::PathVector pv;\r
-        rectanglepv.back().close();\r
         // Double exponent\r
         path_str = "M 1,2 4,2 4,8 1,8 z m 13e4e5,15";\r
         pv = sp_svg_read_pathv(path_str);\r
-        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepv));\r
+        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepvclosed));\r
         // Double sign\r
         path_str = "M 1,2 4,2 4,8 1,8 z m +-13,15";\r
         pv = sp_svg_read_pathv(path_str);\r
-        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepv));\r
+        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepvclosed));\r
         // Double sign\r
         path_str = "M 1,2 4,2 4,8 1,8 z m 13e+-12,15";\r
         pv = sp_svg_read_pathv(path_str);\r
-        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepv));\r
+        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepvclosed));\r
         // No digit\r
         path_str = "M 1,2 4,2 4,8 1,8 z m .e12,15";\r
         pv = sp_svg_read_pathv(path_str);\r
-        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepv));\r
+        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepvclosed));\r
         // No digit\r
         path_str = "M 1,2 4,2 4,8 1,8 z m .,15";\r
         pv = sp_svg_read_pathv(path_str);\r
-        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepv));\r
+        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepvclosed));\r
         // No digit\r
         path_str = "M 1,2 4,2 4,8 1,8 z m +,15";\r
         pv = sp_svg_read_pathv(path_str);\r
-        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepv));\r
+        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepvclosed));\r
         // No digit\r
         path_str = "M 1,2 4,2 4,8 1,8 z m +.e+,15";\r
         pv = sp_svg_read_pathv(path_str);\r
-        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepv));\r
+        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepvclosed));\r
     }\r
 \r
     void testReadErrorJunk() {\r
         char const * path_str;\r
         Geom::PathVector pv;\r
-        rectanglepv.back().close();\r
         // Junk\r
         path_str = "M 1,2 4,2 4,8 1,8 z j 357 hkjh.,34e34 90ih6kj4 h5k6vlh4N.,6,45wikuyi3yere..3487 m 13,23";\r
         pv = sp_svg_read_pathv(path_str);\r
-        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepv));\r
+        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepvclosed));\r
     }\r
 \r
     void testReadErrorStopReading() {\r
         char const * path_str;\r
         Geom::PathVector pv;\r
-        rectanglepv.back().close();\r
         // Unrecognized parameter\r
         path_str = "M 1,2 4,2 4,8 1,8 z m #$%,23,34";\r
         pv = sp_svg_read_pathv(path_str);\r
-        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepv));\r
+        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepvclosed));\r
         // Invalid parameter\r
         path_str = "M 1,2 4,2 4,8 1,8 z m #$%,23,34";\r
         pv = sp_svg_read_pathv(path_str);\r
-        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepv));\r
+        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepvclosed));\r
         // Illformed parameter\r
         path_str = "M 1,2 4,2 4,8 1,8 z m +-12,23,34";\r
         pv = sp_svg_read_pathv(path_str);\r
-        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepv));\r
+        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepvclosed));\r
 \r
-        rectanglepv.back().close(false);\r
         // "Third" parameter\r
         path_str = "M 1,2 4,2 4,8 1,8 1,2,3 M 12,23";\r
         pv = sp_svg_read_pathv(path_str);\r
-        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepv));\r
+        TSM_ASSERT(path_str, bpathEqual(pv,rectanglepvopen));\r
     }\r
 \r
     void testRoundTrip() {\r
@@ -371,20 +406,28 @@ private:
     bool bpathEqual(Geom::PathVector const &a, Geom::PathVector const &b, double eps = 1e-16) {\r
         if (a.size() != b.size()) {\r
             char temp[100];\r
-            sprintf(temp, "PathVectors not the same size. (%u != %u)", a.size(), b.size());\r
+            sprintf(temp, "PathVectors not the same size: %u != %u", a.size(), b.size());\r
             TS_FAIL(temp);\r
             return false;\r
         }\r
         for(size_t i=0; i<a.size(); i++) {\r
             Geom::Path const &pa = a[i];\r
             Geom::Path const &pb = b[i];\r
-            if (pa.closed() != pb.closed()) {\r
-                TS_FAIL("One path is closed, the other open.");\r
+            if (pa.closed() && !pb.closed()) {\r
+                char temp[100];\r
+                sprintf(temp, "Left subpath is closed, right subpath is open. Subpath: %u", i);\r
+                TS_FAIL(temp);\r
+                return false;\r
+            }\r
+            if (!pa.closed() && pb.closed()) {\r
+                char temp[100];\r
+                sprintf(temp, "Right subpath is closed, left subpath is open. Subpath: %u", i);\r
+                TS_FAIL(temp);\r
                 return false;\r
             }\r
             if (pa.size() != pb.size()) {\r
                 char temp[100];\r
-                sprintf(temp, "Not the same number of curves in path. (%u != %u)", pa.size(), pb.size());\r
+                sprintf(temp, "Not the same number of segments: %u != %u, subpath: %u", pa.size(), pb.size(), i);\r
                 TS_FAIL(temp);\r
                 return false;\r
             }\r
@@ -398,13 +441,13 @@ private:
                         Geom::LineSegment const *lb = dynamic_cast<Geom::LineSegment const*>(cb);\r
                         if (!Geom::are_near((*la)[0],(*lb)[0], eps)) {\r
                             char temp[200];\r
-                            sprintf(temp, "Different start of segment: (%g,%g) != (%g,%g)", (*la)[0][Geom::X], (*la)[0][Geom::Y], (*lb)[0][Geom::X], (*lb)[0][Geom::Y]);\r
+                            sprintf(temp, "Different start of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la)[0][Geom::X], (*la)[0][Geom::Y], (*lb)[0][Geom::X], (*lb)[0][Geom::Y], i, j);\r
                             TS_FAIL(temp);\r
                             return false;\r
                         }\r
                         if (!Geom::are_near((*la)[1],(*lb)[1], eps)) {\r
                             char temp[200];\r
-                            sprintf(temp, "Different end of segment: (%g,%g) != (%g,%g)", (*la)[1][Geom::X], (*la)[1][Geom::Y], (*lb)[1][Geom::X], (*lb)[1][Geom::Y]);\r
+                            sprintf(temp, "Different end of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la)[1][Geom::X], (*la)[1][Geom::Y], (*lb)[1][Geom::X], (*lb)[1][Geom::Y], i, j);\r
                             TS_FAIL(temp);\r
                             return false;\r
                         }\r
@@ -414,13 +457,13 @@ private:
                         Geom::HLineSegment const *lb = dynamic_cast<Geom::HLineSegment const*>(cb);\r
                         if (!Geom::are_near((*la).initialPoint(),(*lb).initialPoint(), eps)) {\r
                             char temp[200];\r
-                            sprintf(temp, "Different start of segment: (%g,%g) != (%g,%g)", (*la).initialPoint()[Geom::X], (*la).initialPoint()[Geom::Y], (*lb).initialPoint()[Geom::X], (*lb).initialPoint()[Geom::Y]);\r
+                            sprintf(temp, "Different start of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la).initialPoint()[Geom::X], (*la).initialPoint()[Geom::Y], (*lb).initialPoint()[Geom::X], (*lb).initialPoint()[Geom::Y], i, j);\r
                             TS_FAIL(temp);\r
                             return false;\r
                         }\r
                         if (!Geom::are_near((*la).finalPoint(),(*lb).finalPoint(), eps)) {\r
                             char temp[200];\r
-                            sprintf(temp, "Different end of segment: (%g,%g) != (%g,%g)", (*la).finalPoint()[Geom::X], (*la).finalPoint()[Geom::Y], (*lb).finalPoint()[Geom::X], (*lb).finalPoint()[Geom::Y]);\r
+                            sprintf(temp, "Different end of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la).finalPoint()[Geom::X], (*la).finalPoint()[Geom::Y], (*lb).finalPoint()[Geom::X], (*lb).finalPoint()[Geom::Y], i, j);\r
                             TS_FAIL(temp);\r
                             return false;\r
                         }\r
@@ -430,13 +473,13 @@ private:
                         Geom::VLineSegment const *lb = dynamic_cast<Geom::VLineSegment const*>(cb);\r
                         if (!Geom::are_near((*la).initialPoint(),(*lb).initialPoint(), eps)) {\r
                             char temp[200];\r
-                            sprintf(temp, "Different start of segment: (%g,%g) != (%g,%g)", (*la).initialPoint()[Geom::X], (*la).initialPoint()[Geom::Y], (*lb).initialPoint()[Geom::X], (*lb).initialPoint()[Geom::Y]);\r
+                            sprintf(temp, "Different start of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la).initialPoint()[Geom::X], (*la).initialPoint()[Geom::Y], (*lb).initialPoint()[Geom::X], (*lb).initialPoint()[Geom::Y], i, j);\r
                             TS_FAIL(temp);\r
                             return false;\r
                         }\r
                         if (!Geom::are_near((*la).finalPoint(),(*lb).finalPoint(), eps)) {\r
                             char temp[200];\r
-                            sprintf(temp, "Different end of segment: (%g,%g) != (%g,%g)", (*la).finalPoint()[Geom::X], (*la).finalPoint()[Geom::Y], (*lb).finalPoint()[Geom::X], (*lb).finalPoint()[Geom::Y]);\r
+                            sprintf(temp, "Different end of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la).finalPoint()[Geom::X], (*la).finalPoint()[Geom::Y], (*lb).finalPoint()[Geom::X], (*lb).finalPoint()[Geom::Y], i, j);\r
                             TS_FAIL(temp);\r
                             return false;\r
                         }\r
@@ -446,33 +489,34 @@ private:
                         Geom::CubicBezier const *lb = dynamic_cast<Geom::CubicBezier const*>(cb);\r
                         if (!Geom::are_near((*la)[0],(*lb)[0], eps)) {\r
                             char temp[200];\r
-                            sprintf(temp, "Different start of segment: (%g,%g) != (%g,%g)", (*la)[0][Geom::X], (*la)[0][Geom::Y], (*lb)[0][Geom::X], (*lb)[0][Geom::Y]);\r
+                            sprintf(temp, "Different start of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la)[0][Geom::X], (*la)[0][Geom::Y], (*lb)[0][Geom::X], (*lb)[0][Geom::Y], i, j);\r
                             TS_FAIL(temp);\r
                             return false;\r
                         }\r
                         if (!Geom::are_near((*la)[1],(*lb)[1], eps)) {\r
                             char temp[200];\r
-                            sprintf(temp, "Different 1st control point: (%g,%g) != (%g,%g)", (*la)[1][Geom::X], (*la)[1][Geom::Y], (*lb)[1][Geom::X], (*lb)[1][Geom::Y]);\r
+                            sprintf(temp, "Different 1st control point: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la)[1][Geom::X], (*la)[1][Geom::Y], (*lb)[1][Geom::X], (*lb)[1][Geom::Y], i, j);\r
                             TS_FAIL(temp);\r
                             return false;\r
                         }\r
                         if (!Geom::are_near((*la)[2],(*lb)[2], eps)) {\r
                             char temp[200];\r
-                            sprintf(temp, "Different 2nd control point: (%g,%g) != (%g,%g)", (*la)[2][Geom::X], (*la)[2][Geom::Y], (*lb)[2][Geom::X], (*lb)[2][Geom::Y]);\r
+                            sprintf(temp, "Different 2nd control point: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la)[2][Geom::X], (*la)[2][Geom::Y], (*lb)[2][Geom::X], (*lb)[2][Geom::Y], i, j);\r
                             TS_FAIL(temp);\r
                             return false;\r
                         }\r
                         if (!Geom::are_near((*la)[3],(*lb)[3], eps)) {\r
                             char temp[200];\r
-                            sprintf(temp, "Different end of segment: (%g,%g) != (%g,%g)", (*la)[3][Geom::X], (*la)[3][Geom::Y], (*lb)[3][Geom::X], (*lb)[3][Geom::Y]);\r
+                            sprintf(temp, "Different end of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la)[3][Geom::X], (*la)[3][Geom::Y], (*lb)[3][Geom::X], (*lb)[3][Geom::Y], i, j);\r
                             TS_FAIL(temp);\r
                             return false;\r
                         }\r
                     }\r
                     else\r
                     {\r
-                        TS_FAIL((std::string("Unknown curve type: ") + typeid(*ca).name()).c_str());\r
-                        return false;\r
+                        char temp[200];\r
+                        sprintf(temp, "Unknown curve type: %s, subpath: %u, segment: %u", typeid(*ca).name(), i, j);\r
+                        TS_FAIL(temp);\r
                     }\r
                 }\r
                 else // not same type\r
@@ -482,32 +526,39 @@ private:
                         if (Geom::HLineSegment const *lb = dynamic_cast<Geom::HLineSegment const*>(cb)) {\r
                             if (!Geom::are_near((*la).initialPoint(),(*lb).initialPoint(), eps)) {\r
                                 char temp[200];\r
-                                sprintf(temp, "Different start of segment: (%g,%g) != (%g,%g)", (*la).initialPoint()[Geom::X], (*la).initialPoint()[Geom::Y], (*lb).initialPoint()[Geom::X], (*lb).initialPoint()[Geom::Y]);\r
+                                sprintf(temp, "Different start of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la).initialPoint()[Geom::X], (*la).initialPoint()[Geom::Y], (*lb).initialPoint()[Geom::X], (*lb).initialPoint()[Geom::Y], i, j);\r
                                 TS_FAIL(temp);\r
                                 return false;\r
                             }\r
                             if (!Geom::are_near((*la).finalPoint(),(*lb).finalPoint(), eps)) {\r
                                 char temp[200];\r
-                                sprintf(temp, "Different end of segment: (%g,%g) != (%g,%g)", (*la).finalPoint()[Geom::X], (*la).finalPoint()[Geom::Y], (*lb).finalPoint()[Geom::X], (*lb).finalPoint()[Geom::Y]);\r
+                                sprintf(temp, "Different end of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la).finalPoint()[Geom::X], (*la).finalPoint()[Geom::Y], (*lb).finalPoint()[Geom::X], (*lb).finalPoint()[Geom::Y], i, j);\r
                                 TS_FAIL(temp);\r
                                 return false;\r
                             }\r
+                            char temp[200];\r
+                            sprintf(temp, "A LineSegment and an HLineSegment have been considered equal. Subpath: %u, segment: %u", i, j);\r
+                            TS_TRACE(temp);\r
                         } else if (Geom::VLineSegment const *lb = dynamic_cast<Geom::VLineSegment const*>(cb)) {\r
                             if (!Geom::are_near((*la).initialPoint(),(*lb).initialPoint(), eps)) {\r
                                 char temp[200];\r
-                                sprintf(temp, "Different start of segment: (%g,%g) != (%g,%g)", (*la).initialPoint()[Geom::X], (*la).initialPoint()[Geom::Y], (*lb).initialPoint()[Geom::X], (*lb).initialPoint()[Geom::Y]);\r
+                                sprintf(temp, "Different start of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la).initialPoint()[Geom::X], (*la).initialPoint()[Geom::Y], (*lb).initialPoint()[Geom::X], (*lb).initialPoint()[Geom::Y], i, j);\r
                                 TS_FAIL(temp);\r
                                 return false;\r
                             }\r
                             if (!Geom::are_near((*la).finalPoint(),(*lb).finalPoint(), eps)) {\r
                                 char temp[200];\r
-                                sprintf(temp, "Different end of segment: (%g,%g) != (%g,%g)", (*la).finalPoint()[Geom::X], (*la).finalPoint()[Geom::Y], (*lb).finalPoint()[Geom::X], (*lb).finalPoint()[Geom::Y]);\r
+                                sprintf(temp, "Different end of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la).finalPoint()[Geom::X], (*la).finalPoint()[Geom::Y], (*lb).finalPoint()[Geom::X], (*lb).finalPoint()[Geom::Y], i, j);\r
                                 TS_FAIL(temp);\r
                                 return false;\r
                             }\r
+                            char temp[200];\r
+                            sprintf(temp, "A LineSegment and a VLineSegment have been considered equal. Subpath: %u, segment: %u", i, j);\r
+                            TS_TRACE(temp);\r
                         } else {\r
-                            TS_FAIL((std::string("Different curve types: ") + typeid(*ca).name() + " != " + typeid(*cb).name()).c_str());\r
-                            return false;\r
+                            char temp[200];\r
+                            sprintf(temp, "Different curve types: %s != %s, subpath: %u, segment: %u", typeid(*ca).name(), typeid(*cb).name(), i, j);\r
+                            TS_FAIL(temp);\r
                         }\r
                     }\r
                     else if(Geom::LineSegment const *lb = dynamic_cast<Geom::LineSegment const*>(cb))\r
@@ -515,33 +566,45 @@ private:
                         if (Geom::HLineSegment const *la = dynamic_cast<Geom::HLineSegment const*>(ca)) {\r
                             if (!Geom::are_near((*la).initialPoint(),(*lb).initialPoint(), eps)) {\r
                                 char temp[200];\r
-                                sprintf(temp, "Different start of segment: (%g,%g) != (%g,%g)", (*la).initialPoint()[Geom::X], (*la).initialPoint()[Geom::Y], (*lb).initialPoint()[Geom::X], (*lb).initialPoint()[Geom::Y]);\r
+                                sprintf(temp, "Different start of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la).initialPoint()[Geom::X], (*la).initialPoint()[Geom::Y], (*lb).initialPoint()[Geom::X], (*lb).initialPoint()[Geom::Y], i, j);\r
                                 TS_FAIL(temp);\r
                                 return false;\r
                             }\r
                             if (!Geom::are_near((*la).finalPoint(),(*lb).finalPoint(), eps)) {\r
                                 char temp[200];\r
-                                sprintf(temp, "Different end of segment: (%g,%g) != (%g,%g)", (*la).finalPoint()[Geom::X], (*la).finalPoint()[Geom::Y], (*lb).finalPoint()[Geom::X], (*lb).finalPoint()[Geom::Y]);\r
+                                sprintf(temp, "Different end of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la).finalPoint()[Geom::X], (*la).finalPoint()[Geom::Y], (*lb).finalPoint()[Geom::X], (*lb).finalPoint()[Geom::Y], i, j);\r
                                 TS_FAIL(temp);\r
                                 return false;\r
                             }\r
+                            char temp[200];\r
+                            sprintf(temp, "An HLineSegment and a LineSegment have been considered equal. Subpath: %u, segment: %u", i, j);\r
+                            TS_TRACE(temp);\r
                         } else if (Geom::VLineSegment const *la = dynamic_cast<Geom::VLineSegment const*>(ca)) {\r
                             if (!Geom::are_near((*la).initialPoint(),(*lb).initialPoint(), eps)) {\r
                                 char temp[200];\r
-                                sprintf(temp, "Different start of segment: (%g,%g) != (%g,%g)", (*la).initialPoint()[Geom::X], (*la).initialPoint()[Geom::Y], (*lb).initialPoint()[Geom::X], (*lb).initialPoint()[Geom::Y]);\r
+                                sprintf(temp, "Different start of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la).initialPoint()[Geom::X], (*la).initialPoint()[Geom::Y], (*lb).initialPoint()[Geom::X], (*lb).initialPoint()[Geom::Y], i, j);\r
                                 TS_FAIL(temp);\r
                                 return false;\r
                             }\r
                             if (!Geom::are_near((*la).finalPoint(),(*lb).finalPoint(), eps)) {\r
                                 char temp[200];\r
-                                sprintf(temp, "Different end of segment: (%g,%g) != (%g,%g)", (*la).finalPoint()[Geom::X], (*la).finalPoint()[Geom::Y], (*lb).finalPoint()[Geom::X], (*lb).finalPoint()[Geom::Y]);\r
+                                sprintf(temp, "Different end of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la).finalPoint()[Geom::X], (*la).finalPoint()[Geom::Y], (*lb).finalPoint()[Geom::X], (*lb).finalPoint()[Geom::Y], i, j);\r
                                 TS_FAIL(temp);\r
                                 return false;\r
                             }\r
+                            char temp[200];\r
+                            sprintf(temp, "A VLineSegment and a LineSegment have been considered equal. Subpath: %u, segment: %u", i, j);\r
+                            TS_TRACE(temp);\r
                         } else {\r
-                            TS_FAIL((std::string("Different curve types: ") + typeid(*ca).name() + " != " + typeid(*cb).name()).c_str());\r
+                            char temp[200];\r
+                            sprintf(temp, "Different curve types: %s != %s, subpath: %u, segment: %u", typeid(*ca).name(), typeid(*cb).name(), i, j);\r
+                            TS_FAIL(temp);\r
                             return false;\r
                         }\r
+                    } else {\r
+                        char temp[200];\r
+                        sprintf(temp, "Different curve types: %s != %s, subpath: %u, segment: %u", typeid(*ca).name(), typeid(*cb).name(), i, j);\r
+                        TS_FAIL(temp);\r
                     }\r
                 }\r
             }\r
index df9c4605116328ce24ff7a02a958cdca9325c433..58f7cd0e7e59db13819850665b189589298667df 100644 (file)
@@ -1,3 +1,10 @@
+/* WARNING: These tests are not completely correct!
+ * Specifically, 'M 0,0 L 1,1 z' and 'M 0,0 L 1,1 L 0,0 z' are treated as equal, but aren't.
+ * This difference is (probably?) only relevant in the context of markers.
+ * However, since NArtBpath has no (valid) way to distinguish these two and is being retired,
+ * these tests have not been updated to reflect this.
+ */
+
 #include <cxxtest/TestSuite.h>
 #include "libnr/n-art-bpath.h"
 #include "svg/svg.h"