golib/3p/transform/transform_test.go

251 lines
5.7 KiB
Go

package transform
import (
"bufio"
"bytes"
"fmt"
"io"
"io/ioutil"
"log"
"math/rand"
"regexp"
"strings"
"testing"
"time"
)
func Rot13(r io.Reader) *Transformer {
buf := make([]byte, rand.Int()%256+1) // used to test varying slice sizes
//buf := make([]byte, 256)
return NewTransformer(func() ([]byte, error) {
n, err := r.Read(buf)
if err != nil {
return nil, err
}
for i := 0; i < n; i++ {
if buf[i] >= 'a' && buf[i] <= 'z' {
buf[i] = ((buf[i] - 'a' + 13) % 26) + 'a'
} else if buf[i] >= 'A' && buf[i] <= 'Z' {
buf[i] = ((buf[i] - 'A' + 13) % 26) + 'A'
}
}
return buf[:n], nil
})
}
func TestTransformer(t *testing.T) {
// simple
msg := "Hello\n13th Floor"
data, err := ioutil.ReadAll(Rot13(Rot13(bytes.NewBufferString(msg))))
if err != nil {
t.Fatal(err)
}
if msg != string(data) {
t.Fatalf("expected '%v', got '%v'\n", msg, string(data))
}
// random
rand.Seed(time.Now().UnixNano())
buf := make([]byte, 10000)
for i := 0; i < 1000; i++ {
_, err := rand.Read(buf)
if err != nil {
t.Fatal(err)
}
data, err := ioutil.ReadAll(Rot13(Rot13(bytes.NewBuffer(buf))))
if err != nil {
t.Fatal(err)
}
if string(buf) != string(data) {
t.Fatalf("expected '%v', got '%v'\n", string(buf), string(data))
}
}
}
func ExampleTransformer_rot13() {
// Rot13 transformation
rot13 := func(r io.Reader) *Transformer {
buf := make([]byte, 256)
return NewTransformer(func() ([]byte, error) {
n, err := r.Read(buf)
if err != nil {
return nil, err
}
for i := 0; i < n; i++ {
if buf[i] >= 'a' && buf[i] <= 'z' {
buf[i] = ((buf[i] - 'a' + 13) % 26) + 'a'
} else if buf[i] >= 'A' && buf[i] <= 'Z' {
buf[i] = ((buf[i] - 'A' + 13) % 26) + 'A'
}
}
return buf[:n], nil
})
}
// Pass the string though the transformer.
out, err := ioutil.ReadAll(rot13(bytes.NewBufferString("Hello World")))
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", out)
// Output:
// Uryyb Jbeyq
}
func ExampleTransformer_toUpper() {
// Convert a string to uppper case. Unicode aware.
toUpper := func(r io.Reader) *Transformer {
br := bufio.NewReader(r)
return NewTransformer(func() ([]byte, error) {
c, _, err := br.ReadRune()
if err != nil {
return nil, err
}
return []byte(strings.ToUpper(string([]rune{c}))), nil
})
}
// Pass the string though the transformer.
out, err := ioutil.ReadAll(toUpper(bytes.NewBufferString("Hello World")))
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", out)
// Output:
// HELLO WORLD
}
func ExampleTransformer_lineMatcherRegExp() {
// Filter lines matching a pattern
matcher := func(r io.Reader, pattern string) *Transformer {
br := bufio.NewReader(r)
return NewTransformer(func() ([]byte, error) {
for {
line, err := br.ReadBytes('\n')
matched, _ := regexp.Match(pattern, line)
if matched {
return line, err
}
if err != nil {
return nil, err
}
}
})
}
logs := `
23 Apr 17:32:23.604 [INFO] DB loaded in 0.551 seconds
23 Apr 17:32:23.605 [WARN] Disk space is low
23 Apr 17:32:23.054 [INFO] Server started on port 7812
23 Apr 17:32:23.141 [INFO] Ready for connections
`
// Pass the string though the transformer.
out, err := ioutil.ReadAll(matcher(bytes.NewBufferString(logs), "WARN"))
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", out)
// Output:
// 23 Apr 17:32:23.605 [WARN] Disk space is low
}
func ExampleTransformer_trimmer() {
// Trim space from all lines
trimmer := func(r io.Reader) *Transformer {
br := bufio.NewReader(r)
return NewTransformer(func() ([]byte, error) {
for {
line, err := br.ReadBytes('\n')
if len(line) > 0 {
line = append(bytes.TrimSpace(line), '\n')
}
return line, err
}
})
}
phrases := " lacy timber \n"
phrases += "\t\thybrid gossiping\t\n"
phrases += " coy radioactivity\n"
phrases += "rocky arrow \n"
// Pass the string though the transformer.
out, err := ioutil.ReadAll(trimmer(bytes.NewBufferString(phrases)))
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", out)
// Output:
// lacy timber
// hybrid gossiping
// coy radioactivity
// rocky arrow
}
func ExampleTransformer_pipeline() {
// Filter lines matching a pattern
matcher := func(r io.Reader, pattern string) *Transformer {
br := bufio.NewReader(r)
return NewTransformer(func() ([]byte, error) {
for {
line, err := br.ReadBytes('\n')
matched, _ := regexp.Match(pattern, line)
if matched {
return line, err
}
if err != nil {
return nil, err
}
}
})
}
// Trim space from all lines
trimmer := func(r io.Reader) *Transformer {
br := bufio.NewReader(r)
return NewTransformer(func() ([]byte, error) {
for {
line, err := br.ReadBytes('\n')
if len(line) > 0 {
line = append(bytes.TrimSpace(line), '\n')
}
return line, err
}
})
}
// Convert a string to uppper case. Unicode aware. In this example
// we only process one rune at a time. It works but it's not ideal
// for production.
toUpper := func(r io.Reader) *Transformer {
br := bufio.NewReader(r)
return NewTransformer(func() ([]byte, error) {
c, _, err := br.ReadRune()
if err != nil {
return nil, err
}
return []byte(strings.ToUpper(string([]rune{c}))), nil
})
}
phrases := " lacy timber \n"
phrases += "\t\thybrid gossiping\t\n"
phrases += " coy radioactivity\n"
phrases += "rocky arrow \n"
// create a transformer that matches lines on the letter 'o', trims the
// space from the lines, and transforms to upper case.
r := toUpper(trimmer(matcher(bytes.NewBufferString(phrases), "o")))
// Pass the string though the transformer.
out, err := ioutil.ReadAll(r)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", out)
// Output:
// HYBRID GOSSIPING
// COY RADIOACTIVITY
// ROCKY ARROW
}