Commit 27779dd6 authored by Rob Pike's avatar Rob Pike

fix bug in bytes.Map and add test cases for Map in both strings and bytes packages.

thanks to ulrik.sverdrup for the test case.

Fixes #191.

R=rsc
CC=golang-dev
https://golang.org/cl/155056
parent 13ad5d40
...@@ -220,9 +220,7 @@ func Map(mapping func(rune int) int, s []byte) []byte { ...@@ -220,9 +220,7 @@ func Map(mapping func(rune int) int, s []byte) []byte {
for i := 0; i < len(s); { for i := 0; i < len(s); {
wid := 1; wid := 1;
rune := int(s[i]); rune := int(s[i]);
if rune < utf8.RuneSelf { if rune >= utf8.RuneSelf {
rune = mapping(rune)
} else {
rune, wid = utf8.DecodeRune(s[i:len(s)]) rune, wid = utf8.DecodeRune(s[i:len(s)])
} }
rune = mapping(rune); rune = mapping(rune);
......
...@@ -268,9 +268,22 @@ func tenRunes(rune int) string { ...@@ -268,9 +268,22 @@ func tenRunes(rune int) string {
return string(r); return string(r);
} }
// User-defined self-inverse mapping function
func rot13(rune int) int {
step := 13;
if rune >= 'a' && rune <= 'z' {
return ((rune - 'a' + step) % 26) + 'a'
}
if rune >= 'A' && rune <= 'Z' {
return ((rune - 'A' + step) % 26) + 'A'
}
return rune;
}
func TestMap(t *testing.T) { func TestMap(t *testing.T) {
// Run a couple of awful growth/shrinkage tests // Run a couple of awful growth/shrinkage tests
a := tenRunes('a'); a := tenRunes('a');
// 1. Grow. This triggers two reallocations in Map. // 1. Grow. This triggers two reallocations in Map.
maxRune := func(rune int) int { return unicode.MaxRune }; maxRune := func(rune int) int { return unicode.MaxRune };
m := Map(maxRune, Bytes(a)); m := Map(maxRune, Bytes(a));
...@@ -278,6 +291,7 @@ func TestMap(t *testing.T) { ...@@ -278,6 +291,7 @@ func TestMap(t *testing.T) {
if string(m) != expect { if string(m) != expect {
t.Errorf("growing: expected %q got %q", expect, m) t.Errorf("growing: expected %q got %q", expect, m)
} }
// 2. Shrink // 2. Shrink
minRune := func(rune int) int { return 'a' }; minRune := func(rune int) int { return 'a' };
m = Map(minRune, Bytes(tenRunes(unicode.MaxRune))); m = Map(minRune, Bytes(tenRunes(unicode.MaxRune)));
...@@ -285,6 +299,20 @@ func TestMap(t *testing.T) { ...@@ -285,6 +299,20 @@ func TestMap(t *testing.T) {
if string(m) != expect { if string(m) != expect {
t.Errorf("shrinking: expected %q got %q", expect, m) t.Errorf("shrinking: expected %q got %q", expect, m)
} }
// 3. Rot13
m = Map(rot13, Bytes("a to zed"));
expect = "n gb mrq";
if string(m) != expect {
t.Errorf("rot13: expected %q got %q", expect, m)
}
// 4. Rot13^2
m = Map(rot13, Map(rot13, Bytes("a to zed")));
expect = "a to zed";
if string(m) != expect {
t.Errorf("rot13: expected %q got %q", expect, m)
}
} }
func TestToUpper(t *testing.T) { runStringTests(t, ToUpper, "ToUpper", upperTests) } func TestToUpper(t *testing.T) { runStringTests(t, ToUpper, "ToUpper", upperTests) }
......
...@@ -226,6 +226,18 @@ func tenRunes(rune int) string { ...@@ -226,6 +226,18 @@ func tenRunes(rune int) string {
return string(r); return string(r);
} }
// User-defined self-inverse mapping function
func rot13(rune int) int {
step := 13;
if rune >= 'a' && rune <= 'z' {
return ((rune - 'a' + step) % 26) + 'a'
}
if rune >= 'A' && rune <= 'Z' {
return ((rune - 'A' + step) % 26) + 'A'
}
return rune;
}
func TestMap(t *testing.T) { func TestMap(t *testing.T) {
// Run a couple of awful growth/shrinkage tests // Run a couple of awful growth/shrinkage tests
a := tenRunes('a'); a := tenRunes('a');
...@@ -236,6 +248,7 @@ func TestMap(t *testing.T) { ...@@ -236,6 +248,7 @@ func TestMap(t *testing.T) {
if m != expect { if m != expect {
t.Errorf("growing: expected %q got %q", expect, m) t.Errorf("growing: expected %q got %q", expect, m)
} }
// 2. Shrink // 2. Shrink
minRune := func(rune int) int { return 'a' }; minRune := func(rune int) int { return 'a' };
m = Map(minRune, tenRunes(unicode.MaxRune)); m = Map(minRune, tenRunes(unicode.MaxRune));
...@@ -243,6 +256,20 @@ func TestMap(t *testing.T) { ...@@ -243,6 +256,20 @@ func TestMap(t *testing.T) {
if m != expect { if m != expect {
t.Errorf("shrinking: expected %q got %q", expect, m) t.Errorf("shrinking: expected %q got %q", expect, m)
} }
// 3. Rot13
m = Map(rot13, "a to zed");
expect = "n gb mrq";
if m != expect {
t.Errorf("rot13: expected %q got %q", expect, m)
}
// 4. Rot13^2
m = Map(rot13, Map(rot13, "a to zed"));
expect = "a to zed";
if m != expect {
t.Errorf("rot13: expected %q got %q", expect, m)
}
} }
func TestToUpper(t *testing.T) { runStringTests(t, ToUpper, "ToUpper", upperTests) } func TestToUpper(t *testing.T) { runStringTests(t, ToUpper, "ToUpper", upperTests) }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment