Clever::Tagline::Pending

Author Archive

Moved to SliceHost

by Doug on Sep.26, 2007, under Linux

I’ve moved this blog to SliceHost! Now this site is running on a snappy Gentoo 2006.1 VPS, with Apache2 and PHP5 serving the article that you’re reading. In the course of migrating the site, the following links helped immensely:

  • Check your DNS: http://pingability.com/zoneinfo.jsp
  • Configuring Postfix as your MTA: http://rimuhosting.com/support/settingupemail.jsp?mta=postfix
  • More Postfix goodness: http://www.gentoo.org/doc/en/virt-mail-howto.xml
  • Installing MySQL: http://www.gentoo.org/doc/en/mysql-howto.xml
  • WordPress, Gentoo style: http://mormanski.net/?p=5
3 Comments more...

Installing SSHFS on MacPorts

by Doug on Sep.15, 2007, under OSX

I came across SSHFS in an article by Paul Gross and thought of trying it out. Unfortunately, I had to take a slightly more complicated route to have it installed with MacPorts on my laptop.

Running

sudo port install sshfs

caused this particular error to appear:

--->  Building fusefs

Error: Target org.macports.build returned: shell command "cd "/opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_ports_fuse_fusefs/work/fusefs" && xcodebuild  -target "fusefs" -configuration Release build OBJROOT=build/ SYMROOT=build/ OBJROOT=build/ SYMROOT=build/" returned error 1

Command output: === BUILDING NATIVE TARGET fusefs WITH CONFIGURATION Release ===Checking Dependencies...

Cpp build/Release/fusefs.kext/Contents/Info.plist build/fusefs.build/Release/fusefs.build/Info.plist

    cd /opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_ports_fuse_fusefs/work/fusefs

    /usr/bin/gcc -E -P -x c -Wno-trigraphs /opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_ports_fuse_fusefs/work/fusefs/build/fusefs.build/Release/fusefs.build/Info.plist -o /opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_ports_fuse_fusefs/work/fusefs/build/Release/fusefs.kext/Contents/Info.plist

/opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_ports_fuse_fusefs/work/fusefs/build/fusefs.build/Release/fusefs.build/Info.plist:1:33: error: common/fuse_version.h: No such file or directory

/opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_ports_fuse_fusefs/work/fusefs/build/fusefs.build/Release/fusefs.build/Info.plist:2:31: error: common/fuse_param.h: No such file or directory

** BUILD FAILED **

Error: The following dependencies failed to build: fusefs libfuse

Error: Status 1 encountered during processing.

