<div dir="ltr">From my reading of the current summary code it doesn't handle cases of malicious tests using shell expansion. <div><br></div><div>On the other hand I'm certain that my code does not do *any* expansion, so you would end up with folders named '/home/foo/tests/~shaders/$HOME/blah/blah/blah.html', since python doesn't expand *anything* implicitly, and I have not used os.path.expandvars() or os.path.expanduser()</div>
<div><br></div><div style>Otherwise I'll make the changes.</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Sat, May 25, 2013 at 3:00 AM, Kenneth Graunke <span dir="ltr"><<a href="mailto:kenneth@whitecape.org" target="_blank">kenneth@whitecape.org</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im">On 05/17/2013 09:31 AM, Dylan Baker wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
With 10,000+ tests all living in the same folder it can be hard to<br>
identify a single file, especially when trying to work with the HTML<br>
generation itself. This patch changes the behavior so that each test<br>
has a directory tree for the group results with tests under it (ie<br>
spec/GLSL 1.0/foo/bar/test.html)<br>
<br>
A side effect of this is that the group names of tests don't have to be<br>
altered to create a valid name (since the slashes in the group names<br>
just become the slashes in the folder structure) and this was the single<br>
most expensive operation of HTML generation (about 1/3 of the total<br>
time). This is a tidy little speedup.<br>
</blockquote>
<br></div>
I'm nervous about skipping sanitizing of output filenames entirely.  It seems kind of dangerous.  For example, I could (accidentally or maliciously) create a file named tests/shaders/~.shader_test or tests/shaders/$HOME.frag and it'll automatically create tests of similar names.  I suppose since '/' can't be part of a filename, it might work out fine, but I'd rather not have to think about it...<br>

<br>
Regarding the speed, as I mentioned earlier, I think your implementation of sanitizePath could be a lot more efficient.  tr/translate would be much faster, for example.<br>
<br>
You could probably also just sanitize it once (instead of twice) and pass the path name around.  Dunno.<br>
<br>
I'm not opposed to putting things in subdirectories.<div><div class="h5"><br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Signed-off-by: Dylan Baker <<a href="mailto:baker.dylan.c@gmail.com" target="_blank">baker.dylan.c@gmail.com</a>><br>
---<br>
  framework/summary.py       | 76 ++++++++++++++++--------------<u></u>----------------<br>
  templates/test_result.mako |  6 ++--<br>
  2 files changed, 30 insertions(+), 52 deletions(-)<br>
<br>
diff --git a/framework/summary.py b/framework/summary.py<br>
index 867dbad..9f2a924 100644<br>
--- a/framework/summary.py<br>
+++ b/framework/summary.py<br>
@@ -472,8 +472,7 @@ class BuildHTMLIndex(list):<br>
          """<br>
          self.append({'type': 'testResult',<br>
                       'class': text,<br>
-                     'href': path.join(self._sanitizePath(<u></u>group),<br>
-                                       self._sanitizePath(href + ".html")),<br>
+                     'href': path.join(group, href + ".html"),<br>
                       'text': text})<br>
<br>
      def _subtestResult(self, group, text):<br>
@@ -489,29 +488,6 @@ class BuildHTMLIndex(list):<br>
                       'class': text,<br>
                       'text': text})<br>
<br>
-    # This will be removed from here in a later patch<br>
-    def _sanitizePath(self, path):<br>
-        """<br>
-        Private: convert the testname to only contain valid characters for<br>
-        a path<br>
-<br>
-        This attempts to faithfully reconstruct the output of<br>
-        pigli-summary-html.<u></u>testPathToHtmlFilename, but without the use of<br>
-        lambda. The advantage to not using lambda is readability, and the<br>
-        desire to make future changes to the way that sub-tests are written<br>
-        """<br>
-        valid_chars = frozenset("_-.%s%s" % (string.ascii_letters,<br>
-                                              string.digits))<br>
-        out = []<br>
-        for c in path:<br>
-            if c in valid_chars:<br>
-                out.append(c)<br>
-            elif c == "/":<br>
-                out.append("__")<br>
-            else:<br>
-                out.append("_")<br>
-        return ''.join(out)<br>
-<br>
<br>
  class NewSummary:<br>
      """<br>
@@ -635,10 +611,17 @@ class NewSummary:<br>
                              output_encoding  = "utf-8",<br>
                              module_directory = ".makotmp")<br>
<br>
+        # Although these are only referenced once, that refernce is in a loop<br>
+        # and they are less expensive to find once and store than find<br>
+        # 10,000+ times<br>
</blockquote>
<br></div></div>
This is kind of a "You don't say" moment - not doing things in a loop is of course faster.  I don't think you need to explain it.  If you'd like to keep the comment, there's a typo: "reference"<div class="im">
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+        resultCss = path.join(destination, "result.css")<br>
+        index = path.join(destination, "index.html")<br>
+<br>
          # Iterate across the tests creating the various test specific files<br>
          for each in self.results:<br>
              os.mkdir(path.join(<u></u>destination, <a href="http://each.name" target="_blank">each.name</a>))<br>
