Added tests and test data, refactored where needed (#4)
Added tests and closes #2 . - [x] Added tests, including defensive tests - [X] Code coverage is 87.8% - [X] Added testdata - [X] Refactored where needed Co-authored-by: Nicolas Herry <beastieboy@beastieboy.net> Reviewed-on: http://www.beastieboy.net:3000/git/beastieboy/marmotte/pulls/4 Co-authored-by: beastieboy <beastieboy@beastieboy.net> Co-committed-by: beastieboy <beastieboy@beastieboy.net>pull/9/head
parent
c1fb7f09f8
commit
22ac3810bd
@ -0,0 +1,136 @@ |
||||
package gopher |
||||
|
||||
|
||||
import ( |
||||
"testing" |
||||
"os" |
||||
|
||||
// "github.com/google/go-cmp/cmp"
|
||||
) |
||||
|
||||
func DummyRequestTransformer(c *Context, rq *Request, rs Response, err error) (*Context, *Request, Response, error) { |
||||
return c, rq, rs, err |
||||
} |
||||
|
||||
func DummyRequestPredicate(c Context, rq Request, rs Response, err error) bool { |
||||
return true |
||||
} |
||||
|
||||
func TestAddRequestTransformer(t *testing.T) { |
||||
d, _ := os.Getwd() |
||||
c := Context { Root: d + "/../testdata" } |
||||
|
||||
rt := RequestTransformer { Transformer: DummyRequestTransformer, |
||||
Predicate: DummyRequestPredicate, |
||||
} |
||||
|
||||
expected := len(c.RequestTransformers) |
||||
expected++ |
||||
c.AddRequestTransformer(rt) |
||||
got := len(c.RequestTransformers) |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected number of RequestTransformer instances in context after adding a valid transformer: expected %d, got %d", |
||||
expected, got) |
||||
} |
||||
|
||||
rt = RequestTransformer { Transformer: DummyRequestTransformer, |
||||
Predicate: nil, |
||||
} |
||||
|
||||
_, err := c.AddRequestTransformer(rt) |
||||
got = len(c.RequestTransformers) |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected number of RequestTransformer instances in context after adding an invalid transformer: expected %d, got %d", |
||||
expected, got) |
||||
} |
||||
|
||||
if err == nil { |
||||
t.Error("Expected an error after adding an invalid Transformer to a context, didn't get any") |
||||
} |
||||
} |
||||
|
||||
func TestAddRequestTransformerFor(t *testing.T) { |
||||
d, _ := os.Getwd() |
||||
c := Context { Root: d + "/../testdata" } |
||||
|
||||
p := "/" |
||||
|
||||
expected := len(c.RequestTransformers) |
||||
expected++ |
||||
_, err := c.AddRequestTransformerFor(p, DummyRequestTransformer) |
||||
|
||||
if err != nil { |
||||
t.Errorf("Unexpected error when adding a valid Transformer to a context for a valid path: Path=%s, error=%s", p, err) |
||||
} |
||||
|
||||
got := len(c.RequestTransformers) |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected number of RequestTransformer instances in context after adding a valid transformer: expected %d, got %d", expected, got) |
||||
} |
||||
|
||||
_, err = c.AddRequestTransformerFor(p, nil) |
||||
|
||||
got = len(c.RequestTransformers) |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected number of RequestTransformer instances in context after adding an invalid transformer: expected %d, got %d", |
||||
expected, got) |
||||
} |
||||
|
||||
if err == nil { |
||||
t.Error("Expected an error after adding an invalid Transformer to a context, didn't get any") |
||||
} |
||||
|
||||
expected = len(c.RequestTransformers) |
||||
|
||||
p = ".*aa[" |
||||
gotTransformers, err := c.AddRequestTransformerFor(p, DummyRequestTransformer) |
||||
|
||||
got = len(gotTransformers) |
||||
|
||||
if err == nil { |
||||
t.Errorf("Expected an error after using an invalid pattern to add a RequestTransformer to a context, got none, for pattern %s", p) |
||||
} |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected number of RequestTransformer instances in context after adding an invalid path %s, expected %d, got %d", p, expected, got) |
||||
|
||||
} |
||||
} |
||||
|
||||
func TestDefaultResponseTransformers(t *testing.T) { |
||||
d, _ := os.Getwd() |
||||
c := Context { Root: d + "/../testdata" } |
||||
|
||||
c.DefaultResponseTransformers() |
||||
|
||||
files := map[string]string{ |
||||
"gophermapfile":"/gophermap", |
||||
"textfile": "/attic/Goblin_Market", |
||||
"binaryfile": "/attic/cat", |
||||
"imagefile": "/attic/pictures/hamtori.gif", |
||||
"audiofile": "/attic/audio/Bubbles-SoundBible.com-810959520.mp3", |
||||
} |
||||
|
||||
for ft, fp := range files { |
||||
|
||||
rq, _ := NewRequest(c, fp) |
||||
rs := NewResponse(c, *rq) |
||||
found := false |
||||
var err error = nil |
||||
|
||||
for _, t := range c.ResponseTransformers { |
||||
if t.Predicate(c, *rq, *rs, err) { |
||||
found = true |
||||
} |
||||
} |
||||
|
||||
if found != true { |
||||
t.Errorf("No predicate returned true for base file type %s, with path %s", ft, fp) |
||||
} |
||||
} |
||||
} |
||||
|
@ -0,0 +1,76 @@ |
||||
package gopher |
||||
|
||||
import ( |
||||
"testing" |
||||
"os" |
||||
) |
||||
|
||||
func TestFileType(t *testing.T) { |
||||
d, _ := os.Getwd() |
||||
c := Context { Root: d + "/../testdata" } |
||||
|
||||
files := map[string]ResponseType {c.Root + "/attic/Goblin_Market": PlainText, |
||||
c.Root + "/attic/pictures/starry_night.jpg": Image, |
||||
c.Root + "/attic/pictures/hamtori.gif": Image, |
||||
c.Root + "/attic/audio/Bubbles-SoundBible.com-810959520.mp3": Audio, |
||||
c.Root + "/": Directory, |
||||
} |
||||
|
||||
for f, expected := range files { |
||||
got, err := FileType(f) |
||||
|
||||
if err != nil { |
||||
t.Errorf("Error determining the file type of %s: %s", f, err) |
||||
} |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected file type for %s: expected %d, got %d", f, int(expected), int(got)) |
||||
} |
||||
} |
||||
|
||||
p := "/attic/non-existent" |
||||
|
||||
_, err := FileType(p) |
||||
|
||||
if err == nil { |
||||
t.Errorf("Expected an error when calling FileType with a non-existent path %s, didn'r receive any", p) |
||||
} |
||||
} |
||||
|
||||
|
||||
func TestGopherMap(t *testing.T) { |
||||
d, _ := os.Getwd() |
||||
c := Context { Root: d + "/../testdata" } |
||||
|
||||
lines, err := GopherMap(c, "") |
||||
|
||||
expected := true |
||||
got := len(lines) > 0 |
||||
|
||||
if err != nil { |
||||
t.Errorf("Unexpected error when calling GopherMap with an empty path: %s", err) |
||||
} |
||||
|
||||
if got != expected { |
||||
t.Error("Unexpected empty lines when calling GopherMap with an empty path") |
||||
} |
||||
|
||||
p := "/some/non/existant/path" |
||||
lines, err = GopherMap(c, p) |
||||
|
||||
expectedlines := 0 |
||||
gotlines := len(lines) |
||||
|
||||
if err == nil { |
||||
t.Errorf("Expected receiving an error when calling GopherMap with an invalid path: %s, err: %s", p, err) |
||||
} |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected non-empty lines when calling GopherMap with an empty path, expected %d, got %d", expectedlines, gotlines) |
||||
} |
||||
|
||||
|
||||
} |
||||
|
||||
|
||||
|
@ -0,0 +1,219 @@ |
||||
package gopher |
||||
|
||||
|
||||
import ( |
||||
"testing" |
||||
"os" |
||||
) |
||||
|
||||
func TestFullPathMatchPredicateFor(t *testing.T) { |
||||
d, _ := os.Getwd() |
||||
c := Context { Root: d + "/../testdata" } |
||||
rq, _ := NewRequest(c, "/attic/Goblin_Market") |
||||
rs := NewResponse(c, *rq) |
||||
|
||||
p := "/attic" |
||||
|
||||
pred := FullPathMatchPredicateFor(p) |
||||
expected := true |
||||
got := pred(c, *rq, *rs, nil) |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected return value from a generated FullPathMatchPredicate for path %s, expected %t, got %t", p, expected, got) |
||||
} |
||||
|
||||
rq, _ = NewRequest(c, "/writings") |
||||
rs = NewResponse(c, *rq) |
||||
|
||||
expected = false |
||||
got = pred(c, *rq, *rs, nil) |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected return value from a generated FullPathMatchPredicate for path %s, expected %t, got %t", p, expected, got) |
||||
} |
||||
} |
||||
|
||||
func TestGopherMapPredicate(t *testing.T) { |
||||
d, _ := os.Getwd() |
||||
c := Context { Root: d + "/../testdata" } |
||||
p:= "" |
||||
rq, _ := NewRequest(c, p) |
||||
rs := NewResponse(c, *rq) |
||||
|
||||
expected := true |
||||
got := GopherMapPredicate(c, *rq, *rs, nil) |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected return value from GopherMapPredicate for path %s, expected %t, got %t", p, expected, got) |
||||
} |
||||
|
||||
p = "/attic" |
||||
rq, _ = NewRequest(c, p) |
||||
rs = NewResponse(c, *rq) |
||||
|
||||
expected = true |
||||
got = GopherMapPredicate(c, *rq, *rs, nil) |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected return value from GopherMapPredicate for path %s, expected %t, got %t", p, expected, got) |
||||
} |
||||
} |
||||
|
||||
func TestFileTypeBinaryPredicate(t *testing.T) { |
||||
d, _ := os.Getwd() |
||||
c := Context { Root: d + "/../testdata" } |
||||
p:= "/attic/cat" |
||||
rq, _ := NewRequest(c, p) |
||||
rs := NewResponse(c, *rq) |
||||
|
||||
expected := true |
||||
got := FileTypeBinaryPredicate(c, *rq, *rs, nil) |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected return value from FileTypeBinaryPredicate for path %s, expected %t, got %t", p, expected, got) |
||||
} |
||||
|
||||
p = "/attic/Goblin_Market" |
||||
rq, _ = NewRequest(c, p) |
||||
rs = NewResponse(c, *rq) |
||||
|
||||
expected = false |
||||
got = FileTypeBinaryPredicate(c, *rq, *rs, nil) |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected return value from FileTypeBinaryPredicate for path %s, expected %t, got %t", p, expected, got) |
||||
} |
||||
} |
||||
|
||||
func TestFileTypePlainTextPredicate(t *testing.T) { |
||||
d, _ := os.Getwd() |
||||
c := Context { Root: d + "/../testdata" } |
||||
p:= "/attic/Goblin_Market" |
||||
rq, _ := NewRequest(c, p) |
||||
rs := NewResponse(c, *rq) |
||||
|
||||
expected := true |
||||
got := FileTypePlainTextPredicate(c, *rq, *rs, nil) |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected return value from FileTypePlainTextPredicate for path %s, expected %t, got %t", p, expected, got) |
||||
} |
||||
|
||||
p = "/attic/" |
||||
rq, _ = NewRequest(c, p) |
||||
rs = NewResponse(c, *rq) |
||||
|
||||
expected = false |
||||
got = FileTypeBinaryPredicate(c, *rq, *rs, nil) |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected return value from FileTypePlainTextPredicate for path %s, expected %t, got %t", p, expected, got) |
||||
} |
||||
} |
||||
|
||||
func TestFileTypeAudioPredicate(t *testing.T) { |
||||
d, _ := os.Getwd() |
||||
c := Context { Root: d + "/../testdata" } |
||||
p:= "/attic/audio/Bubbles-SoundBible.com-810959520.mp3" |
||||
rq, _ := NewRequest(c, p) |
||||
rs := NewResponse(c, *rq) |
||||
|
||||
expected := true |
||||
got := FileTypeAudioPredicate(c, *rq, *rs, nil) |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected return value from FileTypeAudioPredicate for path %s, expected %t, got %t", p, expected, got) |
||||
} |
||||
|
||||
p = "/attic/Goblin_Market" |
||||
rq, _ = NewRequest(c, p) |
||||
rs = NewResponse(c, *rq) |
||||
|
||||
expected = false |
||||
got = FileTypeAudioPredicate(c, *rq, *rs, nil) |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected return value from FileTypeAudioPredicate for path %s, expected %t, got %t", p, expected, got) |
||||
} |
||||
} |
||||
|
||||
func TestFileTypeImagePredicate(t *testing.T) { |
||||
d, _ := os.Getwd() |
||||
c := Context { Root: d + "/../testdata" } |
||||
p:= "/attic/pictures/hamtori.gif" |
||||
rq, _ := NewRequest(c, p) |
||||
rs := NewResponse(c, *rq) |
||||
|
||||
expected := true |
||||
got := FileTypeImagePredicate(c, *rq, *rs, nil) |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected return value from FileTypeImagePredicate for path %s, expected %t, got %t", p, expected, got) |
||||
} |
||||
|
||||
p = "/attic/Goblin_Market" |
||||
rq, _ = NewRequest(c, p) |
||||
rs = NewResponse(c, *rq) |
||||
|
||||
expected = false |
||||
got = FileTypeImagePredicate(c, *rq, *rs, nil) |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected return value from FileTypeImagePredicate for path %s, expected %t, got %t", p, expected, got) |
||||
} |
||||
} |
||||
|
||||
func TestFileTypePDFPredicate(t *testing.T) { |
||||
d, _ := os.Getwd() |
||||
c := Context { Root: d + "/../testdata" } |
||||
p:= "/attic/rfc1436.txt.pdf" |
||||
rq, _ := NewRequest(c, p) |
||||
rs := NewResponse(c, *rq) |
||||
|
||||
expected := true |
||||
got := FileTypePDFPredicate(c, *rq, *rs, nil) |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected return value from FileTypePDFPredicate for path %s, expected %t, got %t", p, expected, got) |
||||
} |
||||
|
||||
p = "/attic/Goblin_Market" |
||||
rq, _ = NewRequest(c, p) |
||||
rs = NewResponse(c, *rq) |
||||
|
||||
expected = false |
||||
got = FileTypePDFPredicate(c, *rq, *rs, nil) |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected return value from FileTypePDFPredicate for path %s, expected %t, got %t", p, expected, got) |
||||
} |
||||
} |
||||
|
||||
func TestFileTypeDocPredicate(t *testing.T) { |
||||
d, _ := os.Getwd() |
||||
c := Context { Root: d + "/../testdata" } |
||||
p:= "/attic/gopher.docx" |
||||
rq, _ := NewRequest(c, p) |
||||
rs := NewResponse(c, *rq) |
||||
|
||||
expected := true |
||||
got := FileTypeDocPredicate(c, *rq, *rs, nil) |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected return value from FileTypeDocPredicate for path %s, expected %t, got %t", p, expected, got) |
||||
} |
||||
|
||||
p = "/attic/Goblin_Market" |
||||
rq, _ = NewRequest(c, p) |
||||
rs = NewResponse(c, *rq) |
||||
|
||||
expected = false |
||||
got = FileTypePDFPredicate(c, *rq, *rs, nil) |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected return value from FileTypeDocPredicate for path %s, expected %t, got %t", p, expected, got) |
||||
} |
||||
} |
||||
|
||||
|
||||
|
@ -0,0 +1,111 @@ |
||||
package gopher |
||||
|
||||
import ( |
||||
"testing" |
||||
"os" |
||||
|
||||
"github.com/google/go-cmp/cmp" |
||||
) |
||||
|
||||
func TestNewRequest(t *testing.T) { |
||||
d, _ := os.Getwd() |
||||
c := Context { Root: d + "/../testdata" } |
||||
|
||||
// root gophermap
|
||||
rq, err := NewRequest(c, "") |
||||
|
||||
if err != nil { |
||||
t.Error("Expected no error, got: ", err) |
||||
} |
||||
|
||||
expectedType := Map |
||||
|
||||
if rq.Type != expectedType { |
||||
t.Errorf("Unexpected type for Request, expected %d, got %d", expectedType, rq.Type) |
||||
} |
||||
|
||||
expectedPath := "/" |
||||
|
||||
if rq.Path != expectedPath { |
||||
t.Errorf("Unexpected path for Request, expected %s got %s", expectedPath, rq.Path) |
||||
} |
||||
|
||||
rq, err = NewRequest(c, "/") |
||||
|
||||
if err != nil { |
||||
t.Error("Expected no error, got: ", err) |
||||
} |
||||
|
||||
expectedType = Map |
||||
|
||||
if rq.Type != expectedType { |
||||
t.Errorf("Unexpected type for Request, expected %d, got %d", expectedType, rq.Type) |
||||
} |
||||
|
||||
expectedPath = "/" |
||||
|
||||
if rq.Path != expectedPath { |
||||
t.Errorf("Unexpected path for Request, expected %s got %s", expectedPath, rq.Path) |
||||
} |
||||
|
||||
rq, err = NewRequest(c, "/attic") |
||||
|
||||
if err != nil { |
||||
t.Error("Expected no error, got: ", err) |
||||
} |
||||
|
||||
expectedType = Map |
||||
|
||||
if rq.Type != expectedType { |
||||
t.Errorf("Unexpected type for Request, expected %d, got %d", expectedType, rq.Type) |
||||
} |
||||
|
||||
expectedPath = "/attic" |
||||
|
||||
if rq.Path != expectedPath { |
||||
t.Errorf("Unexpected path for Request, expected %s got %s", expectedPath, rq.Path) |
||||
} |
||||
|
||||
rq, err = NewRequest(c, "/attic/Goblin_Market") |
||||
|
||||
if err != nil { |
||||
t.Error("Expected no error, got: ", err) |
||||
} |
||||
|
||||
expectedType = File |
||||
|
||||
if rq.Type != expectedType { |
||||
t.Errorf("Unexpected type for Request, expected %d, got %d", expectedType, rq.Type) |
||||
} |
||||
|
||||
expectedPath = "/attic/Goblin_Market" |
||||
|
||||
if rq.Path != expectedPath { |
||||
t.Errorf("Unexpected path for Request, expected %s got %s", expectedPath, rq.Path) |
||||
} |
||||
|
||||
rq, err = NewRequest(c, "NO-LEADING-SLASH") |
||||
|
||||
if err == nil { |
||||
t.Error("Expected to receive an error, didn't get any for a non-implemented request") |
||||
} |
||||
|
||||
expectedRq := Request{ Type: NotImplemented } |
||||
|
||||
if ! cmp.Equal(&expectedRq, rq) { |
||||
t.Errorf("Unexpected Request instance returned by NewRequest for an non-implemented request: %s", cmp.Diff(&expectedRq, rq)) |
||||
} |
||||
|
||||
p := "/non-existent" |
||||
rq, err = NewRequest(c, p) |
||||
|
||||
if err == nil { |
||||
t.Errorf("Expected to receive an error, didn't get any for a non-existent request %s", p) |
||||
} |
||||
|
||||
expectedRq = Request{ Path: p, FullPath: c.Root + p} |
||||
|
||||
if ! cmp.Equal(&expectedRq, rq) { |
||||
t.Errorf("Unexpected Request instance returned by NewRequest for an non-existent request %s: %s", p, cmp.Diff(&expectedRq, rq)) |
||||
} |
||||
} |
@ -0,0 +1,86 @@ |
||||
package gopher |
||||
|
||||
import ( |
||||
"testing" |
||||
"os" |
||||
) |
||||
|
||||
func TestNewResponse(t *testing.T) { |
||||
d, _ := os.Getwd() |
||||
c := Context { Root: d + "/../testdata" } |
||||
|
||||
// root gophermap
|
||||
rq, _ := NewRequest(c, "") |
||||
rs := NewResponse(c, *rq) |
||||
|
||||
var expectedType ResponseType = PlainText |
||||
|
||||
if rs.Type != expectedType { |
||||
t.Errorf("Unexpected type for Response for %s, expected %d, got %d", rq.Path, expectedType, rs.Type) |
||||
} |
||||
|
||||
rq, _ = NewRequest(c, "/") |
||||
rs = NewResponse(c, *rq) |
||||
|
||||
expectedType = PlainText |
||||
|
||||
if rs.Type != expectedType { |
||||
t.Errorf("Unexpected type for Response %s, expected %d, got %d", rq.Path, expectedType, rs.Type) |
||||
} |
||||
|
||||
rq, _ = NewRequest(c, "/attic") |
||||
rs = NewResponse(c, *rq) |
||||
|
||||
expectedType = PlainText |
||||
|
||||
if rs.Type != expectedType { |
||||
t.Errorf("Unexpected type for Response for %s, expected %d, got %d", rq.Path, expectedType, rs.Type) |
||||
} |
||||
|
||||
rq, _ = NewRequest(c, "/attic/Goblin_Market") |
||||
rs = NewResponse(c, *rq) |
||||
|
||||
expectedType = PlainText |
||||
|
||||
if rs.Type != expectedType { |
||||
t.Errorf("Unexpected type for Response for %s, expected %d, got %d", rq.Path, expectedType, rs.Type) |
||||
} |
||||
|
||||
rq, _ = NewRequest(c, "/attic/pictures/starry_night.jpg") |
||||
rs = NewResponse(c, *rq) |
||||
|
||||
expectedType = Image |
||||
|
||||
if rs.Type != expectedType { |
||||
t.Errorf("Unexpected type for Response for %s, expected %d, got %d", rq.Path, expectedType, rs.Type) |
||||
} |
||||
|
||||
rq, _ = NewRequest(c, "/attic/pictures/hamtori.gif") |
||||
rs = NewResponse(c, *rq) |
||||
|
||||
expectedType = Image |
||||
|
||||
if rs.Type != expectedType { |
||||
t.Errorf("Unexpected type for Response for %s, expected %d, got %d", rq.Path, expectedType, rs.Type) |
||||
} |
||||
|
||||
rq, _ = NewRequest(c, "/attic/audio/Bubbles-SoundBible.com-810959520.mp3") |
||||
rs = NewResponse(c, *rq) |
||||
|
||||
expectedType = Audio |
||||
|
||||
if rs.Type != expectedType { |
||||
t.Errorf("Unexpected type for Response for %s, expected %d, got %d", rq.Path, expectedType, rs.Type) |
||||
} |
||||
|
||||
rq, _ = NewRequest(c, "/attic/blob") |
||||
rs = NewResponse(c, *rq) |
||||
|
||||
expectedType = Binary |
||||
|
||||
if rs.Type != expectedType { |
||||
t.Errorf("Unexpected type for Response for %s, expected %d, got %d", rq.Path, expectedType, rs.Type) |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,125 @@ |
||||
package gopher |
||||
|
||||
import ( |
||||
"os" |
||||
"strings" |
||||
"testing" |
||||
|
||||
"github.com/google/go-cmp/cmp" |
||||
) |
||||
|
||||
type fakeWriter struct { Buffer []byte} |
||||
|
||||
func (w *fakeWriter) Write(b []byte) (n int, err error) { |
||||
w.Buffer = append(w.Buffer, b...) |
||||
|
||||
return len(w.Buffer), nil |
||||
} |
||||
|
||||
type brokenReader struct { Text string } |
||||
|
||||
func (r *brokenReader) Read(p []byte) (n int, err error) { |
||||
p = []byte(r.Text) |
||||
|
||||
return len(p), nil |
||||
} |
||||
|
||||
func TestWrite(t *testing.T) { |
||||
d, _ := os.Getwd() |
||||
c := Context { Root: d + "/../testdata" } |
||||
p:= "/attic/Goblin_Market" |
||||
rq, _ := NewRequest(c, p) |
||||
rs := NewResponse(c, *rq) |
||||
|
||||
w := fakeWriter { Buffer: []byte{} } |
||||
var err error = nil |
||||
|
||||
TextFileTransformer(&c, *rq, rs, err) |
||||
err = write(&c, *rq, rs, &w) |
||||
|
||||
expected := true |
||||
got := len(w.Buffer) > 0 |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected empty buffer in fakeWriter instance after a valid write call for text on path %s", p) |
||||
} |
||||
|
||||
p = "/attic/cat" |
||||
rq, _ = NewRequest(c, p) |
||||
rs = NewResponse(c, *rq) |
||||
|
||||
w = fakeWriter { Buffer: []byte{} } |
||||
|
||||
BinaryFileTransformer(&c, *rq, rs, err) |
||||
err = write(&c, *rq, rs, &w) |
||||
|
||||
expected = true |
||||
got = len(w.Buffer) > 0 |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected empty buffer in fakeWriter instance after a valid write call for binary on path %s", p) |
||||
} |
||||
} |
||||
|
||||
func TestParseRequest(t *testing.T) { |
||||
d, _ := os.Getwd() |
||||
c := Context { Root: d + "/../testdata" } |
||||
p:= "/attic/Goblin_Market\r\n" |
||||
|
||||
r := strings.NewReader(p) |
||||
|
||||
rq, err := ParseRequest(&c, r) |
||||
|
||||
if err != nil { |
||||
t.Errorf("Unexpected error when parsing the request string %s: %s", p, err) |
||||
} |
||||
|
||||
expected := File |
||||
got := rq.Type |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected file type in Request instance when parsing the request string %s, expected %d, got %d", p, expected, got) |
||||
} |
||||
|
||||
expectedRq := Request{} |
||||
gotRq, err := ParseRequest(&c, nil) |
||||
|
||||
if err == nil { |
||||
t.Error("Expected receiving an error when calling ParseRequest with a nil reader, didn't get any") |
||||
} |
||||
|
||||
if ! cmp.Equal(&expectedRq, gotRq) { |
||||
t.Errorf("Unexpected Request instance after parsing a request with a nil reader, diff: %s", cmp.Diff(&expectedRq, gotRq)) |
||||
} |
||||
|
||||
b := brokenReader{} |
||||
expectedRq = Request{} |
||||
gotRq, err = ParseRequest(&c, &b) |
||||
|
||||
if err == nil { |
||||
t.Error("Expected receiving an error when calling ParseRequest with a brokenReader, didn't get any") |
||||
} |
||||
|
||||
if ! cmp.Equal(&expectedRq, gotRq) { |
||||
t.Errorf("Unexpected Request instance after parsing a request with a brokenReader, diff: %s", cmp.Diff(&expectedRq, gotRq)) |
||||
} |
||||
|
||||
} |
||||
|
||||
func TestTransform(t *testing.T) { |
||||
d, _ := os.Getwd() |
||||
c := Context { Root: d + "/../testdata" } |
||||
c.DefaultResponseTransformers() |
||||
p:= "/attic/Goblin_Market" |
||||
rq, _ := NewRequest(c, p) |
||||
rs := NewResponse(c, *rq) |
||||
var err error = nil |
||||
|
||||
transformers := Transform(&c, *rq, rs, err) |
||||
expected := true |
||||
got := len(transformers) > 0 |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected empty list of applied transformers after a call to Transform for path %s", p) |
||||
} |
||||
} |
@ -0,0 +1,179 @@ |
||||
package gopher |
||||
|
||||
import ( |
||||
"testing" |
||||
"os" |
||||
) |
||||
|
||||
func TestGopherMapTransformer(t *testing.T) { |
||||
d, _ := os.Getwd() |
||||
c := Context { Root: d + "/../testdata" } |
||||
p:= "/attic/" |
||||
rq, _ := NewRequest(c, p) |
||||
rs := NewResponse(c, *rq) |
||||
|
||||
var err error = nil |
||||
GopherMapTransformer(&c, *rq, rs, err) |
||||
|
||||
expected := true |
||||
got := len(rs.ContentText) > 0 |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected empty ContentText in Response instance after a valid GopherMapTransformer call on path %s", p) |
||||
} |
||||
|
||||
expected = false |
||||
got = len(rs.ContentBinary) > 0 |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected non-empty ContentBinary in Response instance after a valid GopherMapTransformer call on path %s", p) |
||||
} |
||||
|
||||
p = "/attic/non/existent/path" |
||||
rq, _ = NewRequest(c, "") |
||||
// craft an invalid request
|
||||
rq.FullPath = c.Root + p |
||||
rq.Path = p |
||||
rs = NewResponse(c, *rq) |
||||
|
||||
err = nil |
||||
_, _, _, err = GopherMapTransformer(&c, *rq, rs, err) |
||||
|
||||
expectedlines := 0 |
||||
gotlines := len(rs.ContentText) |
||||
|
||||
if err == nil { |
||||
t.Errorf("Expected receiving an error when calling GopherMapTransformer with a non-existent directory %s", p) |
||||
} |
||||
|
||||
if gotlines != expectedlines { |
||||
t.Errorf("Unexpected number of lines when calling GopherMapTransformer with a non-existent directory %s, expected %d, got %d", p, expectedlines, gotlines) |
||||
} |
||||
|
||||
} |
||||
|
||||
func TestTextFileTransformer(t *testing.T) { |
||||
d, _ := os.Getwd() |
||||
c := Context { Root: d + "/../testdata" } |
||||
p:= "/attic/Goblin_Market" |
||||
rq, _ := NewRequest(c, p) |
||||
rs := NewResponse(c, *rq) |
||||
|
||||
var err error = nil |
||||
TextFileTransformer(&c, *rq, rs, err) |
||||
|
||||
expected := true |
||||
got := len(rs.ContentText) > 0 |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected empty ContentText in Response instance after a valid TextFileTransformer call on path %s", p) |
||||
} |
||||
|
||||
expected = false |
||||
got = len(rs.ContentBinary) > 0 |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected non-empty ContentBinary in Response instance after a valid TextFileTransformer call on path %s", p) |
||||
} |
||||
|
||||
p = "/attic/Goblin_Market" |
||||
rq, _ = NewRequest(c, p) |
||||
rs = NewResponse(c, *rq) |
||||
|
||||
// craft a broken request
|
||||
rq.FullPath = c.Root + "/non-existent" |
||||
rq.Path = "/non-existent" |
||||
err = nil |
||||
|
||||
expectedlines := len(rs.ContentText) |
||||
_, _, _, err = TextFileTransformer(&c, *rq, rs, err) |
||||
|
||||
gotlines := len(rs.ContentText) |
||||
|
||||
if err == nil { |
||||
t.Errorf("Expected receiving an error after calling TextFileTransformer with a broken path %s in the request, didn't receive any", p) |
||||
} |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected number of lines for ContentText in Response instance after an invalid TextFileTransformer call on path %s, expected %d, got %d", p, expectedlines, gotlines) |
||||
} |
||||
|
||||
} |
||||
|
||||
func TestBinaryFileTransformer(t *testing.T) { |
||||
d, _ := os.Getwd() |
||||
c := Context { Root: d + "/../testdata" } |
||||
p:= "/attic/cat" |
||||
rq, _ := NewRequest(c, p) |
||||
rs := NewResponse(c, *rq) |
||||
|
||||
var err error = nil |
||||
BinaryFileTransformer(&c, *rq, rs, err) |
||||
|
||||
expected := true |
||||
got := len(rs.ContentBinary) > 0 |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected empty ContentBinary in Response instance after a valid BinaryFileTransformer call on path %s", p) |
||||
} |
||||
|
||||
expected = false |
||||
got = len(rs.ContentText) > 0 |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected non-empty ContentText in Response instance after a valid BinaryFileTransformer call on path %s", p) |
||||
} |
||||
|
||||
p = "/attic/cat" |
||||
rq, _ = NewRequest(c, p) |
||||
rs = NewResponse(c, *rq) |
||||
|
||||
// craft a broken request
|
||||
rq.FullPath = c.Root + "/non-existent" |
||||
rq.Path = "/non-existent" |
||||
|
||||
err = nil |
||||
expectedsize := len(rs.ContentBinary) |
||||
_, _, _, err = BinaryFileTransformer(&c, *rq, rs, err) |
||||
|
||||
gotsize := len(rs.ContentBinary) |
||||
|
||||
if err == nil { |
||||
t.Errorf("Expected an error after calling BinaryFileTransformer with a broken path %s in the request, didn't get any", p) |
||||
} |
||||
|
||||
if gotsize != expectedsize { |
||||
t.Errorf("Unexpected size of ContentBinary in Response instance after an invalid BinaryFileTransformer call on path %s, expected %d, got %d", p, expectedsize, gotsize) |
||||
} |
||||
|
||||
} |
||||
|
||||
func TestHeaderTransformer(t *testing.T) { |
||||
d, _ := os.Getwd() |
||||
c := Context { Root: d + "/../testdata", Header: []string{"powered", "by", "marmotte"} } |
||||
c.ResponseTransformers = append(c.ResponseTransformers, ResponseTransformer{ |
||||
Transformer: HeaderTransformer, |
||||
Predicate: GopherMapPredicate }) |
||||
|
||||
p:= "/attic/" |
||||
rq, _ := NewRequest(c, p) |
||||
rs := NewResponse(c, *rq) |
||||
|
||||
var err error = nil |
||||
HeaderTransformer(&c, *rq, rs, err) |
||||
|
||||
for i, h := range c.Header { |
||||
expected := "i" + h + "\r\n" |
||||
got := rs.ContentText[i] |
||||
if got != expected { |
||||
t.Errorf("Unexpected line in ContentText of a Response instance, expected %s, got %s (index %d)", expected, got, i) |
||||
} |
||||
} |
||||
|
||||
expected := false |
||||
got := len(rs.ContentBinary) > 0 |
||||
|
||||
if got != expected { |
||||
t.Errorf("Unexpected non-empty ContentBinary in Response instance after a valid HeaderTransformer call on path %s", p) |
||||
} |
||||
} |
@ -0,0 +1 @@ |
||||
I am beastieboy and I write funny programs. |
@ -0,0 +1 @@ |
||||
This server is an experimental Gopher server written in Go. |
@ -0,0 +1,597 @@ |
||||
Goblin Market |
||||
By Christina Rossetti |
||||
Morning and evening |
||||
Maids heard the goblins cry: |
||||
“Come buy our orchard fruits, |
||||
Come buy, come buy: |
||||
Apples and quinces, |
||||
Lemons and oranges, |
||||
Plump unpeck’d cherries, |
||||
Melons and raspberries, |
||||
Bloom-down-cheek’d peaches, |
||||
Swart-headed mulberries, |
||||
Wild free-born cranberries, |
||||
Crab-apples, dewberries, |
||||
Pine-apples, blackberries, |
||||
Apricots, strawberries;— |
||||
All ripe together |
||||
In summer weather,— |
||||
Morns that pass by, |
||||
Fair eves that fly; |
||||
Come buy, come buy: |
||||
Our grapes fresh from the vine, |
||||
Pomegranates full and fine, |
||||
Dates and sharp bullaces, |
||||
Rare pears and greengages, |
||||
Damsons and bilberries, |
||||
Taste them and try: |
||||
Currants and gooseberries, |
||||
Bright-fire-like barberries, |
||||
Figs to fill your mouth, |
||||
Citrons from the South, |
||||
Sweet to tongue and sound to eye; |
||||
Come buy, come buy.” |
||||
|
||||
Evening by evening |
||||
Among the brookside rushes, |
||||
Laura bow’d her head to hear, |
||||
Lizzie veil’d her blushes: |
||||
Crouching close together |
||||
In the cooling weather, |
||||
With clasping arms and cautioning lips, |
||||
With tingling cheeks and finger tips. |
||||
“Lie close,” Laura said, |
||||
Pricking up her golden head: |
||||
“We must not look at goblin men, |
||||
We must not buy their fruits: |
||||
Who knows upon what soil they fed |
||||
Their hungry thirsty roots?” |
||||
“Come buy,” call the goblins |
||||
Hobbling down the glen. |
||||
|
||||
“Oh,” cried Lizzie, “Laura, Laura, |
||||
You should not peep at goblin men.” |
||||
Lizzie cover’d up her eyes, |
||||
Cover’d close lest they should look; |
||||
Laura rear’d her glossy head, |
||||
And whisper’d like the restless brook: |
||||
“Look, Lizzie, look, Lizzie, |
||||
Down the glen tramp little men. |
||||
One hauls a basket, |
||||
One bears a plate, |
||||
One lugs a golden dish |
||||
Of many pounds weight. |
||||
How fair the vine must grow |
||||
Whose grapes are so luscious; |
||||
How warm the wind must blow |
||||
Through those fruit bushes.” |
||||
“No,” said Lizzie, “No, no, no; |
||||
Their offers should not charm us, |
||||
Their evil gifts would harm us.” |
||||
She thrust a dimpled finger |
||||
In each ear, shut eyes and ran: |
||||
Curious Laura chose to linger |
||||
Wondering at each merchant man. |
||||
One had a cat’s face, |
||||
One whisk’d a tail, |
||||
One tramp’d at a rat’s pace, |
||||
One crawl’d like a snail, |
||||
One like a wombat prowl’d obtuse and furry, |
||||
One like a ratel tumbled hurry skurry. |
||||
She heard a voice like voice of doves |
||||
Cooing all together: |
||||
They sounded kind and full of loves |
||||
In the pleasant weather. |
||||
|
||||
Laura stretch’d her gleaming neck |
||||
Like a rush-imbedded swan, |
||||
Like a lily from the beck, |
||||
Like a moonlit poplar branch, |
||||
Like a vessel at the launch |
||||
When its last restraint is gone. |
||||
|
||||
Backwards up the mossy glen |
||||
Turn’d and troop’d the goblin men, |
||||
With their shrill repeated cry, |
||||
“Come buy, come buy.” |
||||
When they reach’d where Laura was |
||||
They stood stock still upon the moss, |
||||
Leering at each other, |
||||
Brother with queer brother; |
||||
Signalling each other, |
||||
Brother with sly brother. |
||||
One set his basket down, |
||||
One rear’d his plate; |
||||
One began to weave a crown |
||||
Of tendrils, leaves, and rough nuts brown |
||||
(Men sell not such in any town); |
||||
One heav’d the golden weight |
||||
Of dish and fruit to offer her: |
||||
“Come buy, come buy,” was still their cry. |
||||
Laura stared but did not stir, |
||||
Long’d but had no money: |
||||
The whisk-tail’d merchant bade her taste |
||||
In tones as smooth as honey, |
||||
The cat-faced purr’d, |
||||
The rat-faced spoke a word |
||||
Of welcome, and the snail-paced even was heard; |
||||
One parrot-voiced and jolly |
||||
Cried “Pretty Goblin” still for “Pretty Polly;”— |
||||
One whistled like a bird. |
||||
|
||||
But sweet-tooth Laura spoke in haste: |
||||
“Good folk, I have no coin; |
||||
To take were to purloin: |
||||
I have no copper in my purse, |
||||
I have no silver either, |
||||
And all my gold is on the furze |
||||
That shakes in windy weather |
||||
Above the rusty heather.” |
||||
“You have much gold upon your head,” |
||||
They answer’d all together: |
||||
“Buy from us with a golden curl.” |
||||
She clipp’d a precious golden lock, |
||||
She dropp’d a tear more rare than pearl, |
||||
Then suck’d their fruit globes fair or red: |
||||
Sweeter than honey from the rock, |
||||
Stronger than man-rejoicing wine, |
||||
Clearer than water flow’d that juice; |
||||
She never tasted such before, |
||||
How should it cloy with length of use? |
||||
She suck’d and suck’d and suck’d the more |
||||
Fruits which that unknown orchard bore; |
||||
She suck’d until her lips were sore; |
||||
Then flung the emptied rinds away |
||||
But gather’d up one kernel stone, |
||||
And knew not was it night or day |
||||
As she turn’d home alone. |
||||
|
||||
Lizzie met her at the gate |
||||
Full of wise upbraidings: |
||||
“Dear, you should not stay so late, |
||||
Twilight is not good for maidens; |
||||
Should not loiter in the glen |
||||
In the haunts of goblin men. |
||||
Do you not remember Jeanie, |
||||
How she met them in the moonlight, |
||||
Took their gifts both choice and many, |
||||
Ate their fruits and wore their flowers |
||||
Pluck’d from bowers |
||||
Where summer ripens at all hours? |
||||
But ever in the noonlight |
||||
She pined and pined away; |
||||
Sought them by night and day, |
||||
Found them no more, but dwindled and grew grey; |
||||
Then fell with the first snow, |
||||
While to this day no grass will grow |
||||
Where she lies low: |
||||
I planted daisies there a year ago |
||||
That never blow. |
||||
You should not loiter so.” |
||||
“Nay, hush,” said Laura: |
||||
“Nay, hush, my sister: |
||||
I ate and ate my fill, |
||||
Yet my mouth waters still; |
||||
To-morrow night I will |
||||
Buy more;” and kiss’d her: |
||||
“Have done with sorrow; |
||||
I’ll bring you plums to-morrow |
||||
Fresh on their mother twigs, |
||||
Cherries worth getting; |
||||
You cannot think what figs |
||||
My teeth have met in, |
||||
What melons icy-cold |
||||
Piled on a dish of gold |
||||
Too huge for me to hold, |
||||
What peaches with a velvet nap, |
||||
Pellucid grapes without one seed: |
||||
Odorous indeed must be the mead |
||||
Whereon they grow, and pure the wave they drink |
||||
With lilies at the brink, |
||||
And sugar-sweet their sap.” |
||||
|
||||
Golden head by golden head, |
||||
Like two pigeons in one nest |
||||
Folded in each other’s wings, |
||||
They lay down in their curtain’d bed: |
||||
Like two blossoms on one stem, |
||||
Like two flakes of new-fall’n snow, |
||||
Like two wands of ivory |
||||
Tipp’d with gold for awful kings. |
||||
Moon and stars gaz’d in at them, |
||||
Wind sang to them lullaby, |
||||
Lumbering owls forbore to fly, |
||||
Not a bat flapp’d to and fro |
||||
Round their rest: |
||||
Cheek to cheek and breast to breast |
||||
Lock’d together in one nest. |
||||
|
||||
Early in the morning |
||||
When the first cock crow’d his warning, |
||||
Neat like bees, as sweet and busy, |
||||
Laura rose with Lizzie: |
||||
Fetch’d in honey, milk’d the cows, |
||||
Air’d and set to rights the house, |
||||
Kneaded cakes of whitest wheat, |
||||
Cakes for dainty mouths to eat, |
||||
Next churn’d butter, whipp’d up cream, |
||||
Fed their poultry, sat and sew’d; |
||||
Talk’d as modest maidens should: |
||||
Lizzie with an open heart, |
||||
Laura in an absent dream, |
||||
One content, one sick in part; |
||||
One warbling for the mere bright day’s delight, |
||||
One longing for the night. |
||||
|
||||
At length slow evening came: |
||||
They went with pitchers to the reedy brook; |
||||
Lizzie most placid in her look, |
||||
Laura most like a leaping flame. |
||||
They drew the gurgling water from its deep; |
||||
Lizzie pluck’d purple and rich golden flags, |
||||
Then turning homeward said: “The sunset flushes |
||||
Those furthest loftiest crags; |
||||
Come, Laura, not another maiden lags. |
||||
No wilful squirrel wags, |
||||
The beasts and birds are fast asleep.” |
||||
But Laura loiter’d still among the rushes |
||||
And said the bank was steep. |
||||
|
||||
And said the hour was early still |
||||
The dew not fall’n, the wind not chill; |
||||
Listening ever, but not catching |
||||
The customary cry, |
||||
“Come buy, come buy,” |
||||
With its iterated jingle |
||||
Of sugar-baited words: |
||||
Not for all her watching |
||||
Once discerning even one goblin |
||||
Racing, whisking, tumbling, hobbling; |
||||
Let alone the herds |
||||
That used to tramp along the glen, |
||||
In groups or single, |
||||
Of brisk fruit-merchant men. |
||||
|
||||
Till Lizzie urged, “O Laura, come; |
||||
I hear the fruit-call but I dare not look: |
||||
You should not loiter longer at this brook: |
||||
Come with me home. |
||||
The stars rise, the moon bends her arc, |
||||
Each glowworm winks her spark, |
||||
Let us get home before the night grows dark: |
||||
For clouds may gather |
||||
Though this is summer weather, |
||||
Put out the lights and drench us through; |
||||
Then if we lost our way what should we do?” |
||||
|
||||
Laura turn’d cold as stone |
||||
To find her sister heard that cry alone, |
||||
That goblin cry, |
||||
“Come buy our fruits, come buy.” |
||||
Must she then buy no more such dainty fruit? |
||||
Must she no more such succous pasture find, |
||||
Gone deaf and blind? |
||||
Her tree of life droop’d from the root: |
||||
She said not one word in her heart’s sore ache; |
||||
But peering thro’ the dimness, nought discerning, |
||||
Trudg’d home, her pitcher dripping all the way; |
||||
So crept to bed, and lay |
||||
Silent till Lizzie slept; |
||||
Then sat up in a passionate yearning, |
||||
And gnash’d her teeth for baulk’d desire, and wept |
||||
As if her heart would break. |
||||
|
||||
Day after day, night after night, |
||||
Laura kept watch in vain |
||||
In sullen silence of exceeding pain. |
||||
She never caught again the goblin cry: |
||||
“Come buy, come buy;”— |
||||
She never spied the goblin men |
||||
Hawking their fruits along the glen: |
||||
But when the noon wax’d bright |
||||
Her hair grew thin and grey; |
||||
She dwindled, as the fair full moon doth turn |
||||
To swift decay and burn |
||||
Her fire away. |
||||
|
||||
One day remembering her kernel-stone |
||||
She set it by a wall that faced the south; |
||||
Dew’d it with tears, hoped for a root, |
||||
Watch’d for a waxing shoot, |
||||
But there came none; |
||||
It never saw the sun, |
||||
It never felt the trickling moisture run: |
||||
While with sunk eyes and faded mouth |
||||
She dream’d of melons, as a traveller sees |
||||
False waves in desert drouth |
||||
With shade of leaf-crown’d trees, |
||||
And burns the thirstier in the sandful breeze. |
||||
|
||||
She no more swept the house, |
||||
Tended the fowls or cows, |
||||
Fetch’d honey, kneaded cakes of wheat, |
||||
Brought water from the brook: |
||||
But sat down listless in the chimney-nook |
||||
And would not eat. |
||||
|
||||
Tender Lizzie could not bear |
||||
To watch her sister’s cankerous care |
||||
Yet not to share. |
||||
She night and morning |
||||
Caught the goblins’ cry: |
||||
“Come buy our orchard fruits, |
||||
Come buy, come buy;”— |
||||
Beside the brook, along the glen, |
||||
She heard the tramp of goblin men, |
||||
The yoke and stir |
||||
Poor Laura could not hear; |
||||
Long’d to buy fruit to comfort her, |
||||
But fear’d to pay too dear. |
||||
She thought of Jeanie in her grave, |
||||
Who should have been a bride; |
||||
But who for joys brides hope to have |
||||
Fell sick and died |
||||
In her gay prime, |
||||
In earliest winter time |
||||
With the first glazing rime, |
||||
With the first snow-fall of crisp winter time. |
||||
|
||||
Till Laura dwindling |
||||
Seem’d knocking at Death’s door: |
||||
Then Lizzie weigh’d no more |
||||
Better and worse; |
||||
But put a silver penny in her purse, |
||||
Kiss’d Laura, cross’d the heath with clumps of furze |
||||
At twilight, halted by the brook: |
||||
And for the first time in her life |
||||
Began to listen and look. |
||||
|
||||
Laugh’d every goblin |
||||
When they spied her peeping: |
||||
Came towards her hobbling, |
||||
Flying, running, leaping, |
||||
Puffing and blowing, |
||||
Chuckling, clapping, crowing, |
||||
Clucking and gobbling, |
||||
Mopping and mowing, |
||||
Full of airs and graces, |
||||
Pulling wry faces, |
||||
Demure grimaces, |
||||
Cat-like and rat-like, |
||||
Ratel- and wombat-like, |
||||
Snail-paced in a hurry, |
||||
Parrot-voiced and whistler, |
||||
Helter skelter, hurry skurry, |
||||
Chattering like magpies, |
||||
Fluttering like pigeons, |
||||
Gliding like fishes,— |
||||
Hugg’d her and kiss’d her: |
||||
Squeez’d and caress’d her: |
||||
Stretch’d up their dishes, |
||||
Panniers, and plates: |
||||
“Look at our apples |
||||
Russet and dun, |
||||
Bob at our cherries, |
||||
Bite at our peaches, |
||||
Citrons and dates, |
||||
Grapes for the asking, |
||||
Pears red with basking |
||||
Out in the sun, |
||||
Plums on their twigs; |
||||
Pluck them and suck them, |
||||
Pomegranates, figs.”— |
||||
|
||||
“Good folk,” said Lizzie, |
||||
Mindful of Jeanie: |
||||
“Give me much and many: — |
||||
Held out her apron, |
||||
Toss’d them her penny. |
||||
“Nay, take a seat with us, |
||||
Honour and eat with us,” |
||||
They answer’d grinning: |
||||
“Our feast is but beginning. |
||||
Night yet is early, |
||||
Warm and dew-pearly, |
||||
Wakeful and starry: |
||||
Such fruits as these |
||||
No man can carry: |
||||
Half their bloom would fly, |
||||
Half their dew would dry, |
||||
Half their flavour would pass by. |
||||
Sit down and feast with us, |
||||
Be welcome guest with us, |
||||
Cheer you and rest with us.”— |
||||
“Thank you,” said Lizzie: “But one waits |
||||
At home alone for me: |
||||
So without further parleying, |
||||
If you will not sell me any |
||||
Of your fruits though much and many, |
||||
Give me back my silver penny |
||||
I toss’d you for a fee.”— |
||||
They began to scratch their pates, |
||||
No longer wagging, purring, |
||||
But visibly demurring, |
||||
Grunting and snarling. |
||||
One call’d her proud, |
||||
Cross-grain’d, uncivil; |
||||
Their tones wax’d loud, |
||||
Their looks were evil. |
||||
Lashing their tails |
||||
They trod and hustled her, |
||||
Elbow’d and jostled her, |
||||
Claw’d with their nails, |
||||
Barking, mewing, hissing, mocking, |
||||
Tore her gown and soil’d her stocking, |
||||
Twitch’d her hair out by the roots, |
||||
Stamp’d upon her tender feet, |
||||
Held her hands and squeez’d their fruits |
||||
Against her mouth to make her eat. |
||||
|
||||
White and golden Lizzie stood, |
||||
Like a lily in a flood,— |
||||
Like a rock of blue-vein’d stone |
||||
Lash’d by tides obstreperously,— |
||||
Like a beacon left alone |
||||
In a hoary roaring sea, |
||||
Sending up a golden fire,— |
||||
Like a fruit-crown’d orange-tree |
||||
White with blossoms honey-sweet |
||||
Sore beset by wasp and bee,— |
||||
Like a royal virgin town |
||||
Topp’d with gilded dome and spire |
||||
Close beleaguer’d by a fleet |
||||
Mad to tug her standard down. |
||||
|
||||
One may lead a horse to water, |
||||
Twenty cannot make him drink. |
||||
Though the goblins cuff’d and caught her, |
||||
Coax’d and fought her, |
||||
Bullied and besought her, |
||||
Scratch’d her, pinch’d her black as ink, |
||||
Kick’d and knock’d her, |
||||
Maul’d and mock’d her, |
||||
Lizzie utter’d not a word; |
||||
Would not open lip from lip |
||||
Lest they should cram a mouthful in: |
||||
But laugh’d in heart to feel the drip |
||||
Of juice that syrupp’d all her face, |
||||
And lodg’d in dimples of her chin, |
||||
And streak’d her neck which quaked like curd. |
||||
At last the evil people, |
||||
Worn out by her resistance, |
||||
Flung back her penny, kick’d their fruit |
||||
Along whichever road they took, |
||||
Not leaving root or stone or shoot; |
||||
Some writh’d into the ground, |
||||
Some div’d into the brook |
||||
With ring and ripple, |
||||
Some scudded on the gale without a sound, |
||||
Some vanish’d in the distance. |
||||
|
||||
In a smart, ache, tingle, |
||||
Lizzie went her way; |
||||
Knew not was it night or day; |
||||
Sprang up the bank, tore thro’ the furze, |
||||
Threaded copse and dingle, |
||||
And heard her penny jingle |
||||
Bouncing in her purse,— |
||||
Its bounce was music to her ear. |
||||
She ran and ran |
||||
As if she fear’d some goblin man |
||||
Dogg’d her with gibe or curse |
||||
Or something worse: |
||||
But not one goblin scurried after, |
||||
Nor was she prick’d by fear; |
||||
The kind heart made her windy-paced |
||||
That urged her home quite out of breath with haste |
||||
And inward laughter. |
||||
|
||||
She cried, “Laura,” up the garden, |
||||
“Did you miss me? |
||||
Come and kiss me. |
||||
Never mind my bruises, |
||||
Hug me, kiss me, suck my juices |
||||
Squeez’d from goblin fruits for you, |
||||
Goblin pulp and goblin dew. |
||||
Eat me, drink me, love me; |
||||
Laura, make much of me; |
||||
For your sake I have braved the glen |
||||
And had to do with goblin merchant men.” |
||||
|
||||
Laura started from her chair, |
||||
Flung her arms up in the air, |
||||
Clutch’d her hair: |
||||
“Lizzie, Lizzie, have you tasted |
||||
For my sake the fruit forbidden? |
||||
Must your light like mine be hidden, |
||||
Your young life like mine be wasted, |
||||
Undone in mine undoing, |
||||
And ruin’d in my ruin, |
||||
Thirsty, canker’d, goblin-ridden?”— |
||||
She clung about her sister, |
||||
Kiss’d and kiss’d and kiss’d her: |
||||
Tears once again |
||||
Refresh’d her shrunken eyes, |
||||
Dropping like rain |
||||
After long sultry drouth; |
||||
Shaking with aguish fear, and pain, |
||||
She kiss’d and kiss’d her with a hungry mouth. |
||||
|
||||
Her lips began to scorch, |
||||
That juice was wormwood to her tongue, |
||||
She loath’d the feast: |
||||
Writhing as one possess’d she leap’d and sung, |
||||
Rent all her robe, and wrung |
||||
Her hands in lamentable haste, |
||||
And beat her breast. |
||||
Her locks stream’d like the torch |
||||
Borne by a racer at full speed, |
||||
Or like the mane of horses in their flight, |
||||
Or like an eagle when she stems the light |
||||
Straight toward the sun, |
||||
Or like a caged thing freed, |
||||
Or like a flying flag when armies run. |
||||
|
||||
Swift fire spread through her veins, knock’d at her heart, |
||||
Met the fire smouldering there |
||||
And overbore its lesser flame; |
||||
She gorged on bitterness without a name: |
||||
Ah! fool, to choose such part |
||||
Of soul-consuming care! |
||||
Sense fail’d in the mortal strife: |
||||
Like the watch-tower of a town |
||||
Which an earthquake shatters down, |
||||
Like a lightning-stricken mast, |
||||
Like a wind-uprooted tree |
||||
Spun about, |
||||
Like a foam-topp’d waterspout |
||||
Cast down headlong in the sea, |
||||
She fell at last; |
||||
Pleasure past and anguish past, |
||||
Is it death or is it life? |
||||
|
||||
Life out of death. |
||||
That night long Lizzie watch’d by her, |
||||
Counted her pulse’s flagging stir, |
||||
Felt for her breath, |
||||
Held water to her lips, and cool’d her face |
||||
With tears and fanning leaves: |
||||
But when the first birds chirp’d about their eaves, |
||||
And early reapers plodded to the place |
||||
Of golden sheaves, |
||||
And dew-wet grass |
||||
Bow’d in the morning winds so brisk to pass, |
||||
And new buds with new day |
||||
Open’d of cup-like lilies on the stream, |
||||
Laura awoke as from a dream, |
||||
Laugh’d in the innocent old way, |
||||
Hugg’d Lizzie but not twice or thrice; |
||||
Her gleaming locks show’d not one thread of grey, |
||||
Her breath was sweet as May |
||||
And light danced in her eyes. |
||||
|
||||
Days, weeks, months, years |
||||
Afterwards, when both were wives |
||||
With children of their own; |
||||
Their mother-hearts beset with fears, |
||||
Their lives bound up in tender lives; |
||||
Laura would call the little ones |
||||
And tell them of her early prime, |
||||
Those pleasant days long gone |
||||
Of not-returning time: |
||||
Would talk about the haunted glen, |
||||
The wicked, quaint fruit-merchant men, |
||||
Their fruits like honey to the throat |
||||
But poison in the blood; |
||||
(Men sell not such in any town): |
||||
Would tell them how her sister stood |
||||
In deadly peril to do her good, |
||||
And win the fiery antidote: |
||||
Then joining hands to little hands |
||||
Would bid them cling together, |
||||
“For there is no friend like a sister |
||||
In calm or stormy weather; |
||||
To cheer one on the tedious way, |
||||
To fetch one if one goes astray, |
||||
To lift one if one totters down, |
||||
To strengthen whilst one stands.” |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 1001 KiB |
After Width: | Height: | Size: 296 KiB |
Binary file not shown.
@ -0,0 +1,5 @@ |
||||
iThis is the menu from the gophermap! fake (NULL) 0 |
||||
1Writings /writings localhost 7070 |
||||
1Attic /attic localhost 7070 |
||||
0About this server /about-server localhost 7070 |
||||
0About me /about-me localhost 7070 |
@ -0,0 +1 @@ |
||||
0Rime Of the Ancient Mariner, by Samuel Taylor Coleridge /writings/rime_of_the_ancient_mariner localhost 7070 |
@ -0,0 +1,788 @@ |
||||
The Rime of the Ancient Mariner (text of 1834) |
||||
By Samuel Taylor Coleridge |
||||
|
||||
Argument |
||||
|
||||
How a Ship having passed the Line was driven by storms to the cold Country towards the South Pole; and how from thence she made her course to the tropical Latitude of the Great Pacific Ocean; and of the strange things that befell; and in what manner the Ancyent Marinere came back to his own Country. |
||||
|
||||
PART I |
||||
It is an ancient Mariner, |
||||
And he stoppeth one of three. |
||||
'By thy long grey beard and glittering eye, |
||||
Now wherefore stopp'st thou me? |
||||
|
||||
The Bridegroom's doors are opened wide, |
||||
And I am next of kin; |
||||
The guests are met, the feast is set: |
||||
May'st hear the merry din.' |
||||
|
||||
He holds him with his skinny hand, |
||||
'There was a ship,' quoth he. |
||||
'Hold off! unhand me, grey-beard loon!' |
||||
Eftsoons his hand dropt he. |
||||
|
||||
He holds him with his glittering eye— |
||||
The Wedding-Guest stood still, |
||||
And listens like a three years' child: |
||||
The Mariner hath his will. |
||||
|
||||
The Wedding-Guest sat on a stone: |
||||
He cannot choose but hear; |
||||
And thus spake on that ancient man, |
||||
The bright-eyed Mariner. |
||||
|
||||
'The ship was cheered, the harbour cleared, |
||||
Merrily did we drop |
||||
Below the kirk, below the hill, |
||||
Below the lighthouse top. |
||||
|
||||
The Sun came up upon the left, |
||||
Out of the sea came he! |
||||
And he shone bright, and on the right |
||||
Went down into the sea. |
||||
|
||||
Higher and higher every day, |
||||
Till over the mast at noon—' |
||||
The Wedding-Guest here beat his breast, |
||||
For he heard the loud bassoon. |
||||
|
||||
The bride hath paced into the hall, |
||||
Red as a rose is she; |
||||
Nodding their heads before her goes |
||||
The merry minstrelsy. |
||||
|
||||
The Wedding-Guest he beat his breast, |
||||
Yet he cannot choose but hear; |
||||
And thus spake on that ancient man, |
||||
The bright-eyed Mariner. |
||||
|
||||
And now the STORM-BLAST came, and he |
||||
Was tyrannous and strong: |
||||
He struck with his o'ertaking wings, |
||||
And chased us south along. |
||||
|
||||
With sloping masts and dipping prow, |
||||
As who pursued with yell and blow |
||||
Still treads the shadow of his foe, |
||||
And forward bends his head, |
||||
The ship drove fast, loud roared the blast, |
||||
And southward aye we fled. |
||||
|
||||
And now there came both mist and snow, |
||||
And it grew wondrous cold: |
||||
And ice, mast-high, came floating by, |
||||
As green as emerald. |
||||
|
||||
And through the drifts the snowy clifts |
||||
Did send a dismal sheen: |
||||
Nor shapes of men nor beasts we ken— |
||||
The ice was all between. |
||||
|
||||
The ice was here, the ice was there, |
||||
The ice was all around: |
||||
It cracked and growled, and roared and howled, |
||||
Like noises in a swound! |
||||
|
||||
At length did cross an Albatross, |
||||
Thorough the fog it came; |
||||
As if it had been a Christian soul, |
||||
We hailed it in God's name. |
||||
|
||||
It ate the food it ne'er had eat, |
||||
And round and round it flew. |
||||
The ice did split with a thunder-fit; |
||||
The helmsman steered us through! |
||||
|
||||
And a good south wind sprung up behind; |
||||
The Albatross did follow, |
||||
And every day, for food or play, |
||||
Came to the mariner's hollo! |
||||
|
||||
In mist or cloud, on mast or shroud, |
||||
It perched for vespers nine; |
||||
Whiles all the night, through fog-smoke white, |
||||
Glimmered the white Moon-shine.' |
||||
|
||||
'God save thee, ancient Mariner! |
||||
From the fiends, that plague thee thus!— |
||||
Why look'st thou so?'—With my cross-bow |
||||
I shot the ALBATROSS. |
||||
|
||||
PART II |
||||
The Sun now rose upon the right: |
||||
Out of the sea came he, |
||||
Still hid in mist, and on the left |
||||
Went down into the sea. |
||||
|
||||
And the good south wind still blew behind, |
||||
But no sweet bird did follow, |
||||
Nor any day for food or play |
||||
Came to the mariner's hollo! |
||||
|
||||
And I had done a hellish thing, |
||||
And it would work 'em woe: |
||||
For all averred, I had killed the bird |
||||
That made the breeze to blow. |
||||
Ah wretch! said they, the bird to slay, |
||||
That made the breeze to blow! |
||||
|
||||
Nor dim nor red, like God's own head, |
||||
The glorious Sun uprist: |
||||
Then all averred, I had killed the bird |
||||
That brought the fog and mist. |
||||
'Twas right, said they, such birds to slay, |
||||
That bring the fog and mist. |
||||
|
||||
The fair breeze blew, the white foam flew, |
||||
The furrow followed free; |
||||
We were the first that ever burst |
||||
Into that silent sea. |
||||
|
||||
Down dropt the breeze, the sails dropt down, |
||||
'Twas sad as sad could be; |
||||
And we did speak only to break |
||||
The silence of the sea! |
||||
|
||||
All in a hot and copper sky, |
||||
The bloody Sun, at noon, |
||||
Right up above the mast did stand, |
||||
No bigger than the Moon. |
||||
|
||||
Day after day, day after day, |
||||
We stuck, nor breath nor motion; |
||||
As idle as a painted ship |
||||
Upon a painted ocean. |
||||
|
||||
Water, water, every where, |
||||
And all the boards did shrink; |
||||
Water, water, every where, |
||||
Nor any drop to drink. |
||||
|
||||
The very deep did rot: O Christ! |
||||
That ever this should be! |
||||
Yea, slimy things did crawl with legs |
||||
Upon the slimy sea. |
||||
|
||||
About, about, in reel and rout |
||||
The death-fires danced at night; |
||||
The water, like a witch's oils, |
||||
Burnt green, and blue and white. |
||||
|
||||
And some in dreams assurèd were |
||||
Of the Spirit that plagued us so; |
||||
Nine fathom deep he had followed us |
||||
From the land of mist and snow. |
||||
|
||||
And every tongue, through utter drought, |
||||
Was withered at the root; |
||||
We could not speak, no more than if |
||||
We had been choked with soot. |
||||
|
||||
Ah! well a-day! what evil looks |
||||
Had I from old and young! |
||||
Instead of the cross, the Albatross |
||||
About my neck was hung. |
||||
|
||||
PART III |
||||
There passed a weary time. Each throat |
||||
Was parched, and glazed each eye. |
||||
A weary time! a weary time! |
||||
How glazed each weary eye, |
||||
|
||||
When looking westward, I beheld |
||||
A something in the sky. |
||||
|
||||
At first it seemed a little speck, |
||||
And then it seemed a mist; |
||||
It moved and moved, and took at last |
||||
A certain shape, I wist. |
||||
|
||||
A speck, a mist, a shape, I wist! |
||||
And still it neared and neared: |
||||
As if it dodged a water-sprite, |
||||
It plunged and tacked and veered. |
||||
|
||||
With throats unslaked, with black lips baked, |
||||
We could nor laugh nor wail; |
||||
Through utter drought all dumb we stood! |
||||
I bit my arm, I sucked the blood, |
||||
And cried, A sail! a sail! |
||||
|
||||
With throats unslaked, with black lips baked, |
||||
Agape they heard me call: |
||||
Gramercy! they for joy did grin, |
||||
And all at once their breath drew in. |
||||
As they were drinking all. |
||||
|
||||
See! see! (I cried) she tacks no more! |
||||
Hither to work us weal; |
||||
Without a breeze, without a tide, |
||||
She steadies with upright keel! |
||||
|
||||
The western wave was all a-flame. |
||||
The day was well nigh done! |
||||
Almost upon the western wave |
||||
Rested the broad bright Sun; |
||||
When that strange shape drove suddenly |
||||
Betwixt us and the Sun. |
||||
|
||||
And straight the Sun was flecked with bars, |
||||
(Heaven's Mother send us grace!) |
||||
As if through a dungeon-grate he peered |
||||
With broad and burning face. |
||||
|
||||
Alas! (thought I, and my heart beat loud) |
||||
How fast she nears and nears! |
||||
Are those her sails that glance in the Sun, |
||||
Like restless gossameres? |
||||
|
||||
Are those her ribs through which the Sun |
||||
Did peer, as through a grate? |
||||
And is that Woman all her crew? |
||||
Is that a DEATH? and are there two? |
||||
Is DEATH that woman's mate? |
||||
|
||||
Her lips were red, her looks were free, |
||||
Her locks were yellow as gold: |
||||
Her skin was as white as leprosy, |
||||
The Night-mare LIFE-IN-DEATH was she, |
||||
Who thicks man's blood with cold. |
||||
|
||||
The naked hulk alongside came, |
||||
And the twain were casting dice; |
||||
'The game is done! I've won! I've won!' |
||||
Quoth she, and whistles thrice. |
||||
|
||||
The Sun's rim dips; the stars rush out; |
||||
At one stride comes the dark; |
||||
With far-heard whisper, o'er the sea, |
||||
Off shot the spectre-bark. |
||||
|
||||
We listened and looked sideways up! |
||||
Fear at my heart, as at a cup, |
||||
My life-blood seemed to sip! |
||||
The stars were dim, and thick the night, |
||||
The steersman's face by his lamp gleamed white; |
||||
From the sails the dew did drip— |
||||
Till clomb above the eastern bar |
||||
The hornèd Moon, with one bright star |
||||
Within the nether tip. |
||||
|
||||
One after one, by the star-dogged Moon, |
||||
Too quick for groan or sigh, |
||||
Each turned his face with a ghastly pang, |
||||
And cursed me with his eye. |
||||
|
||||
Four times fifty living men, |
||||
(And I heard nor sigh nor groan) |
||||
With heavy thump, a lifeless lump, |
||||
They dropped down one by one. |
||||
|
||||
The souls did from their bodies fly,— |
||||
They fled to bliss or woe! |
||||
And every soul, it passed me by, |
||||
Like the whizz of my cross-bow! |
||||
|
||||
PART IV |
||||
'I fear thee, ancient Mariner! |
||||
I fear thy skinny hand! |
||||
And thou art long, and lank, and brown, |
||||
As is the ribbed sea-sand. |
||||
|
||||
I fear thee and thy glittering eye, |
||||
And thy skinny hand, so brown.'— |
||||
Fear not, fear not, thou Wedding-Guest! |
||||
This body dropt not down. |
||||
|
||||
Alone, alone, all, all alone, |
||||
Alone on a wide wide sea! |
||||
And never a saint took pity on |
||||
My soul in agony. |
||||
|
||||
The many men, so beautiful! |
||||
And they all dead did lie: |
||||
And a thousand thousand slimy things |
||||
Lived on; and so did I. |
||||
|
||||
I looked upon the rotting sea, |
||||
And drew my eyes away; |
||||
I looked upon the rotting deck, |
||||
And there the dead men lay. |
||||
|
||||
I looked to heaven, and tried to pray; |
||||
But or ever a prayer had gusht, |
||||
A wicked whisper came, and made |
||||
My heart as dry as dust. |
||||
|
||||
I closed my lids, and kept them close, |
||||
And the balls like pulses beat; |
||||
For the sky and the sea, and the sea and the sky |
||||
Lay dead like a load on my weary eye, |
||||
And the dead were at my feet. |
||||
|
||||
The cold sweat melted from their limbs, |
||||
Nor rot nor reek did they: |
||||
The look with which they looked on me |
||||
Had never passed away. |
||||
|
||||
An orphan's curse would drag to hell |
||||
A spirit from on high; |
||||
But oh! more horrible than that |
||||
Is the curse in a dead man's eye! |
||||
Seven days, seven nights, I saw that curse, |
||||
And yet I could not die. |
||||
|
||||
The moving Moon went up the sky, |
||||
And no where did abide: |
||||
Softly she was going up, |
||||
And a star or two beside— |
||||
|
||||
Her beams bemocked the sultry main, |
||||
Like April hoar-frost spread; |
||||
But where the ship's huge shadow lay, |
||||
The charmèd water burnt alway |
||||
A still and awful red. |
||||
|
||||
Beyond the shadow of the ship, |
||||
I watched the water-snakes: |
||||
They moved in tracks of shining white, |
||||
And when they reared, the elfish light |
||||
Fell off in hoary flakes. |
||||
|
||||
Within the shadow of the ship |
||||
I watched their rich attire: |
||||
Blue, glossy green, and velvet black, |
||||
They coiled and swam; and every track |
||||
Was a flash of golden fire. |
||||
|
||||
O happy living things! no tongue |
||||
Their beauty might declare: |
||||
A spring of love gushed from my heart, |
||||
And I blessed them unaware: |
||||
Sure my kind saint took pity on me, |
||||
And I blessed them unaware. |
||||
|
||||
The self-same moment I could pray; |
||||
And from my neck so free |
||||
The Albatross fell off, and sank |
||||
Like lead into the sea. |
||||
|
||||
PART V |
||||
Oh sleep! it is a gentle thing, |
||||
Beloved from pole to pole! |
||||
To Mary Queen the praise be given! |
||||
She sent the gentle sleep from Heaven, |
||||
That slid into my soul. |
||||
|
||||
The silly buckets on the deck, |
||||
That had so long remained, |
||||
I dreamt that they were filled with dew; |
||||
And when I awoke, it rained. |
||||
|
||||
My lips were wet, my throat was cold, |
||||
My garments all were dank; |
||||
Sure I had drunken in my dreams, |
||||
And still my body drank. |
||||
|
||||
I moved, and could not feel my limbs: |
||||
I was so light—almost |
||||
I thought that I had died in sleep, |
||||
And was a blessed ghost. |
||||
|
||||
And soon I heard a roaring wind: |
||||
It did not come anear; |
||||
But with its sound it shook the sails, |
||||
That were so thin and sere. |
||||
|
||||
The upper air burst into life! |
||||
And a hundred fire-flags sheen, |
||||
To and fro they were hurried about! |
||||
And to and fro, and in and out, |
||||
The wan stars danced between. |
||||
|
||||
And the coming wind did roar more loud, |
||||
And the sails did sigh like sedge, |
||||
And the rain poured down from one black cloud; |
||||
The Moon was at its edge. |
||||
|
||||
The thick black cloud was cleft, and still |
||||
The Moon was at its side: |
||||
Like waters shot from some high crag, |
||||
The lightning fell with never a jag, |
||||
A river steep and wide. |
||||
|
||||
The loud wind never reached the ship, |
||||
Yet now the ship moved on! |
||||
Beneath the lightning and the Moon |
||||
The dead men gave a groan. |
||||
|
||||
They groaned, they stirred, they all uprose, |
||||
Nor spake, nor moved their eyes; |
||||
It had been strange, even in a dream, |
||||
To have seen those dead men rise. |
||||
|
||||
The helmsman steered, the ship moved on; |
||||
Yet never a breeze up-blew; |
||||
The mariners all 'gan work the ropes, |
||||
Where they were wont to do; |
||||
They raised their limbs like lifeless tools— |
||||
We were a ghastly crew. |
||||
|
||||
The body of my brother's son |
||||
Stood by me, knee to knee: |
||||
The body and I pulled at one rope, |
||||
But he said nought to me. |
||||
|
||||
'I fear thee, ancient Mariner!' |
||||
Be calm, thou Wedding-Guest! |
||||
'Twas not those souls that fled in pain, |
||||
Which to their corses came again, |
||||
But a troop of spirits blest: |
||||
|
||||
For when it dawned—they dropped their arms, |
||||
And clustered round the mast; |
||||
Sweet sounds rose slowly through their mouths, |
||||
And from their bodies passed. |
||||
|
||||
Around, around, flew each sweet sound, |
||||
Then darted to the Sun; |
||||
Slowly the sounds came back again, |
||||
Now mixed, now one by one. |
||||
|
||||
Sometimes a-dropping from the sky |
||||
I heard the sky-lark sing; |
||||
Sometimes all little birds that are, |
||||
How they seemed to fill the sea and air |
||||
With their sweet jargoning! |
||||
|
||||
And now 'twas like all instruments, |
||||
Now like a lonely flute; |
||||
And now it is an angel's song, |
||||
That makes the heavens be mute. |
||||
|
||||
It ceased; yet still the sails made on |
||||
A pleasant noise till noon, |
||||
A noise like of a hidden brook |
||||
In the leafy month of June, |
||||
That to the sleeping woods all night |
||||
Singeth a quiet tune. |
||||
|
||||
Till noon we quietly sailed on, |
||||
Yet never a breeze did breathe: |
||||
Slowly and smoothly went the ship, |
||||
Moved onward from beneath. |
||||
|
||||
Under the keel nine fathom deep, |
||||
From the land of mist and snow, |
||||
The spirit slid: and it was he |
||||
That made the ship to go. |
||||
The sails at noon left off their tune, |
||||
And the ship stood still also. |
||||
|
||||
The Sun, right up above the mast, |
||||
Had fixed her to the ocean: |
||||
But in a minute she 'gan stir, |
||||
With a short uneasy motion— |
||||
Backwards and forwards half her length |
||||
With a short uneasy motion. |
||||
|
||||
Then like a pawing horse let go, |
||||
She made a sudden bound: |
||||
It flung the blood into my head, |
||||
And I fell down in a swound. |
||||
|
||||
How long in that same fit I lay, |
||||
I have not to declare; |
||||
But ere my living life returned, |
||||
I heard and in my soul discerned |
||||
Two voices in the air. |
||||
|
||||
'Is it he?' quoth one, 'Is this the man? |
||||
By him who died on cross, |
||||
With his cruel bow he laid full low |
||||
The harmless Albatross. |
||||
|
||||
The spirit who bideth by himself |
||||
In the land of mist and snow, |
||||
He loved the bird that loved the man |
||||
Who shot him with his bow.' |
||||
|
||||
The other was a softer voice, |
||||
As soft as honey-dew: |
||||
Quoth he, 'The man hath penance done, |
||||
And penance more will do.' |
||||
|
||||
PART VI |
||||
|
||||
First Voice |
||||
'But tell me, tell me! speak again, |
||||
Thy soft response renewing— |
||||
What makes that ship drive on so fast? |
||||
What is the ocean doing?' |
||||
|
||||
Second Voice |
||||
Still as a slave before his lord, |
||||
The ocean hath no blast; |
||||
His great bright eye most silently |
||||
Up to the Moon is cast— |
||||
|
||||
If he may know which way to go; |
||||
For she guides him smooth or grim. |
||||
See, brother, see! how graciously |
||||
She looketh down on him.' |
||||
|
||||
First Voice |
||||
'But why drives on that ship so fast, |
||||
Without or wave or wind?' |
||||
|
||||
Second Voice |
||||
'The air is cut away before, |
||||
And closes from behind. |
||||
|
||||
Fly, brother, fly! more high, more high! |
||||
Or we shall be belated: |
||||
For slow and slow that ship will go, |
||||
When the Mariner's trance is abated.' |
||||
|
||||
I woke, and we were sailing on |
||||
As in a gentle weather: |
||||
'Twas night, calm night, the moon was high; |
||||
The dead men stood together. |
||||
|
||||
All stood together on the deck, |
||||
For a charnel-dungeon fitter: |
||||
All fixed on me their stony eyes, |
||||
That in the Moon did glitter. |
||||
|
||||
The pang, the curse, with which they died, |
||||
Had never passed away: |
||||
I could not draw my eyes from theirs, |
||||
Nor turn them up to pray. |
||||
|
||||
And now this spell was snapt: once more |
||||
I viewed the ocean green, |
||||
And looked far forth, yet little saw |
||||
Of what had else been seen— |
||||
|
||||
Like one, that on a lonesome road |
||||
Doth walk in fear and dread, |
||||
And having once turned round walks on, |
||||
And turns no more his head; |
||||
Because he knows, a frightful fiend |
||||
Doth close behind him tread. |
||||
|
||||
But soon there breathed a wind on me, |
||||
Nor sound nor motion made: |
||||
Its path was not upon the sea, |
||||
In ripple or in shade. |
||||
|
||||
It raised my hair, it fanned my cheek |
||||
Like a meadow-gale of spring— |
||||
It mingled strangely with my fears, |
||||
Yet it felt like a welcoming. |
||||
|
||||
Swiftly, swiftly flew the ship, |
||||
Yet she sailed softly too: |
||||
Sweetly, sweetly blew the breeze— |
||||
On me alone it blew. |
||||
|
||||
Oh! dream of joy! is this indeed |
||||
The light-house top I see? |
||||
Is this the hill? is this the kirk? |
||||
Is this mine own countree? |
||||
|
||||
We drifted o'er the harbour-bar, |
||||
And I with sobs did pray— |
||||
O let me be awake, my God! |
||||
Or let me sleep alway. |
||||
|
||||
The harbour-bay was clear as glass, |
||||
So smoothly it was strewn! |
||||
And on the bay the moonlight lay, |
||||
And the shadow of the Moon. |
||||
|
||||
The rock shone bright, the kirk no less, |
||||
That stands above the rock: |
||||
The moonlight steeped in silentness |
||||
The steady weathercock. |
||||
|
||||
And the bay was white with silent light, |
||||
Till rising from the same, |
||||
Full many shapes, that shadows were, |
||||
In crimson colours came. |
||||
|
||||
A little distance from the prow |
||||
Those crimson shadows were: |
||||
I turned my eyes upon the deck— |
||||
Oh, Christ! what saw I there! |
||||
|
||||
Each corse lay flat, lifeless and flat, |
||||
And, by the holy rood! |
||||
A man all light, a seraph-man, |
||||
On every corse there stood. |
||||
|
||||
This seraph-band, each waved his hand: |
||||
It was a heavenly sight! |
||||
They stood as signals to the land, |
||||
Each one a lovely light; |
||||
|
||||
This seraph-band, each waved his hand, |
||||
No voice did they impart— |
||||
No voice; but oh! the silence sank |
||||
Like music on my heart. |
||||
|
||||
But soon I heard the dash of oars, |
||||
I heard the Pilot's cheer; |
||||
My head was turned perforce away |
||||
And I saw a boat appear. |
||||
|
||||
The Pilot and the Pilot's boy, |
||||
I heard them coming fast: |
||||
Dear Lord in Heaven! it was a joy |
||||
The dead men could not blast. |
||||
|
||||
I saw a third—I heard his voice: |
||||
It is the Hermit good! |
||||
He singeth loud his godly hymns |
||||
That he makes in the wood. |
||||
He'll shrieve my soul, he'll wash away |
||||
The Albatross's blood. |
||||
|
||||
PART VII |
||||
This Hermit good lives in that wood |
||||
Which slopes down to the sea. |
||||
How loudly his sweet voice he rears! |
||||
He loves to talk with marineres |
||||
That come from a far countree. |
||||
|
||||
He kneels at morn, and noon, and eve— |
||||
He hath a cushion plump: |
||||
It is the moss that wholly hides |
||||
The rotted old oak-stump. |
||||
|
||||
The skiff-boat neared: I heard them talk, |
||||
'Why, this is strange, I trow! |
||||
Where are those lights so many and fair, |
||||
That signal made but now?' |
||||
|
||||
'Strange, by my faith!' the Hermit said— |
||||
'And they answered not our cheer! |
||||
The planks looked warped! and see those sails, |
||||
How thin they are and sere! |
||||
I never saw aught like to them, |
||||
Unless perchance it were |
||||
|
||||
Brown skeletons of leaves that lag |
||||
My forest-brook along; |
||||
When the ivy-tod is heavy with snow, |
||||
And the owlet whoops to the wolf below, |
||||
That eats the she-wolf's young.' |
||||
|
||||
'Dear Lord! it hath a fiendish look— |
||||
(The Pilot made reply) |
||||
I am a-feared'—'Push on, push on!' |
||||
Said the Hermit cheerily. |
||||
|
||||
The boat came closer to the ship, |
||||
But I nor spake nor stirred; |
||||
The boat came close beneath the ship, |
||||
And straight a sound was heard. |
||||
|
||||
Under the water it rumbled on, |
||||
Still louder and more dread: |
||||
It reached the ship, it split the bay; |
||||
The ship went down like lead. |
||||
|
||||
Stunned by that loud and dreadful sound, |
||||
Which sky and ocean smote, |
||||
Like one that hath been seven days drowned |
||||
My body lay afloat; |
||||
But swift as dreams, myself I found |
||||
Within the Pilot's boat. |
||||
|
||||
Upon the whirl, where sank the ship, |
||||
The boat spun round and round; |
||||
And all was still, save that the hill |
||||
Was telling of the sound. |
||||
|
||||
I moved my lips—the Pilot shrieked |
||||
And fell down in a fit; |
||||
The holy Hermit raised his eyes, |
||||
And prayed where he did sit. |
||||
|
||||
I took the oars: the Pilot's boy, |
||||
Who now doth crazy go, |
||||
Laughed loud and long, and all the while |
||||
His eyes went to and fro. |
||||
'Ha! ha!' quoth he, 'full plain I see, |
||||
The Devil knows how to row.' |
||||
|
||||
And now, all in my own countree, |
||||
I stood on the firm land! |
||||
The Hermit stepped forth from the boat, |
||||
And scarcely he could stand. |
||||
|
||||
'O shrieve me, shrieve me, holy man!' |
||||
The Hermit crossed his brow. |
||||
'Say quick,' quoth he, 'I bid thee say— |
||||
What manner of man art thou?' |
||||
|
||||
Forthwith this frame of mine was wrenched |
||||
With a woful agony, |
||||
Which forced me to begin my tale; |
||||
And then it left me free. |
||||
|
||||
|
||||
Since then, at an uncertain hour, |
||||
That agony returns: |
||||
And till my ghastly tale is told, |
||||
This heart within me burns. |
||||
|
||||
I pass, like night, from land to land; |
||||
I have strange power of speech; |
||||
That moment that his face I see, |
||||
I know the man that must hear me: |
||||
To him my tale I teach. |
||||
|
||||
What loud uproar bursts from that door! |
||||
The wedding-guests are there: |
||||
But in the garden-bower the bride |
||||
And bride-maids singing are: |
||||
And hark the little vesper bell, |
||||
Which biddeth me to prayer! |
||||
|
||||
O Wedding-Guest! this soul hath been |
||||
Alone on a wide wide sea: |
||||
So lonely 'twas, that God himself |
||||
Scarce seemèd there to be. |
||||
|
||||
O sweeter than the marriage-feast, |
||||
'Tis sweeter far to me, |
||||
To walk together to the kirk |
||||
With a goodly company!— |
||||
|
||||
To walk together to the kirk, |
||||
And all together pray, |
||||
While each to his great Father bends, |
||||
Old men, and babes, and loving friends |
||||
And youths and maidens gay! |
||||
|
||||
Farewell, farewell! but this I tell |
||||
To thee, thou Wedding-Guest! |
||||
He prayeth well, who loveth well |
||||
Both man and bird and beast. |
||||
|
||||
He prayeth best, who loveth best |
||||
All things both great and small; |
||||
For the dear God who loveth us, |
||||
He made and loveth all. |
||||
|
||||
The Mariner, whose eye is bright, |
||||
Whose beard with age is hoar, |
||||
Is gone: and now the Wedding-Guest |
||||
Turned from the bridegroom's door. |
||||
|
||||
He went like one that hath been stunned, |
||||
And is of sense forlorn: |
||||
A sadder and a wiser man, |
||||
He rose the morrow morn. |
Loading…
Reference in new issue