A quick spot of googling found the answer to this pretty quickly. Hans-Göran (comment #24) mentioned that he managed to install fusefs after copying the files that the error was complaining were missing.

At first glance, it seems that the file in question (common/fuse_param.h) is indeed present in the build directory. It appears that the error is being triggered from the property list file for the build.

/opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_ports_fuse_fusefs/work/fusefs/build/fusefs.build/Release/fusefs.build/Info.plist

Taking a look at its contents reveals that it’s including 2 header files from its containing directory

#include "common/fuse_version.h"

#include "common/fuse_param.h"

So I copied over the missing directory and re-ran the sshfs install.

cd /opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_ports_fuse_fusefs/work/fusefs

sudo cp -r common build/fusefs.build/Release/fusefs.build/

sudo port install sshfs
--->  Fetching libfuse
--->  Attempting to fetch fuse-2.6.5-macosx.patch from http://macfuse.googlecode.com/svn/tags/macfuse-0.4.0/libfuse/
--->  Attempting to fetch fuse-2.6.5.tar.gz from http://downloads.sourceforge.net/fuse
--->  Verifying checksum(s) for libfuse
--->  Extracting libfuse
--->  Applying patches to libfuse
--->  Configuring libfuse
--->  Building libfuse with target all
--->  Staging libfuse into destroot
--->  Installing libfuse 2.6.5_1
--->  Activating libfuse 2.6.5_1
--->  Cleaning libfuse
--->  Fetching sshfs
--->  Attempting to fetch sshfs-fuse-1.7-macosx.patch from http://macfuse.googlecode.com/svn/tags/macfuse-0.4.0/filesystems/sshfs
--->  Attempting to fetch sshfs-fuse-1.7.tar.gz from http://downloads.sourceforge.net/fuse
--->  Verifying checksum(s) for sshfs
--->  Extracting sshfs
--->  Applying patches to sshfs
--->  Configuring sshfs
--->  Building sshfs with target all
--->  Staging sshfs into destroot
--->  Installing sshfs 1.7_5
--->  Activating sshfs 1.7_5
--->  Cleaning sshfs

Now sshfs is installed!

Comments Off more...

Raising URI::InvalidURIError from a perfectly valid URI

by Doug on Sep.15, 2007, under Ruby

I was puzzled by URI::parse raising an URI::InvalidURIError on a perfectly well formed URI recently.

[ruby]
URI::InvalidURIError: bad URI(is not URI?): http://practicalguile.com/articles?query=latest
from /opt/local/lib/ruby/1.8/uri/common.rb:436:in `split’
from /opt/local/lib/ruby/1.8/uri/common.rb:485:in `parse’
from (irb):2
from :0
[/ruby]

What’s not apparent in this exception message is that the url contained a trailing space and this was causing URI.parse to fail. The following specifications demonstrate how it can trigger this particular exception.

uri.spec.rb
[ruby]
require ‘rubygems’
require ‘spec’
require ‘uri’

describe URI do
it “should raise an InvalidURIException with leading whitespace in url” do
lambda{ URI.parse(‘ http://www.ruby-lang.org’) }.should raise_error(URI::InvalidURIError)
end

it “should raise an InvalidURIException with trailing whitespace in url” do
lambda{ URI.parse(‘http://www.ruby-lang.org ‘) }.should raise_error(URI::InvalidURIError)
end
end
[/ruby]

Running the spec will get you the result below.

ruby uri.spec.rb

..Finished in 0.030051 seconds

2 examples, 0 failures

Looking at the stacktrace in the exception, it’s being raised by URI.split after URI.parse is invoked with the offending URL.

RUBY_INSTALL/1.8/uri/common.rb

[ruby]
def self.parse(uri)
scheme, userinfo, host, port,
registry, path, opaque, query, fragment = self.split(uri)

if scheme && @@schemes.include?(scheme.upcase)
@@schemes[scheme.upcase].new(scheme, userinfo, host, port,
registry, path, opaque, query,
fragment)
else
Generic.new(scheme, userinfo, host, port,
registry, path, opaque, query,
fragment)
end
end
[/ruby]

Nothing weird happening in URI.parse, its a straightforward call to URI.split. So I’ll go into URI.split, comments removed for brevity.

[ruby]
def self.split(uri)
case uri
when ”
when ABS_URI
scheme, opaque, userinfo, host, port,
registry, path, query, fragment = $~[1..-1]

if !scheme
raise InvalidURIError,
“bad URI(absolute but no scheme): #{uri}”
end
if !opaque && (!path && (!host && !registry))
raise InvalidURIError,
“bad URI(absolute but no path): #{uri}”
end
when REL_URI
scheme = nil
opaque = nil

userinfo, host, port, registry,
rel_segment, abs_path, query, fragment = $~[1..-1]
if rel_segment && abs_path
path = rel_segment + abs_path
elsif rel_segment
path = rel_segment
elsif abs_path
path = abs_path
end
else
raise InvalidURIError, “bad URI(is not URI?): #{uri}”
end

path = ” if !path && !opaque # (see RFC2396 Section 5.2)
ret = [
scheme,
userinfo, host, port, # X
registry, # X
path, # Y
opaque, # Y
query,
fragment
]
return ret
end
[/ruby]

URI.split is matching the incoming url with an empty string as well as regular expressions for absolute and relative URIs. It’s obvious from the specifications earlier that urls with leading/trailing whitespace do not match any of these and the case statement raises InvalidURIError, with the rather misleading message.

The regexes used for matching absolute and relative URIs is shown below, if you really want to know.
[ruby]
require ‘uri’
include URI::REGEXP

ABS_URI
/^
([a-zA-Z][-+.a-zA-Z\d]*): (?# 1: scheme)
(?:
((?:[-_.!~*'()a-zA-Z\d;?:@&=+$,]|%[a-fA-F\d]{2})(?:[-_.!~*'()a-zA-Z\d;\/?:@&=+$,\[\]]|%[a-fA-F\d]{2})*) (?# 2: opaque)
|
(?:(?:
\/\/(?:
(?:(?:((?:[-_.!~*'()a-zA-Z\d;:&=+$,]|%[a-fA-F\d]{2})*)@)? (?# 3: userinfo)
(?:((?:(?:(?:[a-zA-Z\d](?:[-a-zA-Z\d]*[a-zA-Z\d])?)\.)*(?:[a-zA-Z](?:[-a-zA-Z\d]*[a-zA-Z\d])?)\.?|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\[(?:(?:[a-fA-F\d]{1,4}:)*(?:[a-fA-F\d]{1,4}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|(?:(?:[a-fA-F\d]{1,4}:)*[a-fA-F\d]{1,4})?::(?:(?:[a-fA-F\d]{1,4}:)*(?:[a-fA-F\d]{1,4}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}))?)\]))(?::(\d*))?))?(?# 4: host, 5: port) |
((?:[-_.!~*'()a-zA-Z\d$,;+@&=+]|%[a-fA-F\d]{2})+) (?# 6: registry)
)
|
(?!\/\/)) (?# XXX: ‘\/\/’ is the mark for hostport)
(\/(?:[-_.!~*'()a-zA-Z\d:@&=+$,]|%[a-fA-F\d]{2})*(?:;(?:[-_.!~*'()a-zA-Z\d:@&=+$,]|%[a-fA-F\d]{2})*)*(?:\/(?:[-_.!~*'()a-zA-Z\d:@&=+$,]|%[a-fA-F\d]{2})*(?:;(?:[-_.!~*'()a-zA-Z\d:@&=+$,]|%[a-fA-F\d]{2})*)*)*)? (?# 7: path)
)(?:\?((?:[-_.!~*'()a-zA-Z\d;\/?:@&=+$,\[\]]|%[a-fA-F\d]{2})*))? (?# 8: query)
)
(?:\#((?:[-_.!~*'()a-zA-Z\d;\/?:@&=+$,\[\]]|%[a-fA-F\d]{2})*))? (?# 9: fragment)
$/xn

REL_URI
/^
(?:
(?:
\/\/
(?:
(?:((?:[-_.!~*'()a-zA-Z\d;:&=+$,]|%[a-fA-F\d]{2})*)@)? (?# 1: userinfo)
((?:(?:(?:[a-zA-Z\d](?:[-a-zA-Z\d]*[a-zA-Z\d])?)\.)*(?:[a-zA-Z](?:[-a-zA-Z\d]*[a-zA-Z\d])?)\.?|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\[(?:(?:[a-fA-F\d]{1,4}:)*(?:[a-fA-F\d]{1,4}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|(?:(?:[a-fA-F\d]{1,4}:)*[a-fA-F\d]{1,4})?::(?:(?:[a-fA-F\d]{1,4}:)*(?:[a-fA-F\d]{1,4}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}))?)\]))?(?::(\d*))? (?# 2: host, 3: port)
|
((?:[-_.!~*'()a-zA-Z\d$,;+@&=+]|%[a-fA-F\d]{2})+) (?# 4: registry)
)
)
|
((?:[-_.!~*'()a-zA-Z\d;@&=+$,]|%[a-fA-F\d]{2})+) (?# 5: rel_segment)
)?
(\/(?:[-_.!~*'()a-zA-Z\d:@&=+$,]|%[a-fA-F\d]{2})*(?:;(?:[-_.!~*'()a-zA-Z\d:@&=+$,]|%[a-fA-F\d]{2})*)*(?:\/(?:[-_.!~*'()a-zA-Z\d:@&=+$,]|%[a-fA-F\d]{2})*(?:;(?:[-_.!~*'()a-zA-Z\d:@&=+$,]|%[a-fA-F\d]{2})*)*)*)? (?# 6: abs_path)
(?:\?((?:[-_.!~*'()a-zA-Z\d;\/?:@&=+$,\[\]]|%[a-fA-F\d]{2})*))? (?# 7: query)
(?:\#((?:[-_.!~*'()a-zA-Z\d;\/?:@&=+$,\[\]]|%[a-fA-F\d]{2})*))? (?# 8: fragment)
$/xn
[/ruby]

Looks rather intimidating, doesn’t it? However, we’re more interested in the beginning and end of the regular expressions so its safe to ignore all the stuff in between. Narrowing our focus down to the regex anchors (^ and $), we can see that there is no matching of whitespace, thus preventing a valid URI from being matched in URI.split.

This all means that URI.split has a undocumented pre-condition on the uri parameter being stripped of any whitespace around it.

3 Comments more...

Listening to your tests

by Doug on Aug.26, 2007, under Behaviour Driven Development

One of the challenges I’ve been trying to overcome in practicing Test First Development(TFD) has been making sense of the feedback that comes from TFD. It was not obvious to me till recently, after I’ve read an excellent article (IEEE Explorer account required) by Bas Vodde and Lasse Koskela in IEEE Software. Bas and Lasse recount their experiences in conducting TFD workshops in Nokia and in particular the insights gleaned from a TFD coding exercise.

One key point made by the authors was that although the participants in the coding exercise followed the test-code-refactor cycle, their code became progressively complex and littered with nested branching constructs. It made keeping track of the software’s behaviour difficult. Bas and Lasse observed that once the the initial design approach was chosen, none of the participants thought about whether the design was still suitable for the current requirements.

Essentially, the test-code-refactor cycle was taking longer to complete and the code was turning out to be an unmaintainable mess. This feedback was lost on the participants and while some decided to hide the code’s complexity behind refactorings that make the code read better, others simply added more tests and attempted to make them pass.

It should be obvious that emergent design will only occur when there is constant reflective thinking about the state of the code. This takes a bit of skill and confidence on the part of the developer. Simply going through the motions of test-code-refactor to the simplest design without this reflective thinking will lower the effectiveness of TFD as a design technique.

Comments Off more...

Programming Erlang, almost

by Doug on Aug.20, 2007, under Erlang

So I’ve bit the bullet and purchased the PDF of Programming Erlang from the Pragmatic Programmers. This despite the fact that I’ve got 6 other technical books to finish. This would probably be a good time to get used to skip reading books the first time through.

1 Comment more...

Using Factories for Rails Fixtures and Test Doubles

by Doug on Aug.11, 2007, under Behaviour Driven Development, Rails, Ruby

Chris Wanstrath has written about making Rails fixtures less painful than they need to be with the FixtureScenarios plugin. Personally, I prefer the Factory approach, nicely explained by Daniel Manges.

I’ve been using factory methods to create in-database ActiveRecord objects for a project that I’ve been working on in Bezurk. Reading Daniel’s article gave me a few ideas on improving the way I create fixtures and mocks. Since I’ve been using RSpec extensively in this project, I’ll present the examples in RSpec.

As the models evolve with the design and its behaviour change accordingly, there is a need to go through all the specifications that create this model and make sure that its created in a valid state. This is more pronounced with the use of test doubles, the test doubles also need to have its method stubs changed to reflect the latest state of the model that its is representing. I happen to make much use of test doubles for test isolation, so trying to manage all these objects became an exercise in patience. As it was getting painful, It’s time to change the way I create these models and test doubles.

As always, a layer of indirection will always go some way to solving a software problem. We introduce a Factory that encapsulates the creation of ActiveRecord objects by providing creation methods.

[ruby]
module FixtureFactory
def create_user(attributes = {})
User.create!(ModelAttributes.user(attributes))
end
end
[/ruby]
We’ll have a Factory for test doubles too.

[ruby]
module MockFactory
def mock_user(method_stubs = {})
mock_model(User, ModelAttributes.user(method_stubs))
end
end
[/ruby]
And the attributes for this model will be declared in a module that’s used by both Factories

[ruby]
module ModelAttributes
def self.user(attributes)
attributes.reverse_merge({:name => ‘doug’})
end
end
[/ruby]

The Factory modules are then included in Spec::Runnner

[ruby]
Spec::Runner.configure do |config|
include FixtureFactory
include MockFactory
end
[/ruby]

The objects can now be created using the factory methods available to all specifications.

[ruby]
doug = create_user
doppelganger = mock_user
[/ruby]

Update
Added links to Chris Wanstrath and Daniel Manges’ articles on managing Rails fixtures.

Comments Off more...

Behaviour Driven Development with RSpec slides

by Doug on Jul.26, 2007, under Behaviour Driven Development, Ruby

Here’s my slides for the talk on Behaviour Driven Development and RSpec at the July 2007 singapore.rb meeting. It might not make much sense if you weren’t at the meeting.

Comments Off more...

The Business of Software

by Doug on Jul.08, 2007, under Entrepreneurship

Joel Spolsky has a new wiki launched for aggregating information related to the business of software. It’s pretty spare right now, with a handful of content largely on microISVs. Still, it could turn out to be a good resource for people starting out on their first software enterprise.

1 Comment more...

Joining Bezurk

by Doug on May.22, 2007, under General

I’m excited to announce that I’ll be joining Bezurk as a Ruby on Rails Developer starting the middle of June. The startup is providing some extremely interesting services in the online travel booking space with tons of potential for growth.

Bezurk is currently continuing to recruit Rails developers to join the team. You’ll be working in a great location, interacting with smart people and challenged with building easy to use web applications that help people plan their holidays :) .

3 Comments more...

RSpec your functional tests

by Doug on May.10, 2007, under Behaviour Driven Development, Ruby

The release of RSpec 0.9.4 can be considered a landmark release of sorts. With the inclusion of Spec::Ui 0.2.0, RSpec can now perform functional testing of web applications within a browser. Out of the box support is limited to Watir/Internet Explorer for now as the Selenium RC custom matchers are not implemented yet. includes WATIR/Windows and Watirsafari/OSX. The custom matchers for Selenium RC are not implemented yet but its certainly possible to use Selenium with Spec::Ui, it just won’t read as nicely compared to WATIR. Spec::Ui also comes with a custom result formatter that packages a screenshot of the browser on spec failure, along with its HTML source in the report.

To use Watirsafari in your functional specs, you’ll need to install the gem for it: gem install watirsafari

spec_helper.rb should be updated to include the snippet below (code lifted from the original release announcement):

[ruby]
Spec::Runner.configure do |config|
config.include Spec::Matchers::Watir
end
[/ruby]

The specification will need before and after blocks like this:
[ruby]
before(:all) do
@browser = Watir::Browser.new
end

after(:each) do
# This is needed to make screenshots work
Spec::Ui::ScreenshotFormatter.browser = @browser
end

after(:all) do
@browser.kill! rescue nil
end
[/ruby]

There are a lot more useful information available in the examples supplied with Spec::Ui. Take a look at the samples to get up and running.

Update
My thanks to Aslak Hellesoy for correcting me on support for WATIR and Selenium.

1 Comment more...

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

Visit our friends!

A few highly recommended friends...