OLD | NEW |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package block | 5 package block |
6 | 6 |
7 import ( | 7 import ( |
8 » "bytes"; | 8 » "bytes" |
9 » "fmt"; | 9 » "fmt" |
10 » "io"; | 10 » "io" |
11 » "testing"; | 11 » "testing" |
12 » "testing/iotest"; | 12 » "testing/iotest" |
13 ) | 13 ) |
14 | 14 |
15 // Simple "pseudo-random" stream for testing. | 15 // Simple "pseudo-random" stream for testing. |
16 type incStream struct { | 16 type incStream struct { |
17 » buf» []byte; | 17 » buf []byte |
18 » n» byte; | 18 » n byte |
19 } | 19 } |
20 | 20 |
21 func newIncStream(blockSize int) *incStream { | 21 func newIncStream(blockSize int) *incStream { |
22 » x := new(incStream); | 22 » x := new(incStream) |
23 » x.buf = make([]byte, blockSize); | 23 » x.buf = make([]byte, blockSize) |
24 » return x; | 24 » return x |
25 } | 25 } |
26 | 26 |
27 func (x *incStream) Next() []byte { | 27 func (x *incStream) Next() []byte { |
28 » x.n++; | 28 » x.n++ |
29 for i := range x.buf { | 29 for i := range x.buf { |
30 » » x.buf[i] = x.n; | 30 » » x.buf[i] = x.n |
31 » » x.n++; | 31 » » x.n++ |
32 } | 32 } |
33 » return x.buf; | 33 » return x.buf |
34 } | 34 } |
35 | 35 |
36 func testXorWriter(t *testing.T, maxio int) { | 36 func testXorWriter(t *testing.T, maxio int) { |
37 » var plain, crypt [256]byte; | 37 » var plain, crypt [256]byte |
38 for i := 0; i < len(plain); i++ { | 38 for i := 0; i < len(plain); i++ { |
39 plain[i] = byte(i) | 39 plain[i] = byte(i) |
40 } | 40 } |
41 » b := new(bytes.Buffer); | 41 » b := new(bytes.Buffer) |
42 for block := 1; block <= 64 && block <= maxio; block *= 2 { | 42 for block := 1; block <= 64 && block <= maxio; block *= 2 { |
43 // compute encrypted version | 43 // compute encrypted version |
44 » » n := byte(0); | 44 » » n := byte(0) |
45 for i := 0; i < len(crypt); i++ { | 45 for i := 0; i < len(crypt); i++ { |
46 if i%block == 0 { | 46 if i%block == 0 { |
47 n++ | 47 n++ |
48 } | 48 } |
49 » » » crypt[i] = plain[i] ^ n; | 49 » » » crypt[i] = plain[i] ^ n |
50 » » » n++; | 50 » » » n++ |
51 } | 51 } |
52 | 52 |
53 for frag := 0; frag < 2; frag++ { | 53 for frag := 0; frag < 2; frag++ { |
54 » » » test := fmt.Sprintf("block=%d frag=%d maxio=%d", block,
frag, maxio); | 54 » » » test := fmt.Sprintf("block=%d frag=%d maxio=%d", block,
frag, maxio) |
55 » » » b.Reset(); | 55 » » » b.Reset() |
56 » » » r := bytes.NewBuffer(&plain); | 56 » » » r := bytes.NewBuffer(&plain) |
57 » » » s := newIncStream(block); | 57 » » » s := newIncStream(block) |
58 » » » w := newXorWriter(s, b); | 58 » » » w := newXorWriter(s, b) |
59 | 59 |
60 // copy plain into w in increasingly large chunks: 1, 1,
2, 4, 8, ... | 60 // copy plain into w in increasingly large chunks: 1, 1,
2, 4, 8, ... |
61 // if frag != 0, move the 1 to the end to cause fragment
ation. | 61 // if frag != 0, move the 1 to the end to cause fragment
ation. |
62 if frag == 0 { | 62 if frag == 0 { |
63 » » » » _, err := io.Copyn(w, r, 1); | 63 » » » » _, err := io.Copyn(w, r, 1) |
64 if err != nil { | 64 if err != nil { |
65 » » » » » t.Errorf("%s: first Copyn: %s", test, er
r); | 65 » » » » » t.Errorf("%s: first Copyn: %s", test, er
r) |
66 » » » » » continue; | 66 » » » » » continue |
67 } | 67 } |
68 } | 68 } |
69 for n := 1; n <= len(plain)/2; n *= 2 { | 69 for n := 1; n <= len(plain)/2; n *= 2 { |
70 » » » » _, err := io.Copyn(w, r, int64(n)); | 70 » » » » _, err := io.Copyn(w, r, int64(n)) |
71 if err != nil { | 71 if err != nil { |
72 t.Errorf("%s: Copyn %d: %s", test, n, er
r) | 72 t.Errorf("%s: Copyn %d: %s", test, n, er
r) |
73 } | 73 } |
74 } | 74 } |
75 | 75 |
76 // check output | 76 // check output |
77 » » » crypt := crypt[0 : len(crypt)-frag]; | 77 » » » crypt := crypt[0 : len(crypt)-frag] |
78 » » » data := b.Bytes(); | 78 » » » data := b.Bytes() |
79 if len(data) != len(crypt) { | 79 if len(data) != len(crypt) { |
80 » » » » t.Errorf("%s: want %d bytes, got %d", test, len(
crypt), len(data)); | 80 » » » » t.Errorf("%s: want %d bytes, got %d", test, len(
crypt), len(data)) |
81 » » » » continue; | 81 » » » » continue |
82 } | 82 } |
83 | 83 |
84 if string(data) != string(crypt) { | 84 if string(data) != string(crypt) { |
85 t.Errorf("%s: want %x got %x", test, data, crypt
) | 85 t.Errorf("%s: want %x got %x", test, data, crypt
) |
86 } | 86 } |
87 } | 87 } |
88 } | 88 } |
89 } | 89 } |
90 | 90 |
91 | 91 |
92 func TestXorWriter(t *testing.T) { | 92 func TestXorWriter(t *testing.T) { |
93 // Do shorter I/O sizes first; they're easier to debug. | 93 // Do shorter I/O sizes first; they're easier to debug. |
94 for n := 1; n <= 256 && !t.Failed(); n *= 2 { | 94 for n := 1; n <= 256 && !t.Failed(); n *= 2 { |
95 testXorWriter(t, n) | 95 testXorWriter(t, n) |
96 } | 96 } |
97 } | 97 } |
98 | 98 |
99 func testXorReader(t *testing.T, maxio int) { | 99 func testXorReader(t *testing.T, maxio int) { |
100 var readers = []func(io.Reader) io.Reader{ | 100 var readers = []func(io.Reader) io.Reader{ |
101 func(r io.Reader) io.Reader { return r }, | 101 func(r io.Reader) io.Reader { return r }, |
102 iotest.OneByteReader, | 102 iotest.OneByteReader, |
103 iotest.HalfReader, | 103 iotest.HalfReader, |
104 » }; | 104 » } |
105 » var plain, crypt [256]byte; | 105 » var plain, crypt [256]byte |
106 for i := 0; i < len(plain); i++ { | 106 for i := 0; i < len(plain); i++ { |
107 plain[i] = byte(255 - i) | 107 plain[i] = byte(255 - i) |
108 } | 108 } |
109 » b := new(bytes.Buffer); | 109 » b := new(bytes.Buffer) |
110 for block := 1; block <= 64 && block <= maxio; block *= 2 { | 110 for block := 1; block <= 64 && block <= maxio; block *= 2 { |
111 // compute encrypted version | 111 // compute encrypted version |
112 » » n := byte(0); | 112 » » n := byte(0) |
113 for i := 0; i < len(crypt); i++ { | 113 for i := 0; i < len(crypt); i++ { |
114 if i%block == 0 { | 114 if i%block == 0 { |
115 n++ | 115 n++ |
116 } | 116 } |
117 » » » crypt[i] = plain[i] ^ n; | 117 » » » crypt[i] = plain[i] ^ n |
118 » » » n++; | 118 » » » n++ |
119 } | 119 } |
120 | 120 |
121 for mode := 0; mode < len(readers); mode++ { | 121 for mode := 0; mode < len(readers); mode++ { |
122 for frag := 0; frag < 2; frag++ { | 122 for frag := 0; frag < 2; frag++ { |
123 » » » » test := fmt.Sprintf("block=%d mode=%d frag=%d ma
xio=%d", block, mode, frag, maxio); | 123 » » » » test := fmt.Sprintf("block=%d mode=%d frag=%d ma
xio=%d", block, mode, frag, maxio) |
124 » » » » s := newIncStream(block); | 124 » » » » s := newIncStream(block) |
125 » » » » b.Reset(); | 125 » » » » b.Reset() |
126 » » » » r := newXorReader(s, readers[mode](bytes.NewBuff
er(crypt[0:maxio]))); | 126 » » » » r := newXorReader(s, readers[mode](bytes.NewBuff
er(crypt[0:maxio]))) |
127 | 127 |
128 // read from crypt in increasingly large chunks:
1, 1, 2, 4, 8, ... | 128 // read from crypt in increasingly large chunks:
1, 1, 2, 4, 8, ... |
129 // if frag == 1, move the 1 to the end to cause
fragmentation. | 129 // if frag == 1, move the 1 to the end to cause
fragmentation. |
130 if frag == 0 { | 130 if frag == 0 { |
131 » » » » » _, err := io.Copyn(b, r, 1); | 131 » » » » » _, err := io.Copyn(b, r, 1) |
132 if err != nil { | 132 if err != nil { |
133 » » » » » » t.Errorf("%s: first Copyn: %s",
test, err); | 133 » » » » » » t.Errorf("%s: first Copyn: %s",
test, err) |
134 » » » » » » continue; | 134 » » » » » » continue |
135 } | 135 } |
136 } | 136 } |
137 for n := 1; n <= maxio/2; n *= 2 { | 137 for n := 1; n <= maxio/2; n *= 2 { |
138 » » » » » _, err := io.Copyn(b, r, int64(n)); | 138 » » » » » _, err := io.Copyn(b, r, int64(n)) |
139 if err != nil { | 139 if err != nil { |
140 t.Errorf("%s: Copyn %d: %s", tes
t, n, err) | 140 t.Errorf("%s: Copyn %d: %s", tes
t, n, err) |
141 } | 141 } |
142 } | 142 } |
143 | 143 |
144 // check output | 144 // check output |
145 » » » » data := b.Bytes(); | 145 » » » » data := b.Bytes() |
146 » » » » crypt := crypt[0 : maxio-frag]; | 146 » » » » crypt := crypt[0 : maxio-frag] |
147 » » » » plain := plain[0 : maxio-frag]; | 147 » » » » plain := plain[0 : maxio-frag] |
148 if len(data) != len(plain) { | 148 if len(data) != len(plain) { |
149 » » » » » t.Errorf("%s: want %d bytes, got %d", te
st, len(plain), len(data)); | 149 » » » » » t.Errorf("%s: want %d bytes, got %d", te
st, len(plain), len(data)) |
150 » » » » » continue; | 150 » » » » » continue |
151 } | 151 } |
152 | 152 |
153 if string(data) != string(plain) { | 153 if string(data) != string(plain) { |
154 t.Errorf("%s: input=%x want %x got %x",
test, crypt, plain, data) | 154 t.Errorf("%s: input=%x want %x got %x",
test, crypt, plain, data) |
155 } | 155 } |
156 } | 156 } |
157 } | 157 } |
158 } | 158 } |
159 } | 159 } |
160 | 160 |
161 func TestXorReader(t *testing.T) { | 161 func TestXorReader(t *testing.T) { |
162 // Do shorter I/O sizes first; they're easier to debug. | 162 // Do shorter I/O sizes first; they're easier to debug. |
163 for n := 1; n <= 256 && !t.Failed(); n *= 2 { | 163 for n := 1; n <= 256 && !t.Failed(); n *= 2 { |
164 testXorReader(t, n) | 164 testXorReader(t, n) |
165 } | 165 } |
166 } | 166 } |
167 | 167 |
168 // TODO(rsc): Test handling of writes after write errors. | 168 // TODO(rsc): Test handling of writes after write errors. |
OLD | NEW |