selfcare init
This commit is contained in:
19
proxy_go/public/go-oi@v1.0.0/LICENSE
Normal file
19
proxy_go/public/go-oi@v1.0.0/LICENSE
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2016 Charles Iliya Krempeaux <charles@reptile.ca> :: http://changelog.ca/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
64
proxy_go/public/go-oi@v1.0.0/README.md
Normal file
64
proxy_go/public/go-oi@v1.0.0/README.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# go-oi
|
||||
|
||||
Package **oi** provides useful tools to be used with the Go programming language's standard "io" package.
|
||||
|
||||
For example, did you know that when you call the `Write` method on something that fits the `io.Writer`
|
||||
interface, that it is possible that not everything was be written?!
|
||||
|
||||
I.e., that a _**short write**_ happened.
|
||||
|
||||
That just doing the following is (in general) **not** enough:
|
||||
```
|
||||
n, err := writer.Write(p)
|
||||
```
|
||||
|
||||
That, for example, you should be checking if `err == io.ErrShortWrite`, and then maybe calling the `Write`
|
||||
method again but only with what didn't get written.
|
||||
|
||||
For a simple example of this (that actually is **not** sufficient to solve this problem, but illustrates
|
||||
the direction you would need to go to solve this problem is):
|
||||
```
|
||||
n, err := w.Write(p)
|
||||
|
||||
if io.ErrShortWrite == err {
|
||||
n2, err2 := w.Write(p[n:])
|
||||
}
|
||||
```
|
||||
|
||||
Note that the second call to the `Write` method passed `p[n:]` (instead of just `p`), to account for the `n` bytes
|
||||
already being written (with the first call to the `Write` method).
|
||||
|
||||
A more "production quality" version of this would likely be in a loop, but such that that the loop had "guards"
|
||||
against looping forever, and also possibly looping for "too long".
|
||||
|
||||
Well package **oi** provides tools that helps you deal with this and other problems. For example, you
|
||||
can handle a _**short write**_ with the following **oi** func:
|
||||
```
|
||||
n, err := oi.LongWrite(writer, p)
|
||||
```
|
||||
|
||||
|
||||
## Documention
|
||||
|
||||
Online documentation, which includes examples, can be found at: http://godoc.org/github.com/reiver/go-oi
|
||||
|
||||
[](https://godoc.org/github.com/reiver/go-oi)
|
||||
|
||||
|
||||
## Example
|
||||
```
|
||||
import (
|
||||
"github.com/reiver/go-oi"
|
||||
)
|
||||
|
||||
// ...
|
||||
|
||||
p := []byte("It is important that this message be written!!!")
|
||||
|
||||
n, err := oi.LongWrite(writer, p)
|
||||
if nil != err {
|
||||
//@TODO: Handle error.
|
||||
return
|
||||
}
|
||||
|
||||
```
|
||||
39
proxy_go/public/go-oi@v1.0.0/doc.go
Normal file
39
proxy_go/public/go-oi@v1.0.0/doc.go
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Package oi provides useful tools to be used with Go's standard "io" package.
|
||||
|
||||
For example, did you know that when you call the Write method on something that fits the io.Writer
|
||||
interface, that it is possible that not everything was be written?!
|
||||
|
||||
I.e., that a 'short write' happened.
|
||||
|
||||
That just doing the following is (in general) not enough:
|
||||
|
||||
n, err := writer.Write(p)
|
||||
|
||||
That, for example, you should be checking if "err == io.ErrShortWrite", and then maybe calling the Write
|
||||
method again but only with what didn't get written.
|
||||
|
||||
For a simple example of this (that actually is not sufficient to solve this problem, but illustrates
|
||||
the direction you would need to go to solve this problem is):
|
||||
|
||||
n, err := w.Write(p)
|
||||
|
||||
if io.ErrShortWrite == err {
|
||||
n2, err2 := w.Write(p[n:])
|
||||
}
|
||||
|
||||
Note that the second call to the Write method passed "p[n:]" (instead of just "p"), to account for the "n" bytes
|
||||
already being written (with the first call to the `Write` method).
|
||||
|
||||
A more "production quality" version of this would likely be in a loop, but such that that the loop had "guards"
|
||||
against looping forever, and also possibly looping for "too long".
|
||||
|
||||
|
||||
Well package oi provides tools that helps you deal with this and other problems. For example, you
|
||||
can handle a 'short write' with the following oi func:
|
||||
```
|
||||
n, err := oi.LongWrite(writer, p)
|
||||
```
|
||||
|
||||
*/
|
||||
package oi
|
||||
39
proxy_go/public/go-oi@v1.0.0/longwrite.go
Normal file
39
proxy_go/public/go-oi@v1.0.0/longwrite.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package oi
|
||||
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
|
||||
// LongWrite tries to write the bytes from 'p' to the writer 'w', such that it deals
|
||||
// with "short writes" where w.Write would return an error of io.ErrShortWrite and
|
||||
// n < len(p).
|
||||
//
|
||||
// Note that LongWrite still could return the error io.ErrShortWrite; but this
|
||||
// would only be after trying to handle the io.ErrShortWrite a number of times, and
|
||||
// then eventually giving up.
|
||||
func LongWrite(w io.Writer, p []byte) (int64, error) {
|
||||
|
||||
numWritten := int64(0)
|
||||
for {
|
||||
//@TODO: Should check to make sure this doesn't get stuck in an infinite loop writting nothing!
|
||||
n, err := w.Write(p)
|
||||
numWritten += int64(n)
|
||||
if nil != err && io.ErrShortWrite != err {
|
||||
return numWritten, err
|
||||
}
|
||||
|
||||
if !(n < len(p)) {
|
||||
break
|
||||
}
|
||||
|
||||
p = p[n:]
|
||||
|
||||
if len(p) < 1 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return numWritten, nil
|
||||
}
|
||||
195
proxy_go/public/go-oi@v1.0.0/longwrite_test.go
Normal file
195
proxy_go/public/go-oi@v1.0.0/longwrite_test.go
Normal file
@@ -0,0 +1,195 @@
|
||||
package oi
|
||||
|
||||
|
||||
import (
|
||||
"github.com/reiver/go-oi/test"
|
||||
|
||||
"errors"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
||||
func TestLongWrite(t *testing.T) {
|
||||
|
||||
tests := []struct{
|
||||
String string
|
||||
}{
|
||||
{
|
||||
String: "",
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
String: "apple",
|
||||
},
|
||||
{
|
||||
String: "banana",
|
||||
},
|
||||
{
|
||||
String: "cherry",
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
String: "Hello world!",
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
String: "😁😂😃😄😅😆😉😊😋😌😍😏😒😓😔😖😘😚😜😝😞😠😡😢😣😤😥😨😩😪😫😭😰😱😲😳😵😷",
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
String: "0123456789",
|
||||
},
|
||||
{
|
||||
String: "٠١٢٣٤٥٦٧٨٩", // Arabic-Indic Digits
|
||||
},
|
||||
{
|
||||
String: "۰۱۲۳۴۵۶۷۸۹", // Extended Arabic-Indic Digits
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
String: "Ⅰ Ⅱ Ⅲ Ⅳ Ⅴ Ⅵ Ⅶ Ⅷ Ⅸ Ⅹ Ⅺ Ⅻ Ⅼ Ⅽ Ⅾ Ⅿ",
|
||||
},
|
||||
{
|
||||
String: "ⅰ ⅱ ⅲ ⅳ ⅴ ⅵ ⅶ ⅷ ⅸ ⅹ ⅺ ⅻ ⅼ ⅽ ⅾ ⅿ",
|
||||
},
|
||||
{
|
||||
String: "ↀ ↁ ↂ Ↄ ↄ ↅ ↆ ↇ ↈ",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
for testNumber, test := range tests {
|
||||
|
||||
p := []byte(test.String)
|
||||
|
||||
var writer oitest.ShortWriter
|
||||
n, err := LongWrite(&writer, p)
|
||||
if nil != err {
|
||||
t.Errorf("For test #%d, did not expect an error, but actually got one: (%T) %q; for %q.", testNumber, err, err.Error(), test.String)
|
||||
continue
|
||||
}
|
||||
if expected, actual := int64(len([]byte(test.String))), n; expected != actual {
|
||||
t.Errorf("For test #%d, expected %d, but actually got %d; for %q.", testNumber, expected, actual, test.String)
|
||||
continue
|
||||
}
|
||||
if expected, actual := test.String, writer.String(); expected != actual {
|
||||
t.Errorf("For test #%d, expected %q, but actually got %q", testNumber, expected, actual)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func TestLongWriteExpectError(t *testing.T) {
|
||||
|
||||
tests := []struct{
|
||||
String string
|
||||
Expected string
|
||||
Writes []int
|
||||
Err error
|
||||
}{
|
||||
{
|
||||
String: "apple",
|
||||
Expected: "appl",
|
||||
Writes: []int{2,2},
|
||||
Err: errors.New("Crabapple!"),
|
||||
},
|
||||
{
|
||||
String: "apple",
|
||||
Expected: "appl",
|
||||
Writes: []int{2,2,0},
|
||||
Err: errors.New("Crabapple!!"),
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
String: "banana",
|
||||
Expected: "banan",
|
||||
Writes: []int{2,3},
|
||||
Err: errors.New("bananananananana!"),
|
||||
},
|
||||
{
|
||||
String: "banana",
|
||||
Expected: "banan",
|
||||
Writes: []int{2,3,0},
|
||||
Err: errors.New("bananananananananananananana!!!"),
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
String: "cherry",
|
||||
Expected: "cher",
|
||||
Writes: []int{1,1,1,1},
|
||||
Err: errors.New("C.H.E.R.R.Y."),
|
||||
},
|
||||
{
|
||||
String: "cherry",
|
||||
Expected: "cher",
|
||||
Writes: []int{1,1,1,1,0},
|
||||
Err: errors.New("C_H_E_R_R_Y"),
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
String: "Hello world!",
|
||||
Expected: "Hello world",
|
||||
Writes: []int{1,2,3,5},
|
||||
Err: errors.New("Welcome!"),
|
||||
},
|
||||
{
|
||||
String: "Hello world!",
|
||||
Expected: "Hello world",
|
||||
Writes: []int{1,2,3,5,0},
|
||||
Err: errors.New("WeLcOmE!!!"),
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
String: " ",
|
||||
Expected: " ",
|
||||
Writes: []int{1,2,3,5,8,13},
|
||||
Err: errors.New("Space, the final frontier"),
|
||||
},
|
||||
{
|
||||
String: " ",
|
||||
Expected: " ",
|
||||
Writes: []int{1,2,3,5,8,13,0},
|
||||
Err: errors.New("Space, the final frontier"),
|
||||
},
|
||||
}
|
||||
|
||||
for testNumber, test := range tests {
|
||||
|
||||
p := []byte(test.String)
|
||||
|
||||
writer := oitest.NewWritesThenErrorWriter(test.Err, test.Writes...)
|
||||
n, err := LongWrite(writer, p)
|
||||
if nil == err {
|
||||
t.Errorf("For test #%d, expected to get an error, but actually did not get one: %v; for %q.", testNumber, err, test.String)
|
||||
continue
|
||||
}
|
||||
if expected, actual := test.Err, err; expected != actual {
|
||||
t.Errorf("For test #%d, expected to get error (%T) %q, but actually got (%T) %q; for %q.", testNumber, expected, expected.Error(), actual, actual.Error(), test.String)
|
||||
continue
|
||||
}
|
||||
if expected, actual := int64(len(test.Expected)), n; expected != actual {
|
||||
t.Errorf("For test #%d, expected number of bytes written to be %d = len(%q), but actually was %d = len(%q); for %q.", testNumber, expected, test.Expected, actual, writer.String(), test.String)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
28
proxy_go/public/go-oi@v1.0.0/longwritebyte.go
Normal file
28
proxy_go/public/go-oi@v1.0.0/longwritebyte.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package oi
|
||||
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
|
||||
// LongWriteByte trys to write the byte from 'b' to the writer 'w', such that it deals
|
||||
// with "short writes" where w.Write would return an error of io.ErrShortWrite and
|
||||
// n < 1.
|
||||
//
|
||||
// Note that LongWriteByte still could return the error io.ErrShortWrite; but this
|
||||
// would only be after trying to handle the io.ErrShortWrite a number of times, and
|
||||
// then eventually giving up.
|
||||
func LongWriteByte(w io.Writer, b byte) error {
|
||||
var buffer [1]byte
|
||||
p := buffer[:]
|
||||
|
||||
buffer[0] = b
|
||||
|
||||
numWritten, err := LongWrite(w, p)
|
||||
if 1 != numWritten {
|
||||
return io.ErrShortWrite
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
101
proxy_go/public/go-oi@v1.0.0/longwritebyte_test.go
Normal file
101
proxy_go/public/go-oi@v1.0.0/longwritebyte_test.go
Normal file
@@ -0,0 +1,101 @@
|
||||
package oi
|
||||
|
||||
|
||||
import (
|
||||
"github.com/reiver/go-oi/test"
|
||||
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
||||
func TestLongWriteByte(t *testing.T) {
|
||||
|
||||
tests := []struct{
|
||||
Byte byte
|
||||
}{}
|
||||
|
||||
for b := byte(' '); b <= byte('/'); b++ {
|
||||
test := struct {
|
||||
Byte byte
|
||||
}{
|
||||
Byte:b,
|
||||
}
|
||||
|
||||
tests = append(tests, test)
|
||||
}
|
||||
|
||||
for b := byte('0'); b <= byte('9'); b++ {
|
||||
test := struct {
|
||||
Byte byte
|
||||
}{
|
||||
Byte:b,
|
||||
}
|
||||
|
||||
tests = append(tests, test)
|
||||
}
|
||||
|
||||
for b := byte(':'); b <= byte('@'); b++ {
|
||||
test := struct {
|
||||
Byte byte
|
||||
}{
|
||||
Byte:b,
|
||||
}
|
||||
|
||||
tests = append(tests, test)
|
||||
}
|
||||
|
||||
for b := byte('A'); b <= byte('Z'); b++ {
|
||||
test := struct {
|
||||
Byte byte
|
||||
}{
|
||||
Byte:b,
|
||||
}
|
||||
|
||||
tests = append(tests, test)
|
||||
}
|
||||
|
||||
for b := byte('['); b <= byte('`'); b++ {
|
||||
test := struct {
|
||||
Byte byte
|
||||
}{
|
||||
Byte:b,
|
||||
}
|
||||
|
||||
tests = append(tests, test)
|
||||
}
|
||||
|
||||
for b := byte('a'); b <= byte('z'); b++ {
|
||||
test := struct {
|
||||
Byte byte
|
||||
}{
|
||||
Byte:b,
|
||||
}
|
||||
|
||||
tests = append(tests, test)
|
||||
}
|
||||
|
||||
for b := byte('{'); b <= byte('~'); b++ {
|
||||
test := struct {
|
||||
Byte byte
|
||||
}{
|
||||
Byte:b,
|
||||
}
|
||||
|
||||
tests = append(tests, test)
|
||||
}
|
||||
|
||||
|
||||
for testNumber, test := range tests {
|
||||
|
||||
var writer oitest.ShortWriter
|
||||
err := LongWriteByte(&writer, test.Byte)
|
||||
if nil != err {
|
||||
t.Errorf("For test #%d, did not expect an error, but actually got one: (%T) %q; for %d (%q).", testNumber, err, err.Error(), test.Byte, string(test.Byte))
|
||||
continue
|
||||
}
|
||||
if expected, actual := string(test.Byte), writer.String(); expected != actual {
|
||||
t.Errorf("For test #%d, expected %q, but actually got %q", testNumber, expected, actual)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
39
proxy_go/public/go-oi@v1.0.0/longwritestring.go
Normal file
39
proxy_go/public/go-oi@v1.0.0/longwritestring.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package oi
|
||||
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
|
||||
// LongWriteString tries to write the bytes from 's' to the writer 'w', such that it deals
|
||||
// with "short writes" where w.Write (or w.WriteString) would return an error of io.ErrShortWrite
|
||||
// and n < len(s).
|
||||
//
|
||||
// Note that LongWriteString still could return the error io.ErrShortWrite; but this
|
||||
// would only be after trying to handle the io.ErrShortWrite a number of times, and
|
||||
// then eventually giving up.
|
||||
func LongWriteString(w io.Writer, s string) (int64, error) {
|
||||
|
||||
numWritten := int64(0)
|
||||
for {
|
||||
//@TODO: Should check to make sure this doesn't get stuck in an infinite loop writting nothing!
|
||||
n, err := io.WriteString(w, s)
|
||||
numWritten += int64(n)
|
||||
if nil != err && io.ErrShortWrite != err {
|
||||
return numWritten, err
|
||||
}
|
||||
|
||||
if !(n < len(s)) {
|
||||
break
|
||||
}
|
||||
|
||||
s = s[n:]
|
||||
|
||||
if len(s) < 1 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return numWritten, nil
|
||||
}
|
||||
191
proxy_go/public/go-oi@v1.0.0/longwritestring_test.go
Normal file
191
proxy_go/public/go-oi@v1.0.0/longwritestring_test.go
Normal file
@@ -0,0 +1,191 @@
|
||||
package oi
|
||||
|
||||
|
||||
import (
|
||||
"github.com/reiver/go-oi/test"
|
||||
|
||||
"errors"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
||||
func TestLongWriteString(t *testing.T) {
|
||||
|
||||
tests := []struct{
|
||||
String string
|
||||
}{
|
||||
{
|
||||
String: "",
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
String: "apple",
|
||||
},
|
||||
{
|
||||
String: "banana",
|
||||
},
|
||||
{
|
||||
String: "cherry",
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
String: "Hello world!",
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
String: "😁😂😃😄😅😆😉😊😋😌😍😏😒😓😔😖😘😚😜😝😞😠😡😢😣😤😥😨😩😪😫😭😰😱😲😳😵😷",
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
String: "0123456789",
|
||||
},
|
||||
{
|
||||
String: "٠١٢٣٤٥٦٧٨٩", // Arabic-Indic Digits
|
||||
},
|
||||
{
|
||||
String: "۰۱۲۳۴۵۶۷۸۹", // Extended Arabic-Indic Digits
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
String: "Ⅰ Ⅱ Ⅲ Ⅳ Ⅴ Ⅵ Ⅶ Ⅷ Ⅸ Ⅹ Ⅺ Ⅻ Ⅼ Ⅽ Ⅾ Ⅿ",
|
||||
},
|
||||
{
|
||||
String: "ⅰ ⅱ ⅲ ⅳ ⅴ ⅵ ⅶ ⅷ ⅸ ⅹ ⅺ ⅻ ⅼ ⅽ ⅾ ⅿ",
|
||||
},
|
||||
{
|
||||
String: "ↀ ↁ ↂ Ↄ ↄ ↅ ↆ ↇ ↈ",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
for testNumber, test := range tests {
|
||||
|
||||
var writer oitest.ShortWriter
|
||||
n, err := LongWriteString(&writer, test.String)
|
||||
if nil != err {
|
||||
t.Errorf("For test #%d, did not expect an error, but actually got one: (%T) %q; for %q.", testNumber, err, err.Error(), test.String)
|
||||
continue
|
||||
}
|
||||
if expected, actual := int64(len([]byte(test.String))), n; expected != actual {
|
||||
t.Errorf("For test #%d, expected %d, but actually got %d; for %q.", testNumber, expected, actual, test.String)
|
||||
continue
|
||||
}
|
||||
if expected, actual := test.String, writer.String(); expected != actual {
|
||||
t.Errorf("For test #%d, expected %q, but actually got %q", testNumber, expected, actual)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func TestLongWriteStringExpectError(t *testing.T) {
|
||||
|
||||
tests := []struct{
|
||||
String string
|
||||
Expected string
|
||||
Writes []int
|
||||
Err error
|
||||
}{
|
||||
{
|
||||
String: "apple",
|
||||
Expected: "appl",
|
||||
Writes: []int{2,2},
|
||||
Err: errors.New("Crabapple!"),
|
||||
},
|
||||
{
|
||||
String: "apple",
|
||||
Expected: "appl",
|
||||
Writes: []int{2,2,0},
|
||||
Err: errors.New("Crabapple!!"),
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
String: "banana",
|
||||
Expected: "banan",
|
||||
Writes: []int{2,3},
|
||||
Err: errors.New("bananananananana!"),
|
||||
},
|
||||
{
|
||||
String: "banana",
|
||||
Expected: "banan",
|
||||
Writes: []int{2,3,0},
|
||||
Err: errors.New("bananananananananananananana!!!"),
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
String: "cherry",
|
||||
Expected: "cher",
|
||||
Writes: []int{1,1,1,1},
|
||||
Err: errors.New("C.H.E.R.R.Y."),
|
||||
},
|
||||
{
|
||||
String: "cherry",
|
||||
Expected: "cher",
|
||||
Writes: []int{1,1,1,1,0},
|
||||
Err: errors.New("C_H_E_R_R_Y"),
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
String: "Hello world!",
|
||||
Expected: "Hello world",
|
||||
Writes: []int{1,2,3,5},
|
||||
Err: errors.New("Welcome!"),
|
||||
},
|
||||
{
|
||||
String: "Hello world!",
|
||||
Expected: "Hello world",
|
||||
Writes: []int{1,2,3,5,0},
|
||||
Err: errors.New("WeLcOmE!!!"),
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
String: " ",
|
||||
Expected: " ",
|
||||
Writes: []int{1,2,3,5,8,13},
|
||||
Err: errors.New("Space, the final frontier"),
|
||||
},
|
||||
{
|
||||
String: " ",
|
||||
Expected: " ",
|
||||
Writes: []int{1,2,3,5,8,13,0},
|
||||
Err: errors.New("Space, the final frontier"),
|
||||
},
|
||||
}
|
||||
|
||||
for testNumber, test := range tests {
|
||||
|
||||
writer := oitest.NewWritesThenErrorWriter(test.Err, test.Writes...)
|
||||
n, err := LongWriteString(writer, test.String)
|
||||
if nil == err {
|
||||
t.Errorf("For test #%d, expected to get an error, but actually did not get one: %v; for %q.", testNumber, err, test.String)
|
||||
continue
|
||||
}
|
||||
if expected, actual := test.Err, err; expected != actual {
|
||||
t.Errorf("For test #%d, expected to get error (%T) %q, but actually got (%T) %q; for %q.", testNumber, expected, expected.Error(), actual, actual.Error(), test.String)
|
||||
continue
|
||||
}
|
||||
if expected, actual := int64(len(test.Expected)), n; expected != actual {
|
||||
t.Errorf("For test #%d, expected number of bytes written to be %d = len(%q), but actually was %d = len(%q); for %q.", testNumber, expected, test.Expected, actual, writer.String(), test.String)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
5
proxy_go/public/go-oi@v1.0.0/test/doc.go
Normal file
5
proxy_go/public/go-oi@v1.0.0/test/doc.go
Normal file
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Package oitest provides useful tools to be used for testing implementations of interfaces in Go's standard "io" package.
|
||||
|
||||
*/
|
||||
package oitest
|
||||
12
proxy_go/public/go-oi@v1.0.0/test/randomness.go
Normal file
12
proxy_go/public/go-oi@v1.0.0/test/randomness.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package oitest
|
||||
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
||||
var (
|
||||
randomness = rand.New(rand.NewSource( time.Now().UTC().UnixNano() ))
|
||||
)
|
||||
80
proxy_go/public/go-oi@v1.0.0/test/short_writer.go
Normal file
80
proxy_go/public/go-oi@v1.0.0/test/short_writer.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package oitest
|
||||
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
|
||||
// ShortWriter is useful for testing things that makes use of
|
||||
// or accept an io.Writer.
|
||||
//
|
||||
// In particular, it is useful to see if that thing can handle
|
||||
// an io.Writer that does a "short write".
|
||||
//
|
||||
// A "short write" is the case when a call like:
|
||||
//
|
||||
// n, err := w.Write(p)
|
||||
//
|
||||
// Returns an n < len(p) and err == io.ErrShortWrite.
|
||||
//
|
||||
// A thing that can "handle" this situation might try
|
||||
// writing again, but only what didn't get written.
|
||||
//
|
||||
// For a simple example of this:
|
||||
//
|
||||
// n, err := w.Write(p)
|
||||
//
|
||||
// if io.ErrShortWrite == err {
|
||||
// n2, err2 := w.Write(p[n:])
|
||||
// }
|
||||
//
|
||||
// Note that the second call to the Write method passed
|
||||
// 'p[n:]' (instead of just 'p'), to account for 'n' bytes
|
||||
// already written (with the first call to the Write
|
||||
// method).
|
||||
//
|
||||
// A more "production quality" version of this would likely
|
||||
// be in a loop, but such that that loop had "guards" against
|
||||
// looping forever, and also possibly looping for "too long".
|
||||
type ShortWriter struct {
|
||||
buffer bytes.Buffer
|
||||
}
|
||||
|
||||
|
||||
// Write makes it so ShortWriter fits the io.Writer interface.
|
||||
//
|
||||
// ShortWriter's version of Write will "short write" if len(p) >= 2,
|
||||
// else it will
|
||||
func (w *ShortWriter) Write(p []byte) (int, error) {
|
||||
if len(p) < 1 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
m := 1
|
||||
if limit := len(p)-1; limit > 1 {
|
||||
m += randomness.Intn(len(p)-1)
|
||||
}
|
||||
|
||||
n, err := w.buffer.Write(p[:m])
|
||||
|
||||
err = nil
|
||||
if n < len(p) {
|
||||
err = io.ErrShortWrite
|
||||
}
|
||||
|
||||
return n, err
|
||||
}
|
||||
|
||||
|
||||
// Returns what was written to the ShortWriter as a []byte.
|
||||
func (w ShortWriter) Bytes() []byte {
|
||||
return w.buffer.Bytes()
|
||||
}
|
||||
|
||||
|
||||
// Returns what was written to the ShortWriter as a string.
|
||||
func (w ShortWriter) String() string {
|
||||
return w.buffer.String()
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package oitest
|
||||
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
|
||||
// WritesThenErrorWriter is useful for testing things that makes
|
||||
// use of or accept an io.Writer.
|
||||
//
|
||||
// In particular, it is useful to see if that thing can handle
|
||||
// an io.Writer that does a "short write".
|
||||
//
|
||||
// A "short write" is the case when a call like:
|
||||
//
|
||||
// n, err := w.Write(p)
|
||||
//
|
||||
// Returns an n < len(p) and err == io.ErrShortWrite.
|
||||
//
|
||||
// A thing that can "handle" this situation might try
|
||||
// writing again, but only what didn't get written.
|
||||
//
|
||||
// For a simple example of this:
|
||||
//
|
||||
// n, err := w.Write(p)
|
||||
//
|
||||
// if io.ErrShortWrite == err {
|
||||
// n2, err2 := w.Write(p[n:])
|
||||
// }
|
||||
//
|
||||
// Note that the second call to the Write method passed
|
||||
// 'p[n:]' (instead of just 'p'), to account for 'n' bytes
|
||||
// already written (with the first call to the Write
|
||||
// method).
|
||||
//
|
||||
// A more "production quality" version of this would likely
|
||||
// be in a loop, but such that that loop had "guards" against
|
||||
// looping forever, and also possibly looping for "too long".
|
||||
type WritesThenErrorWriter struct {
|
||||
buffer bytes.Buffer
|
||||
err error
|
||||
numbersWritten []int
|
||||
writeNumber int
|
||||
}
|
||||
|
||||
|
||||
// NewWritesThenErrorWriter returns a new *WritesThenErrorWriter.
|
||||
func NewWritesThenErrorWriter(err error, numbersWritten ...int) *WritesThenErrorWriter {
|
||||
|
||||
slice := make([]int, len(numbersWritten))
|
||||
copy(slice, numbersWritten)
|
||||
|
||||
writer := WritesThenErrorWriter{
|
||||
err:err,
|
||||
numbersWritten:slice,
|
||||
writeNumber:0,
|
||||
}
|
||||
|
||||
return &writer
|
||||
}
|
||||
|
||||
|
||||
// Write makes it so *WritesThenErrorWriter fits the io.Writer interface.
|
||||
//
|
||||
// *WritesThenErrorWriter's version of Write will "short write" all but
|
||||
// the last call to write, where it will return the specified error (which
|
||||
// could, of course, be nil, if that was specified).
|
||||
func (writer *WritesThenErrorWriter) Write(p []byte) (int, error) {
|
||||
|
||||
m := writer.numbersWritten[writer.writeNumber]
|
||||
|
||||
writer.buffer.Write(p[:m])
|
||||
|
||||
writer.writeNumber++
|
||||
|
||||
if len(writer.numbersWritten) == writer.writeNumber {
|
||||
return m, writer.err
|
||||
}
|
||||
|
||||
return m, io.ErrShortWrite
|
||||
}
|
||||
|
||||
|
||||
// Returns what was written to the ShortWriter as a []byte.
|
||||
func (w WritesThenErrorWriter) Bytes() []byte {
|
||||
return w.buffer.Bytes()
|
||||
}
|
||||
|
||||
|
||||
// Returns what was written to the ShortWriter as a string.
|
||||
func (w WritesThenErrorWriter) String() string {
|
||||
return w.buffer.String()
|
||||
}
|
||||
|
||||
38
proxy_go/public/go-oi@v1.0.0/writenopcloser.go
Normal file
38
proxy_go/public/go-oi@v1.0.0/writenopcloser.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package oi
|
||||
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
|
||||
// WriteNopCloser takes an io.Writer and returns an io.WriteCloser where
|
||||
// calling the Write method on the returned io.WriterCloser calls the
|
||||
// Write method on the io.Writer it received, but whre calling the Close
|
||||
// method on the returned io.WriterCloser does "nothing" (i.e., is a "nop").
|
||||
//
|
||||
// This is useful in cases where an io.WriteCloser is expected, but you
|
||||
// only have an io.Writer (where closing doesn't make sense) and you
|
||||
// need to make your io.Writer fit. (I.e., you need an adaptor.)
|
||||
func WriteNopCloser(w io.Writer) io.WriteCloser {
|
||||
wc := internalWriteNopCloser{
|
||||
writer:w,
|
||||
}
|
||||
|
||||
return &wc
|
||||
}
|
||||
|
||||
|
||||
type internalWriteNopCloser struct {
|
||||
writer io.Writer
|
||||
}
|
||||
|
||||
|
||||
func (wc * internalWriteNopCloser) Write(p []byte) (n int, err error) {
|
||||
return wc.writer.Write(p)
|
||||
}
|
||||
|
||||
|
||||
func (wc * internalWriteNopCloser) Close() error {
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user