Categories
Uncategorized

JavaScript URI Objects

I started looking at a dashcode project the other day. Within a few minutes, I realised that I needed something like URI.pm, in order to resolve URIs into an absolute form. I had a quick look around and there didn’t seem to be anything code out there that does this.

So, I had a quick look at RFC 3986 and noticed that amongst other things it contains pseudo-code for parsing and resolving URLs. I coded it up first in Ruby, which took the pseudo-code almost word for word, and made some tests for it. Then I translated into JavaScript and figured out how to use Test.Simple.

The end result is js-uri, a small URI object. It does what I need at the moment.

  // Parsing.
  var some_uri = new URI("http://www.example.com/foo/bar");
  alert(some_uri.authority); // www.example.com
  alert(some_uri);           // http://www.example.com/foo/bar

  // Resolving.
  var blah      = new URI("blah");
  var blah_full = blah.resolve(some_uri);
  alert(blah_full);         // http://www.example.com/foo/blah

There’s quite a bit it doesn’t do yet.

  • %-escaping and unescaping.
  • Parsing the URL in more detail. It would be useful to pull out the query parameters and host / port for instance.
  • For some reason, the tests only work in Firefox. Not sure why.

But hopefully it’s still useful.

In the process of developing the JavaScript, I spent ages tracking down one particular problem. I was trying to introduce new scope to define a couple of private helper functions:

  (function () {
      function merge(base, rel_path) { ... }

      function remove_dot_segments(path) { ... }

      URI.prototype.resolve = function (base) {
          var target = new URI();
          // ...
          return target;
      }
  })();

Looks perfectly legit right? It caused syntax errors in every browser I tried. Eventually, JSLint managed to tell me the problem: a missing semicolon after the URI.prototype.resolve definition. I hate JavaScript for trying to guess where the semicolon should go. Because it can get it so wrong like this.

Categories
Uncategorized

Dynamic JUnit

Recently, I wanted to do something slightly unusual with JUnit. I’m working on a cocoon project, so there are squillions of little XML files floating around. These need to be all well-formed. So I want a test that parses each one. Then, CruiseControl can let us know when they get broken.

First, I gave the task to a colleague. He came up with something that checked each file, and returned a list of the bad ones. It then asserted that the nonWellFormed list had a zero length. Which is great and all, but didn’t tell you which file was broken, nor why.

What I really wanted to do was have a single test per file, so it could display the errors correctly. This seemed like an easy thing to do… Until I tried it. This is what I eventually arrived at:

  class WellFormedTest extends TestCase {
    public static Test suite() {
        final TestSuite suite = new TestSuite(WellFormedTest.class.getCanonicalName());
        // Stupid bloody Java regexes have to match from the beginning of the
        // string.
        Pattern p = Pattern.compile(".*\.(xml|xslt|xconf|xmap)$");
        FindFiles ff = new FindFiles(p) {
            protected void processFile(final File file) {
                suite.addTest(new WellFormedTest(file));
            }
        };
        ff.search("web");
        return suite;
    }

    private File file;

    public WellFormedTest(File file) {
      super("Well-Formed? " + file.toString());
      this.file = file;
    }

    protected void runTest() throws Throwable {
      XmlValidator validator = new XmlValidator();
      String result = validator.isWellFormed(file);
      assertEquals(file.toString(), null, result);
    }
  }
  • FindFiles is a utility class to walk a directory tree. Tell me again why Java doesn’t have something this basic in it’s vast class libraries?
  • You have to call super("blah") in your constructor to name each test sensibly.
  • But if you do this, you have to override runTest() in order for things to actually work. The usual mechanism for determining which tests to run doesn’t work if you supply a custom name. This took forever to work out and required delving into the JUnit source. Halleluljah for Open Source.
    • As part of prodding around in the debugger, I noticed that JUnit creates a new TestCase object for each test in the class. So it’s OK to just do one thing in runTest(), as that’s all that’s going to happen anyway.
  • XmlValidator is another custom helper class. It just parses the file and returns a String containing the error (or null).
  • Yes, this is JUnit 3.8. I know I need to migrate to JUnit 4. That’s a battle for another day, dependent on upgrading ant first.

Originally, I tried to get the test done inside a nested anonymous subclass of TestCase, but there’s no constructor there, so that doesn’t work too well. Plus it bumps the ugliness of the source another level.

The end result works quite well and provides a useful example for doing dynamic tests with JUnit.