Archive for June, 2006
Whilst discussing presentation software the other day with a colleague, he kindly pointed me at S5. It is simple, it is standards-based, and it is a slide show system. In short, it does exactly what is says on the tin:
S5 is a slide show format based entirely on XHTML, CSS, and JavaScript. With one file, you can run a complete slide show and have a printer-friendly version as well. The markup used for the slides is very simple, highly semantic, and completely accessible. Anyone with even a smidgen of familiarity with HTML or XHTML can look at the markup and figure out how to adapt it to their particular needs. Anyone familiar with CSS can create their own slide show theme. It’s totally simple, and it’s totally standards-driven.
June 21st, 2006
lee
On a modern PC, the motherboard controls the power to the CPU fan, and has sensors that monitor the temperature of the CPU and the speed at which the fans are spinning. The slower the fan spins, the quieter it is, so it’s desirable to monitor the CPU temperature and adjust the fan speed appropriately.
Under Linux, the lm-sensors package is responsible for hardware monitoring and control. It comes with a script, “fancontrol”, which is meant for this exact job; every ten seconds, it reads the CPU temperature, and adjusts the fan power. This way it can trade off a hotter CPU for a quieter system, while keeping the CPU temperature within acceptable limits.
Unfortunately, its algorithm for choosing the fan power doesn’t work well on my system.
Continue Reading June 20th, 2006
Paul Crowley
I was recently asked to code up a bi-directional unbounded buffer in the pi-calculus, i.e. a process parameterised by two names x,y that buffers all values received on x and y, and outputs them on y and x respectively. Here is what I came up with, in the syntax of MWB:
agent Cell(c,v,n) = 'c<v>.'c<n>.0
agent Waiting(x,c,n) = x(v).(^ m)(Cell(n,v,m) | Waiting(x,c,m)) \
+ c(w).c(c).Ready(x,c,n,w)
agent Ready(x,c,n,w) = x(v).(^ m)(Cell(n,v,m) | Ready(x,c,m,w)) \
+ 'x<w>.Waiting(x,c,n)
agent Buffer(x,y) = (^ n,m)(Waiting(x,n,m) | Waiting(y,m,n))
Stepping through a few possible traces of the Buffer process in MWB produces the expected result. The main complication in the implementation is the need to prevent the ends of the buffer from consuming their own outputs. This means they cannot be implemented as a parallel composition of an input and output process; we have to use a choice instead.
It should be the case that Buffer(x,y) is weakly bisimilar to (^ z)(Buffer(x,z) | Buffer(z,y)). Unfortunately MWB goes into a spin when trying to prove this, probably because the Buffer process has infinitely many states (since it is an unbounded buffer).
June 17th, 2006
matthias
Q: When is (i != 0) equivalent to
((i >= 0) && ((i >= -1073741824) && (i < 1073741824)))
?
A: When GCC 4.0.4’s -O, -O1, -O2 or -O3 is used on it.
See GCC bug 28042. Particularly interesting is that removing the redundant set of parentheses around the second && avoids the optimiser bug.
June 16th, 2006
tonyg
Print envy is typically satisfied by producing pictures of text in the desired font with the desired special effects. Now it’s trendy to pay attention to standards and accessibility guidelines, however, it’s become clear that this approach is inadequate.
Continue Reading June 16th, 2006
mikeb
Peter Van Roy recently claimed
(article,
slides) that
there are signs of a Definitive Programming Language emerging that,
as he put it, gives
good solutions at its level of abstraction, allowing computer
science researchers to move on and work at higher levels.
The argument is based on the observation that four languages,
designed independently and for different purposes all arrived at
the same layered language design of
- strictly functional language at the core
- deterministic concurrency (aka dataflow concurrency)
- asynchronous message passing
- global mutable state
The claim is that the odds of this happening at random are the same as
lightning striking in the same place four times and that instead we
should consider this particular language structure as a definitive
design that arises naturally and inevitably.
Unfortunately these claims do not stand up to scrutiny.
Continue Reading June 13th, 2006
matthias
Those of you with an interest in interactive fiction who’ve not yet checked out Inform 7 - run, do not walk, to your nearest mac or windows machine and have a go! (Sadly, the IDE hasn’t been ported to Linux yet.)
I spent quite a few hours over the weekend building a toy game using I7, and I really enjoyed the experience. I may yet get round to dusting off my old MUD engine and freshening up its parser a little…
June 12th, 2006
tonyg
In my continued
experiments with
Maude I have been investigating its I/O
system and, more generally, how to integrate Maude with other systems
and extend its built-in capabilities.
Libraries are arguably Maude’s weakest point. The standard libraries
are very rudimentary. Furthermore, there is no FFI, so there is no
easy way to hook in third party libraries. As we shall see, this is
actually less of a problem than it may seem.
Continue Reading June 11th, 2006
matthias
I have been looking for something to help me do some automated functional tests on an existing web application, and came across Selenium. It is a framework that executes tests from within a browser using a combination of Javascript and DHTML. It supports IE, Firefox and Mozilla, thus allowing browser compatibility testing.
There are three Selenium components:
The latter component provides an easy way in and so I looked at this first.
Selenium IDE
I decided to use a source build (2006-05-19) as the project looked active and I like to tinker. The build was very straightforward and once installed there was a “Selenium IDE” entry in the tools menu. Clicking this brings up the IDE window:
I tried it out on the BBC News site as it is publicly available and has good quality HTML. The “record” button in the IDE is depressed at startup so I just entered http://news.bbc.co.uk/ into the location bar in my browser and the site appeared. Nothing happened in the IDE window though - it waits for the first action within the site itself before updating. For the first test suite, I limited myself to simple link checking. Clicking on “World” in the BBC site navigation brings up the page as expected, but also updates the IDE window:
The base URL has been filled in. All test commands apply to relative paths meaning that tests can be run on development, stage and production servers just by changing this field. The actions have also been populated:
open; command to open a URL. This can be relative or absolute but as mentioned above, relative URLs will allow your tests to be used on different hosts.
assertTitle; after each page load, Selenium IDE will automatically insert an assertion to check the title. This can be disabled in the “Options” dialog.
clickAndWait; clicks an item in the page. The “AndWait” suffix is available on several of the commands and forces the IDE to wait for a page load before continuing. Depending on how a link is constructed, for example, where Javascript is used to load the next page, the IDE may not recognize that it has to wait and may just record a click command. In these cases you must manually change the command otherwise the subsequent tests may be applied to the wrong page.
The target for the click is shown as link=World which means Selenium looks for a hyperlink with the visible text of “World”. The Selenium Core reference has more information on how elements can be located.
To build up the test I continued to go through and click the other navigation links, i.e., UK, England, Northern Ireland, etc. I then clicked the “Play” button and Selenium directs the browser through the path just taken and checks the specified assertions. Commands that succeeded are coloured green in the IDE and those that failed will turn red:
Selenium supports several formats for test scripts but the IDE supports just two; HTML (also known as Selenese) and Ruby. HTML is the easiest to parse for non-programmers, and the default. It is visible in the “Source” tab:
I saved this test to disk and created a new blank test.
Selenium also supports forms and so in the search box at the top of the BBC News website, I entered theo and clicked “Search”. The IDE shows these actions including the command type. The target is listed as just q which is the name of the input element where the typing should go:
One thing to note is that the BBC uses a separate host for searching (search.bbc.co.uk). The tests will run in the IDE because it is a Firefox extension, but they will not work in Selenium Core or RC because Javascript is security restricted to making calls to the page origin host and port only (See “The Same Origin Policy“).
The football player, Theo Walcott, has been in the news a lot so I want to assert that his name comes back in the search results. I highlight the text “Walcott”, right click on the selection and then click “assertTextPresent Walcott”:
This creates an entry in the IDE that checks that the text “Walcott” is present somewhere in the document:
It is possible to do a more precise check for text. Looking at the web page source code, the search summary “Page 1 of 145 pages for theo” is contained within a paragraph. In the IDE, I click the row below the last command in the IDE and below the test list, select “assertText” in the Command column. In the Target column, I enter the XPath that identifies that paragraph element: //p[@class='bodymainResults allmainr borders']. Clicking on “Find” in the IDE will flash the selected node (this requires the DOM Inspector to be installed):
Because the actual number of pages will change, I use a wildcard to match this part of the text and enter Page 1 of * pages for theo in the “Value” column:
Selenium Core and RC
The Selenium Core component contains the main test runner. A web page within the test runner directory provides the necessary controls to run the tests.
Because of the same origin restriction and the fact that I could not deploy Selenium Core onto the BBC web site, I used Selenium RC to automate the test running. As well as a server that can launch browsers and initiate the tests, it contains a proxy server that makes it look like the Selenium Core test runner is hosted on the target web site.
Both of these components can be driven using various languages, e.g., Java, .NET, Python, Ruby. They can also use the HTML style tests that were saved from the IDE and this is the most interesting method of test execution for me at the moment as it allows non-programmers, i.e., not me, to build up test suites.
Selenium RC works with test suites rather than the test files themselves. A test suite file is a HTML document with a table referring to the test files:
<html>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">
<title>Test Suite</title>
</head>
<body>
<table id="suiteTable" cellpadding="1" cellspacing="1" border="1">
<tbody>
<tr><td><b>Test Suite</b></td></tr>
<tr><td><a href="./check-nav-links.html">Check nav links</a></td></tr>
</tbody>
</table>
</body>
</html>
I put the test suite and test files into a directory along with “server/selenium-server.jar” from the Selenium RC distribution. I launched the server and tests via the following command line (Windows):
java -jar selenium-server.jar -htmlSuite "*firefox" "http://news.bbc.co.uk" "C:\selenium-rc\test-suite.html" "C:\selenium-rc\test-output.html"
This launches the proxy server, forwarding non-Selenium requests onto “http://news.bbc.co.uk”. It then launches the designated browser, in this case, Firefox. Internet Explorer can be launched by substituting "iexplore” for "firefox”. I found that occasionally IE would try and run the tests before the proxy server was fully functional and would therefore trigger a 404 error (Release 0.7.1. Release 0.8 is already out and so this may be fixed). This is because the Selenium specific URL does not exist, e.g.:
http://news.bbc.co.uk/selenium-server/TestRunner.html?auto=true&test=http://news.bbc.co.uk/selenium-server/test-suite.html
Other browsers can also be launched and the documentation has details on how to do this. When using Firefox or IE, a new profile is created in the current working directory.
Once the browser is launched, it ran the core test runner via the proxy:
A HTML copy of the report was written to disk when it finished.
It is also possible to run the server in interactive mode. The documentation gives some good examples of this.
Conclusion
Selenium provides a quick and powerful way to write functional tests for web applications, and an environment where they can be run across different hosts. I am sufficiently impressed that I am looking for projects which could benefit from this approach.
Ideally, I would like the tests to integrate with Ant, NAnt or Maven. Because Selenium RC can be driven via Java, this should not be a problem; use a JUnit TestDecorator to start and stop the proxy server and JUnit setup and tear down methods to control the browser instances. Reading the tests from HTML format is a little trickier but a new major version has just been released and contains a tool to convert Selenese HTML tests to Java.
No doubt there are other goodies in the new release too which I shall report on in due course.
June 8th, 2006
lee
I was looking around for an easy-to-use, no-fuss command line tool to check the links on a web site. First I tried wget:
wget -o wget.log -nv -r -p <site>
The resulting wget.log contains all the links that were followed. It’s easy to spot the errors but there is no obvious way to get hold of the referrer.
Next was linkchecker:
linkchecker -t3 --no-warnings -Fblacklist/blacklist.out http://<site> > linkchecker.log
This produces a list of broken links in blacklist.out. There is no referrer information in that, but one can get hold of it by cross-referencing the full log in linkchecker.log. That is not entirely trivial though; it’s certainly beyond grep. More significantly, linkchecker seems to run forever and checking the same links over and over again - I gave up after it had spent 1 hour and checked 100,000 links on a site that contains no more than a few hundred actual links.
Finally, I tried linklint:
linklint -error -warn -xref -forward -out linklint.out -net -http -host <site> /@
This completed in a few minutes and produced a nice report in linklint.out. The report contains a summary of the kinds of links, files and errors found, a per-referrer break-down of all broken links, and a list of all moved URLs referenced by the site. This is pretty much exactly what I was after!
All three tools are available as debian packages. linklint development seems to have stopped a few years ago, yet it was the best of the bunch for what I was trying to achieve. YMMV.
June 8th, 2006
matthias
Next Posts
Previous Posts