<br>
+            # Create an index file for each test run<br>
              file = open(path.join(destination, <a href="http://each.name" target="_blank">each.name</a>, "index.html"), 'w')<br>
              file.write(testindex.render(<u></u>name    = <a href="http://each.name" target="_blank">each.name</a>,<br>
                                          time    = each.time,<br>
@@ -649,15 +632,32 @@ class NewSummary:<br>
<br>
              # Then build the individual test results<br>
              for key, value in each.tests.iteritems():<br>
+<br>
+                # This is also improves performance, by cutting the number of<br>
+                # times path.join and path.dirname is by 3, that's 20,000+<br>
+                # times!<br>
</blockquote>
<br></div>
This English is very broken.  I'm not sure it needs explaining either.<div class="im"><br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+                tPath = path.join(destination, <a href="http://each.name" target="_blank">each.name</a>, path.dirname(key))<br>
+<br>
+                # os.makedirs is very annoying, it throws an OSError if the<br>
+                # path requested already exists, so do this check to esnure<br>
+                # that it doesn't<br>
+                if not path.exists(tPath):<br>
+                    os.makedirs(tPath)<br>
</blockquote>
<br></div>
If you want, you could use checkDir.  But this is also fine.<br>
"ensure" (typo)<div class="im"><br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
                  file = open(path.join(destination,<br>
                                        <a href="http://each.name" target="_blank">each.name</a>,<br>
-                                      self._sanitizePath(key + ".html")), 'w')<br>
+                                      key + ".html"),<br>
+                            'w')<br>
                  file.write(testfile.render(<u></u>testname   = key,<br>
                                             status     = value['result'],<br>
                                             returncode = value['returncode'],<br>
                                             time       = value['time'],<br>
                                             info       = value['info'],<br>
-                                           command    = value['command']))<br>
+                                           command    = value['command'],<br>
+                                           css        = path.relpath(resultCss,<br>
+                                                                     tPath),<br>
+                                           index      = index))<br>
+<br>
                  file.close()<br>
</blockquote>
<br></div>
I'd probably use "with open(...) as file:" syntax here, but that's just me...it's your call.<div class="HOEnZb"><div class="h5"><br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
          # Finally build the root html files: index, regressions, etc<br>
@@ -811,25 +811,3 @@ class NewSummary:<br>
          assert(len(currentStatus) == 1)<br>
<br>
          return counts, status<br>
-<br>
-    def _sanitizePath(self, path):<br>
-        """<br>
-        Private: convert the testname to only contain valid characters for<br>
-        a path<br>
-<br>
-        This attempts to faithfully reconstruct the output of<br>
-        pigli-summary-html.<u></u>testPathToHtmlFilename, but without the use of<br>
-        lambda. The advantage to not using lambda is readability, and the<br>
-        desire to make future changes to the way that sub-tests are written<br>
-        """<br>
-        valid_chars = frozenset("_-.%s%s" % (string.ascii_letters,<br>
-                                              string.digits))<br>
-        out = []<br>
-        for c in path:<br>
-            if c in valid_chars:<br>
-                out.append(c)<br>
-            elif c == "/":<br>
-                out.append("__")<br>
-            else:<br>
-                out.append("_")<br>
-        return ''.join(out)<br>
diff --git a/templates/test_result.mako b/templates/test_result.mako<br>
index 1f944cb..7de0af7 100644<br>
--- a/templates/test_result.mako<br>
+++ b/templates/test_result.mako<br>
@@ -5,7 +5,7 @@<br>
        <head><br>
                <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><br>
                <title>${testname} - Details</title><br>
-               <link rel="stylesheet" href="../result.css" type="text/css" /><br>
+               <link rel="stylesheet" href="${css}" type="text/css" /><br>
        </head><br>
        <body><br>
                <h1>Results for ${testname}</h1><br>
@@ -14,7 +14,7 @@<br>
                        <p><b>Status:</b> ${status}</p><br>
                        <p><b>Result:</b> ${status}</p><br>
                </div><br>
-               <p><a href="../index.html">Back to summary</a></p><br>
+               <p><a href="${index}">Back to summary</a></p><br>
                <h2>Details</h2><br>
                <table><br>
                        <tr><br>
@@ -42,6 +42,6 @@<br>
                                </td><br>
                        </tr><br>
                </table><br>
-               <p><a href="../index.html">Back to summary</a></p><br>
+               <p><a href="${index}">Back to summary</a></p><br>
        </body><br>
  </html><br>
<br>
</blockquote>
<br>
</div></div></blockquote></div><br></div>