This post follows on from my previous post about gocheck. gocheck uses a checker abstraction to test arbitrary properties in tests, in the previous post for example we used the Equals and Panic checkers to test our code. It is very simple to write your own checkers and I will walk through some more complicated checker in this post. Read more…
I’ve been working with parsing number literals in Smalltalk recently. I’ve discovered a small collection of tricks not entirely explained in PetitParser’s otherwise excellent documentation, so I thought I’d share my experiences:
Squeak Smalltalk ships with an, ahem, mildly controversial feature: a case statement. Case statements usually evoke “but that’s not OO!” from people, usually with good reason: a complicated case statement only gets less understandable as it evolves, while a State implementation’s complexity remains more or less constant. (You can concentrate on only the bit you care about; a nightmare case statement requires you to know about a great deal more code.)
And yet. And yet, I managed to extend Andreas Raab’s DNSClient library[1] to parse SRV and NAPTR records by adding a single statement each, thanks to a case statement.
So with my hat firmly in the pragmatist corner (as opposed to the ideologically pure corner, for a change), let’s use our new unification library, and build a pattern matching (really, a unifying) case statement.
The Go programming language comes with a simple built in test framework testing - this is usable and functional but is lacking in features that you might find in other languages test frameworks. A more fully featured testing framework called gocheck has been developed by Gustavo Niemeyer, this blog post walks through developing an extremely simple go program using gocheck.
The code we will try and produce is a package for editing two dimensional images such as icons. To start with lets write a minimal implementation of the library and a test. We will use a struct that holds a two dimensional array of integers and the size of the image and add a New function so that we can hide the underlying array from consumers of the library.
package image
type Image struct {
M, N int
content [][]int
}
func New(M, N int) *Image {
c := make([][]int, M, M)
for i := 0; i < M; i++ {
c[i] = make([]int, N, N)
}
return &Image{N, M, c}
}
For the first test I would really like not to be able to create images with negative sizes and would like the library to panic if that happens. gocheck allows panics to be tested for so this is our first basic test.
package image
import (
. "launchpad.net/gocheck"
"testing"
"os"
)
// This plumbs gocheck into testing
func Test(t *testing.T) {
TestingT(t)
}
// This is a fixure used by a suite of tests
type S struct{}
var _ = Suite(&S{})
// This is a test
func (s *S) TestNew(c *C) {
c.Assert(func(){New(-1, -2)}, Panics, os.NewError("Bang"))
}
Now I run the test!
make test gotest rm -f _test/test.a 8g -o _gotest_.8 image.go image_test.go rm -f _test/test.a gopack grc _test/test.a _gotest_.8 ---------------------------------------------------------------------- PANIC: image_test.go:16: test.S.TestNew ... Panic: runtime error: makeslice: len out of range (PC=0x8056ABA) /home/tim/Tools/go/src/pkg/runtime/proc.c:1041 in runtime.panic /home/tim/Tools/go/src/pkg/runtime/runtime.c:116 in runtime.panicstring /home/tim/Tools/go/src/pkg/runtime/slice.c:22 in runtime.makeslice image.go:9 in test.New image_test.go:17 in test.S.TestNew OOPS: 0 passed, 1 PANICKED --- FAIL: image.Test (0.01 seconds) FAIL gotest: "./8.out" failed: exit status 1 make: *** [test] Error 2
It has failed, a panic occurred but not the panic I expected, so lets modify the New function to produce a specific panic if negative sizes are passed in.
const newError = "An image dimension cannot be negative (M = %d N = %d)"
func New(M, N int) *Image {
if M < 0 || N < 0 {
panic(fmt.Errorf(newError, M, N))
}
c := make([][]int, M, M)
for i := 0; i < M; i++ {
c[i] = make([]int, N, N)
}
return &Image{N, M, c}
}
Running the tests again produces a pass.
make test gotest rm -f _test/test.a 8g -o _gotest_.8 image.go image_test.go rm -f _test/test.a gopack grc _test/test.a _gotest_.8 OK: 1 passed PASS
Now lets provide a function to allow values to be read from the image, to add a small wrinkle let us make the origin of the image be at (1, 1) as opposed to (0, 0). Additionally in go style let us return an error with the result in a similar way to go maps. We use two auxiliary methods and a function to check that coordinates are valid.
func check(val, limit int) bool {
return val > 0 && val <= limit
}
func (i Image) checkX(x int) bool {
return check(x, i.M)
}
func (i Image) checkY(y int) bool {
return check(y, i.N)
}
func (i Image) ValueAt(x, y int) (value int, ok bool) {
if i.checkX(x) && i.checkY(y) {
return i.content[x - 1][y - 1], true
}
return 0, false
}
The accompanying test looks like this:
func (s *S) TestNewShouldPanicWithNegatives(c *C) {
c.Assert(func() { New(-1, -2) }, Panics, fmt.Errorf(newError, -1, -2))
}
func (s *S) TestNew(c *C) {
c.Assert(New(1, 2), NotNil)
}
func (s *S) TestValueAt(c *C) {
i := New(1, 2)
v, ok := i.ValueAt(-1, 2)
c.Assert(v, Equals, 0)
c.Assert(ok, Equals, false)
v, ok = i.ValueAt(1, 1)
c.Assert(v, Equals, 0)
c.Assert(ok, Equals, true)
}
Running this gives us another pass.
make test gotest rm -f _test/test.a 8g -o _gotest_.8 image.go image_test.go rm -f _test/test.a gopack grc _test/test.a _gotest_.8 OK: 3 passed PASS
Now lets add a function to put data into the image pixel, by pixel, this function also returns a value to indicate whether the pixel value was set, if you attempt to set a pixel outside of the image it will return false.
func (i* Image) SetValueAt(x, y, v int) (ok bool) {
if i.checkX(x) && i.checkY(y) {
i.content[x - 1][y - 1] = v
return true
}
return false
}
With an accompanying test:
func (s *S) TestSetValueAt(c *C) {
i := New(1, 2)
c.Assert(i.SetValueAt(-1, -2, 3), Equals, false)
c.Assert(i.SetValueAt(1, 2, 3), Equals, true)
v, ok := i.ValueAt(1, 2)
c.Assert(v, Equals, 3)
c.Assert(ok, Equals, true)
}
Which will of course pass.
make test
gotest
rm -f _test/test.a
8g -o _gotest_.8 image.go image_test.go
rm -f _test/test.a
gopack grc _test/test.a _gotest_.8
----------------------------------------------------------------------
FAIL: image_test.go:36: test.S.TestSetValueAt
image_test.go:39:
c.Assert(i.SetValueAt(1, 2, 3), Equals, true)
... obtained bool = false
... expected bool = true
OOPS: 3 passed, 1 FAILED
--- FAIL: image.Test (0.01 seconds)
FAIL
gotest: "./8.out" failed: exit status 1
make: *** [test] Error 2
And I have been overconfident, aarghhhhh! why doesn’t it pass? Much pondering later I realised that I was having problems with my alphabet in my New function since I swap N for M when I construct the struct. The correct New function looks like this:
func New(M, N int) *Image {
if M < 0 || N < 0 {
panic(fmt.Errorf(newError, M, N))
}
c := make([][]int, M, M)
for i := 0; i < M; i++ {
c[i] = make([]int, N, N)
}
return &Image{M, N, c}
}
Running the tests again:
make test gotest rm -f _test/test.a 8g -o _gotest_.8 image.go image_test.go rm -f _test/test.a gopack grc _test/test.a _gotest_.8 OK: 4 passed PASS
Now I refactor my test to removes some of the duplication and put some common code into the fixture.
type S struct{
i *Image
}
func (s *S) SetUpTest(c *C) {
s.i = New(1, 2)
}
func (s *S) TearDownTest(c *C) {
s.i = nil
}
func (s *S) TestValueAt(c *C) {
v, ok := s.i.ValueAt(-1, 2)
c.Assert(v, Equals, 0)
c.Assert(ok, Equals, false)
v, ok = s.i.ValueAt(1, 1)
c.Assert(v, Equals, 0)
c.Assert(ok, Equals, true)
}
func (s *S) TestSetValueAt(c *C) {
c.Assert(s.i.SetValueAt(-1, -2, 3), Equals, false)
c.Assert(s.i.SetValueAt(1, 2, 3), Equals, true)
v, ok := s.i.ValueAt(1, 2)
c.Assert(v, Equals, 3)
c.Assert(ok, Equals, true)
}
Now it would be handy to actually see the image so lets make it to conform to the Stringer interface required by the various Print* functions in the fmt package. First the test:
func (s *S) TestString(c *C) {
var stringer fmt.Stringer
c.Assert(s.i, Implements, &stringer)
}
Which fails:
make test
gotest
rm -f _test/test.a
8g -o _gotest_.8 image.go image_test.go
rm -f _test/test.a
gopack grc _test/test.a _gotest_.8
----------------------------------------------------------------------
FAIL: image_test.go:54: test.S.TestString
image_test.go:56:
c.Assert(s.i, Implements, &stringer)
... obtained *image.Image = &image.Image{M:1, N:2, content:[][]int{[]int{0, 0}}}
… ifaceptr *fmt.Stringer = (*fmt.Stringer)(0×500017a8)
OOPS: 4 passed, 1 FAILED
— FAIL: image.Test (0.01 seconds)
FAIL
gotest: “./8.out” failed: exit status 1
make: *** [test] Error 2
I add a simple String function:
func (i Image) String() string {
return "Image"
}
And the tests pass:
make test gotest rm -f _test/test.a 8g -o _gotest_.8 image.go image_test.go rm -f _test/test.a gopack grc _test/test.a _gotest_.8 OK: 5 passed PASS
So we have some basic functionality and it is all tested. Next time I will extend this example and write a custom checker for gocheck to help out.
It’s time to visit another Smalltalk PEG parser. We’ve seen OMeta2, and now it’s time for a rather different approach to parsing. Lukas Renggli wrote PetitParser, a parser library based on parser combinators. Read more…
I am working towards finishing a small project in go and my thoughts have turned to how I will package it up and release the code. The latest release of go has made some changes to goinstall so that code installed by you as a user can be kept separate from the base installation of go.
The first step in using goinstall is to create a directory structure for your local source, packages and binaries. This can be done like this
% cd ~/work % mkdir -p gocode/src gocode/pkg gocode/bin
You can then create a GOPATH variable:
export GOPATH=~/work/gocode
Now any go projects can be placed in the $GOPATH/src directory and installed locally, you don’t even need to write makefiles.
For example:
% cd ~/work/gocode/src % mkdir -p experiment/plutonium
Now create a file experiment.go in the directory:
package plutonium
import (
"fmt"
)
func ExperimentOne(s string) string {
return fmt.Sprintf("! DANGER ! %s ! DANGER !", s)
}
Now this code can be installed locally making it available to your other go projects:
% cd ~/work/gocode/src/experiment/plutonium % goinstall . % ls -l ~/work/gocode/pkg/linux_386/experiment -rw-r--r-- 1 tim tim 9004 Jun 30 13:29 plutonium.a
You can also create executable programs:
% cd ~/work/gocode/src % mkdir -p experiment/bang % cd experiment/bang
Create a file called main.go:
package main
import (
"experiment/plutonium"
"log"
)
func main() {
log.Print("Running experiment", plutonium.ExperimentOne("Highly dangerous"))
log.Print("Careful now")
}
Install and run the program:
% cd ~/work/gocode/src/experiment/bang % goinstall . % cd ~/work/gocode/bin % ./bang 2011/06/30 13:38:45 Running experiment! DANGER ! Highly dangerous ! DANGER ! 2011/06/30 13:38:45 Careful now
So no Makefiles are needed! I would still create Makefiles because you will need them if you want to use gotest to run your unit tests.
“A zipper is a[n editable] suspended walk.”[1]
Take a map: it takes some traversable structure, executes a function on each element, and returns a new traversable structure with the values obtained by applying the function to the elements of that structure.
Define a function that returns a pair (value, partial continuation) where the partial continuation represents the path taken to reach a particular value. This is a zipper on the given value.
It doesn’t particularly matter which control operators you use to get that partial continuation. shift/reset’s convenient because I’ve already implemented it, but Chung-chieh Shan showed that they’re all equally expressible.
Finally, give the map over the suspensible walk a function that composes the partial continuation with a “decider” function. This function takes some value and either returns that value, or the value of the node associated with the zipper.
This gives you a zipper on the first node. When you feed a value into the zipper, it returns you a new zipper, on the next node in your structure. When you’ve reached the end of your traversal, return a zipper that indicates that you’ve finished the traversal.
Hey presto, you have a zipper, derived from the traversal of an arbitrary structure.
So what’s that look like in Smalltalk?
I’ve recently acquired a Kindle, and although it’s major use-case is for reading books, it’s also pretty good for reading long articles. This is particularly useful when I find out about said article via my phone (e.g. on Twitter) as my phone isn’t exactly good for reading anything really big. I started using the Send To Kindle app, but as it turns out that it does exactly what the name might suggest is actually a bad thing! The app attempts to do everything on it’s own, and as Amazon need to be sent an entire document to get stuff onto a Kindle, my phone gets tied up for multiple minutes in some cases, and that’s in the good case when I’ve got lots of bandwidth…
What would be a slightly more sensible option is just being able to send the URL of the article to Amazon, but as that isn’t an option, we need an intermediary, something else willing to do all the hard work of grabbing a page and sending it off for me. Read more…
Magritte is a metamodel description framework for Smalltalk, that is, a way of describing your domain objects. Having a description of your domain objects allows you to do a bunch of neat things, like automatically building a Seaside form for displaying an object.
If you’ve used C#’s ASP.Net MVC framework, you might think of the Magritte description as the collection of annotations your Model or ViewModel objects might have. Instead of
public class Person {
[DisplayName("First Name")]
public string FirstName { get; set; }
[DisplayName("Last Name")]
public string LastName { get; set; }
}
you have
Person class>>descriptionFirstName
^ MAStringDescription new
label: 'First Name';
yourself
Person class>>descriptionLastName
^ MAStringDescription new
label: 'Last Name';
yourself
Magritte allows you to describe more than how to render a field, or in what order to render fields. It allows you to describe how to access the parts of an object, whether directly calling its selector, plugging into a chain of accessors, or a memento-decorated object, and so on. Magritte can also describe the relationships between objects, like one-to-one or one-to-many.
Magritte provides us with a uniform way of accessing parts of an object, without resorting to reflection.
How would one zip over a tree of Magritte-described objects? Building on our previous work it’s not hard at all: we have an n-ary tree of objects. First, we make sure we fully annotate our domain objects with Magritte descriptions.
Next, we do two things: first, Magritte allows us to serialise all our children as an OrderedCollection:
MZBase>>children
^ self description children collect: [:each | each accessor read: self].
and so we can unserialise this collection as a newly-instantiated object:
Object>>withValues: aCollection
^ self new.
MZBase>>withValues: aCollection
"Conceptually this mirrors Scala's apply, in a variadic manner."
| o |
"Create a new object, of the appropriate type."
o := self new.
"Initialise it. Each setter returns a _new instance_ so while functionally
pure, this isn't exactly efficient."
"#with:do: is a pair-wise version of #do:."
o description children with: aCollection do:
[:acc :val | o := acc accessor write: val to: o].
^ o.
We need to adjust our original TreeZipper, which had a few hard-coded bits. We change references to TreeZipper new to self class new, and instead of creating ZTrees with ZTree value: foo children: bar we allow subclasses to create their own objects: self newFocusOn: foo children: bar. In particular, we say
TreeZipper subclass: #MagritteZipper.
MagritteZipper>>newFocusOn: anObject children: aCollection
^ aCollection isEmpty
ifTrue: [anObject]
ifFalse: [anObject class withValues: aCollection].
We’re being a bit tricky here: if aCollection is empty, we have a “primitive” value - something with no subcomponents, like a number or a String[1] - while a non-empty aCollection indicates some composite object: an MZBase object.
And that’s it!
| p p2 z |
p := MZPerson firstName: 'Foo' lastName: 'Bar' at: (MZAddress at: 'foo').
z := MagritteZipper on: p.
p2 := ((z down changeTo: 'Barzzz') right changeTo: 'Brzz') root.
p2 firstName --> 'Barzzz'
As always, everything’s available at SqueakSource. Here’s the load script:
Installer ss
project: 'Seaside31';
install: 'Grease-Core-pmm.39';
install: 'Grease-Pharo-Core-pmm.22'.
Installer lukas
project: 'magritte2';
install: 'Magritte-Model-fbs.405';
install: 'Magritte-Pharo-Model-lr.22'.
Installer ss
project: 'Zippers';
install: 'Zippers-fbs.35'.
Installer ss
project: 'MagZip';
install: 'MagZip-fbs.2'.
[1] Yes, a String’s actually an OrderedCollection of Character, but usually the individual characters aren’t interesting, so we treat it as a primitive value.
Veritas cluster server is often used in corporate environments to provide clustering and high availability. Veritas is a complex, closed source product that provides integration for lots of enterprise software such as SAP or Oracle, but it is very simple to use it to cluster open source software as well.
In order for Veritas to manage a piece of open source software you need to provide three scripts; a script to start the service, a script to stop the service and a script that monitors the status of the software. The start and stop scripts don’t need any special knowledge they just need to start and stop the service, if the application has an init.d script that should be sufficient for the start and stop script.
So if we have a mythical open source application called gherkin then the Veritas agent can be configured to use this as a start script:
/etc/init.d/gherkin start
and this for the stop script:
/etc/init.d/gherkin stop
Unfortunately Veritas doesn’t use standard UNIX return codes for monitoring it has its own numeric values, namely 110 for an active service and 100 for an inactive service, so you will need to provide a script to map the services status to these numbers.
For example if our mythical open source application returns status from its init.d script then we will need a script like this:
#!/bin/bash if /etc/init.d/gherkin status &> /dev/null; then exit 110 else exit 100 fi
This maps a standard UNIX successful return code to the Veritas success code, 110, and everything else to the Veritas failure code, 100.