This commit is contained in:
Zack Scholl 2018-06-26 22:04:45 -06:00
parent e438b0a270
commit 44c08329fb
1580 changed files with 66170 additions and 826003 deletions

44
Gopkg.lock generated
View File

@ -4,8 +4,8 @@
[[projects]]
name = "github.com/briandowns/spinner"
packages = ["."]
revision = "48dbb65d7bd5c74ab50d53d04c949f20e3d14944"
version = "1.0"
revision = "5b875a9171af19dbde37e70a8fcbe2ebd7285e05"
version = "1.1"
[[projects]]
name = "github.com/cihub/seelog"
@ -97,6 +97,12 @@
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
version = "v1.0.0"
[[projects]]
branch = "master"
name = "github.com/schollz/bytetoword"
packages = ["."]
revision = "a75e6c9cd0e1fe6444905174c32d91aec9ce14f8"
[[projects]]
name = "github.com/schollz/mnemonicode"
packages = ["."]
@ -148,26 +154,48 @@
[[projects]]
branch = "master"
name = "github.com/yudai/hcl"
packages = [".","hcl","json"]
packages = [
".",
"hcl",
"json"
]
revision = "5fa2393b3552119bf33a69adb1402a1160cba23d"
[[projects]]
branch = "master"
name = "golang.org/x/crypto"
packages = ["curve25519","internal/subtle","nacl/box","nacl/secretbox","pbkdf2","poly1305","salsa20/salsa","scrypt","ssh/terminal"]
packages = [
"curve25519",
"internal/subtle",
"nacl/box",
"nacl/secretbox",
"pbkdf2",
"poly1305",
"salsa20/salsa",
"scrypt",
"ssh/terminal"
]
revision = "a49355c7e3f8fe157a85be2f77e6e269a0f89602"
[[projects]]
branch = "master"
name = "golang.org/x/net"
packages = ["bpf","internal/iana","internal/socket","ipv4"]
packages = [
"bpf",
"internal/iana",
"internal/socket",
"ipv4"
]
revision = "afe8f62b1d6bbd81f31868121a50b06d8188e1f9"
[[projects]]
branch = "master"
name = "golang.org/x/sys"
packages = ["unix","windows"]
revision = "a200a19cb90b19de298170992778b1fda7217bd6"
packages = [
"unix",
"windows"
]
revision = "c4afb3effaa53fd9a06ca61262dc7ce8df4c081b"
[[projects]]
name = "golang.org/x/text"
@ -184,6 +212,6 @@
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "2a7904ad8b3751617f1723e2d66b80203d1450df18b27439262ea385beac62b8"
inputs-digest = "a89b8e32b8dbb85f236a17be149ba201f551f415791d1d6b95b203853fa7957c"
solver-name = "gps-cdcl"
solver-version = 1

View File

@ -73,7 +73,7 @@ index | character set
* Update the spinner character set
* Update the spinner speed
* Prefix or append text
* Change spinner color
* Change spinner color, background, and text attributes such as bold / italics
* Get spinner status
* Chain, pipe, redirect output
* Output final string on spinner/indicator completion
@ -145,6 +145,84 @@ s.Suffix = " :appended text" // Append text after the spinner
s.Color("red") // Set the spinner color to red
```
You can specify both the background and foreground color, as well as additional attributes such as `bold` or `underline`.
```Go
s.Color("red", "bold") // Set the spinner color to a bold red
```
Or to set the background to black, the foreground to a bold red:
```Go
s.Color("bgBlack", "bold", "fgRed")
```
Below is the full color and attribute list:
```
// default colors
red
black
green
yellow
blue
magenta
cyan
white
// attributes
reset
bold
faint
italic
underline
blinkslow
blinkrapid
reversevideo
concealed
crossedout
// foreground text
fgBlack
fgRed
fgGreen
fgYellow
fgBlue
fgMagenta
fgCyan
fgWhite
// foreground Hi-Intensity text
fgHiBlack
fgHiRed
fgHiGreen
fgHiYellow
fgHiBlue
fgHiMagenta
fgHiCyan
fgHiWhite
// background text
bgBlack
bgRed
bgGreen
bgYellow
bgBlue
bgMagenta
bgCyan
bgWhite
// background Hi-Intensity text
bgHiBlack
bgHiRed
bgHiGreen
bgHiYellow
bgHiBlue
bgHiMagenta
bgHiCyan
bgHiWhite
```
## Generate a sequence of numbers
```Go
@ -155,7 +233,7 @@ s := spinner.New(setOfDigits, 100*time.Millisecond)
## Get spinner status
```Go
fmt.Println(s.ST)
fmt.Println(s.Active())
```
## Unix pipe and redirect

View File

@ -1,113 +0,0 @@
// Example application that uses all of the available API options.
package main
import (
"log"
"time"
"github.com/briandowns/spinner"
)
func main() {
s := spinner.New(spinner.CharSets[9], 100*time.Millisecond) // Build our new spinner
s.Color("red") // Set the spinner color to red
s.Start() // Start the spinner
time.Sleep(4 * time.Second) // Run for some time to simulate work
s.UpdateCharSet(spinner.CharSets[9]) // Update spinner to use a different character set
s.UpdateSpeed(100 * time.Millisecond) // Update the speed the spinner spins at
s.Prefix = "prefixed text: " // Prefix text before the spinner
time.Sleep(4 * time.Second)
s.Prefix = ""
s.Suffix = " :appended text" // Append text after the spinner
time.Sleep(4 * time.Second)
s.Prefix = "Colors: "
if err := s.Color("yellow"); err != nil {
log.Fatalln(err)
}
s.Start()
time.Sleep(4 * time.Second) // Run for some time to simulate work
if err := s.Color("red"); err != nil {
log.Fatalln(err)
}
s.UpdateCharSet(spinner.CharSets[20])
s.Reverse()
s.Restart()
time.Sleep(4 * time.Second) // Run for some time to simulate work
if err := s.Color("blue"); err != nil {
log.Fatalln(err)
}
s.UpdateCharSet(spinner.CharSets[3])
s.Restart()
time.Sleep(4 * time.Second) // Run for some time to simulate work
if err := s.Color("cyan"); err != nil {
log.Fatalln(err)
}
s.UpdateCharSet(spinner.CharSets[28])
s.Reverse()
s.Restart()
time.Sleep(4 * time.Second) // Run for some time to simulate work
if err := s.Color("green"); err != nil {
log.Fatalln(err)
}
s.UpdateCharSet(spinner.CharSets[25])
s.Restart()
time.Sleep(4 * time.Second) // Run for some time to simulate work
if err := s.Color("magenta"); err != nil {
log.Fatalln(err)
}
s.UpdateCharSet(spinner.CharSets[32])
s.Restart()
time.Sleep(4 * time.Second) // Run for some time to simulate work
if err := s.Color("white"); err != nil {
log.Fatalln(err)
}
s.FinalMSG = "Complete!\nNew line!\nAnother one!\n"
s.UpdateCharSet(spinner.CharSets[31])
s.Restart()
time.Sleep(4 * time.Second) // Run for some time to simulate work
s.Stop() // Stop the spinner
s.Prefix = "Earth! "
s.UpdateCharSet(spinner.CharSets[39])
s.Restart()
time.Sleep(4 * time.Second) // Run for some time to simulate work
s.Stop() // Stop the spinner
println("")
}

View File

@ -21,6 +21,7 @@ import (
"sync"
"time"
"unicode/utf8"
"encoding/hex"
"github.com/fatih/color"
)
@ -30,6 +31,8 @@ var errInvalidColor = errors.New("invalid color")
// validColors holds an array of the only colors allowed
var validColors = map[string]bool{
// default colors for backwards compatibility
"black": true,
"red": true,
"green": true,
"yellow": true,
@ -37,10 +40,64 @@ var validColors = map[string]bool{
"magenta": true,
"cyan": true,
"white": true,
// attributes
"reset": true,
"bold": true,
"faint": true,
"italic": true,
"underline": true,
"blinkslow": true,
"blinkrapid": true,
"reversevideo": true,
"concealed": true,
"crossedout": true,
// foreground text
"fgBlack": true,
"fgRed": true,
"fgGreen": true,
"fgYellow": true,
"fgBlue": true,
"fgMagenta": true,
"fgCyan": true,
"fgWhite": true,
// foreground Hi-Intensity text
"fgHiBlack": true,
"fgHiRed": true,
"fgHiGreen": true,
"fgHiYellow": true,
"fgHiBlue": true,
"fgHiMagenta": true,
"fgHiCyan": true,
"fgHiWhite": true,
// background text
"bgBlack": true,
"bgRed": true,
"bgGreen": true,
"bgYellow": true,
"bgBlue": true,
"bgMagenta": true,
"bgCyan": true,
"bgWhite": true,
// background Hi-Intensity text
"bgHiBlack": true,
"bgHiRed": true,
"bgHiGreen": true,
"bgHiYellow": true,
"bgHiBlue": true,
"bgHiMagenta": true,
"bgHiCyan": true,
"bgHiWhite": true,
}
// returns a valid color's foreground text color attribute
var colorAttributeMap = map[string]color.Attribute{
// default colors for backwards compatibility
"black": color.FgBlack,
"red": color.FgRed,
"green": color.FgGreen,
"yellow": color.FgYellow,
@ -48,6 +105,58 @@ var colorAttributeMap = map[string]color.Attribute{
"magenta": color.FgMagenta,
"cyan": color.FgCyan,
"white": color.FgWhite,
// attributes
"reset": color.Reset,
"bold": color.Bold,
"faint": color.Faint,
"italic": color.Italic,
"underline": color.Underline,
"blinkslow": color.BlinkSlow,
"blinkrapid": color.BlinkRapid,
"reversevideo": color.ReverseVideo,
"concealed": color.Concealed,
"crossedout": color.CrossedOut,
// foreground text colors
"fgBlack": color.FgBlack,
"fgRed": color.FgRed,
"fgGreen": color.FgGreen,
"fgYellow": color.FgYellow,
"fgBlue": color.FgBlue,
"fgMagenta": color.FgMagenta,
"fgCyan": color.FgCyan,
"fgWhite": color.FgWhite,
// foreground Hi-Intensity text colors
"fgHiBlack": color.FgHiBlack,
"fgHiRed": color.FgHiRed,
"fgHiGreen": color.FgHiGreen,
"fgHiYellow": color.FgHiYellow,
"fgHiBlue": color.FgHiBlue,
"fgHiMagenta": color.FgHiMagenta,
"fgHiCyan": color.FgHiCyan,
"fgHiWhite": color.FgHiWhite,
// background text colors
"bgBlack": color.BgBlack,
"bgRed": color.BgRed,
"bgGreen": color.BgGreen,
"bgYellow": color.BgYellow,
"bgBlue": color.BgBlue,
"bgMagenta": color.BgMagenta,
"bgCyan": color.BgCyan,
"bgWhite": color.BgWhite,
// background Hi-Intensity text colors
"bgHiBlack": color.BgHiBlack,
"bgHiRed": color.BgHiRed,
"bgHiGreen": color.BgHiGreen,
"bgHiYellow": color.BgHiYellow,
"bgHiBlue": color.BgHiBlue,
"bgHiMagenta": color.BgHiMagenta,
"bgHiCyan": color.BgHiCyan,
"bgHiWhite": color.BgHiWhite,
}
// validColor will make sure the given color is actually allowed
@ -87,6 +196,11 @@ func New(cs []string, d time.Duration) *Spinner {
}
}
// Active will return whether or not the spinner is currently active
func (s *Spinner) Active() bool {
return s.active
}
// Start will start the indicator
func (s *Spinner) Start() {
if s.active {
@ -147,11 +261,20 @@ func (s *Spinner) Reverse() {
}
// Color will set the struct field for the given color to be used
func (s *Spinner) Color(c string) error {
if !validColor(c) {
return errInvalidColor
func (s *Spinner) Color(colors ...string) error {
colorAttributes := make([]color.Attribute, len(colors))
// Verify colours are valid and place the appropriate attribute in the array
for index, c := range colors {
if !validColor(c) {
return errInvalidColor
}
colorAttributes[index] = colorAttributeMap[c]
}
s.color = color.New(colorAttributeMap[c]).SprintFunc()
s.color = color.New(colorAttributes...).SprintFunc()
s.Restart()
return nil
}
@ -175,7 +298,8 @@ func (s *Spinner) UpdateCharSet(cs []string) {
// Caller must already hold s.lock.
func (s *Spinner) erase() {
n := utf8.RuneCountInString(s.lastOutput)
for _, c := range []string{"\b", " ", "\b"} {
del, _ := hex.DecodeString("7f")
for _, c := range []string{"\b", string(del), "\b"} {
for i := 0; i < n; i++ {
fmt.Fprintf(s.Writer, c)
}

View File

@ -1,217 +0,0 @@
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package spinner
import (
"bytes"
"fmt"
"reflect"
"sync"
"testing"
"time"
)
const baseWait = 3
// syncBuffer
type syncBuffer struct {
sync.Mutex
bytes.Buffer
}
// Write
func (b *syncBuffer) Write(data []byte) (int, error) {
b.Lock()
defer b.Unlock()
return b.Buffer.Write(data)
}
// withOutput
func withOutput(a []string, d time.Duration) (*Spinner, *syncBuffer) {
var out syncBuffer
s := New(a, d)
s.Writer = &out
return s, &out
}
// TestNew verifies that the returned instance is of the proper type
func TestNew(t *testing.T) {
for i := 0; i < len(CharSets); i++ {
s := New(CharSets[i], 1*time.Second)
if reflect.TypeOf(s).String() != "*spinner.Spinner" {
t.Errorf("New returned incorrect type kind=%d", i)
}
}
}
// TestStart will verify a spinner can be started
func TestStart(t *testing.T) {
s := New(CharSets[1], 100*time.Millisecond)
s.Color("red")
s.Start()
time.Sleep(baseWait * time.Second)
s.Stop()
time.Sleep(100 * time.Millisecond)
}
// TestStop will verify a spinner can be stopped
func TestStop(t *testing.T) {
p, out := withOutput(CharSets[14], 100*time.Millisecond)
p.Color("yellow")
p.Start()
time.Sleep(500 * time.Millisecond)
p.Stop()
// because the spinner will print an appropriate number of backspaces before stopping,
// let it complete that sleep
time.Sleep(100 * time.Millisecond)
out.Lock()
len1 := out.Len()
out.Unlock()
time.Sleep(300 * time.Millisecond)
out.Lock()
defer out.Unlock()
len2 := out.Len()
if len1 != len2 {
t.Errorf("expected equal, got %v != %v", len1, len2)
}
p = nil
}
// TestRestart will verify a spinner can be stopped and started again
func TestRestart(t *testing.T) {
s := New(CharSets[4], 50*time.Millisecond)
var out syncBuffer
s.Writer = &out
s.Start()
s.Color("cyan")
time.Sleep(200 * time.Millisecond)
s.Restart()
time.Sleep(200 * time.Millisecond)
s.Stop()
time.Sleep(50 * time.Millisecond)
out.Lock()
defer out.Unlock()
result := out.Bytes()
first := result[:len(result)/2]
secnd := result[len(result)/2:]
if string(first) != string(secnd) {
t.Errorf("Expected ==, got \n%#v != \n%#v", first, secnd)
}
s = nil
}
// TestReverse will verify that the given spinner can stop and start again reversed
func TestReverse(t *testing.T) {
a := New(CharSets[10], 1*time.Second)
a.Color("red")
a.Start()
time.Sleep(baseWait * time.Second)
a.Reverse()
a.Restart()
time.Sleep(baseWait * time.Second)
a.Reverse()
a.Restart()
time.Sleep(baseWait * time.Second)
a.Stop()
a = nil
}
// TestUpdateSpeed verifies that the delay can be updated
func TestUpdateSpeed(t *testing.T) {
s := New(CharSets[10], 1*time.Second)
delay1 := s.Delay
s.UpdateSpeed(baseWait * time.Second)
delay2 := s.Delay
if delay1 == delay2 {
t.Error("update of speed failed")
}
s = nil
}
// TestUpdateCharSet verifies that character sets can be updated
func TestUpdateCharSet(t *testing.T) {
s := New(CharSets[14], 1*time.Second)
charSet1 := s.chars
s.UpdateCharSet(CharSets[1])
charSet2 := s.chars
for i := range charSet1 {
if charSet1[i] == charSet2[i] {
t.Error("update of char set failed")
}
}
s = nil
}
// TestGenerateNumberSequence verifies that a string slice of a spefic size is returned
func TestGenerateNumberSequence(t *testing.T) {
elementCount := 100
seq := GenerateNumberSequence(elementCount)
if reflect.TypeOf(seq).String() != "[]string" {
t.Error("received incorrect type in return from GenerateNumberSequence")
}
t.Log("In: ", elementCount)
t.Log("Out: ", len(seq))
if len(seq) != elementCount {
t.Error("number of elements in slice doesn't match expected count")
}
}
// TestBackspace proves that the correct number of characters are removed.
func TestBackspace(t *testing.T) {
// Because of buffering of output and time weirdness, somethings
// are broken for an indeterminant reason without a wait
time.Sleep(75 * time.Millisecond)
fmt.Println()
s := New(CharSets[0], 100*time.Millisecond)
s.Color("blue")
s.Start()
fmt.Print("This is on the same line as the spinner: ")
time.Sleep(baseWait * time.Second)
s.Stop()
}
// TestColorError tests that if an invalid color string is passed to the Color
// function, the invalid color error is returned
func TestColorError(t *testing.T) {
s := New(CharSets[0], 100*time.Millisecond)
invalidColorName := "bluez"
validColorName := "green"
if s.Color(invalidColorName) != errInvalidColor {
t.Error("Color method did not return an error when given an invalid color.")
}
if s.Color(validColorName) != nil {
t.Error("Color method did not return nil when given a valid color name.")
}
}
/*
Benchmarks
*/
// BenchmarkNew runs a benchmark for the New() function
func BenchmarkNew(b *testing.B) {
for n := 0; n < b.N; n++ {
New(CharSets[1], 1*time.Second)
}
}
func BenchmarkNewStartStop(b *testing.B) {
for n := 0; n < b.N; n++ {
s := New(CharSets[1], 1*time.Second)
s.Start()
s.Stop()
}
}

View File

@ -1,124 +0,0 @@
// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package seelog
import (
"bufio"
"bytes"
"fmt"
"io"
"io/ioutil"
"strconv"
"testing"
)
func countSequencedRowsInFile(filePath string) (int64, error) {
bts, err := ioutil.ReadFile(filePath)
if err != nil {
return 0, err
}
bufReader := bufio.NewReader(bytes.NewBuffer(bts))
var gotCounter int64
for {
line, _, bufErr := bufReader.ReadLine()
if bufErr != nil && bufErr != io.EOF {
return 0, bufErr
}
lineString := string(line)
if lineString == "" {
break
}
intVal, atoiErr := strconv.ParseInt(lineString, 10, 64)
if atoiErr != nil {
return 0, atoiErr
}
if intVal != gotCounter {
return 0, fmt.Errorf("wrong order: %d Expected: %d\n", intVal, gotCounter)
}
gotCounter++
}
return gotCounter, nil
}
func Test_Adaptive(t *testing.T) {
fileName := "beh_test_adaptive.log"
count := 100
Current.Close()
if e := tryRemoveFile(fileName); e != nil {
t.Error(e)
return
}
defer func() {
if e := tryRemoveFile(fileName); e != nil {
t.Error(e)
}
}()
testConfig := `
<seelog type="adaptive" mininterval="1000" maxinterval="1000000" critmsgcount="100">
<outputs formatid="msg">
<file path="` + fileName + `"/>
</outputs>
<formats>
<format id="msg" format="%Msg%n"/>
</formats>
</seelog>`
logger, _ := LoggerFromConfigAsString(testConfig)
err := ReplaceLogger(logger)
if err != nil {
t.Error(err)
return
}
for i := 0; i < count; i++ {
Trace(strconv.Itoa(i))
}
Flush()
gotCount, err := countSequencedRowsInFile(fileName)
if err != nil {
t.Error(err)
return
}
if int64(count) != gotCount {
t.Errorf("wrong count of log messages. Expected: %v, got: %v.", count, gotCount)
return
}
Current.Close()
}

View File

@ -1,133 +0,0 @@
// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package seelog
import (
"strconv"
"testing"
)
func Test_Asyncloop(t *testing.T) {
fileName := "beh_test_asyncloop.log"
count := 100
Current.Close()
if e := tryRemoveFile(fileName); e != nil {
t.Error(e)
return
}
defer func() {
if e := tryRemoveFile(fileName); e != nil {
t.Error(e)
}
}()
testConfig := `
<seelog type="asyncloop">
<outputs formatid="msg">
<file path="` + fileName + `"/>
</outputs>
<formats>
<format id="msg" format="%Msg%n"/>
</formats>
</seelog>`
logger, _ := LoggerFromConfigAsString(testConfig)
err := ReplaceLogger(logger)
if err != nil {
t.Error(err)
return
}
for i := 0; i < count; i++ {
Trace(strconv.Itoa(i))
}
Flush()
gotCount, err := countSequencedRowsInFile(fileName)
if err != nil {
t.Error(err)
return
}
if int64(count) != gotCount {
t.Errorf("wrong count of log messages. Expected: %v, got: %v.", count, gotCount)
return
}
Current.Close()
}
func Test_AsyncloopOff(t *testing.T) {
fileName := "beh_test_asyncloopoff.log"
count := 100
Current.Close()
if e := tryRemoveFile(fileName); e != nil {
t.Error(e)
return
}
testConfig := `
<seelog type="asyncloop" levels="off">
<outputs formatid="msg">
<file path="` + fileName + `"/>
</outputs>
<formats>
<format id="msg" format="%Msg%n"/>
</formats>
</seelog>`
logger, _ := LoggerFromConfigAsString(testConfig)
err := ReplaceLogger(logger)
if err != nil {
t.Error(err)
return
}
for i := 0; i < count; i++ {
Trace(strconv.Itoa(i))
}
Flush()
ex, err := fileExists(fileName)
if err != nil {
t.Error(err)
}
if ex {
t.Errorf("logger at level OFF is not expected to create log file at all.")
defer func() {
if e := tryRemoveFile(fileName); e != nil {
t.Error(e)
}
}()
}
Current.Close()
}

View File

@ -1,83 +0,0 @@
// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package seelog
import (
"strconv"
"testing"
)
func Test_Asynctimer(t *testing.T) {
fileName := "beh_test_asynctimer.log"
count := 100
Current.Close()
if e := tryRemoveFile(fileName); e != nil {
t.Error(e)
return
}
defer func() {
if e := tryRemoveFile(fileName); e != nil {
t.Error(e)
}
}()
testConfig := `
<seelog type="asynctimer" asyncinterval="100">
<outputs formatid="msg">
<file path="` + fileName + `"/>
</outputs>
<formats>
<format id="msg" format="%Msg%n"/>
</formats>
</seelog>`
logger, _ := LoggerFromConfigAsString(testConfig)
err := ReplaceLogger(logger)
if err != nil {
t.Error(err)
return
}
for i := 0; i < count; i++ {
Trace(strconv.Itoa(i))
}
Flush()
gotCount, err := countSequencedRowsInFile(fileName)
if err != nil {
t.Error(err)
return
}
if int64(count) != gotCount {
t.Errorf("wrong count of log messages. Expected: %v, got: %v.", count, gotCount)
return
}
Current.Close()
}

View File

@ -1,81 +0,0 @@
// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package seelog
import (
"strconv"
"testing"
)
func Test_Sync(t *testing.T) {
fileName := "beh_test_sync.log"
count := 100
Current.Close()
if e := tryRemoveFile(fileName); e != nil {
t.Error(e)
return
}
defer func() {
if e := tryRemoveFile(fileName); e != nil {
t.Error(e)
}
}()
testConfig := `
<seelog type="sync">
<outputs formatid="msg">
<file path="` + fileName + `"/>
</outputs>
<formats>
<format id="msg" format="%Msg%n"/>
</formats>
</seelog>`
logger, _ := LoggerFromConfigAsString(testConfig)
err := ReplaceLogger(logger)
if err != nil {
t.Error(err)
return
}
for i := 0; i < count; i++ {
Trace(strconv.Itoa(i))
}
gotCount, err := countSequencedRowsInFile(fileName)
if err != nil {
t.Error(err)
return
}
if int64(count) != gotCount {
t.Errorf("wrong count of log messages. Expected: %v, got: %v.", count, gotCount)
return
}
Current.Close()
}

View File

@ -1,99 +0,0 @@
// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package seelog
import (
"strings"
"testing"
)
func TestConfig(t *testing.T) {
testConfig :=
`
<seelog levels="trace, debug">
<exceptions>
<exception funcpattern="*getFirst*" filepattern="*" minlevel="off" />
<exception funcpattern="*getSecond*" filepattern="*" levels="info, error" />
</exceptions>
</seelog>
`
conf, err := configFromReader(strings.NewReader(testConfig))
if err != nil {
t.Errorf("parse error: %s\n", err.Error())
return
}
context, err := currentContext(nil)
if err != nil {
t.Errorf("cannot get current context:" + err.Error())
return
}
firstContext, err := getFirstContext()
if err != nil {
t.Errorf("cannot get current context:" + err.Error())
return
}
secondContext, err := getSecondContext()
if err != nil {
t.Errorf("cannot get current context:" + err.Error())
return
}
if !conf.IsAllowed(TraceLvl, context) {
t.Errorf("error: deny trace in current context")
}
if conf.IsAllowed(TraceLvl, firstContext) {
t.Errorf("error: allow trace in first context")
}
if conf.IsAllowed(ErrorLvl, context) {
t.Errorf("error: allow error in current context")
}
if !conf.IsAllowed(ErrorLvl, secondContext) {
t.Errorf("error: deny error in second context")
}
// cache test
if !conf.IsAllowed(TraceLvl, context) {
t.Errorf("error: deny trace in current context")
}
if conf.IsAllowed(TraceLvl, firstContext) {
t.Errorf("error: allow trace in first context")
}
if conf.IsAllowed(ErrorLvl, context) {
t.Errorf("error: allow error in current context")
}
if !conf.IsAllowed(ErrorLvl, secondContext) {
t.Errorf("error: deny error in second context")
}
}
func getFirstContext() (LogContextInterface, error) {
return currentContext(nil)
}
func getSecondContext() (LogContextInterface, error) {
return currentContext(nil)
}

File diff suppressed because it is too large Load Diff

View File

@ -1,196 +0,0 @@
// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package seelog
import (
"testing"
)
func TestInvalidminMaxConstraints(t *testing.T) {
constr, err := NewMinMaxConstraints(CriticalLvl, WarnLvl)
if err == nil || constr != nil {
t.Errorf("expected an error and a nil value for minmax constraints: min = %d, max = %d. Got: %v, %v",
CriticalLvl, WarnLvl, err, constr)
return
}
}
func TestInvalidLogLevels(t *testing.T) {
var invalidMin uint8 = 123
var invalidMax uint8 = 124
minMaxConstr, errMinMax := NewMinMaxConstraints(LogLevel(invalidMin), LogLevel(invalidMax))
if errMinMax == nil || minMaxConstr != nil {
t.Errorf("expected an error and a nil value for minmax constraints: min = %d, max = %d. Got: %v, %v",
invalidMin, invalidMax, errMinMax, minMaxConstr)
return
}
invalidList := []LogLevel{145}
listConstr, errList := NewListConstraints(invalidList)
if errList == nil || listConstr != nil {
t.Errorf("expected an error and a nil value for constraints list: %v. Got: %v, %v",
invalidList, errList, listConstr)
return
}
}
func TestlistConstraintsWithDuplicates(t *testing.T) {
duplicateList := []LogLevel{TraceLvl, DebugLvl, InfoLvl,
WarnLvl, ErrorLvl, CriticalLvl, CriticalLvl, CriticalLvl}
listConstr, errList := NewListConstraints(duplicateList)
if errList != nil || listConstr == nil {
t.Errorf("expected a valid constraints list struct for: %v, got error: %v, value: %v",
duplicateList, errList, listConstr)
return
}
listLevels := listConstr.AllowedLevels()
if listLevels == nil {
t.Fatalf("listConstr.AllowedLevels() == nil")
return
}
if len(listLevels) != 6 {
t.Errorf("expected: listConstr.AllowedLevels() length == 6. Got: %d", len(listLevels))
return
}
}
func TestlistConstraintsWithOffInList(t *testing.T) {
offList := []LogLevel{TraceLvl, DebugLvl, Off}
listConstr, errList := NewListConstraints(offList)
if errList == nil || listConstr != nil {
t.Errorf("expected an error and a nil value for constraints list with 'Off': %v. Got: %v, %v",
offList, errList, listConstr)
return
}
}
type logLevelTestCase struct {
level LogLevel
allowed bool
}
var minMaxTests = []logLevelTestCase{
{TraceLvl, false},
{DebugLvl, false},
{InfoLvl, true},
{WarnLvl, true},
{ErrorLvl, false},
{CriticalLvl, false},
{123, false},
{6, false},
}
func TestValidminMaxConstraints(t *testing.T) {
constr, err := NewMinMaxConstraints(InfoLvl, WarnLvl)
if err != nil || constr == nil {
t.Errorf("expected a valid constraints struct for minmax constraints: min = %d, max = %d. Got: %v, %v",
InfoLvl, WarnLvl, err, constr)
return
}
for _, minMaxTest := range minMaxTests {
allowed := constr.IsAllowed(minMaxTest.level)
if allowed != minMaxTest.allowed {
t.Errorf("expected IsAllowed() = %t for level = %d. Got: %t",
minMaxTest.allowed, minMaxTest.level, allowed)
return
}
}
}
var listTests = []logLevelTestCase{
{TraceLvl, true},
{DebugLvl, false},
{InfoLvl, true},
{WarnLvl, true},
{ErrorLvl, false},
{CriticalLvl, true},
{123, false},
{6, false},
}
func TestValidlistConstraints(t *testing.T) {
validList := []LogLevel{TraceLvl, InfoLvl, WarnLvl, CriticalLvl}
constr, err := NewListConstraints(validList)
if err != nil || constr == nil {
t.Errorf("expected a valid constraints list struct for: %v. Got error: %v, value: %v",
validList, err, constr)
return
}
for _, minMaxTest := range listTests {
allowed := constr.IsAllowed(minMaxTest.level)
if allowed != minMaxTest.allowed {
t.Errorf("expected IsAllowed() = %t for level = %d. Got: %t",
minMaxTest.allowed, minMaxTest.level, allowed)
return
}
}
}
var offTests = []logLevelTestCase{
{TraceLvl, false},
{DebugLvl, false},
{InfoLvl, false},
{WarnLvl, false},
{ErrorLvl, false},
{CriticalLvl, false},
{123, false},
{6, false},
}
func TestValidListoffConstraints(t *testing.T) {
validList := []LogLevel{Off}
constr, err := NewListConstraints(validList)
if err != nil || constr == nil {
t.Errorf("expected a valid constraints list struct for: %v. Got error: %v, value: %v",
validList, err, constr)
return
}
for _, minMaxTest := range offTests {
allowed := constr.IsAllowed(minMaxTest.level)
if allowed != minMaxTest.allowed {
t.Errorf("expected IsAllowed() = %t for level = %d. Got: %t",
minMaxTest.allowed, minMaxTest.level, allowed)
return
}
}
}

View File

@ -1,127 +0,0 @@
// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package seelog
import (
"os"
"path/filepath"
"strings"
"testing"
)
const (
testShortPath = "common_context_test.go"
)
var (
commonPrefix string
testFullPath string
)
func init() {
// Here we remove the hardcoding of the package name which
// may break forks and some CI environments such as jenkins.
_, _, funcName, _, _ := extractCallerInfo(1)
preIndex := strings.Index(funcName, "init·")
if preIndex == -1 {
preIndex = strings.Index(funcName, "init")
}
commonPrefix = funcName[:preIndex]
wd, err := os.Getwd()
if err == nil {
// Transform the file path into a slashed form:
// This is the proper platform-neutral way.
testFullPath = filepath.ToSlash(filepath.Join(wd, testShortPath))
}
}
func TestContext(t *testing.T) {
context, err := currentContext(nil)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if context == nil {
t.Fatalf("unexpected error: context is nil")
}
if fn, funcName := context.Func(), commonPrefix+"TestContext"; fn != funcName {
// Account for a case when the func full path is longer than commonPrefix but includes it.
if !strings.HasSuffix(fn, funcName) {
t.Errorf("expected context.Func == %s ; got %s", funcName, context.Func())
}
}
if context.ShortPath() != testShortPath {
t.Errorf("expected context.ShortPath == %s ; got %s", testShortPath, context.ShortPath())
}
if len(testFullPath) == 0 {
t.Fatal("working directory seems invalid")
}
if context.FullPath() != testFullPath {
t.Errorf("expected context.FullPath == %s ; got %s", testFullPath, context.FullPath())
}
}
func innerContext() (context LogContextInterface, err error) {
return currentContext(nil)
}
func TestInnerContext(t *testing.T) {
context, err := innerContext()
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if context == nil {
t.Fatalf("unexpected error: context is nil")
}
if fn, funcName := context.Func(), commonPrefix+"innerContext"; fn != funcName {
// Account for a case when the func full path is longer than commonPrefix but includes it.
if !strings.HasSuffix(fn, funcName) {
t.Errorf("expected context.Func == %s ; got %s", funcName, context.Func())
}
}
if context.ShortPath() != testShortPath {
t.Errorf("expected context.ShortPath == %s ; got %s", testShortPath, context.ShortPath())
}
if len(testFullPath) == 0 {
t.Fatal("working directory seems invalid")
}
if context.FullPath() != testFullPath {
t.Errorf("expected context.FullPath == %s ; got %s", testFullPath, context.FullPath())
}
}
type testContext struct {
field string
}
func TestCustomContext(t *testing.T) {
expected := "testStr"
context, err := currentContext(&testContext{expected})
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if st, _ := context.CustomContext().(*testContext); st.field != expected {
t.Errorf("expected context.CustomContext == %s ; got %s", expected, st.field)
}
}

View File

@ -1,98 +0,0 @@
// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package seelog
import (
"testing"
)
type exceptionTestCase struct {
funcPattern string
filePattern string
funcName string
fileName string
match bool
}
var exceptionTestCases = []exceptionTestCase{
{"*", "*", "func", "file", true},
{"func*", "*", "func", "file", true},
{"*func", "*", "func", "file", true},
{"*func", "*", "1func", "file", true},
{"func*", "*", "func1", "file", true},
{"fu*nc", "*", "func", "file", true},
{"fu*nc", "*", "fu1nc", "file", true},
{"fu*nc", "*", "func1nc", "file", true},
{"*fu*nc*", "*", "somefuntonc", "file", true},
{"fu*nc", "*", "f1nc", "file", false},
{"func*", "*", "fun", "file", false},
{"fu*nc", "*", "func1n", "file", false},
{"**f**u**n**c**", "*", "func1n", "file", true},
}
func TestMatchingCorrectness(t *testing.T) {
constraints, err := NewListConstraints([]LogLevel{TraceLvl})
if err != nil {
t.Error(err)
return
}
for _, testCase := range exceptionTestCases {
rule, ruleError := NewLogLevelException(testCase.funcPattern, testCase.filePattern, constraints)
if ruleError != nil {
t.Fatalf("Unexpected error on rule creation: [ %v, %v ]. %v",
testCase.funcPattern, testCase.filePattern, ruleError)
}
match := rule.match(testCase.funcName, testCase.fileName)
if match != testCase.match {
t.Errorf("incorrect matching for [ %v, %v ] [ %v, %v ] Expected: %t. Got: %t",
testCase.funcPattern, testCase.filePattern, testCase.funcName, testCase.fileName, testCase.match, match)
}
}
}
func TestAsterisksReducing(t *testing.T) {
constraints, err := NewListConstraints([]LogLevel{TraceLvl})
if err != nil {
t.Error(err)
return
}
rule, err := NewLogLevelException("***func**", "fi*****le", constraints)
if err != nil {
t.Error(err)
return
}
expectFunc := "*func*"
if rule.FuncPattern() != expectFunc {
t.Errorf("asterisks must be reduced. Expect:%v, Got:%v", expectFunc, rule.FuncPattern())
}
expectFile := "fi*le"
if rule.FilePattern() != expectFile {
t.Errorf("asterisks must be reduced. Expect:%v, Got:%v", expectFile, rule.FilePattern())
}
}

View File

@ -1,177 +0,0 @@
// Copyright (c) 2013 - Cloud Instruments Co., Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package seelog
import (
"testing"
)
type testCustomDispatcherMessageReceiver struct {
customTestReceiver
}
func TestCustomDispatcher_Message(t *testing.T) {
recName := "TestCustomDispatcher_Message"
RegisterReceiver(recName, &testCustomDispatcherMessageReceiver{})
customDispatcher, err := NewCustomReceiverDispatcher(onlyMessageFormatForTest, recName, CustomReceiverInitArgs{
XmlCustomAttrs: map[string]string{
"test": "testdata",
},
})
if err != nil {
t.Error(err)
return
}
context, err := currentContext(nil)
if err != nil {
t.Error(err)
return
}
bytes := []byte("Hello")
customDispatcher.Dispatch(string(bytes), TraceLvl, context, func(err error) {})
cout := customDispatcher.innerReceiver.(*testCustomDispatcherMessageReceiver).customTestReceiver.co
if cout.initCalled != true {
t.Error("Init not called")
return
}
if cout.dataPassed != "testdata" {
t.Errorf("wrong data passed: '%s'", cout.dataPassed)
return
}
if cout.messageOutput != string(bytes) {
t.Errorf("wrong message output: '%s'", cout.messageOutput)
return
}
if cout.levelOutput != TraceLvl {
t.Errorf("wrong log level: '%s'", cout.levelOutput)
return
}
if cout.flushed {
t.Error("Flush was not expected")
return
}
if cout.closed {
t.Error("Closing was not expected")
return
}
}
type testCustomDispatcherFlushReceiver struct {
customTestReceiver
}
func TestCustomDispatcher_Flush(t *testing.T) {
recName := "TestCustomDispatcher_Flush"
RegisterReceiver(recName, &testCustomDispatcherFlushReceiver{})
customDispatcher, err := NewCustomReceiverDispatcher(onlyMessageFormatForTest, recName, CustomReceiverInitArgs{
XmlCustomAttrs: map[string]string{
"test": "testdata",
},
})
if err != nil {
t.Error(err)
return
}
customDispatcher.Flush()
cout := customDispatcher.innerReceiver.(*testCustomDispatcherFlushReceiver).customTestReceiver.co
if cout.initCalled != true {
t.Error("Init not called")
return
}
if cout.dataPassed != "testdata" {
t.Errorf("wrong data passed: '%s'", cout.dataPassed)
return
}
if cout.messageOutput != "" {
t.Errorf("wrong message output: '%s'", cout.messageOutput)
return
}
if cout.levelOutput != TraceLvl {
t.Errorf("wrong log level: '%s'", cout.levelOutput)
return
}
if !cout.flushed {
t.Error("Flush was expected")
return
}
if cout.closed {
t.Error("Closing was not expected")
return
}
}
type testCustomDispatcherCloseReceiver struct {
customTestReceiver
}
func TestCustomDispatcher_Close(t *testing.T) {
recName := "TestCustomDispatcher_Close"
RegisterReceiver(recName, &testCustomDispatcherCloseReceiver{})
customDispatcher, err := NewCustomReceiverDispatcher(onlyMessageFormatForTest, recName, CustomReceiverInitArgs{
XmlCustomAttrs: map[string]string{
"test": "testdata",
},
})
if err != nil {
t.Error(err)
return
}
customDispatcher.Close()
cout := customDispatcher.innerReceiver.(*testCustomDispatcherCloseReceiver).customTestReceiver.co
if cout.initCalled != true {
t.Error("Init not called")
return
}
if cout.dataPassed != "testdata" {
t.Errorf("wrong data passed: '%s'", cout.dataPassed)
return
}
if cout.messageOutput != "" {
t.Errorf("wrong message output: '%s'", cout.messageOutput)
return
}
if cout.levelOutput != TraceLvl {
t.Errorf("wrong log level: '%s'", cout.levelOutput)
return
}
if !cout.flushed {
t.Error("Flush was expected")
return
}
if !cout.closed {
t.Error("Closing was expected")
return
}
}

View File

@ -1,67 +0,0 @@
// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package seelog
import (
"testing"
)
func TestfilterDispatcher_Pass(t *testing.T) {
writer, _ := newBytesVerifier(t)
filter, err := NewFilterDispatcher(onlyMessageFormatForTest, []interface{}{writer}, TraceLvl)
if err != nil {
t.Error(err)
return
}
context, err := currentContext(nil)
if err != nil {
t.Error(err)
return
}
bytes := []byte("Hello")
writer.ExpectBytes(bytes)
filter.Dispatch(string(bytes), TraceLvl, context, func(err error) {})
writer.MustNotExpect()
}
func TestfilterDispatcher_Deny(t *testing.T) {
writer, _ := newBytesVerifier(t)
filter, err := NewFilterDispatcher(DefaultFormatter, []interface{}{writer})
if err != nil {
t.Error(err)
return
}
context, err := currentContext(nil)
if err != nil {
t.Error(err)
return
}
bytes := []byte("Hello")
filter.Dispatch(string(bytes), TraceLvl, context, func(err error) {})
}

View File

@ -1,64 +0,0 @@
// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package seelog
import (
"fmt"
"testing"
)
var onlyMessageFormatForTest *formatter
func init() {
var err error
onlyMessageFormatForTest, err = NewFormatter("%Msg")
if err != nil {
fmt.Println("Can not create only message format: " + err.Error())
}
}
func TestsplitDispatcher(t *testing.T) {
writer1, _ := newBytesVerifier(t)
writer2, _ := newBytesVerifier(t)
spliter, err := NewSplitDispatcher(onlyMessageFormatForTest, []interface{}{writer1, writer2})
if err != nil {
t.Error(err)
return
}
context, err := currentContext(nil)
if err != nil {
t.Error(err)
return
}
bytes := []byte("Hello")
writer1.ExpectBytes(bytes)
writer2.ExpectBytes(bytes)
spliter.Dispatch(string(bytes), TraceLvl, context, func(err error) {})
writer1.MustNotExpect()
writer2.MustNotExpect()
}

View File

@ -1,236 +0,0 @@
// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package seelog
import (
"fmt"
"strings"
"testing"
"time"
)
const (
TestFuncName = "TestFormats"
)
type formatTest struct {
formatString string
input string
inputLogLevel LogLevel
expectedOutput string
errorExpected bool
}
var formatTests = []formatTest{
{"test", "abcdef", TraceLvl, "test", false},
{"", "abcdef", TraceLvl, "", false},
{"%Level", "", TraceLvl, "Trace", false},
{"%Level", "", DebugLvl, "Debug", false},
{"%Level", "", InfoLvl, "Info", false},
{"%Level", "", WarnLvl, "Warn", false},
{"%Level", "", ErrorLvl, "Error", false},
{"%Level", "", CriticalLvl, "Critical", false},
{"[%Level]", "", TraceLvl, "[Trace]", false},
{"[%Level]", "abc", DebugLvl, "[Debug]", false},
{"%LevelLevel", "", InfoLvl, "InfoLevel", false},
{"[%Level][%Level]", "", WarnLvl, "[Warn][Warn]", false},
{"[%Level]X[%Level]", "", ErrorLvl, "[Error]X[Error]", false},
{"%Levelll", "", CriticalLvl, "Criticalll", false},
{"%Lvl", "", TraceLvl, "", true},
{"%%Level", "", DebugLvl, "%Level", false},
{"%Level%", "", InfoLvl, "", true},
{"%sevel", "", WarnLvl, "", true},
{"Level", "", ErrorLvl, "Level", false},
{"%LevelLevel", "", CriticalLvl, "CriticalLevel", false},
{"%Lev", "", TraceLvl, "Trc", false},
{"%Lev", "", DebugLvl, "Dbg", false},
{"%Lev", "", InfoLvl, "Inf", false},
{"%Lev", "", WarnLvl, "Wrn", false},
{"%Lev", "", ErrorLvl, "Err", false},
{"%Lev", "", CriticalLvl, "Crt", false},
{"[%Lev]", "", TraceLvl, "[Trc]", false},
{"[%Lev]", "abc", DebugLvl, "[Dbg]", false},
{"%LevLevel", "", InfoLvl, "InfLevel", false},
{"[%Level][%Lev]", "", WarnLvl, "[Warn][Wrn]", false},
{"[%Lev]X[%Lev]", "", ErrorLvl, "[Err]X[Err]", false},
{"%Levll", "", CriticalLvl, "Crtll", false},
{"%LEVEL", "", TraceLvl, "TRACE", false},
{"%LEVEL", "", DebugLvl, "DEBUG", false},
{"%LEVEL", "", InfoLvl, "INFO", false},
{"%LEVEL", "", WarnLvl, "WARN", false},
{"%LEVEL", "", ErrorLvl, "ERROR", false},
{"%LEVEL", "", CriticalLvl, "CRITICAL", false},
{"[%LEVEL]", "", TraceLvl, "[TRACE]", false},
{"[%LEVEL]", "abc", DebugLvl, "[DEBUG]", false},
{"%LEVELLEVEL", "", InfoLvl, "INFOLEVEL", false},
{"[%LEVEL][%LEVEL]", "", WarnLvl, "[WARN][WARN]", false},
{"[%LEVEL]X[%Level]", "", ErrorLvl, "[ERROR]X[Error]", false},
{"%LEVELLL", "", CriticalLvl, "CRITICALLL", false},
{"%LEV", "", TraceLvl, "TRC", false},
{"%LEV", "", DebugLvl, "DBG", false},
{"%LEV", "", InfoLvl, "INF", false},
{"%LEV", "", WarnLvl, "WRN", false},
{"%LEV", "", ErrorLvl, "ERR", false},
{"%LEV", "", CriticalLvl, "CRT", false},
{"[%LEV]", "", TraceLvl, "[TRC]", false},
{"[%LEV]", "abc", DebugLvl, "[DBG]", false},
{"%LEVLEVEL", "", InfoLvl, "INFLEVEL", false},
{"[%LEVEL][%LEV]", "", WarnLvl, "[WARN][WRN]", false},
{"[%LEV]X[%LEV]", "", ErrorLvl, "[ERR]X[ERR]", false},
{"%LEVLL", "", CriticalLvl, "CRTLL", false},
{"%l", "", TraceLvl, "t", false},
{"%l", "", DebugLvl, "d", false},
{"%l", "", InfoLvl, "i", false},
{"%l", "", WarnLvl, "w", false},
{"%l", "", ErrorLvl, "e", false},
{"%l", "", CriticalLvl, "c", false},
{"[%l]", "", TraceLvl, "[t]", false},
{"[%l]", "abc", DebugLvl, "[d]", false},
{"%Level%Msg", "", TraceLvl, "Trace", false},
{"%Level%Msg", "A", DebugLvl, "DebugA", false},
{"%Level%Msg", "", InfoLvl, "Info", false},
{"%Level%Msg", "test", WarnLvl, "Warntest", false},
{"%Level%Msg", " ", ErrorLvl, "Error ", false},
{"%Level%Msg", "", CriticalLvl, "Critical", false},
{"[%Level]", "", TraceLvl, "[Trace]", false},
{"[%Level]", "abc", DebugLvl, "[Debug]", false},
{"%Level%MsgLevel", "A", InfoLvl, "InfoALevel", false},
{"[%Level]%Msg[%Level]", "test", WarnLvl, "[Warn]test[Warn]", false},
{"[%Level]%MsgX[%Level]", "test", ErrorLvl, "[Error]testX[Error]", false},
{"%Levell%Msgl", "Test", CriticalLvl, "CriticallTestl", false},
{"%Lev%Msg%LEVEL%LEV%l%Msg", "Test", InfoLvl, "InfTestINFOINFiTest", false},
{"%n", "", CriticalLvl, "\n", false},
{"%t", "", CriticalLvl, "\t", false},
}
func TestFormats(t *testing.T) {
context, conErr := currentContext(nil)
if conErr != nil {
t.Fatal("Cannot get current context:" + conErr.Error())
return
}
for _, test := range formatTests {
form, err := NewFormatter(test.formatString)
if (err != nil) != test.errorExpected {
t.Errorf("input: %s \nInput LL: %s\n* Expected error:%t Got error: %t\n",
test.input, test.inputLogLevel, test.errorExpected, (err != nil))
if err != nil {
t.Logf("%s\n", err.Error())
}
continue
} else if err != nil {
continue
}
msg := form.Format(test.input, test.inputLogLevel, context)
if err == nil && msg != test.expectedOutput {
t.Errorf("format: %s \nInput: %s \nInput LL: %s\n* Expected: %s \n* Got: %s\n",
test.formatString, test.input, test.inputLogLevel, test.expectedOutput, msg)
}
}
}
func TestDateFormat(t *testing.T) {
_, err := NewFormatter("%Date")
if err != nil {
t.Error("Unexpected error: " + err.Error())
}
}
func TestDateParameterizedFormat(t *testing.T) {
testFormat := "Mon Jan 02 2006 15:04:05"
preciseForamt := "Mon Jan 02 2006 15:04:05.000"
context, conErr := currentContext(nil)
if conErr != nil {
t.Fatal("Cannot get current context:" + conErr.Error())
return
}
form, err := NewFormatter("%Date(" + preciseForamt + ")")
if err != nil {
t.Error("Unexpected error: " + err.Error())
}
dateBefore := time.Now().Format(testFormat)
msg := form.Format("", TraceLvl, context)
dateAfter := time.Now().Format(testFormat)
if !strings.HasPrefix(msg, dateBefore) && !strings.HasPrefix(msg, dateAfter) {
t.Errorf("incorrect message: %v. Expected %v or %v", msg, dateBefore, dateAfter)
}
_, err = NewFormatter("%Date(" + preciseForamt)
if err == nil {
t.Error("Expected error for invalid format")
}
}
func createTestFormatter(format string) FormatterFunc {
return func(message string, level LogLevel, context LogContextInterface) interface{} {
return "TEST " + context.Func() + " TEST"
}
}
func TestCustomFormatterRegistration(t *testing.T) {
err := RegisterCustomFormatter("Level", createTestFormatter)
if err == nil {
t.Errorf("expected an error when trying to register a custom formatter with a reserved alias")
}
err = RegisterCustomFormatter("EscM", createTestFormatter)
if err == nil {
t.Errorf("expected an error when trying to register a custom formatter with a reserved parameterized alias")
}
err = RegisterCustomFormatter("TEST", createTestFormatter)
if err != nil {
t.Fatalf("Registering custom formatter: unexpected error: %s", err)
}
err = RegisterCustomFormatter("TEST", createTestFormatter)
if err == nil {
t.Errorf("expected an error when trying to register a custom formatter with duplicate name")
}
context, conErr := currentContext(nil)
if conErr != nil {
t.Fatal("Cannot get current context:" + conErr.Error())
return
}
form, err := NewFormatter("%Msg %TEST 123")
if err != nil {
t.Fatalf("%s\n", err.Error())
}
expected := fmt.Sprintf("test TEST %sTestCustomFormatterRegistration TEST 123", commonPrefix)
msg := form.Format("test", DebugLvl, context)
if msg != expected {
t.Fatalf("Custom formatter: invalid output. Expected: '%s'. Got: '%s'", expected, msg)
}
}

View File

@ -1,118 +0,0 @@
// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package seelog
import (
"errors"
"strconv"
"testing"
)
// bytesVerifier is a byte receiver which is used for correct input testing.
// It allows to compare expected result and actual result in context of received bytes.
type bytesVerifier struct {
expectedBytes []byte // bytes that are expected to be written in next Write call
waitingForInput bool // true if verifier is waiting for a Write call
writtenData []byte // real bytes that actually were received during the last Write call
testEnv *testing.T
}
func newBytesVerifier(t *testing.T) (*bytesVerifier, error) {
if t == nil {
return nil, errors.New("testing environment param is nil")
}
verifier := new(bytesVerifier)
verifier.testEnv = t
return verifier, nil
}
// Write is used to check whether verifier was waiting for input and whether bytes are the same as expectedBytes.
// After Write call, waitingForInput is set to false.
func (verifier *bytesVerifier) Write(bytes []byte) (n int, err error) {
if !verifier.waitingForInput {
verifier.testEnv.Errorf("unexpected input: %v", string(bytes))
return
}
verifier.waitingForInput = false
verifier.writtenData = bytes
if verifier.expectedBytes != nil {
if bytes == nil {
verifier.testEnv.Errorf("incoming 'bytes' is nil")
} else {
if len(bytes) != len(verifier.expectedBytes) {
verifier.testEnv.Errorf("'Bytes' has unexpected len. Expected: %d. Got: %d. . Expected string: %q. Got: %q",
len(verifier.expectedBytes), len(bytes), string(verifier.expectedBytes), string(bytes))
} else {
for i := 0; i < len(bytes); i++ {
if verifier.expectedBytes[i] != bytes[i] {
verifier.testEnv.Errorf("incorrect data on position %d. Expected: %d. Got: %d. Expected string: %q. Got: %q",
i, verifier.expectedBytes[i], bytes[i], string(verifier.expectedBytes), string(bytes))
break
}
}
}
}
}
return len(bytes), nil
}
func (verifier *bytesVerifier) ExpectBytes(bytes []byte) {
verifier.waitingForInput = true
verifier.expectedBytes = bytes
}
func (verifier *bytesVerifier) MustNotExpect() {
if verifier.waitingForInput {
errorText := "Unexpected input: "
if verifier.expectedBytes != nil {
errorText += "len = " + strconv.Itoa(len(verifier.expectedBytes))
errorText += ". text = " + string(verifier.expectedBytes)
}
verifier.testEnv.Errorf(errorText)
}
}
func (verifier *bytesVerifier) Close() error {
return nil
}
// nullWriter implements io.Writer inteface and does nothing, always returning a successful write result
type nullWriter struct {
}
func (writer *nullWriter) Write(bytes []byte) (n int, err error) {
return len(bytes), nil
}
func (writer *nullWriter) Close() error {
return nil
}

View File

@ -1,196 +0,0 @@
// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package seelog
import (
"strings"
"testing"
//"fmt"
"reflect"
)
var testEnv *testing.T
/*func TestWrapper(t *testing.T) {
testEnv = t
s := "<a d='a'><g m='a'></g><g h='t' j='kk'></g></a>"
reader := strings.NewReader(s)
config, err := unmarshalConfig(reader)
if err != nil {
testEnv.Error(err)
return
}
printXML(config, 0)
}
func printXML(node *xmlNode, level int) {
indent := strings.Repeat("\t", level)
fmt.Print(indent + node.name)
for key, value := range node.attributes {
fmt.Print(" " + key + "/" + value)
}
fmt.Println()
for _, child := range node.children {
printXML(child, level+1)
}
}*/
var xmlNodeTests []xmlNodeTest
type xmlNodeTest struct {
testName string
inputXML string
expected interface{}
errorExpected bool
}
func getXMLTests() []xmlNodeTest {
if xmlNodeTests == nil {
xmlNodeTests = make([]xmlNodeTest, 0)
testName := "Simple test"
testXML := `<a></a>`
testExpected := newNode()
testExpected.name = "a"
xmlNodeTests = append(xmlNodeTests, xmlNodeTest{testName, testXML, testExpected, false})
testName = "Multiline test"
testXML =
`
<a>
</a>
`
testExpected = newNode()
testExpected.name = "a"
xmlNodeTests = append(xmlNodeTests, xmlNodeTest{testName, testXML, testExpected, false})
testName = "Multiline test #2"
testXML =
`
<a>
</a>
`
testExpected = newNode()
testExpected.name = "a"
xmlNodeTests = append(xmlNodeTests, xmlNodeTest{testName, testXML, testExpected, false})
testName = "Incorrect names"
testXML = `< a >< /a >`
xmlNodeTests = append(xmlNodeTests, xmlNodeTest{testName, testXML, nil, true})
testName = "Comments"
testXML =
`<!-- <abcdef/> -->
<a> <!-- <!--12345-->
</a>
`
testExpected = newNode()
testExpected.name = "a"
xmlNodeTests = append(xmlNodeTests, xmlNodeTest{testName, testXML, testExpected, false})
testName = "Multiple roots"
testXML = `<a></a><b></b>`
xmlNodeTests = append(xmlNodeTests, xmlNodeTest{testName, testXML, nil, true})
testName = "Multiple roots + incorrect xml"
testXML = `<a></a><b>`
xmlNodeTests = append(xmlNodeTests, xmlNodeTest{testName, testXML, nil, true})
testName = "Some unicode and data"
testXML = `<俄语>данные</俄语>`
testExpected = newNode()
testExpected.name = "俄语"
testExpected.value = "данные"
xmlNodeTests = append(xmlNodeTests, xmlNodeTest{testName, testXML, testExpected, false})
testName = "Values and children"
testXML = `<俄语>данные<and_a_child></and_a_child></俄语>`
testExpected = newNode()
testExpected.name = "俄语"
testExpected.value = "данные"
child := newNode()
child.name = "and_a_child"
testExpected.children = append(testExpected.children, child)
xmlNodeTests = append(xmlNodeTests, xmlNodeTest{testName, testXML, testExpected, false})
testName = "Just children"
testXML = `<俄语><and_a_child></and_a_child></俄语>`
testExpected = newNode()
testExpected.name = "俄语"
child = newNode()
child.name = "and_a_child"
testExpected.children = append(testExpected.children, child)
xmlNodeTests = append(xmlNodeTests, xmlNodeTest{testName, testXML, testExpected, false})
testName = "Mixed test"
testXML = `<俄语 a="1" b="2.13" c="abc"><child abc="bca"/><child abc="def"></child></俄语>`
testExpected = newNode()
testExpected.name = "俄语"
testExpected.attributes["a"] = "1"
testExpected.attributes["b"] = "2.13"
testExpected.attributes["c"] = "abc"
child = newNode()
child.name = "child"
child.attributes["abc"] = "bca"
testExpected.children = append(testExpected.children, child)
child = newNode()
child.name = "child"
child.attributes["abc"] = "def"
testExpected.children = append(testExpected.children, child)
xmlNodeTests = append(xmlNodeTests, xmlNodeTest{testName, testXML, testExpected, false})
}
return xmlNodeTests
}
func TestXmlNode(t *testing.T) {
for _, test := range getXMLTests() {
reader := strings.NewReader(test.inputXML)
parsedXML, err := unmarshalConfig(reader)
if (err != nil) != test.errorExpected {
t.Errorf("\n%s:\nXML input: %s\nExpected error:%t. Got error: %t\n", test.testName,
test.inputXML, test.errorExpected, (err != nil))
if err != nil {
t.Logf("%s\n", err.Error())
}
continue
}
if err == nil && !reflect.DeepEqual(parsedXML, test.expected) {
t.Errorf("\n%s:\nXML input: %s\nExpected: %s. \nGot: %s\n", test.testName,
test.inputXML, test.expected, parsedXML)
}
}
}

View File

@ -1,78 +0,0 @@
// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package seelog
import (
"testing"
)
func TestChunkWriteOnFilling(t *testing.T) {
writer, _ := newBytesVerifier(t)
bufferedWriter, err := NewBufferedWriter(writer, 1024, 0)
if err != nil {
t.Fatalf("Unexpected buffered writer creation error: %s", err.Error())
}
bytes := make([]byte, 1000)
bufferedWriter.Write(bytes)
writer.ExpectBytes(bytes)
bufferedWriter.Write(bytes)
}
func TestFlushByTimePeriod(t *testing.T) {
writer, _ := newBytesVerifier(t)
bufferedWriter, err := NewBufferedWriter(writer, 1024, 10)
if err != nil {
t.Fatalf("Unexpected buffered writer creation error: %s", err.Error())
}
bytes := []byte("Hello")
for i := 0; i < 2; i++ {
writer.ExpectBytes(bytes)
bufferedWriter.Write(bytes)
}
}
func TestBigMessageMustPassMemoryBuffer(t *testing.T) {
writer, _ := newBytesVerifier(t)
bufferedWriter, err := NewBufferedWriter(writer, 1024, 0)
if err != nil {
t.Fatalf("Unexpected buffered writer creation error: %s", err.Error())
}
bytes := make([]byte, 5000)
for i := 0; i < len(bytes); i++ {
bytes[i] = uint8(i % 255)
}
writer.ExpectBytes(bytes)
bufferedWriter.Write(bytes)
}

View File

@ -1,254 +0,0 @@
// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package seelog
import (
"fmt"
"io"
"os"
"path/filepath"
"strings"
"testing"
)
const (
messageLen = 10
)
var bytesFileTest = []byte(strings.Repeat("A", messageLen))
func TestSimpleFileWriter(t *testing.T) {
t.Logf("Starting file writer tests")
NewFileWriterTester(simplefileWriterTests, simplefileWriterGetter, t).test()
}
//===============================================================
func simplefileWriterGetter(testCase *fileWriterTestCase) (io.WriteCloser, error) {
return NewFileWriter(testCase.fileName)
}
//===============================================================
type fileWriterTestCase struct {
files []string
fileName string
rollingType rollingType
fileSize int64
maxRolls int
datePattern string
writeCount int
resFiles []string
nameMode rollingNameMode
}
func createSimplefileWriterTestCase(fileName string, writeCount int) *fileWriterTestCase {
return &fileWriterTestCase{[]string{}, fileName, rollingTypeSize, 0, 0, "", writeCount, []string{fileName}, 0}
}
var simplefileWriterTests = []*fileWriterTestCase{
createSimplefileWriterTestCase("log.testlog", 1),
createSimplefileWriterTestCase("log.testlog", 50),
createSimplefileWriterTestCase(filepath.Join("dir", "log.testlog"), 50),
}
//===============================================================
type fileWriterTester struct {
testCases []*fileWriterTestCase
writerGetter func(*fileWriterTestCase) (io.WriteCloser, error)
t *testing.T
}
func NewFileWriterTester(
testCases []*fileWriterTestCase,
writerGetter func(*fileWriterTestCase) (io.WriteCloser, error),
t *testing.T) *fileWriterTester {
return &fileWriterTester{testCases, writerGetter, t}
}
func isWriterTestFile(fn string) bool {
return strings.Contains(fn, ".testlog")
}
func cleanupWriterTest(t *testing.T) {
toDel, err := getDirFilePaths(".", isWriterTestFile, true)
if nil != err {
t.Fatal("Cannot list files in test directory!")
}
for _, p := range toDel {
if err = tryRemoveFile(p); nil != err {
t.Errorf("cannot remove file %s in test directory: %s", p, err.Error())
}
}
if err = os.RemoveAll("dir"); nil != err {
t.Errorf("cannot remove temp test directory: %s", err.Error())
}
}
func getWriterTestResultFiles() ([]string, error) {
var p []string
visit := func(path string, f os.FileInfo, err error) error {
if !f.IsDir() && isWriterTestFile(path) {
abs, err := filepath.Abs(path)
if err != nil {
return fmt.Errorf("filepath.Abs failed for %s", path)
}
p = append(p, abs)
}
return nil
}
err := filepath.Walk(".", visit)
if nil != err {
return nil, err
}
return p, nil
}
func (tester *fileWriterTester) testCase(testCase *fileWriterTestCase, testNum int) {
defer cleanupWriterTest(tester.t)
tester.t.Logf("Start test [%v]\n", testNum)
for _, filePath := range testCase.files {
dir, _ := filepath.Split(filePath)
var err error
if 0 != len(dir) {
err = os.MkdirAll(dir, defaultDirectoryPermissions)
if err != nil {
tester.t.Error(err)
return
}
}
fi, err := os.Create(filePath)
if err != nil {
tester.t.Error(err)
return
}
err = fi.Close()
if err != nil {
tester.t.Error(err)
return
}
}
fwc, err := tester.writerGetter(testCase)
if err != nil {
tester.t.Error(err)
return
}
defer fwc.Close()
tester.performWrite(fwc, testCase.writeCount)
files, err := getWriterTestResultFiles()
if err != nil {
tester.t.Error(err)
return
}
tester.checkRequiredFilesExist(testCase, files)
tester.checkJustRequiredFilesExist(testCase, files)
}
func (tester *fileWriterTester) test() {
for i, tc := range tester.testCases {
cleanupWriterTest(tester.t)
tester.testCase(tc, i)
}
}
func (tester *fileWriterTester) performWrite(fileWriter io.Writer, count int) {
for i := 0; i < count; i++ {
_, err := fileWriter.Write(bytesFileTest)
if err != nil {
tester.t.Error(err)
return
}
}
}
func (tester *fileWriterTester) checkRequiredFilesExist(testCase *fileWriterTestCase, files []string) {
var found bool
for _, expected := range testCase.resFiles {
found = false
exAbs, err := filepath.Abs(expected)
if err != nil {
tester.t.Errorf("filepath.Abs failed for %s", expected)
continue
}
for _, f := range files {
if af, e := filepath.Abs(f); e == nil {
tester.t.Log(af)
if exAbs == af {
found = true
break
}
} else {
tester.t.Errorf("filepath.Abs failed for %s", f)
}
}
if !found {
tester.t.Errorf("expected file: %s doesn't exist. Got %v\n", exAbs, files)
}
}
}
func (tester *fileWriterTester) checkJustRequiredFilesExist(testCase *fileWriterTestCase, files []string) {
for _, f := range files {
found := false
for _, expected := range testCase.resFiles {
exAbs, err := filepath.Abs(expected)
if err != nil {
tester.t.Errorf("filepath.Abs failed for %s", expected)
} else {
if exAbs == f {
found = true
break
}
}
}
if !found {
tester.t.Errorf("unexpected file: %v", f)
}
}
}

View File

@ -1,65 +0,0 @@
// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package seelog
import (
"testing"
)
func TestformattedWriter(t *testing.T) {
formatStr := "%Level %LEVEL %Msg"
message := "message"
var logLevel = LogLevel(TraceLvl)
bytesVerifier, err := newBytesVerifier(t)
if err != nil {
t.Error(err)
return
}
formatter, err := NewFormatter(formatStr)
if err != nil {
t.Error(err)
return
}
writer, err := NewFormattedWriter(bytesVerifier, formatter)
if err != nil {
t.Error(err)
return
}
context, err := currentContext(nil)
if err != nil {
t.Error(err)
return
}
logMessage := formatter.Format(message, logLevel, context)
bytesVerifier.ExpectBytes([]byte(logMessage))
writer.Write(message, logLevel, context)
bytesVerifier.MustNotExpect()
}

View File

@ -1,99 +0,0 @@
// Copyright (c) 2012 - Cloud Instruments Co., Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package seelog
import (
"fmt"
"io"
"testing"
)
// fileWriterTestCase is declared in writers_filewriter_test.go
func createRollingSizeFileWriterTestCase(
files []string,
fileName string,
fileSize int64,
maxRolls int,
writeCount int,
resFiles []string,
nameMode rollingNameMode) *fileWriterTestCase {
return &fileWriterTestCase{files, fileName, rollingTypeSize, fileSize, maxRolls, "", writeCount, resFiles, nameMode}
}
func createRollingDatefileWriterTestCase(
files []string,
fileName string,
datePattern string,
writeCount int,
resFiles []string,
nameMode rollingNameMode) *fileWriterTestCase {
return &fileWriterTestCase{files, fileName, rollingTypeTime, 0, 0, datePattern, writeCount, resFiles, nameMode}
}
func TestRollingFileWriter(t *testing.T) {
t.Logf("Starting rolling file writer tests")
NewFileWriterTester(rollingfileWriterTests, rollingFileWriterGetter, t).test()
}
//===============================================================
func rollingFileWriterGetter(testCase *fileWriterTestCase) (io.WriteCloser, error) {
if testCase.rollingType == rollingTypeSize {
return NewRollingFileWriterSize(testCase.fileName, rollingArchiveNone, "", testCase.fileSize, testCase.maxRolls, testCase.nameMode)
} else if testCase.rollingType == rollingTypeTime {
return NewRollingFileWriterTime(testCase.fileName, rollingArchiveNone, "", -1, testCase.datePattern, rollingIntervalDaily, testCase.nameMode)
}
return nil, fmt.Errorf("incorrect rollingType")
}
//===============================================================
var rollingfileWriterTests = []*fileWriterTestCase{
createRollingSizeFileWriterTestCase([]string{}, "log.testlog", 10, 10, 1, []string{"log.testlog"}, rollingNameModePostfix),
createRollingSizeFileWriterTestCase([]string{}, "log.testlog", 10, 10, 2, []string{"log.testlog", "log.testlog.1"}, rollingNameModePostfix),
createRollingSizeFileWriterTestCase([]string{"1.log.testlog"}, "log.testlog", 10, 10, 2, []string{"log.testlog", "1.log.testlog", "2.log.testlog"}, rollingNameModePrefix),
createRollingSizeFileWriterTestCase([]string{"log.testlog.1"}, "log.testlog", 10, 1, 2, []string{"log.testlog", "log.testlog.2"}, rollingNameModePostfix),
createRollingSizeFileWriterTestCase([]string{}, "log.testlog", 10, 1, 2, []string{"log.testlog", "log.testlog.1"}, rollingNameModePostfix),
createRollingSizeFileWriterTestCase([]string{"log.testlog.9"}, "log.testlog", 10, 1, 2, []string{"log.testlog", "log.testlog.10"}, rollingNameModePostfix),
createRollingSizeFileWriterTestCase([]string{"log.testlog.a", "log.testlog.1b"}, "log.testlog", 10, 1, 2, []string{"log.testlog", "log.testlog.1", "log.testlog.a", "log.testlog.1b"}, rollingNameModePostfix),
createRollingSizeFileWriterTestCase([]string{}, `dir/log.testlog`, 10, 10, 1, []string{`dir/log.testlog`}, rollingNameModePostfix),
createRollingSizeFileWriterTestCase([]string{}, `dir/log.testlog`, 10, 10, 2, []string{`dir/log.testlog`, `dir/1.log.testlog`}, rollingNameModePrefix),
createRollingSizeFileWriterTestCase([]string{`dir/dir/log.testlog.1`}, `dir/dir/log.testlog`, 10, 10, 2, []string{`dir/dir/log.testlog`, `dir/dir/log.testlog.1`, `dir/dir/log.testlog.2`}, rollingNameModePostfix),
createRollingSizeFileWriterTestCase([]string{`dir/dir/dir/log.testlog.1`}, `dir/dir/dir/log.testlog`, 10, 1, 2, []string{`dir/dir/dir/log.testlog`, `dir/dir/dir/log.testlog.2`}, rollingNameModePostfix),
createRollingSizeFileWriterTestCase([]string{}, `./log.testlog`, 10, 1, 2, []string{`log.testlog`, `log.testlog.1`}, rollingNameModePostfix),
createRollingSizeFileWriterTestCase([]string{`././././log.testlog.9`}, `log.testlog`, 10, 1, 2, []string{`log.testlog`, `log.testlog.10`}, rollingNameModePostfix),
createRollingSizeFileWriterTestCase([]string{"dir/dir/log.testlog.a", "dir/dir/log.testlog.1b"}, "dir/dir/log.testlog", 10, 1, 2, []string{"dir/dir/log.testlog", "dir/dir/log.testlog.1", "dir/dir/log.testlog.a", "dir/dir/log.testlog.1b"}, rollingNameModePostfix),
createRollingSizeFileWriterTestCase([]string{}, `././dir/log.testlog`, 10, 10, 1, []string{`dir/log.testlog`}, rollingNameModePostfix),
createRollingSizeFileWriterTestCase([]string{}, `././dir/log.testlog`, 10, 10, 2, []string{`dir/log.testlog`, `dir/log.testlog.1`}, rollingNameModePostfix),
createRollingSizeFileWriterTestCase([]string{`././dir/dir/log.testlog.1`}, `dir/dir/log.testlog`, 10, 10, 2, []string{`dir/dir/log.testlog`, `dir/dir/log.testlog.1`, `dir/dir/log.testlog.2`}, rollingNameModePostfix),
createRollingSizeFileWriterTestCase([]string{`././dir/dir/dir/log.testlog.1`}, `dir/dir/dir/log.testlog`, 10, 1, 2, []string{`dir/dir/dir/log.testlog`, `dir/dir/dir/log.testlog.2`}, rollingNameModePostfix),
createRollingSizeFileWriterTestCase([]string{}, `././log.testlog`, 10, 1, 2, []string{`log.testlog`, `log.testlog.1`}, rollingNameModePostfix),
createRollingSizeFileWriterTestCase([]string{`././././log.testlog.9`}, `log.testlog`, 10, 1, 2, []string{`log.testlog`, `log.testlog.10`}, rollingNameModePostfix),
createRollingSizeFileWriterTestCase([]string{"././dir/dir/log.testlog.a", "././dir/dir/log.testlog.1b"}, "dir/dir/log.testlog", 10, 1, 2, []string{"dir/dir/log.testlog", "dir/dir/log.testlog.1", "dir/dir/log.testlog.a", "dir/dir/log.testlog.1b"}, rollingNameModePostfix),
// ====================
}

View File

@ -1,22 +0,0 @@
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe

View File

@ -1,14 +0,0 @@
language: go
go:
- 1.5.4
- 1.6.3
- 1.7
install:
- go get -v golang.org/x/tools/cmd/cover
script:
- go test -v -tags=safe ./spew
- go test -v -tags=testcgo ./spew -covermode=count -coverprofile=profile.cov
after_success:
- go get -v github.com/mattn/goveralls
- export PATH=$PATH:$HOME/gopath/bin
- goveralls -coverprofile=profile.cov -service=travis-ci

View File

@ -1,205 +0,0 @@
go-spew
=======
[![Build Status](https://img.shields.io/travis/davecgh/go-spew.svg)]
(https://travis-ci.org/davecgh/go-spew) [![ISC License]
(http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) [![Coverage Status]
(https://img.shields.io/coveralls/davecgh/go-spew.svg)]
(https://coveralls.io/r/davecgh/go-spew?branch=master)
Go-spew implements a deep pretty printer for Go data structures to aid in
debugging. A comprehensive suite of tests with 100% test coverage is provided
to ensure proper functionality. See `test_coverage.txt` for the gocov coverage
report. Go-spew is licensed under the liberal ISC license, so it may be used in
open source or commercial projects.
If you're interested in reading about how this package came to life and some
of the challenges involved in providing a deep pretty printer, there is a blog
post about it
[here](https://web.archive.org/web/20160304013555/https://blog.cyphertite.com/go-spew-a-journey-into-dumping-go-data-structures/).
## Documentation
[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)]
(http://godoc.org/github.com/davecgh/go-spew/spew)
Full `go doc` style documentation for the project can be viewed online without
installing this package by using the excellent GoDoc site here:
http://godoc.org/github.com/davecgh/go-spew/spew
You can also view the documentation locally once the package is installed with
the `godoc` tool by running `godoc -http=":6060"` and pointing your browser to
http://localhost:6060/pkg/github.com/davecgh/go-spew/spew
## Installation
```bash
$ go get -u github.com/davecgh/go-spew/spew
```
## Quick Start
Add this import line to the file you're working in:
```Go
import "github.com/davecgh/go-spew/spew"
```
To dump a variable with full newlines, indentation, type, and pointer
information use Dump, Fdump, or Sdump:
```Go
spew.Dump(myVar1, myVar2, ...)
spew.Fdump(someWriter, myVar1, myVar2, ...)
str := spew.Sdump(myVar1, myVar2, ...)
```
Alternatively, if you would prefer to use format strings with a compacted inline
printing style, use the convenience wrappers Printf, Fprintf, etc with %v (most
compact), %+v (adds pointer addresses), %#v (adds types), or %#+v (adds types
and pointer addresses):
```Go
spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
```
## Debugging a Web Application Example
Here is an example of how you can use `spew.Sdump()` to help debug a web application. Please be sure to wrap your output using the `html.EscapeString()` function for safety reasons. You should also only use this debugging technique in a development environment, never in production.
```Go
package main
import (
"fmt"
"html"
"net/http"
"github.com/davecgh/go-spew/spew"
)
func handler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
fmt.Fprintf(w, "Hi there, %s!", r.URL.Path[1:])
fmt.Fprintf(w, "<!--\n" + html.EscapeString(spew.Sdump(w)) + "\n-->")
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
```
## Sample Dump Output
```
(main.Foo) {
unexportedField: (*main.Bar)(0xf84002e210)({
flag: (main.Flag) flagTwo,
data: (uintptr) <nil>
}),
ExportedField: (map[interface {}]interface {}) {
(string) "one": (bool) true
}
}
([]uint8) {
00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... |
00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0|
00000020 31 32 |12|
}
```
## Sample Formatter Output
Double pointer to a uint8:
```
%v: <**>5
%+v: <**>(0xf8400420d0->0xf8400420c8)5
%#v: (**uint8)5
%#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5
```
Pointer to circular struct with a uint8 field and a pointer to itself:
```
%v: <*>{1 <*><shown>}
%+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)<shown>}
%#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)<shown>}
%#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)<shown>}
```
## Configuration Options
Configuration of spew is handled by fields in the ConfigState type. For
convenience, all of the top-level functions use a global state available via the
spew.Config global.
It is also possible to create a ConfigState instance that provides methods
equivalent to the top-level functions. This allows concurrent configuration
options. See the ConfigState documentation for more details.
```
* Indent
String to use for each indentation level for Dump functions.
It is a single space by default. A popular alternative is "\t".
* MaxDepth
Maximum number of levels to descend into nested data structures.
There is no limit by default.
* DisableMethods
Disables invocation of error and Stringer interface methods.
Method invocation is enabled by default.
* DisablePointerMethods
Disables invocation of error and Stringer interface methods on types
which only accept pointer receivers from non-pointer variables. This option
relies on access to the unsafe package, so it will not have any effect when
running in environments without access to the unsafe package such as Google
App Engine or with the "safe" build tag specified.
Pointer method invocation is enabled by default.
* DisablePointerAddresses
DisablePointerAddresses specifies whether to disable the printing of
pointer addresses. This is useful when diffing data structures in tests.
* DisableCapacities
DisableCapacities specifies whether to disable the printing of capacities
for arrays, slices, maps and channels. This is useful when diffing data
structures in tests.
* ContinueOnMethod
Enables recursion into types after invoking error and Stringer interface
methods. Recursion after method invocation is disabled by default.
* SortKeys
Specifies map keys should be sorted before being printed. Use
this to have a more deterministic, diffable output. Note that
only native types (bool, int, uint, floats, uintptr and string)
and types which implement error or Stringer interfaces are supported,
with other types sorted according to the reflect.Value.String() output
which guarantees display stability. Natural map order is used by
default.
* SpewKeys
SpewKeys specifies that, as a last resort attempt, map keys should be
spewed to strings and sorted by those strings. This is only considered
if SortKeys is true.
```
## Unsafe Package Dependency
This package relies on the unsafe package to perform some of the more advanced
features, however it also supports a "limited" mode which allows it to work in
environments where the unsafe package is not available. By default, it will
operate in this mode on Google App Engine and when compiled with GopherJS. The
"safe" build tag may also be specified to force the package to build without
using the unsafe package.
## License
Go-spew is licensed under the [copyfree](http://copyfree.org) ISC License.

View File

@ -1,22 +0,0 @@
#!/bin/sh
# This script uses gocov to generate a test coverage report.
# The gocov tool my be obtained with the following command:
# go get github.com/axw/gocov/gocov
#
# It will be installed to $GOPATH/bin, so ensure that location is in your $PATH.
# Check for gocov.
if ! type gocov >/dev/null 2>&1; then
echo >&2 "This script requires the gocov tool."
echo >&2 "You may obtain it with the following command:"
echo >&2 "go get github.com/axw/gocov/gocov"
exit 1
fi
# Only run the cgo tests if gcc is installed.
if type gcc >/dev/null 2>&1; then
(cd spew && gocov test -tags testcgo | gocov report)
else
(cd spew && gocov test | gocov report)
fi

View File

@ -1,298 +0,0 @@
/*
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package spew_test
import (
"fmt"
"reflect"
"testing"
"github.com/davecgh/go-spew/spew"
)
// custom type to test Stinger interface on non-pointer receiver.
type stringer string
// String implements the Stringer interface for testing invocation of custom
// stringers on types with non-pointer receivers.
func (s stringer) String() string {
return "stringer " + string(s)
}
// custom type to test Stinger interface on pointer receiver.
type pstringer string
// String implements the Stringer interface for testing invocation of custom
// stringers on types with only pointer receivers.
func (s *pstringer) String() string {
return "stringer " + string(*s)
}
// xref1 and xref2 are cross referencing structs for testing circular reference
// detection.
type xref1 struct {
ps2 *xref2
}
type xref2 struct {
ps1 *xref1
}
// indirCir1, indirCir2, and indirCir3 are used to generate an indirect circular
// reference for testing detection.
type indirCir1 struct {
ps2 *indirCir2
}
type indirCir2 struct {
ps3 *indirCir3
}
type indirCir3 struct {
ps1 *indirCir1
}
// embed is used to test embedded structures.
type embed struct {
a string
}
// embedwrap is used to test embedded structures.
type embedwrap struct {
*embed
e *embed
}
// panicer is used to intentionally cause a panic for testing spew properly
// handles them
type panicer int
func (p panicer) String() string {
panic("test panic")
}
// customError is used to test custom error interface invocation.
type customError int
func (e customError) Error() string {
return fmt.Sprintf("error: %d", int(e))
}
// stringizeWants converts a slice of wanted test output into a format suitable
// for a test error message.
func stringizeWants(wants []string) string {
s := ""
for i, want := range wants {
if i > 0 {
s += fmt.Sprintf("want%d: %s", i+1, want)
} else {
s += "want: " + want
}
}
return s
}
// testFailed returns whether or not a test failed by checking if the result
// of the test is in the slice of wanted strings.
func testFailed(result string, wants []string) bool {
for _, want := range wants {
if result == want {
return false
}
}
return true
}
type sortableStruct struct {
x int
}
func (ss sortableStruct) String() string {
return fmt.Sprintf("ss.%d", ss.x)
}
type unsortableStruct struct {
x int
}
type sortTestCase struct {
input []reflect.Value
expected []reflect.Value
}
func helpTestSortValues(tests []sortTestCase, cs *spew.ConfigState, t *testing.T) {
getInterfaces := func(values []reflect.Value) []interface{} {
interfaces := []interface{}{}
for _, v := range values {
interfaces = append(interfaces, v.Interface())
}
return interfaces
}
for _, test := range tests {
spew.SortValues(test.input, cs)
// reflect.DeepEqual cannot really make sense of reflect.Value,
// probably because of all the pointer tricks. For instance,
// v(2.0) != v(2.0) on a 32-bits system. Turn them into interface{}
// instead.
input := getInterfaces(test.input)
expected := getInterfaces(test.expected)
if !reflect.DeepEqual(input, expected) {
t.Errorf("Sort mismatch:\n %v != %v", input, expected)
}
}
}
// TestSortValues ensures the sort functionality for relect.Value based sorting
// works as intended.
func TestSortValues(t *testing.T) {
v := reflect.ValueOf
a := v("a")
b := v("b")
c := v("c")
embedA := v(embed{"a"})
embedB := v(embed{"b"})
embedC := v(embed{"c"})
tests := []sortTestCase{
// No values.
{
[]reflect.Value{},
[]reflect.Value{},
},
// Bools.
{
[]reflect.Value{v(false), v(true), v(false)},
[]reflect.Value{v(false), v(false), v(true)},
},
// Ints.
{
[]reflect.Value{v(2), v(1), v(3)},
[]reflect.Value{v(1), v(2), v(3)},
},
// Uints.
{
[]reflect.Value{v(uint8(2)), v(uint8(1)), v(uint8(3))},
[]reflect.Value{v(uint8(1)), v(uint8(2)), v(uint8(3))},
},
// Floats.
{
[]reflect.Value{v(2.0), v(1.0), v(3.0)},
[]reflect.Value{v(1.0), v(2.0), v(3.0)},
},
// Strings.
{
[]reflect.Value{b, a, c},
[]reflect.Value{a, b, c},
},
// Array
{
[]reflect.Value{v([3]int{3, 2, 1}), v([3]int{1, 3, 2}), v([3]int{1, 2, 3})},
[]reflect.Value{v([3]int{1, 2, 3}), v([3]int{1, 3, 2}), v([3]int{3, 2, 1})},
},
// Uintptrs.
{
[]reflect.Value{v(uintptr(2)), v(uintptr(1)), v(uintptr(3))},
[]reflect.Value{v(uintptr(1)), v(uintptr(2)), v(uintptr(3))},
},
// SortableStructs.
{
// Note: not sorted - DisableMethods is set.
[]reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})},
[]reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})},
},
// UnsortableStructs.
{
// Note: not sorted - SpewKeys is false.
[]reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})},
[]reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})},
},
// Invalid.
{
[]reflect.Value{embedB, embedA, embedC},
[]reflect.Value{embedB, embedA, embedC},
},
}
cs := spew.ConfigState{DisableMethods: true, SpewKeys: false}
helpTestSortValues(tests, &cs, t)
}
// TestSortValuesWithMethods ensures the sort functionality for relect.Value
// based sorting works as intended when using string methods.
func TestSortValuesWithMethods(t *testing.T) {
v := reflect.ValueOf
a := v("a")
b := v("b")
c := v("c")
tests := []sortTestCase{
// Ints.
{
[]reflect.Value{v(2), v(1), v(3)},
[]reflect.Value{v(1), v(2), v(3)},
},
// Strings.
{
[]reflect.Value{b, a, c},
[]reflect.Value{a, b, c},
},
// SortableStructs.
{
[]reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})},
[]reflect.Value{v(sortableStruct{1}), v(sortableStruct{2}), v(sortableStruct{3})},
},
// UnsortableStructs.
{
// Note: not sorted - SpewKeys is false.
[]reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})},
[]reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})},
},
}
cs := spew.ConfigState{DisableMethods: false, SpewKeys: false}
helpTestSortValues(tests, &cs, t)
}
// TestSortValuesWithSpew ensures the sort functionality for relect.Value
// based sorting works as intended when using spew to stringify keys.
func TestSortValuesWithSpew(t *testing.T) {
v := reflect.ValueOf
a := v("a")
b := v("b")
c := v("c")
tests := []sortTestCase{
// Ints.
{
[]reflect.Value{v(2), v(1), v(3)},
[]reflect.Value{v(1), v(2), v(3)},
},
// Strings.
{
[]reflect.Value{b, a, c},
[]reflect.Value{a, b, c},
},
// SortableStructs.
{
[]reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})},
[]reflect.Value{v(sortableStruct{1}), v(sortableStruct{2}), v(sortableStruct{3})},
},
// UnsortableStructs.
{
[]reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})},
[]reflect.Value{v(unsortableStruct{1}), v(unsortableStruct{2}), v(unsortableStruct{3})},
},
}
cs := spew.ConfigState{DisableMethods: true, SpewKeys: true}
helpTestSortValues(tests, &cs, t)
}

File diff suppressed because it is too large Load Diff

View File

@ -1,99 +0,0 @@
// Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// NOTE: Due to the following build constraints, this file will only be compiled
// when both cgo is supported and "-tags testcgo" is added to the go test
// command line. This means the cgo tests are only added (and hence run) when
// specifially requested. This configuration is used because spew itself
// does not require cgo to run even though it does handle certain cgo types
// specially. Rather than forcing all clients to require cgo and an external
// C compiler just to run the tests, this scheme makes them optional.
// +build cgo,testcgo
package spew_test
import (
"fmt"
"github.com/davecgh/go-spew/spew/testdata"
)
func addCgoDumpTests() {
// C char pointer.
v := testdata.GetCgoCharPointer()
nv := testdata.GetCgoNullCharPointer()
pv := &v
vcAddr := fmt.Sprintf("%p", v)
vAddr := fmt.Sprintf("%p", pv)
pvAddr := fmt.Sprintf("%p", &pv)
vt := "*testdata._Ctype_char"
vs := "116"
addDumpTest(v, "("+vt+")("+vcAddr+")("+vs+")\n")
addDumpTest(pv, "(*"+vt+")("+vAddr+"->"+vcAddr+")("+vs+")\n")
addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+"->"+vcAddr+")("+vs+")\n")
addDumpTest(nv, "("+vt+")(<nil>)\n")
// C char array.
v2, v2l, v2c := testdata.GetCgoCharArray()
v2Len := fmt.Sprintf("%d", v2l)
v2Cap := fmt.Sprintf("%d", v2c)
v2t := "[6]testdata._Ctype_char"
v2s := "(len=" + v2Len + " cap=" + v2Cap + ") " +
"{\n 00000000 74 65 73 74 32 00 " +
" |test2.|\n}"
addDumpTest(v2, "("+v2t+") "+v2s+"\n")
// C unsigned char array.
v3, v3l, v3c := testdata.GetCgoUnsignedCharArray()
v3Len := fmt.Sprintf("%d", v3l)
v3Cap := fmt.Sprintf("%d", v3c)
v3t := "[6]testdata._Ctype_unsignedchar"
v3t2 := "[6]testdata._Ctype_uchar"
v3s := "(len=" + v3Len + " cap=" + v3Cap + ") " +
"{\n 00000000 74 65 73 74 33 00 " +
" |test3.|\n}"
addDumpTest(v3, "("+v3t+") "+v3s+"\n", "("+v3t2+") "+v3s+"\n")
// C signed char array.
v4, v4l, v4c := testdata.GetCgoSignedCharArray()
v4Len := fmt.Sprintf("%d", v4l)
v4Cap := fmt.Sprintf("%d", v4c)
v4t := "[6]testdata._Ctype_schar"
v4t2 := "testdata._Ctype_schar"
v4s := "(len=" + v4Len + " cap=" + v4Cap + ") " +
"{\n (" + v4t2 + ") 116,\n (" + v4t2 + ") 101,\n (" + v4t2 +
") 115,\n (" + v4t2 + ") 116,\n (" + v4t2 + ") 52,\n (" + v4t2 +
") 0\n}"
addDumpTest(v4, "("+v4t+") "+v4s+"\n")
// C uint8_t array.
v5, v5l, v5c := testdata.GetCgoUint8tArray()
v5Len := fmt.Sprintf("%d", v5l)
v5Cap := fmt.Sprintf("%d", v5c)
v5t := "[6]testdata._Ctype_uint8_t"
v5s := "(len=" + v5Len + " cap=" + v5Cap + ") " +
"{\n 00000000 74 65 73 74 35 00 " +
" |test5.|\n}"
addDumpTest(v5, "("+v5t+") "+v5s+"\n")
// C typedefed unsigned char array.
v6, v6l, v6c := testdata.GetCgoTypdefedUnsignedCharArray()
v6Len := fmt.Sprintf("%d", v6l)
v6Cap := fmt.Sprintf("%d", v6c)
v6t := "[6]testdata._Ctype_custom_uchar_t"
v6s := "(len=" + v6Len + " cap=" + v6Cap + ") " +
"{\n 00000000 74 65 73 74 36 00 " +
" |test6.|\n}"
addDumpTest(v6, "("+v6t+") "+v6s+"\n")
}

View File

@ -1,26 +0,0 @@
// Copyright (c) 2013 Dave Collins <dave@davec.name>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// NOTE: Due to the following build constraints, this file will only be compiled
// when either cgo is not supported or "-tags testcgo" is not added to the go
// test command line. This file intentionally does not setup any cgo tests in
// this scenario.
// +build !cgo !testcgo
package spew_test
func addCgoDumpTests() {
// Don't add any tests for cgo since this file is only compiled when
// there should not be any cgo tests.
}

View File

@ -1,226 +0,0 @@
/*
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package spew_test
import (
"fmt"
"github.com/davecgh/go-spew/spew"
)
type Flag int
const (
flagOne Flag = iota
flagTwo
)
var flagStrings = map[Flag]string{
flagOne: "flagOne",
flagTwo: "flagTwo",
}
func (f Flag) String() string {
if s, ok := flagStrings[f]; ok {
return s
}
return fmt.Sprintf("Unknown flag (%d)", int(f))
}
type Bar struct {
data uintptr
}
type Foo struct {
unexportedField Bar
ExportedField map[interface{}]interface{}
}
// This example demonstrates how to use Dump to dump variables to stdout.
func ExampleDump() {
// The following package level declarations are assumed for this example:
/*
type Flag int
const (
flagOne Flag = iota
flagTwo
)
var flagStrings = map[Flag]string{
flagOne: "flagOne",
flagTwo: "flagTwo",
}
func (f Flag) String() string {
if s, ok := flagStrings[f]; ok {
return s
}
return fmt.Sprintf("Unknown flag (%d)", int(f))
}
type Bar struct {
data uintptr
}
type Foo struct {
unexportedField Bar
ExportedField map[interface{}]interface{}
}
*/
// Setup some sample data structures for the example.
bar := Bar{uintptr(0)}
s1 := Foo{bar, map[interface{}]interface{}{"one": true}}
f := Flag(5)
b := []byte{
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
0x31, 0x32,
}
// Dump!
spew.Dump(s1, f, b)
// Output:
// (spew_test.Foo) {
// unexportedField: (spew_test.Bar) {
// data: (uintptr) <nil>
// },
// ExportedField: (map[interface {}]interface {}) (len=1) {
// (string) (len=3) "one": (bool) true
// }
// }
// (spew_test.Flag) Unknown flag (5)
// ([]uint8) (len=34 cap=34) {
// 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... |
// 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0|
// 00000020 31 32 |12|
// }
//
}
// This example demonstrates how to use Printf to display a variable with a
// format string and inline formatting.
func ExamplePrintf() {
// Create a double pointer to a uint 8.
ui8 := uint8(5)
pui8 := &ui8
ppui8 := &pui8
// Create a circular data type.
type circular struct {
ui8 uint8
c *circular
}
c := circular{ui8: 1}
c.c = &c
// Print!
spew.Printf("ppui8: %v\n", ppui8)
spew.Printf("circular: %v\n", c)
// Output:
// ppui8: <**>5
// circular: {1 <*>{1 <*><shown>}}
}
// This example demonstrates how to use a ConfigState.
func ExampleConfigState() {
// Modify the indent level of the ConfigState only. The global
// configuration is not modified.
scs := spew.ConfigState{Indent: "\t"}
// Output using the ConfigState instance.
v := map[string]int{"one": 1}
scs.Printf("v: %v\n", v)
scs.Dump(v)
// Output:
// v: map[one:1]
// (map[string]int) (len=1) {
// (string) (len=3) "one": (int) 1
// }
}
// This example demonstrates how to use ConfigState.Dump to dump variables to
// stdout
func ExampleConfigState_Dump() {
// See the top-level Dump example for details on the types used in this
// example.
// Create two ConfigState instances with different indentation.
scs := spew.ConfigState{Indent: "\t"}
scs2 := spew.ConfigState{Indent: " "}
// Setup some sample data structures for the example.
bar := Bar{uintptr(0)}
s1 := Foo{bar, map[interface{}]interface{}{"one": true}}
// Dump using the ConfigState instances.
scs.Dump(s1)
scs2.Dump(s1)
// Output:
// (spew_test.Foo) {
// unexportedField: (spew_test.Bar) {
// data: (uintptr) <nil>
// },
// ExportedField: (map[interface {}]interface {}) (len=1) {
// (string) (len=3) "one": (bool) true
// }
// }
// (spew_test.Foo) {
// unexportedField: (spew_test.Bar) {
// data: (uintptr) <nil>
// },
// ExportedField: (map[interface {}]interface {}) (len=1) {
// (string) (len=3) "one": (bool) true
// }
// }
//
}
// This example demonstrates how to use ConfigState.Printf to display a variable
// with a format string and inline formatting.
func ExampleConfigState_Printf() {
// See the top-level Dump example for details on the types used in this
// example.
// Create two ConfigState instances and modify the method handling of the
// first ConfigState only.
scs := spew.NewDefaultConfig()
scs2 := spew.NewDefaultConfig()
scs.DisableMethods = true
// Alternatively
// scs := spew.ConfigState{Indent: " ", DisableMethods: true}
// scs2 := spew.ConfigState{Indent: " "}
// This is of type Flag which implements a Stringer and has raw value 1.
f := flagTwo
// Dump using the ConfigState instances.
scs.Printf("f: %v\n", f)
scs2.Printf("f: %v\n", f)
// Output:
// f: 1
// f: flagTwo
}

File diff suppressed because it is too large Load Diff

View File

@ -1,87 +0,0 @@
/*
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
This test file is part of the spew package rather than than the spew_test
package because it needs access to internals to properly test certain cases
which are not possible via the public interface since they should never happen.
*/
package spew
import (
"bytes"
"reflect"
"testing"
)
// dummyFmtState implements a fake fmt.State to use for testing invalid
// reflect.Value handling. This is necessary because the fmt package catches
// invalid values before invoking the formatter on them.
type dummyFmtState struct {
bytes.Buffer
}
func (dfs *dummyFmtState) Flag(f int) bool {
if f == int('+') {
return true
}
return false
}
func (dfs *dummyFmtState) Precision() (int, bool) {
return 0, false
}
func (dfs *dummyFmtState) Width() (int, bool) {
return 0, false
}
// TestInvalidReflectValue ensures the dump and formatter code handles an
// invalid reflect value properly. This needs access to internal state since it
// should never happen in real code and therefore can't be tested via the public
// API.
func TestInvalidReflectValue(t *testing.T) {
i := 1
// Dump invalid reflect value.
v := new(reflect.Value)
buf := new(bytes.Buffer)
d := dumpState{w: buf, cs: &Config}
d.dump(*v)
s := buf.String()
want := "<invalid>"
if s != want {
t.Errorf("InvalidReflectValue #%d\n got: %s want: %s", i, s, want)
}
i++
// Formatter invalid reflect value.
buf2 := new(dummyFmtState)
f := formatState{value: *v, cs: &Config, fs: buf2}
f.format(*v)
s = buf2.String()
want = "<invalid>"
if s != want {
t.Errorf("InvalidReflectValue #%d got: %s want: %s", i, s, want)
}
}
// SortValues makes the internal sortValues function available to the test
// package.
func SortValues(values []reflect.Value, cs *ConfigState) {
sortValues(values, cs)
}

View File

@ -1,102 +0,0 @@
// Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// NOTE: Due to the following build constraints, this file will only be compiled
// when the code is not running on Google App Engine, compiled by GopherJS, and
// "-tags safe" is not added to the go build command line. The "disableunsafe"
// tag is deprecated and thus should not be used.
// +build !js,!appengine,!safe,!disableunsafe
/*
This test file is part of the spew package rather than than the spew_test
package because it needs access to internals to properly test certain cases
which are not possible via the public interface since they should never happen.
*/
package spew
import (
"bytes"
"reflect"
"testing"
"unsafe"
)
// changeKind uses unsafe to intentionally change the kind of a reflect.Value to
// the maximum kind value which does not exist. This is needed to test the
// fallback code which punts to the standard fmt library for new types that
// might get added to the language.
func changeKind(v *reflect.Value, readOnly bool) {
rvf := (*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + offsetFlag))
*rvf = *rvf | ((1<<flagKindWidth - 1) << flagKindShift)
if readOnly {
*rvf |= flagRO
} else {
*rvf &= ^uintptr(flagRO)
}
}
// TestAddedReflectValue tests functionaly of the dump and formatter code which
// falls back to the standard fmt library for new types that might get added to
// the language.
func TestAddedReflectValue(t *testing.T) {
i := 1
// Dump using a reflect.Value that is exported.
v := reflect.ValueOf(int8(5))
changeKind(&v, false)
buf := new(bytes.Buffer)
d := dumpState{w: buf, cs: &Config}
d.dump(v)
s := buf.String()
want := "(int8) 5"
if s != want {
t.Errorf("TestAddedReflectValue #%d\n got: %s want: %s", i, s, want)
}
i++
// Dump using a reflect.Value that is not exported.
changeKind(&v, true)
buf.Reset()
d.dump(v)
s = buf.String()
want = "(int8) <int8 Value>"
if s != want {
t.Errorf("TestAddedReflectValue #%d\n got: %s want: %s", i, s, want)
}
i++
// Formatter using a reflect.Value that is exported.
changeKind(&v, false)
buf2 := new(dummyFmtState)
f := formatState{value: v, cs: &Config, fs: buf2}
f.format(v)
s = buf2.String()
want = "5"
if s != want {
t.Errorf("TestAddedReflectValue #%d got: %s want: %s", i, s, want)
}
i++
// Formatter using a reflect.Value that is not exported.
changeKind(&v, true)
buf2.Reset()
f = formatState{value: v, cs: &Config, fs: buf2}
f.format(v)
s = buf2.String()
want = "<int8 Value>"
if s != want {
t.Errorf("TestAddedReflectValue #%d got: %s want: %s", i, s, want)
}
}

View File

@ -1,320 +0,0 @@
/*
* Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package spew_test
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"testing"
"github.com/davecgh/go-spew/spew"
)
// spewFunc is used to identify which public function of the spew package or
// ConfigState a test applies to.
type spewFunc int
const (
fCSFdump spewFunc = iota
fCSFprint
fCSFprintf
fCSFprintln
fCSPrint
fCSPrintln
fCSSdump
fCSSprint
fCSSprintf
fCSSprintln
fCSErrorf
fCSNewFormatter
fErrorf
fFprint
fFprintln
fPrint
fPrintln
fSdump
fSprint
fSprintf
fSprintln
)
// Map of spewFunc values to names for pretty printing.
var spewFuncStrings = map[spewFunc]string{
fCSFdump: "ConfigState.Fdump",
fCSFprint: "ConfigState.Fprint",
fCSFprintf: "ConfigState.Fprintf",
fCSFprintln: "ConfigState.Fprintln",
fCSSdump: "ConfigState.Sdump",
fCSPrint: "ConfigState.Print",
fCSPrintln: "ConfigState.Println",
fCSSprint: "ConfigState.Sprint",
fCSSprintf: "ConfigState.Sprintf",
fCSSprintln: "ConfigState.Sprintln",
fCSErrorf: "ConfigState.Errorf",
fCSNewFormatter: "ConfigState.NewFormatter",
fErrorf: "spew.Errorf",
fFprint: "spew.Fprint",
fFprintln: "spew.Fprintln",
fPrint: "spew.Print",
fPrintln: "spew.Println",
fSdump: "spew.Sdump",
fSprint: "spew.Sprint",
fSprintf: "spew.Sprintf",
fSprintln: "spew.Sprintln",
}
func (f spewFunc) String() string {
if s, ok := spewFuncStrings[f]; ok {
return s
}
return fmt.Sprintf("Unknown spewFunc (%d)", int(f))
}
// spewTest is used to describe a test to be performed against the public
// functions of the spew package or ConfigState.
type spewTest struct {
cs *spew.ConfigState
f spewFunc
format string
in interface{}
want string
}
// spewTests houses the tests to be performed against the public functions of
// the spew package and ConfigState.
//
// These tests are only intended to ensure the public functions are exercised
// and are intentionally not exhaustive of types. The exhaustive type
// tests are handled in the dump and format tests.
var spewTests []spewTest
// redirStdout is a helper function to return the standard output from f as a
// byte slice.
func redirStdout(f func()) ([]byte, error) {
tempFile, err := ioutil.TempFile("", "ss-test")
if err != nil {
return nil, err
}
fileName := tempFile.Name()
defer os.Remove(fileName) // Ignore error
origStdout := os.Stdout
os.Stdout = tempFile
f()
os.Stdout = origStdout
tempFile.Close()
return ioutil.ReadFile(fileName)
}
func initSpewTests() {
// Config states with various settings.
scsDefault := spew.NewDefaultConfig()
scsNoMethods := &spew.ConfigState{Indent: " ", DisableMethods: true}
scsNoPmethods := &spew.ConfigState{Indent: " ", DisablePointerMethods: true}
scsMaxDepth := &spew.ConfigState{Indent: " ", MaxDepth: 1}
scsContinue := &spew.ConfigState{Indent: " ", ContinueOnMethod: true}
scsNoPtrAddr := &spew.ConfigState{DisablePointerAddresses: true}
scsNoCap := &spew.ConfigState{DisableCapacities: true}
// Variables for tests on types which implement Stringer interface with and
// without a pointer receiver.
ts := stringer("test")
tps := pstringer("test")
type ptrTester struct {
s *struct{}
}
tptr := &ptrTester{s: &struct{}{}}
// depthTester is used to test max depth handling for structs, array, slices
// and maps.
type depthTester struct {
ic indirCir1
arr [1]string
slice []string
m map[string]int
}
dt := depthTester{indirCir1{nil}, [1]string{"arr"}, []string{"slice"},
map[string]int{"one": 1}}
// Variable for tests on types which implement error interface.
te := customError(10)
spewTests = []spewTest{
{scsDefault, fCSFdump, "", int8(127), "(int8) 127\n"},
{scsDefault, fCSFprint, "", int16(32767), "32767"},
{scsDefault, fCSFprintf, "%v", int32(2147483647), "2147483647"},
{scsDefault, fCSFprintln, "", int(2147483647), "2147483647\n"},
{scsDefault, fCSPrint, "", int64(9223372036854775807), "9223372036854775807"},
{scsDefault, fCSPrintln, "", uint8(255), "255\n"},
{scsDefault, fCSSdump, "", uint8(64), "(uint8) 64\n"},
{scsDefault, fCSSprint, "", complex(1, 2), "(1+2i)"},
{scsDefault, fCSSprintf, "%v", complex(float32(3), 4), "(3+4i)"},
{scsDefault, fCSSprintln, "", complex(float64(5), 6), "(5+6i)\n"},
{scsDefault, fCSErrorf, "%#v", uint16(65535), "(uint16)65535"},
{scsDefault, fCSNewFormatter, "%v", uint32(4294967295), "4294967295"},
{scsDefault, fErrorf, "%v", uint64(18446744073709551615), "18446744073709551615"},
{scsDefault, fFprint, "", float32(3.14), "3.14"},
{scsDefault, fFprintln, "", float64(6.28), "6.28\n"},
{scsDefault, fPrint, "", true, "true"},
{scsDefault, fPrintln, "", false, "false\n"},
{scsDefault, fSdump, "", complex(-10, -20), "(complex128) (-10-20i)\n"},
{scsDefault, fSprint, "", complex(-1, -2), "(-1-2i)"},
{scsDefault, fSprintf, "%v", complex(float32(-3), -4), "(-3-4i)"},
{scsDefault, fSprintln, "", complex(float64(-5), -6), "(-5-6i)\n"},
{scsNoMethods, fCSFprint, "", ts, "test"},
{scsNoMethods, fCSFprint, "", &ts, "<*>test"},
{scsNoMethods, fCSFprint, "", tps, "test"},
{scsNoMethods, fCSFprint, "", &tps, "<*>test"},
{scsNoPmethods, fCSFprint, "", ts, "stringer test"},
{scsNoPmethods, fCSFprint, "", &ts, "<*>stringer test"},
{scsNoPmethods, fCSFprint, "", tps, "test"},
{scsNoPmethods, fCSFprint, "", &tps, "<*>stringer test"},
{scsMaxDepth, fCSFprint, "", dt, "{{<max>} [<max>] [<max>] map[<max>]}"},
{scsMaxDepth, fCSFdump, "", dt, "(spew_test.depthTester) {\n" +
" ic: (spew_test.indirCir1) {\n <max depth reached>\n },\n" +
" arr: ([1]string) (len=1 cap=1) {\n <max depth reached>\n },\n" +
" slice: ([]string) (len=1 cap=1) {\n <max depth reached>\n },\n" +
" m: (map[string]int) (len=1) {\n <max depth reached>\n }\n}\n"},
{scsContinue, fCSFprint, "", ts, "(stringer test) test"},
{scsContinue, fCSFdump, "", ts, "(spew_test.stringer) " +
"(len=4) (stringer test) \"test\"\n"},
{scsContinue, fCSFprint, "", te, "(error: 10) 10"},
{scsContinue, fCSFdump, "", te, "(spew_test.customError) " +
"(error: 10) 10\n"},
{scsNoPtrAddr, fCSFprint, "", tptr, "<*>{<*>{}}"},
{scsNoPtrAddr, fCSSdump, "", tptr, "(*spew_test.ptrTester)({\ns: (*struct {})({\n})\n})\n"},
{scsNoCap, fCSSdump, "", make([]string, 0, 10), "([]string) {\n}\n"},
{scsNoCap, fCSSdump, "", make([]string, 1, 10), "([]string) (len=1) {\n(string) \"\"\n}\n"},
}
}
// TestSpew executes all of the tests described by spewTests.
func TestSpew(t *testing.T) {
initSpewTests()
t.Logf("Running %d tests", len(spewTests))
for i, test := range spewTests {
buf := new(bytes.Buffer)
switch test.f {
case fCSFdump:
test.cs.Fdump(buf, test.in)
case fCSFprint:
test.cs.Fprint(buf, test.in)
case fCSFprintf:
test.cs.Fprintf(buf, test.format, test.in)
case fCSFprintln:
test.cs.Fprintln(buf, test.in)
case fCSPrint:
b, err := redirStdout(func() { test.cs.Print(test.in) })
if err != nil {
t.Errorf("%v #%d %v", test.f, i, err)
continue
}
buf.Write(b)
case fCSPrintln:
b, err := redirStdout(func() { test.cs.Println(test.in) })
if err != nil {
t.Errorf("%v #%d %v", test.f, i, err)
continue
}
buf.Write(b)
case fCSSdump:
str := test.cs.Sdump(test.in)
buf.WriteString(str)
case fCSSprint:
str := test.cs.Sprint(test.in)
buf.WriteString(str)
case fCSSprintf:
str := test.cs.Sprintf(test.format, test.in)
buf.WriteString(str)
case fCSSprintln:
str := test.cs.Sprintln(test.in)
buf.WriteString(str)
case fCSErrorf:
err := test.cs.Errorf(test.format, test.in)
buf.WriteString(err.Error())
case fCSNewFormatter:
fmt.Fprintf(buf, test.format, test.cs.NewFormatter(test.in))
case fErrorf:
err := spew.Errorf(test.format, test.in)
buf.WriteString(err.Error())
case fFprint:
spew.Fprint(buf, test.in)
case fFprintln:
spew.Fprintln(buf, test.in)
case fPrint:
b, err := redirStdout(func() { spew.Print(test.in) })
if err != nil {
t.Errorf("%v #%d %v", test.f, i, err)
continue
}
buf.Write(b)
case fPrintln:
b, err := redirStdout(func() { spew.Println(test.in) })
if err != nil {
t.Errorf("%v #%d %v", test.f, i, err)
continue
}
buf.Write(b)
case fSdump:
str := spew.Sdump(test.in)
buf.WriteString(str)
case fSprint:
str := spew.Sprint(test.in)
buf.WriteString(str)
case fSprintf:
str := spew.Sprintf(test.format, test.in)
buf.WriteString(str)
case fSprintln:
str := spew.Sprintln(test.in)
buf.WriteString(str)
default:
t.Errorf("%v #%d unrecognized function", test.f, i)
continue
}
s := buf.String()
if test.want != s {
t.Errorf("ConfigState #%d\n got: %s want: %s", i, s, test.want)
continue
}
}
}

View File

@ -1,82 +0,0 @@
// Copyright (c) 2013 Dave Collins <dave@davec.name>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// NOTE: Due to the following build constraints, this file will only be compiled
// when both cgo is supported and "-tags testcgo" is added to the go test
// command line. This code should really only be in the dumpcgo_test.go file,
// but unfortunately Go will not allow cgo in test files, so this is a
// workaround to allow cgo types to be tested. This configuration is used
// because spew itself does not require cgo to run even though it does handle
// certain cgo types specially. Rather than forcing all clients to require cgo
// and an external C compiler just to run the tests, this scheme makes them
// optional.
// +build cgo,testcgo
package testdata
/*
#include <stdint.h>
typedef unsigned char custom_uchar_t;
char *ncp = 0;
char *cp = "test";
char ca[6] = {'t', 'e', 's', 't', '2', '\0'};
unsigned char uca[6] = {'t', 'e', 's', 't', '3', '\0'};
signed char sca[6] = {'t', 'e', 's', 't', '4', '\0'};
uint8_t ui8ta[6] = {'t', 'e', 's', 't', '5', '\0'};
custom_uchar_t tuca[6] = {'t', 'e', 's', 't', '6', '\0'};
*/
import "C"
// GetCgoNullCharPointer returns a null char pointer via cgo. This is only
// used for tests.
func GetCgoNullCharPointer() interface{} {
return C.ncp
}
// GetCgoCharPointer returns a char pointer via cgo. This is only used for
// tests.
func GetCgoCharPointer() interface{} {
return C.cp
}
// GetCgoCharArray returns a char array via cgo and the array's len and cap.
// This is only used for tests.
func GetCgoCharArray() (interface{}, int, int) {
return C.ca, len(C.ca), cap(C.ca)
}
// GetCgoUnsignedCharArray returns an unsigned char array via cgo and the
// array's len and cap. This is only used for tests.
func GetCgoUnsignedCharArray() (interface{}, int, int) {
return C.uca, len(C.uca), cap(C.uca)
}
// GetCgoSignedCharArray returns a signed char array via cgo and the array's len
// and cap. This is only used for tests.
func GetCgoSignedCharArray() (interface{}, int, int) {
return C.sca, len(C.sca), cap(C.sca)
}
// GetCgoUint8tArray returns a uint8_t array via cgo and the array's len and
// cap. This is only used for tests.
func GetCgoUint8tArray() (interface{}, int, int) {
return C.ui8ta, len(C.ui8ta), cap(C.ui8ta)
}
// GetCgoTypdefedUnsignedCharArray returns a typedefed unsigned char array via
// cgo and the array's len and cap. This is only used for tests.
func GetCgoTypdefedUnsignedCharArray() (interface{}, int, int) {
return C.tuca, len(C.tuca), cap(C.tuca)
}

View File

@ -1,61 +0,0 @@
github.com/davecgh/go-spew/spew/dump.go dumpState.dump 100.00% (88/88)
github.com/davecgh/go-spew/spew/format.go formatState.format 100.00% (82/82)
github.com/davecgh/go-spew/spew/format.go formatState.formatPtr 100.00% (52/52)
github.com/davecgh/go-spew/spew/dump.go dumpState.dumpPtr 100.00% (44/44)
github.com/davecgh/go-spew/spew/dump.go dumpState.dumpSlice 100.00% (39/39)
github.com/davecgh/go-spew/spew/common.go handleMethods 100.00% (30/30)
github.com/davecgh/go-spew/spew/common.go printHexPtr 100.00% (18/18)
github.com/davecgh/go-spew/spew/common.go unsafeReflectValue 100.00% (13/13)
github.com/davecgh/go-spew/spew/format.go formatState.constructOrigFormat 100.00% (12/12)
github.com/davecgh/go-spew/spew/dump.go fdump 100.00% (11/11)
github.com/davecgh/go-spew/spew/format.go formatState.Format 100.00% (11/11)
github.com/davecgh/go-spew/spew/common.go init 100.00% (10/10)
github.com/davecgh/go-spew/spew/common.go printComplex 100.00% (9/9)
github.com/davecgh/go-spew/spew/common.go valuesSorter.Less 100.00% (8/8)
github.com/davecgh/go-spew/spew/format.go formatState.buildDefaultFormat 100.00% (7/7)
github.com/davecgh/go-spew/spew/format.go formatState.unpackValue 100.00% (5/5)
github.com/davecgh/go-spew/spew/dump.go dumpState.indent 100.00% (4/4)
github.com/davecgh/go-spew/spew/common.go catchPanic 100.00% (4/4)
github.com/davecgh/go-spew/spew/config.go ConfigState.convertArgs 100.00% (4/4)
github.com/davecgh/go-spew/spew/spew.go convertArgs 100.00% (4/4)
github.com/davecgh/go-spew/spew/format.go newFormatter 100.00% (3/3)
github.com/davecgh/go-spew/spew/dump.go Sdump 100.00% (3/3)
github.com/davecgh/go-spew/spew/common.go printBool 100.00% (3/3)
github.com/davecgh/go-spew/spew/common.go sortValues 100.00% (3/3)
github.com/davecgh/go-spew/spew/config.go ConfigState.Sdump 100.00% (3/3)
github.com/davecgh/go-spew/spew/dump.go dumpState.unpackValue 100.00% (3/3)
github.com/davecgh/go-spew/spew/spew.go Printf 100.00% (1/1)
github.com/davecgh/go-spew/spew/spew.go Println 100.00% (1/1)
github.com/davecgh/go-spew/spew/spew.go Sprint 100.00% (1/1)
github.com/davecgh/go-spew/spew/spew.go Sprintf 100.00% (1/1)
github.com/davecgh/go-spew/spew/spew.go Sprintln 100.00% (1/1)
github.com/davecgh/go-spew/spew/common.go printFloat 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go NewDefaultConfig 100.00% (1/1)
github.com/davecgh/go-spew/spew/common.go printInt 100.00% (1/1)
github.com/davecgh/go-spew/spew/common.go printUint 100.00% (1/1)
github.com/davecgh/go-spew/spew/common.go valuesSorter.Len 100.00% (1/1)
github.com/davecgh/go-spew/spew/common.go valuesSorter.Swap 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.Errorf 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.Fprint 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.Fprintf 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.Fprintln 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.Print 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.Printf 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.Println 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.Sprint 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.Sprintf 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.Sprintln 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.NewFormatter 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.Fdump 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.Dump 100.00% (1/1)
github.com/davecgh/go-spew/spew/dump.go Fdump 100.00% (1/1)
github.com/davecgh/go-spew/spew/dump.go Dump 100.00% (1/1)
github.com/davecgh/go-spew/spew/spew.go Fprintln 100.00% (1/1)
github.com/davecgh/go-spew/spew/format.go NewFormatter 100.00% (1/1)
github.com/davecgh/go-spew/spew/spew.go Errorf 100.00% (1/1)
github.com/davecgh/go-spew/spew/spew.go Fprint 100.00% (1/1)
github.com/davecgh/go-spew/spew/spew.go Fprintf 100.00% (1/1)
github.com/davecgh/go-spew/spew/spew.go Print 100.00% (1/1)
github.com/davecgh/go-spew/spew ------------------------------- 100.00% (505/505)

View File

@ -1,220 +0,0 @@
package humanize
import (
"math/big"
"testing"
)
func TestBigByteParsing(t *testing.T) {
tests := []struct {
in string
exp uint64
}{
{"42", 42},
{"42MB", 42000000},
{"42MiB", 44040192},
{"42mb", 42000000},
{"42mib", 44040192},
{"42MIB", 44040192},
{"42 MB", 42000000},
{"42 MiB", 44040192},
{"42 mb", 42000000},
{"42 mib", 44040192},
{"42 MIB", 44040192},
{"42.5MB", 42500000},
{"42.5MiB", 44564480},
{"42.5 MB", 42500000},
{"42.5 MiB", 44564480},
// No need to say B
{"42M", 42000000},
{"42Mi", 44040192},
{"42m", 42000000},
{"42mi", 44040192},
{"42MI", 44040192},
{"42 M", 42000000},
{"42 Mi", 44040192},
{"42 m", 42000000},
{"42 mi", 44040192},
{"42 MI", 44040192},
{"42.5M", 42500000},
{"42.5Mi", 44564480},
{"42.5 M", 42500000},
{"42.5 Mi", 44564480},
{"1,005.03 MB", 1005030000},
// Large testing, breaks when too much larger than
// this.
{"12.5 EB", uint64(12.5 * float64(EByte))},
{"12.5 E", uint64(12.5 * float64(EByte))},
{"12.5 EiB", uint64(12.5 * float64(EiByte))},
}
for _, p := range tests {
got, err := ParseBigBytes(p.in)
if err != nil {
t.Errorf("Couldn't parse %v: %v", p.in, err)
} else {
if got.Uint64() != p.exp {
t.Errorf("Expected %v for %v, got %v",
p.exp, p.in, got)
}
}
}
}
func TestBigByteErrors(t *testing.T) {
got, err := ParseBigBytes("84 JB")
if err == nil {
t.Errorf("Expected error, got %v", got)
}
got, err = ParseBigBytes("")
if err == nil {
t.Errorf("Expected error parsing nothing")
}
}
func bbyte(in uint64) string {
return BigBytes((&big.Int{}).SetUint64(in))
}
func bibyte(in uint64) string {
return BigIBytes((&big.Int{}).SetUint64(in))
}
func TestBigBytes(t *testing.T) {
testList{
{"bytes(0)", bbyte(0), "0 B"},
{"bytes(1)", bbyte(1), "1 B"},
{"bytes(803)", bbyte(803), "803 B"},
{"bytes(999)", bbyte(999), "999 B"},
{"bytes(1024)", bbyte(1024), "1.0 kB"},
{"bytes(1MB - 1)", bbyte(MByte - Byte), "1000 kB"},
{"bytes(1MB)", bbyte(1024 * 1024), "1.0 MB"},
{"bytes(1GB - 1K)", bbyte(GByte - KByte), "1000 MB"},
{"bytes(1GB)", bbyte(GByte), "1.0 GB"},
{"bytes(1TB - 1M)", bbyte(TByte - MByte), "1000 GB"},
{"bytes(1TB)", bbyte(TByte), "1.0 TB"},
{"bytes(1PB - 1T)", bbyte(PByte - TByte), "999 TB"},
{"bytes(1PB)", bbyte(PByte), "1.0 PB"},
{"bytes(1PB - 1T)", bbyte(EByte - PByte), "999 PB"},
{"bytes(1EB)", bbyte(EByte), "1.0 EB"},
// Overflows.
// {"bytes(1EB - 1P)", Bytes((KByte*EByte)-PByte), "1023EB"},
{"bytes(0)", bibyte(0), "0 B"},
{"bytes(1)", bibyte(1), "1 B"},
{"bytes(803)", bibyte(803), "803 B"},
{"bytes(1023)", bibyte(1023), "1023 B"},
{"bytes(1024)", bibyte(1024), "1.0 KiB"},
{"bytes(1MB - 1)", bibyte(MiByte - IByte), "1024 KiB"},
{"bytes(1MB)", bibyte(1024 * 1024), "1.0 MiB"},
{"bytes(1GB - 1K)", bibyte(GiByte - KiByte), "1024 MiB"},
{"bytes(1GB)", bibyte(GiByte), "1.0 GiB"},
{"bytes(1TB - 1M)", bibyte(TiByte - MiByte), "1024 GiB"},
{"bytes(1TB)", bibyte(TiByte), "1.0 TiB"},
{"bytes(1PB - 1T)", bibyte(PiByte - TiByte), "1023 TiB"},
{"bytes(1PB)", bibyte(PiByte), "1.0 PiB"},
{"bytes(1PB - 1T)", bibyte(EiByte - PiByte), "1023 PiB"},
{"bytes(1EiB)", bibyte(EiByte), "1.0 EiB"},
// Overflows.
// {"bytes(1EB - 1P)", bibyte((KIByte*EIByte)-PiByte), "1023EB"},
{"bytes(5.5GiB)", bibyte(5.5 * GiByte), "5.5 GiB"},
{"bytes(5.5GB)", bbyte(5.5 * GByte), "5.5 GB"},
}.validate(t)
}
func TestVeryBigBytes(t *testing.T) {
b, _ := (&big.Int{}).SetString("15347691069326346944512", 10)
s := BigBytes(b)
if s != "15 ZB" {
t.Errorf("Expected 15 ZB, got %v", s)
}
s = BigIBytes(b)
if s != "13 ZiB" {
t.Errorf("Expected 13 ZiB, got %v", s)
}
b, _ = (&big.Int{}).SetString("15716035654990179271180288", 10)
s = BigBytes(b)
if s != "16 YB" {
t.Errorf("Expected 16 YB, got %v", s)
}
s = BigIBytes(b)
if s != "13 YiB" {
t.Errorf("Expected 13 YiB, got %v", s)
}
}
func TestVeryVeryBigBytes(t *testing.T) {
b, _ := (&big.Int{}).SetString("16093220510709943573688614912", 10)
s := BigBytes(b)
if s != "16093 YB" {
t.Errorf("Expected 16093 YB, got %v", s)
}
s = BigIBytes(b)
if s != "13312 YiB" {
t.Errorf("Expected 13312 YiB, got %v", s)
}
}
func TestParseVeryBig(t *testing.T) {
tests := []struct {
in string
out string
}{
{"16 ZB", "16000000000000000000000"},
{"16 ZiB", "18889465931478580854784"},
{"16.5 ZB", "16500000000000000000000"},
{"16.5 ZiB", "19479761741837286506496"},
{"16 Z", "16000000000000000000000"},
{"16 Zi", "18889465931478580854784"},
{"16.5 Z", "16500000000000000000000"},
{"16.5 Zi", "19479761741837286506496"},
{"16 YB", "16000000000000000000000000"},
{"16 YiB", "19342813113834066795298816"},
{"16.5 YB", "16500000000000000000000000"},
{"16.5 YiB", "19947276023641381382651904"},
{"16 Y", "16000000000000000000000000"},
{"16 Yi", "19342813113834066795298816"},
{"16.5 Y", "16500000000000000000000000"},
{"16.5 Yi", "19947276023641381382651904"},
}
for _, test := range tests {
x, err := ParseBigBytes(test.in)
if err != nil {
t.Errorf("Error parsing %q: %v", test.in, err)
continue
}
if x.String() != test.out {
t.Errorf("Expected %q for %q, got %v", test.out, test.in, x)
}
}
}
func BenchmarkParseBigBytes(b *testing.B) {
for i := 0; i < b.N; i++ {
ParseBigBytes("16.5 Z")
}
}
func BenchmarkBigBytes(b *testing.B) {
for i := 0; i < b.N; i++ {
bibyte(16.5 * GByte)
}
}

View File

@ -1,146 +0,0 @@
package humanize
import (
"testing"
)
func TestByteParsing(t *testing.T) {
tests := []struct {
in string
exp uint64
}{
{"42", 42},
{"42MB", 42000000},
{"42MiB", 44040192},
{"42mb", 42000000},
{"42mib", 44040192},
{"42MIB", 44040192},
{"42 MB", 42000000},
{"42 MiB", 44040192},
{"42 mb", 42000000},
{"42 mib", 44040192},
{"42 MIB", 44040192},
{"42.5MB", 42500000},
{"42.5MiB", 44564480},
{"42.5 MB", 42500000},
{"42.5 MiB", 44564480},
// No need to say B
{"42M", 42000000},
{"42Mi", 44040192},
{"42m", 42000000},
{"42mi", 44040192},
{"42MI", 44040192},
{"42 M", 42000000},
{"42 Mi", 44040192},
{"42 m", 42000000},
{"42 mi", 44040192},
{"42 MI", 44040192},
{"42.5M", 42500000},
{"42.5Mi", 44564480},
{"42.5 M", 42500000},
{"42.5 Mi", 44564480},
// Bug #42
{"1,005.03 MB", 1005030000},
// Large testing, breaks when too much larger than
// this.
{"12.5 EB", uint64(12.5 * float64(EByte))},
{"12.5 E", uint64(12.5 * float64(EByte))},
{"12.5 EiB", uint64(12.5 * float64(EiByte))},
}
for _, p := range tests {
got, err := ParseBytes(p.in)
if err != nil {
t.Errorf("Couldn't parse %v: %v", p.in, err)
}
if got != p.exp {
t.Errorf("Expected %v for %v, got %v",
p.exp, p.in, got)
}
}
}
func TestByteErrors(t *testing.T) {
got, err := ParseBytes("84 JB")
if err == nil {
t.Errorf("Expected error, got %v", got)
}
got, err = ParseBytes("")
if err == nil {
t.Errorf("Expected error parsing nothing")
}
got, err = ParseBytes("16 EiB")
if err == nil {
t.Errorf("Expected error, got %v", got)
}
}
func TestBytes(t *testing.T) {
testList{
{"bytes(0)", Bytes(0), "0 B"},
{"bytes(1)", Bytes(1), "1 B"},
{"bytes(803)", Bytes(803), "803 B"},
{"bytes(999)", Bytes(999), "999 B"},
{"bytes(1024)", Bytes(1024), "1.0 kB"},
{"bytes(9999)", Bytes(9999), "10 kB"},
{"bytes(1MB - 1)", Bytes(MByte - Byte), "1000 kB"},
{"bytes(1MB)", Bytes(1024 * 1024), "1.0 MB"},
{"bytes(1GB - 1K)", Bytes(GByte - KByte), "1000 MB"},
{"bytes(1GB)", Bytes(GByte), "1.0 GB"},
{"bytes(1TB - 1M)", Bytes(TByte - MByte), "1000 GB"},
{"bytes(10MB)", Bytes(9999 * 1000), "10 MB"},
{"bytes(1TB)", Bytes(TByte), "1.0 TB"},
{"bytes(1PB - 1T)", Bytes(PByte - TByte), "999 TB"},
{"bytes(1PB)", Bytes(PByte), "1.0 PB"},
{"bytes(1PB - 1T)", Bytes(EByte - PByte), "999 PB"},
{"bytes(1EB)", Bytes(EByte), "1.0 EB"},
// Overflows.
// {"bytes(1EB - 1P)", Bytes((KByte*EByte)-PByte), "1023EB"},
{"bytes(0)", IBytes(0), "0 B"},
{"bytes(1)", IBytes(1), "1 B"},
{"bytes(803)", IBytes(803), "803 B"},
{"bytes(1023)", IBytes(1023), "1023 B"},
{"bytes(1024)", IBytes(1024), "1.0 KiB"},
{"bytes(1MB - 1)", IBytes(MiByte - IByte), "1024 KiB"},
{"bytes(1MB)", IBytes(1024 * 1024), "1.0 MiB"},
{"bytes(1GB - 1K)", IBytes(GiByte - KiByte), "1024 MiB"},
{"bytes(1GB)", IBytes(GiByte), "1.0 GiB"},
{"bytes(1TB - 1M)", IBytes(TiByte - MiByte), "1024 GiB"},
{"bytes(1TB)", IBytes(TiByte), "1.0 TiB"},
{"bytes(1PB - 1T)", IBytes(PiByte - TiByte), "1023 TiB"},
{"bytes(1PB)", IBytes(PiByte), "1.0 PiB"},
{"bytes(1PB - 1T)", IBytes(EiByte - PiByte), "1023 PiB"},
{"bytes(1EiB)", IBytes(EiByte), "1.0 EiB"},
// Overflows.
// {"bytes(1EB - 1P)", IBytes((KIByte*EIByte)-PiByte), "1023EB"},
{"bytes(5.5GiB)", IBytes(5.5 * GiByte), "5.5 GiB"},
{"bytes(5.5GB)", Bytes(5.5 * GByte), "5.5 GB"},
}.validate(t)
}
func BenchmarkParseBytes(b *testing.B) {
for i := 0; i < b.N; i++ {
ParseBytes("16.5 GB")
}
}
func BenchmarkBytes(b *testing.B) {
for i := 0; i < b.N; i++ {
Bytes(16.5 * GByte)
}
}

View File

@ -1,145 +0,0 @@
package humanize
import (
"math"
"math/big"
"testing"
)
func TestCommas(t *testing.T) {
testList{
{"0", Comma(0), "0"},
{"10", Comma(10), "10"},
{"100", Comma(100), "100"},
{"1,000", Comma(1000), "1,000"},
{"10,000", Comma(10000), "10,000"},
{"100,000", Comma(100000), "100,000"},
{"10,000,000", Comma(10000000), "10,000,000"},
{"10,100,000", Comma(10100000), "10,100,000"},
{"10,010,000", Comma(10010000), "10,010,000"},
{"10,001,000", Comma(10001000), "10,001,000"},
{"123,456,789", Comma(123456789), "123,456,789"},
{"maxint", Comma(9.223372e+18), "9,223,372,000,000,000,000"},
{"math.maxint", Comma(math.MaxInt64), "9,223,372,036,854,775,807"},
{"math.minint", Comma(math.MinInt64), "-9,223,372,036,854,775,808"},
{"minint", Comma(-9.223372e+18), "-9,223,372,000,000,000,000"},
{"-123,456,789", Comma(-123456789), "-123,456,789"},
{"-10,100,000", Comma(-10100000), "-10,100,000"},
{"-10,010,000", Comma(-10010000), "-10,010,000"},
{"-10,001,000", Comma(-10001000), "-10,001,000"},
{"-10,000,000", Comma(-10000000), "-10,000,000"},
{"-100,000", Comma(-100000), "-100,000"},
{"-10,000", Comma(-10000), "-10,000"},
{"-1,000", Comma(-1000), "-1,000"},
{"-100", Comma(-100), "-100"},
{"-10", Comma(-10), "-10"},
}.validate(t)
}
func TestCommafWithDigits(t *testing.T) {
testList{
{"1.23, 0", CommafWithDigits(1.23, 0), "1"},
{"1.23, 1", CommafWithDigits(1.23, 1), "1.2"},
{"1.23, 2", CommafWithDigits(1.23, 2), "1.23"},
{"1.23, 3", CommafWithDigits(1.23, 3), "1.23"},
}.validate(t)
}
func TestCommafs(t *testing.T) {
testList{
{"0", Commaf(0), "0"},
{"10.11", Commaf(10.11), "10.11"},
{"100", Commaf(100), "100"},
{"1,000", Commaf(1000), "1,000"},
{"10,000", Commaf(10000), "10,000"},
{"100,000", Commaf(100000), "100,000"},
{"834,142.32", Commaf(834142.32), "834,142.32"},
{"10,000,000", Commaf(10000000), "10,000,000"},
{"10,100,000", Commaf(10100000), "10,100,000"},
{"10,010,000", Commaf(10010000), "10,010,000"},
{"10,001,000", Commaf(10001000), "10,001,000"},
{"123,456,789", Commaf(123456789), "123,456,789"},
{"maxf64", Commaf(math.MaxFloat64), "179,769,313,486,231,570,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000"},
{"minf64", Commaf(math.SmallestNonzeroFloat64), "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005"},
{"-123,456,789", Commaf(-123456789), "-123,456,789"},
{"-10,100,000", Commaf(-10100000), "-10,100,000"},
{"-10,010,000", Commaf(-10010000), "-10,010,000"},
{"-10,001,000", Commaf(-10001000), "-10,001,000"},
{"-10,000,000", Commaf(-10000000), "-10,000,000"},
{"-100,000", Commaf(-100000), "-100,000"},
{"-10,000", Commaf(-10000), "-10,000"},
{"-1,000", Commaf(-1000), "-1,000"},
{"-100.11", Commaf(-100.11), "-100.11"},
{"-10", Commaf(-10), "-10"},
}.validate(t)
}
func BenchmarkCommas(b *testing.B) {
for i := 0; i < b.N; i++ {
Comma(1234567890)
}
}
func BenchmarkCommaf(b *testing.B) {
for i := 0; i < b.N; i++ {
Commaf(1234567890.83584)
}
}
func BenchmarkBigCommas(b *testing.B) {
for i := 0; i < b.N; i++ {
BigComma(big.NewInt(1234567890))
}
}
func bigComma(i int64) string {
return BigComma(big.NewInt(i))
}
func TestBigCommas(t *testing.T) {
testList{
{"0", bigComma(0), "0"},
{"10", bigComma(10), "10"},
{"100", bigComma(100), "100"},
{"1,000", bigComma(1000), "1,000"},
{"10,000", bigComma(10000), "10,000"},
{"100,000", bigComma(100000), "100,000"},
{"10,000,000", bigComma(10000000), "10,000,000"},
{"10,100,000", bigComma(10100000), "10,100,000"},
{"10,010,000", bigComma(10010000), "10,010,000"},
{"10,001,000", bigComma(10001000), "10,001,000"},
{"123,456,789", bigComma(123456789), "123,456,789"},
{"maxint", bigComma(9.223372e+18), "9,223,372,000,000,000,000"},
{"minint", bigComma(-9.223372e+18), "-9,223,372,000,000,000,000"},
{"-123,456,789", bigComma(-123456789), "-123,456,789"},
{"-10,100,000", bigComma(-10100000), "-10,100,000"},
{"-10,010,000", bigComma(-10010000), "-10,010,000"},
{"-10,001,000", bigComma(-10001000), "-10,001,000"},
{"-10,000,000", bigComma(-10000000), "-10,000,000"},
{"-100,000", bigComma(-100000), "-100,000"},
{"-10,000", bigComma(-10000), "-10,000"},
{"-1,000", bigComma(-1000), "-1,000"},
{"-100", bigComma(-100), "-100"},
{"-10", bigComma(-10), "-10"},
}.validate(t)
}
func TestVeryBigCommas(t *testing.T) {
tests := []struct{ in, exp string }{
{
"84889279597249724975972597249849757294578485",
"84,889,279,597,249,724,975,972,597,249,849,757,294,578,485",
},
{
"-84889279597249724975972597249849757294578485",
"-84,889,279,597,249,724,975,972,597,249,849,757,294,578,485",
},
}
for _, test := range tests {
n, _ := (&big.Int{}).SetString(test.in, 10)
got := BigComma(n)
if test.exp != got {
t.Errorf("Expected %q, got %q", test.exp, got)
}
}
}

View File

@ -1,44 +0,0 @@
// +build go1.6
package humanize
import (
"math"
"math/big"
"testing"
)
func BenchmarkBigCommaf(b *testing.B) {
for i := 0; i < b.N; i++ {
Commaf(1234567890.83584)
}
}
func TestBigCommafs(t *testing.T) {
testList{
{"0", BigCommaf(big.NewFloat(0)), "0"},
{"10.11", BigCommaf(big.NewFloat(10.11)), "10.11"},
{"100", BigCommaf(big.NewFloat(100)), "100"},
{"1,000", BigCommaf(big.NewFloat(1000)), "1,000"},
{"10,000", BigCommaf(big.NewFloat(10000)), "10,000"},
{"100,000", BigCommaf(big.NewFloat(100000)), "100,000"},
{"834,142.32", BigCommaf(big.NewFloat(834142.32)), "834,142.32"},
{"10,000,000", BigCommaf(big.NewFloat(10000000)), "10,000,000"},
{"10,100,000", BigCommaf(big.NewFloat(10100000)), "10,100,000"},
{"10,010,000", BigCommaf(big.NewFloat(10010000)), "10,010,000"},
{"10,001,000", BigCommaf(big.NewFloat(10001000)), "10,001,000"},
{"123,456,789", BigCommaf(big.NewFloat(123456789)), "123,456,789"},
{"maxf64", BigCommaf(big.NewFloat(math.MaxFloat64)), "179,769,313,486,231,570,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000"},
{"minf64", BigCommaf(big.NewFloat(math.SmallestNonzeroFloat64)), "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004940656458412465"},
{"-123,456,789", BigCommaf(big.NewFloat(-123456789)), "-123,456,789"},
{"-10,100,000", BigCommaf(big.NewFloat(-10100000)), "-10,100,000"},
{"-10,010,000", BigCommaf(big.NewFloat(-10010000)), "-10,010,000"},
{"-10,001,000", BigCommaf(big.NewFloat(-10001000)), "-10,001,000"},
{"-10,000,000", BigCommaf(big.NewFloat(-10000000)), "-10,000,000"},
{"-100,000", BigCommaf(big.NewFloat(-100000)), "-100,000"},
{"-10,000", BigCommaf(big.NewFloat(-10000)), "-10,000"},
{"-1,000", BigCommaf(big.NewFloat(-1000)), "-1,000"},
{"-100.11", BigCommaf(big.NewFloat(-100.11)), "-100.11"},
{"-10", BigCommaf(big.NewFloat(-10)), "-10"},
}.validate(t)
}

View File

@ -1,18 +0,0 @@
package humanize
import (
"testing"
)
type testList []struct {
name, got, exp string
}
func (tl testList) validate(t *testing.T) {
for _, test := range tl {
if test.got != test.exp {
t.Errorf("On %v, expected '%v', but got '%v'",
test.name, test.exp, test.got)
}
}
}

View File

@ -1,96 +0,0 @@
// Package english provides utilities to generate more user-friendly English output.
package english
import (
"fmt"
"strings"
)
// These are included because they are common technical terms.
var specialPlurals = map[string]string{
"index": "indices",
"matrix": "matrices",
"vertex": "vertices",
}
var sibilantEndings = []string{"s", "sh", "tch", "x"}
var isVowel = map[byte]bool{
'A': true, 'E': true, 'I': true, 'O': true, 'U': true,
'a': true, 'e': true, 'i': true, 'o': true, 'u': true,
}
// PluralWord builds the plural form of an English word.
// The simple English rules of regular pluralization will be used
// if the plural form is an empty string (i.e. not explicitly given).
// The special cases are not guaranteed to work for strings outside ASCII.
func PluralWord(quantity int, singular, plural string) string {
if quantity == 1 {
return singular
}
if plural != "" {
return plural
}
if plural = specialPlurals[singular]; plural != "" {
return plural
}
// We need to guess what the English plural might be. Keep this
// function simple! It doesn't need to know about every possiblity;
// only regular rules and the most common special cases.
//
// Reference: http://en.wikipedia.org/wiki/English_plural
for _, ending := range sibilantEndings {
if strings.HasSuffix(singular, ending) {
return singular + "es"
}
}
l := len(singular)
if l >= 2 && singular[l-1] == 'o' && !isVowel[singular[l-2]] {
return singular + "es"
}
if l >= 2 && singular[l-1] == 'y' && !isVowel[singular[l-2]] {
return singular[:l-1] + "ies"
}
return singular + "s"
}
// Plural formats an integer and a string into a single pluralized string.
// The simple English rules of regular pluralization will be used
// if the plural form is an empty string (i.e. not explicitly given).
func Plural(quantity int, singular, plural string) string {
return fmt.Sprintf("%d %s", quantity, PluralWord(quantity, singular, plural))
}
// WordSeries converts a list of words into a word series in English.
// It returns a string containing all the given words separated by commas,
// the coordinating conjunction, and a serial comma, as appropriate.
func WordSeries(words []string, conjunction string) string {
switch len(words) {
case 0:
return ""
case 1:
return words[0]
default:
return fmt.Sprintf("%s %s %s", strings.Join(words[:len(words)-1], ", "), conjunction, words[len(words)-1])
}
}
// OxfordWordSeries converts a list of words into a word series in English,
// using an Oxford comma (https://en.wikipedia.org/wiki/Serial_comma). It
// returns a string containing all the given words separated by commas, the
// coordinating conjunction, and a serial comma, as appropriate.
func OxfordWordSeries(words []string, conjunction string) string {
switch len(words) {
case 0:
return ""
case 1:
return words[0]
case 2:
return strings.Join(words, fmt.Sprintf(" %s ", conjunction))
default:
return fmt.Sprintf("%s, %s %s", strings.Join(words[:len(words)-1], ", "), conjunction, words[len(words)-1])
}
}

View File

@ -1,94 +0,0 @@
package english
import (
"testing"
)
func TestPluralWord(t *testing.T) {
tests := []struct {
n int
singular, plural string
want string
}{
{0, "object", "", "objects"},
{1, "object", "", "object"},
{-1, "object", "", "objects"},
{42, "object", "", "objects"},
{2, "vax", "vaxen", "vaxen"},
// special cases
{2, "index", "", "indices"},
// ending in a sibilant sound
{2, "bus", "", "buses"},
{2, "bush", "", "bushes"},
{2, "watch", "", "watches"},
{2, "box", "", "boxes"},
// ending with 'o' preceded by a consonant
{2, "hero", "", "heroes"},
// ending with 'y' preceded by a consonant
{2, "lady", "", "ladies"},
{2, "day", "", "days"},
}
for _, tt := range tests {
if got := PluralWord(tt.n, tt.singular, tt.plural); got != tt.want {
t.Errorf("PluralWord(%d, %q, %q)=%q; want: %q", tt.n, tt.singular, tt.plural, got, tt.want)
}
}
}
func TestPlural(t *testing.T) {
tests := []struct {
n int
singular, plural string
want string
}{
{1, "object", "", "1 object"},
{42, "object", "", "42 objects"},
}
for _, tt := range tests {
if got := Plural(tt.n, tt.singular, tt.plural); got != tt.want {
t.Errorf("Plural(%d, %q, %q)=%q; want: %q", tt.n, tt.singular, tt.plural, got, tt.want)
}
}
}
func TestWordSeries(t *testing.T) {
tests := []struct {
words []string
conjunction string
want string
}{
{[]string{}, "and", ""},
{[]string{"foo"}, "and", "foo"},
{[]string{"foo", "bar"}, "and", "foo and bar"},
{[]string{"foo", "bar", "baz"}, "and", "foo, bar and baz"},
{[]string{"foo", "bar", "baz"}, "or", "foo, bar or baz"},
}
for _, tt := range tests {
if got := WordSeries(tt.words, tt.conjunction); got != tt.want {
t.Errorf("WordSeries(%q, %q)=%q; want: %q", tt.words, tt.conjunction, got, tt.want)
}
}
}
func TestOxfordWordSeries(t *testing.T) {
tests := []struct {
words []string
conjunction string
want string
}{
{[]string{}, "and", ""},
{[]string{"foo"}, "and", "foo"},
{[]string{"foo", "bar"}, "and", "foo and bar"},
{[]string{"foo", "bar", "baz"}, "and", "foo, bar, and baz"},
{[]string{"foo", "bar", "baz"}, "or", "foo, bar, or baz"},
}
for _, tt := range tests {
if got := OxfordWordSeries(tt.words, tt.conjunction); got != tt.want {
t.Errorf("OxfordWordSeries(%q, %q)=%q; want: %q", tt.words, tt.conjunction, got, tt.want)
}
}
}

View File

@ -1,123 +0,0 @@
package humanize
import (
"fmt"
"math/rand"
"reflect"
"regexp"
"strconv"
"strings"
"testing"
"testing/quick"
)
func TestFtoa(t *testing.T) {
testList{
{"200", Ftoa(200), "200"},
{"2", Ftoa(2), "2"},
{"2.2", Ftoa(2.2), "2.2"},
{"2.02", Ftoa(2.02), "2.02"},
{"200.02", Ftoa(200.02), "200.02"},
}.validate(t)
}
func TestFtoaWithDigits(t *testing.T) {
testList{
{"1.23, 0", FtoaWithDigits(1.23, 0), "1"},
{"1.23, 1", FtoaWithDigits(1.23, 1), "1.2"},
{"1.23, 2", FtoaWithDigits(1.23, 2), "1.23"},
{"1.23, 3", FtoaWithDigits(1.23, 3), "1.23"},
}.validate(t)
}
func TestStripTrailingDigits(t *testing.T) {
err := quick.Check(func(s string, digits int) bool {
stripped := stripTrailingDigits(s, digits)
// A stripped string will always be a prefix of its original string
if !strings.HasPrefix(s, stripped) {
return false
}
if strings.ContainsRune(s, '.') {
// If there is a dot, the part on the left of the dot will never change
a := strings.Split(s, ".")
b := strings.Split(stripped, ".")
if a[0] != b[0] {
return false
}
} else {
// If there's no dot in the input, the output will always be the same as the input.
if stripped != s {
return false
}
}
return true
}, &quick.Config{
MaxCount: 10000,
Values: func(v []reflect.Value, r *rand.Rand) {
rdigs := func(n int) string {
digs := []rune{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
var rv []rune
for i := 0; i < n; i++ {
rv = append(rv, digs[r.Intn(len(digs))])
}
return string(rv)
}
ls := r.Intn(20)
rs := r.Intn(20)
jc := "."
if rs == 0 {
jc = ""
}
s := rdigs(ls) + jc + rdigs(rs)
digits := r.Intn(len(s) + 1)
v[0] = reflect.ValueOf(s)
v[1] = reflect.ValueOf(digits)
},
})
if err != nil {
t.Error(err)
}
}
func BenchmarkFtoaRegexTrailing(b *testing.B) {
trailingZerosRegex := regexp.MustCompile(`\.?0+$`)
b.ResetTimer()
for i := 0; i < b.N; i++ {
trailingZerosRegex.ReplaceAllString("2.00000", "")
trailingZerosRegex.ReplaceAllString("2.0000", "")
trailingZerosRegex.ReplaceAllString("2.000", "")
trailingZerosRegex.ReplaceAllString("2.00", "")
trailingZerosRegex.ReplaceAllString("2.0", "")
trailingZerosRegex.ReplaceAllString("2", "")
}
}
func BenchmarkFtoaFunc(b *testing.B) {
for i := 0; i < b.N; i++ {
stripTrailingZeros("2.00000")
stripTrailingZeros("2.0000")
stripTrailingZeros("2.000")
stripTrailingZeros("2.00")
stripTrailingZeros("2.0")
stripTrailingZeros("2")
}
}
func BenchmarkFmtF(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = fmt.Sprintf("%f", 2.03584)
}
}
func BenchmarkStrconvF(b *testing.B) {
for i := 0; i < b.N; i++ {
strconv.FormatFloat(2.03584, 'f', 6, 64)
}
}

View File

@ -1,79 +0,0 @@
package humanize
import (
"math"
"testing"
)
type TestStruct struct {
name string
format string
num float64
formatted string
}
func TestFormatFloat(t *testing.T) {
tests := []TestStruct{
{"default", "", 12345.6789, "12,345.68"},
{"#", "#", 12345.6789, "12345.678900000"},
{"#.", "#.", 12345.6789, "12346"},
{"#,#", "#,#", 12345.6789, "12345,7"},
{"#,##", "#,##", 12345.6789, "12345,68"},
{"#,###", "#,###", 12345.6789, "12345,679"},
{"#,###.", "#,###.", 12345.6789, "12,346"},
{"#,###.##", "#,###.##", 12345.6789, "12,345.68"},
{"#,###.###", "#,###.###", 12345.6789, "12,345.679"},
{"#,###.####", "#,###.####", 12345.6789, "12,345.6789"},
{"#.###,######", "#.###,######", 12345.6789, "12.345,678900"},
{"bug46", "#,###.##", 52746220055.92342, "52,746,220,055.92"},
{"#\u202f###,##", "#\u202f###,##", 12345.6789, "12345,68"},
// special cases
{"NaN", "#", math.NaN(), "NaN"},
{"+Inf", "#", math.Inf(1), "Infinity"},
{"-Inf", "#", math.Inf(-1), "-Infinity"},
{"signStr <= -0.000000001", "", -0.000000002, "-0.00"},
{"signStr = 0", "", 0, "0.00"},
{"Format directive must start with +", "+000", 12345.6789, "+12345.678900000"},
}
for _, test := range tests {
got := FormatFloat(test.format, test.num)
if got != test.formatted {
t.Errorf("On %v (%v, %v), got %v, wanted %v",
test.name, test.format, test.num, got, test.formatted)
}
}
// Test a single integer
got := FormatInteger("#", 12345)
if got != "12345.000000000" {
t.Errorf("On %v (%v, %v), got %v, wanted %v",
"integerTest", "#", 12345, got, "12345.000000000")
}
// Test the things that could panic
panictests := []TestStruct{
{"RenderFloat(): invalid positive sign directive", "-", 12345.6789, "12,345.68"},
{"RenderFloat(): thousands separator directive must be followed by 3 digit-specifiers", "0.01", 12345.6789, "12,345.68"},
}
for _, test := range panictests {
didPanic := false
var message interface{}
func() {
defer func() {
if message = recover(); message != nil {
didPanic = true
}
}()
// call the target function
_ = FormatFloat(test.format, test.num)
}()
if didPanic != true {
t.Errorf("On %v, should have panic and did not.",
test.name)
}
}
}

View File

@ -1,22 +0,0 @@
package humanize
import (
"testing"
)
func TestOrdinals(t *testing.T) {
testList{
{"0", Ordinal(0), "0th"},
{"1", Ordinal(1), "1st"},
{"2", Ordinal(2), "2nd"},
{"3", Ordinal(3), "3rd"},
{"4", Ordinal(4), "4th"},
{"10", Ordinal(10), "10th"},
{"11", Ordinal(11), "11th"},
{"12", Ordinal(12), "12th"},
{"13", Ordinal(13), "13th"},
{"101", Ordinal(101), "101st"},
{"102", Ordinal(102), "102nd"},
{"103", Ordinal(103), "103rd"},
}.validate(t)
}

View File

@ -1,124 +0,0 @@
package humanize
import (
"math"
"testing"
)
func TestSI(t *testing.T) {
tests := []struct {
name string
num float64
formatted string
}{
{"e-24", 1e-24, "1 yF"},
{"e-21", 1e-21, "1 zF"},
{"e-18", 1e-18, "1 aF"},
{"e-15", 1e-15, "1 fF"},
{"e-12", 1e-12, "1 pF"},
{"e-12", 2.2345e-12, "2.2345 pF"},
{"e-12", 2.23e-12, "2.23 pF"},
{"e-11", 2.23e-11, "22.3 pF"},
{"e-10", 2.2e-10, "220 pF"},
{"e-9", 2.2e-9, "2.2 nF"},
{"e-8", 2.2e-8, "22 nF"},
{"e-7", 2.2e-7, "220 nF"},
{"e-6", 2.2e-6, "2.2 µF"},
{"e-6", 1e-6, "1 µF"},
{"e-5", 2.2e-5, "22 µF"},
{"e-4", 2.2e-4, "220 µF"},
{"e-3", 2.2e-3, "2.2 mF"},
{"e-2", 2.2e-2, "22 mF"},
{"e-1", 2.2e-1, "220 mF"},
{"e+0", 2.2e-0, "2.2 F"},
{"e+0", 2.2, "2.2 F"},
{"e+1", 2.2e+1, "22 F"},
{"0", 0, "0 F"},
{"e+1", 22, "22 F"},
{"e+2", 2.2e+2, "220 F"},
{"e+2", 220, "220 F"},
{"e+3", 2.2e+3, "2.2 kF"},
{"e+3", 2200, "2.2 kF"},
{"e+4", 2.2e+4, "22 kF"},
{"e+4", 22000, "22 kF"},
{"e+5", 2.2e+5, "220 kF"},
{"e+6", 2.2e+6, "2.2 MF"},
{"e+6", 1e+6, "1 MF"},
{"e+7", 2.2e+7, "22 MF"},
{"e+8", 2.2e+8, "220 MF"},
{"e+9", 2.2e+9, "2.2 GF"},
{"e+10", 2.2e+10, "22 GF"},
{"e+11", 2.2e+11, "220 GF"},
{"e+12", 2.2e+12, "2.2 TF"},
{"e+15", 2.2e+15, "2.2 PF"},
{"e+18", 2.2e+18, "2.2 EF"},
{"e+21", 2.2e+21, "2.2 ZF"},
{"e+24", 2.2e+24, "2.2 YF"},
// special case
{"1F", 1000 * 1000, "1 MF"},
{"1F", 1e6, "1 MF"},
// negative number
{"-100 F", -100, "-100 F"},
}
for _, test := range tests {
got := SI(test.num, "F")
if got != test.formatted {
t.Errorf("On %v (%v), got %v, wanted %v",
test.name, test.num, got, test.formatted)
}
gotf, gotu, err := ParseSI(test.formatted)
if err != nil {
t.Errorf("Error parsing %v (%v): %v", test.name, test.formatted, err)
continue
}
if math.Abs(1-(gotf/test.num)) > 0.01 {
t.Errorf("On %v (%v), got %v, wanted %v (±%v)",
test.name, test.formatted, gotf, test.num,
math.Abs(1-(gotf/test.num)))
}
if gotu != "F" {
t.Errorf("On %v (%v), expected unit F, got %v",
test.name, test.formatted, gotu)
}
}
// Parse error
gotf, gotu, err := ParseSI("x1.21JW") // 1.21 jigga whats
if err == nil {
t.Errorf("Expected error on x1.21JW, got %v %v", gotf, gotu)
}
}
func TestSIWithDigits(t *testing.T) {
tests := []struct {
name string
num float64
digits int
formatted string
}{
{"e-12", 2.234e-12, 0, "2 pF"},
{"e-12", 2.234e-12, 1, "2.2 pF"},
{"e-12", 2.234e-12, 2, "2.23 pF"},
{"e-12", 2.234e-12, 3, "2.234 pF"},
{"e-12", 2.234e-12, 4, "2.234 pF"},
}
for _, test := range tests {
got := SIWithDigits(test.num, test.digits, "F")
if got != test.formatted {
t.Errorf("On %v (%v), got %v, wanted %v",
test.name, test.num, got, test.formatted)
}
}
}
func BenchmarkParseSI(b *testing.B) {
for i := 0; i < b.N; i++ {
ParseSI("2.2346ZB")
}
}

View File

@ -1,124 +0,0 @@
package humanize
import (
"math"
"testing"
"time"
)
func TestPast(t *testing.T) {
now := time.Now()
testList{
{"now", Time(now), "now"},
{"1 second ago", Time(now.Add(-1 * time.Second)), "1 second ago"},
{"12 seconds ago", Time(now.Add(-12 * time.Second)), "12 seconds ago"},
{"30 seconds ago", Time(now.Add(-30 * time.Second)), "30 seconds ago"},
{"45 seconds ago", Time(now.Add(-45 * time.Second)), "45 seconds ago"},
{"1 minute ago", Time(now.Add(-63 * time.Second)), "1 minute ago"},
{"15 minutes ago", Time(now.Add(-15 * time.Minute)), "15 minutes ago"},
{"1 hour ago", Time(now.Add(-63 * time.Minute)), "1 hour ago"},
{"2 hours ago", Time(now.Add(-2 * time.Hour)), "2 hours ago"},
{"21 hours ago", Time(now.Add(-21 * time.Hour)), "21 hours ago"},
{"1 day ago", Time(now.Add(-26 * time.Hour)), "1 day ago"},
{"2 days ago", Time(now.Add(-49 * time.Hour)), "2 days ago"},
{"3 days ago", Time(now.Add(-3 * Day)), "3 days ago"},
{"1 week ago (1)", Time(now.Add(-7 * Day)), "1 week ago"},
{"1 week ago (2)", Time(now.Add(-12 * Day)), "1 week ago"},
{"2 weeks ago", Time(now.Add(-15 * Day)), "2 weeks ago"},
{"1 month ago", Time(now.Add(-39 * Day)), "1 month ago"},
{"3 months ago", Time(now.Add(-99 * Day)), "3 months ago"},
{"1 year ago (1)", Time(now.Add(-365 * Day)), "1 year ago"},
{"1 year ago (1)", Time(now.Add(-400 * Day)), "1 year ago"},
{"2 years ago (1)", Time(now.Add(-548 * Day)), "2 years ago"},
{"2 years ago (2)", Time(now.Add(-725 * Day)), "2 years ago"},
{"2 years ago (3)", Time(now.Add(-800 * Day)), "2 years ago"},
{"3 years ago", Time(now.Add(-3 * Year)), "3 years ago"},
{"long ago", Time(now.Add(-LongTime)), "a long while ago"},
}.validate(t)
}
func TestReltimeOffbyone(t *testing.T) {
testList{
{"1w-1", RelTime(time.Unix(0, 0), time.Unix(7*24*60*60, -1), "ago", ""), "6 days ago"},
{"1w±0", RelTime(time.Unix(0, 0), time.Unix(7*24*60*60, 0), "ago", ""), "1 week ago"},
{"1w+1", RelTime(time.Unix(0, 0), time.Unix(7*24*60*60, 1), "ago", ""), "1 week ago"},
{"2w-1", RelTime(time.Unix(0, 0), time.Unix(14*24*60*60, -1), "ago", ""), "1 week ago"},
{"2w±0", RelTime(time.Unix(0, 0), time.Unix(14*24*60*60, 0), "ago", ""), "2 weeks ago"},
{"2w+1", RelTime(time.Unix(0, 0), time.Unix(14*24*60*60, 1), "ago", ""), "2 weeks ago"},
}.validate(t)
}
func TestFuture(t *testing.T) {
// Add a little time so that these things properly line up in
// the future.
now := time.Now().Add(time.Millisecond * 250)
testList{
{"now", Time(now), "now"},
{"1 second from now", Time(now.Add(+1 * time.Second)), "1 second from now"},
{"12 seconds from now", Time(now.Add(+12 * time.Second)), "12 seconds from now"},
{"30 seconds from now", Time(now.Add(+30 * time.Second)), "30 seconds from now"},
{"45 seconds from now", Time(now.Add(+45 * time.Second)), "45 seconds from now"},
{"15 minutes from now", Time(now.Add(+15 * time.Minute)), "15 minutes from now"},
{"2 hours from now", Time(now.Add(+2 * time.Hour)), "2 hours from now"},
{"21 hours from now", Time(now.Add(+21 * time.Hour)), "21 hours from now"},
{"1 day from now", Time(now.Add(+26 * time.Hour)), "1 day from now"},
{"2 days from now", Time(now.Add(+49 * time.Hour)), "2 days from now"},
{"3 days from now", Time(now.Add(+3 * Day)), "3 days from now"},
{"1 week from now (1)", Time(now.Add(+7 * Day)), "1 week from now"},
{"1 week from now (2)", Time(now.Add(+12 * Day)), "1 week from now"},
{"2 weeks from now", Time(now.Add(+15 * Day)), "2 weeks from now"},
{"1 month from now", Time(now.Add(+30 * Day)), "1 month from now"},
{"1 year from now", Time(now.Add(+365 * Day)), "1 year from now"},
{"2 years from now", Time(now.Add(+2 * Year)), "2 years from now"},
{"a while from now", Time(now.Add(+LongTime)), "a long while from now"},
}.validate(t)
}
func TestRange(t *testing.T) {
start := time.Time{}
end := time.Unix(math.MaxInt64, math.MaxInt64)
x := RelTime(start, end, "ago", "from now")
if x != "a long while from now" {
t.Errorf("Expected a long while from now, got %q", x)
}
}
func TestCustomRelTime(t *testing.T) {
now := time.Now().Add(time.Millisecond * 250)
magnitudes := []RelTimeMagnitude{
{time.Second, "now", time.Second},
{2 * time.Second, "1 second %s", 1},
{time.Minute, "%d seconds %s", time.Second},
{Day - time.Second, "%d minutes %s", time.Minute},
{Day, "%d hours %s", time.Hour},
{2 * Day, "1 day %s", 1},
{Week, "%d days %s", Day},
{2 * Week, "1 week %s", 1},
{6 * Month, "%d weeks %s", Week},
{Year, "%d months %s", Month},
}
customRelTime := func(then time.Time) string {
return CustomRelTime(then, time.Now(), "ago", "from now", magnitudes)
}
testList{
{"now", customRelTime(now), "now"},
{"1 second from now", customRelTime(now.Add(+1 * time.Second)), "1 second from now"},
{"12 seconds from now", customRelTime(now.Add(+12 * time.Second)), "12 seconds from now"},
{"30 seconds from now", customRelTime(now.Add(+30 * time.Second)), "30 seconds from now"},
{"45 seconds from now", customRelTime(now.Add(+45 * time.Second)), "45 seconds from now"},
{"15 minutes from now", customRelTime(now.Add(+15 * time.Minute)), "15 minutes from now"},
{"2 hours from now", customRelTime(now.Add(+2 * time.Hour)), "120 minutes from now"},
{"21 hours from now", customRelTime(now.Add(+21 * time.Hour)), "1260 minutes from now"},
{"1 day from now", customRelTime(now.Add(+26 * time.Hour)), "1 day from now"},
{"2 days from now", customRelTime(now.Add(+49 * time.Hour)), "2 days from now"},
{"3 days from now", customRelTime(now.Add(+3 * Day)), "3 days from now"},
{"1 week from now (1)", customRelTime(now.Add(+7 * Day)), "1 week from now"},
{"1 week from now (2)", customRelTime(now.Add(+12 * Day)), "1 week from now"},
{"2 weeks from now", customRelTime(now.Add(+15 * Day)), "2 weeks from now"},
{"1 month from now", customRelTime(now.Add(+30 * Day)), "4 weeks from now"},
{"6 months from now", customRelTime(now.Add(+6*Month - time.Second)), "25 weeks from now"},
{"1 year from now", customRelTime(now.Add(+365 * Day)), "12 months from now"},
{"2 years from now", customRelTime(now.Add(+2 * Year)), "24 months from now"},
{"a while from now", customRelTime(now.Add(+LongTime)), "444 months from now"},
}.validate(t)
}

View File

@ -1,342 +0,0 @@
package color
import (
"bytes"
"fmt"
"os"
"testing"
"github.com/mattn/go-colorable"
)
// Testing colors is kinda different. First we test for given colors and their
// escaped formatted results. Next we create some visual tests to be tested.
// Each visual test includes the color name to be compared.
func TestColor(t *testing.T) {
rb := new(bytes.Buffer)
Output = rb
NoColor = false
testColors := []struct {
text string
code Attribute
}{
{text: "black", code: FgBlack},
{text: "red", code: FgRed},
{text: "green", code: FgGreen},
{text: "yellow", code: FgYellow},
{text: "blue", code: FgBlue},
{text: "magent", code: FgMagenta},
{text: "cyan", code: FgCyan},
{text: "white", code: FgWhite},
{text: "hblack", code: FgHiBlack},
{text: "hred", code: FgHiRed},
{text: "hgreen", code: FgHiGreen},
{text: "hyellow", code: FgHiYellow},
{text: "hblue", code: FgHiBlue},
{text: "hmagent", code: FgHiMagenta},
{text: "hcyan", code: FgHiCyan},
{text: "hwhite", code: FgHiWhite},
}
for _, c := range testColors {
New(c.code).Print(c.text)
line, _ := rb.ReadString('\n')
scannedLine := fmt.Sprintf("%q", line)
colored := fmt.Sprintf("\x1b[%dm%s\x1b[0m", c.code, c.text)
escapedForm := fmt.Sprintf("%q", colored)
fmt.Printf("%s\t: %s\n", c.text, line)
if scannedLine != escapedForm {
t.Errorf("Expecting %s, got '%s'\n", escapedForm, scannedLine)
}
}
for _, c := range testColors {
line := New(c.code).Sprintf("%s", c.text)
scannedLine := fmt.Sprintf("%q", line)
colored := fmt.Sprintf("\x1b[%dm%s\x1b[0m", c.code, c.text)
escapedForm := fmt.Sprintf("%q", colored)
fmt.Printf("%s\t: %s\n", c.text, line)
if scannedLine != escapedForm {
t.Errorf("Expecting %s, got '%s'\n", escapedForm, scannedLine)
}
}
}
func TestColorEquals(t *testing.T) {
fgblack1 := New(FgBlack)
fgblack2 := New(FgBlack)
bgblack := New(BgBlack)
fgbgblack := New(FgBlack, BgBlack)
fgblackbgred := New(FgBlack, BgRed)
fgred := New(FgRed)
bgred := New(BgRed)
if !fgblack1.Equals(fgblack2) {
t.Error("Two black colors are not equal")
}
if fgblack1.Equals(bgblack) {
t.Error("Fg and bg black colors are equal")
}
if fgblack1.Equals(fgbgblack) {
t.Error("Fg black equals fg/bg black color")
}
if fgblack1.Equals(fgred) {
t.Error("Fg black equals Fg red")
}
if fgblack1.Equals(bgred) {
t.Error("Fg black equals Bg red")
}
if fgblack1.Equals(fgblackbgred) {
t.Error("Fg black equals fg black bg red")
}
}
func TestNoColor(t *testing.T) {
rb := new(bytes.Buffer)
Output = rb
testColors := []struct {
text string
code Attribute
}{
{text: "black", code: FgBlack},
{text: "red", code: FgRed},
{text: "green", code: FgGreen},
{text: "yellow", code: FgYellow},
{text: "blue", code: FgBlue},
{text: "magent", code: FgMagenta},
{text: "cyan", code: FgCyan},
{text: "white", code: FgWhite},
{text: "hblack", code: FgHiBlack},
{text: "hred", code: FgHiRed},
{text: "hgreen", code: FgHiGreen},
{text: "hyellow", code: FgHiYellow},
{text: "hblue", code: FgHiBlue},
{text: "hmagent", code: FgHiMagenta},
{text: "hcyan", code: FgHiCyan},
{text: "hwhite", code: FgHiWhite},
}
for _, c := range testColors {
p := New(c.code)
p.DisableColor()
p.Print(c.text)
line, _ := rb.ReadString('\n')
if line != c.text {
t.Errorf("Expecting %s, got '%s'\n", c.text, line)
}
}
// global check
NoColor = true
defer func() {
NoColor = false
}()
for _, c := range testColors {
p := New(c.code)
p.Print(c.text)
line, _ := rb.ReadString('\n')
if line != c.text {
t.Errorf("Expecting %s, got '%s'\n", c.text, line)
}
}
}
func TestColorVisual(t *testing.T) {
// First Visual Test
Output = colorable.NewColorableStdout()
New(FgRed).Printf("red\t")
New(BgRed).Print(" ")
New(FgRed, Bold).Println(" red")
New(FgGreen).Printf("green\t")
New(BgGreen).Print(" ")
New(FgGreen, Bold).Println(" green")
New(FgYellow).Printf("yellow\t")
New(BgYellow).Print(" ")
New(FgYellow, Bold).Println(" yellow")
New(FgBlue).Printf("blue\t")
New(BgBlue).Print(" ")
New(FgBlue, Bold).Println(" blue")
New(FgMagenta).Printf("magenta\t")
New(BgMagenta).Print(" ")
New(FgMagenta, Bold).Println(" magenta")
New(FgCyan).Printf("cyan\t")
New(BgCyan).Print(" ")
New(FgCyan, Bold).Println(" cyan")
New(FgWhite).Printf("white\t")
New(BgWhite).Print(" ")
New(FgWhite, Bold).Println(" white")
fmt.Println("")
// Second Visual test
Black("black")
Red("red")
Green("green")
Yellow("yellow")
Blue("blue")
Magenta("magenta")
Cyan("cyan")
White("white")
HiBlack("hblack")
HiRed("hred")
HiGreen("hgreen")
HiYellow("hyellow")
HiBlue("hblue")
HiMagenta("hmagenta")
HiCyan("hcyan")
HiWhite("hwhite")
// Third visual test
fmt.Println()
Set(FgBlue)
fmt.Println("is this blue?")
Unset()
Set(FgMagenta)
fmt.Println("and this magenta?")
Unset()
// Fourth Visual test
fmt.Println()
blue := New(FgBlue).PrintlnFunc()
blue("blue text with custom print func")
red := New(FgRed).PrintfFunc()
red("red text with a printf func: %d\n", 123)
put := New(FgYellow).SprintFunc()
warn := New(FgRed).SprintFunc()
fmt.Fprintf(Output, "this is a %s and this is %s.\n", put("warning"), warn("error"))
info := New(FgWhite, BgGreen).SprintFunc()
fmt.Fprintf(Output, "this %s rocks!\n", info("package"))
notice := New(FgBlue).FprintFunc()
notice(os.Stderr, "just a blue notice to stderr")
// Fifth Visual Test
fmt.Println()
fmt.Fprintln(Output, BlackString("black"))
fmt.Fprintln(Output, RedString("red"))
fmt.Fprintln(Output, GreenString("green"))
fmt.Fprintln(Output, YellowString("yellow"))
fmt.Fprintln(Output, BlueString("blue"))
fmt.Fprintln(Output, MagentaString("magenta"))
fmt.Fprintln(Output, CyanString("cyan"))
fmt.Fprintln(Output, WhiteString("white"))
fmt.Fprintln(Output, HiBlackString("hblack"))
fmt.Fprintln(Output, HiRedString("hred"))
fmt.Fprintln(Output, HiGreenString("hgreen"))
fmt.Fprintln(Output, HiYellowString("hyellow"))
fmt.Fprintln(Output, HiBlueString("hblue"))
fmt.Fprintln(Output, HiMagentaString("hmagenta"))
fmt.Fprintln(Output, HiCyanString("hcyan"))
fmt.Fprintln(Output, HiWhiteString("hwhite"))
}
func TestNoFormat(t *testing.T) {
fmt.Printf("%s %%s = ", BlackString("Black"))
Black("%s")
fmt.Printf("%s %%s = ", RedString("Red"))
Red("%s")
fmt.Printf("%s %%s = ", GreenString("Green"))
Green("%s")
fmt.Printf("%s %%s = ", YellowString("Yellow"))
Yellow("%s")
fmt.Printf("%s %%s = ", BlueString("Blue"))
Blue("%s")
fmt.Printf("%s %%s = ", MagentaString("Magenta"))
Magenta("%s")
fmt.Printf("%s %%s = ", CyanString("Cyan"))
Cyan("%s")
fmt.Printf("%s %%s = ", WhiteString("White"))
White("%s")
fmt.Printf("%s %%s = ", HiBlackString("HiBlack"))
HiBlack("%s")
fmt.Printf("%s %%s = ", HiRedString("HiRed"))
HiRed("%s")
fmt.Printf("%s %%s = ", HiGreenString("HiGreen"))
HiGreen("%s")
fmt.Printf("%s %%s = ", HiYellowString("HiYellow"))
HiYellow("%s")
fmt.Printf("%s %%s = ", HiBlueString("HiBlue"))
HiBlue("%s")
fmt.Printf("%s %%s = ", HiMagentaString("HiMagenta"))
HiMagenta("%s")
fmt.Printf("%s %%s = ", HiCyanString("HiCyan"))
HiCyan("%s")
fmt.Printf("%s %%s = ", HiWhiteString("HiWhite"))
HiWhite("%s")
}
func TestNoFormatString(t *testing.T) {
tests := []struct {
f func(string, ...interface{}) string
format string
args []interface{}
want string
}{
{BlackString, "%s", nil, "\x1b[30m%s\x1b[0m"},
{RedString, "%s", nil, "\x1b[31m%s\x1b[0m"},
{GreenString, "%s", nil, "\x1b[32m%s\x1b[0m"},
{YellowString, "%s", nil, "\x1b[33m%s\x1b[0m"},
{BlueString, "%s", nil, "\x1b[34m%s\x1b[0m"},
{MagentaString, "%s", nil, "\x1b[35m%s\x1b[0m"},
{CyanString, "%s", nil, "\x1b[36m%s\x1b[0m"},
{WhiteString, "%s", nil, "\x1b[37m%s\x1b[0m"},
{HiBlackString, "%s", nil, "\x1b[90m%s\x1b[0m"},
{HiRedString, "%s", nil, "\x1b[91m%s\x1b[0m"},
{HiGreenString, "%s", nil, "\x1b[92m%s\x1b[0m"},
{HiYellowString, "%s", nil, "\x1b[93m%s\x1b[0m"},
{HiBlueString, "%s", nil, "\x1b[94m%s\x1b[0m"},
{HiMagentaString, "%s", nil, "\x1b[95m%s\x1b[0m"},
{HiCyanString, "%s", nil, "\x1b[96m%s\x1b[0m"},
{HiWhiteString, "%s", nil, "\x1b[97m%s\x1b[0m"},
}
for i, test := range tests {
s := fmt.Sprintf("%s", test.f(test.format, test.args...))
if s != test.want {
t.Errorf("[%d] want: %q, got: %q", i, test.want, s)
}
}
}

View File

@ -1,397 +0,0 @@
package structs
import (
"reflect"
"testing"
)
// A test struct that defines all cases
type Foo struct {
A string
B int `structs:"y"`
C bool `json:"c"`
d string // not exported
E *Baz
x string `xml:"x"` // not exported, with tag
Y []string
Z map[string]interface{}
*Bar // embedded
}
type Baz struct {
A string
B int
}
type Bar struct {
E string
F int
g []string
}
func newStruct() *Struct {
b := &Bar{
E: "example",
F: 2,
g: []string{"zeynep", "fatih"},
}
// B and x is not initialized for testing
f := &Foo{
A: "gopher",
C: true,
d: "small",
E: nil,
Y: []string{"example"},
Z: nil,
}
f.Bar = b
return New(f)
}
func TestField_Set(t *testing.T) {
s := newStruct()
f := s.Field("A")
err := f.Set("fatih")
if err != nil {
t.Error(err)
}
if f.Value().(string) != "fatih" {
t.Errorf("Setted value is wrong: %s want: %s", f.Value().(string), "fatih")
}
f = s.Field("Y")
err = f.Set([]string{"override", "with", "this"})
if err != nil {
t.Error(err)
}
sliceLen := len(f.Value().([]string))
if sliceLen != 3 {
t.Errorf("Setted values slice length is wrong: %d, want: %d", sliceLen, 3)
}
f = s.Field("C")
err = f.Set(false)
if err != nil {
t.Error(err)
}
if f.Value().(bool) {
t.Errorf("Setted value is wrong: %t want: %t", f.Value().(bool), false)
}
// let's pass a different type
f = s.Field("A")
err = f.Set(123) // Field A is of type string, but we are going to pass an integer
if err == nil {
t.Error("Setting a field's value with a different type than the field's type should return an error")
}
// old value should be still there :)
if f.Value().(string) != "fatih" {
t.Errorf("Setted value is wrong: %s want: %s", f.Value().(string), "fatih")
}
// let's access an unexported field, which should give an error
f = s.Field("d")
err = f.Set("large")
if err != errNotExported {
t.Error(err)
}
// let's set a pointer to struct
b := &Bar{
E: "gopher",
F: 2,
}
f = s.Field("Bar")
err = f.Set(b)
if err != nil {
t.Error(err)
}
baz := &Baz{
A: "helloWorld",
B: 42,
}
f = s.Field("E")
err = f.Set(baz)
if err != nil {
t.Error(err)
}
ba := s.Field("E").Value().(*Baz)
if ba.A != "helloWorld" {
t.Errorf("could not set baz. Got: %s Want: helloWorld", ba.A)
}
}
func TestField_NotSettable(t *testing.T) {
a := map[int]Baz{
4: Baz{
A: "value",
},
}
s := New(a[4])
if err := s.Field("A").Set("newValue"); err != errNotSettable {
t.Errorf("Trying to set non-settable field should error with %q. Got %q instead.", errNotSettable, err)
}
}
func TestField_Zero(t *testing.T) {
s := newStruct()
f := s.Field("A")
err := f.Zero()
if err != nil {
t.Error(err)
}
if f.Value().(string) != "" {
t.Errorf("Zeroed value is wrong: %s want: %s", f.Value().(string), "")
}
f = s.Field("Y")
err = f.Zero()
if err != nil {
t.Error(err)
}
sliceLen := len(f.Value().([]string))
if sliceLen != 0 {
t.Errorf("Zeroed values slice length is wrong: %d, want: %d", sliceLen, 0)
}
f = s.Field("C")
err = f.Zero()
if err != nil {
t.Error(err)
}
if f.Value().(bool) {
t.Errorf("Zeroed value is wrong: %t want: %t", f.Value().(bool), false)
}
// let's access an unexported field, which should give an error
f = s.Field("d")
err = f.Zero()
if err != errNotExported {
t.Error(err)
}
f = s.Field("Bar")
err = f.Zero()
if err != nil {
t.Error(err)
}
f = s.Field("E")
err = f.Zero()
if err != nil {
t.Error(err)
}
v := s.Field("E").value
if !v.IsNil() {
t.Errorf("could not set baz. Got: %s Want: <nil>", v.Interface())
}
}
func TestField(t *testing.T) {
s := newStruct()
defer func() {
err := recover()
if err == nil {
t.Error("Retrieveing a non existing field from the struct should panic")
}
}()
_ = s.Field("no-field")
}
func TestField_Kind(t *testing.T) {
s := newStruct()
f := s.Field("A")
if f.Kind() != reflect.String {
t.Errorf("Field A has wrong kind: %s want: %s", f.Kind(), reflect.String)
}
f = s.Field("B")
if f.Kind() != reflect.Int {
t.Errorf("Field B has wrong kind: %s want: %s", f.Kind(), reflect.Int)
}
// unexported
f = s.Field("d")
if f.Kind() != reflect.String {
t.Errorf("Field d has wrong kind: %s want: %s", f.Kind(), reflect.String)
}
}
func TestField_Tag(t *testing.T) {
s := newStruct()
v := s.Field("B").Tag("json")
if v != "" {
t.Errorf("Field's tag value of a non existing tag should return empty, got: %s", v)
}
v = s.Field("C").Tag("json")
if v != "c" {
t.Errorf("Field's tag value of the existing field C should return 'c', got: %s", v)
}
v = s.Field("d").Tag("json")
if v != "" {
t.Errorf("Field's tag value of a non exported field should return empty, got: %s", v)
}
v = s.Field("x").Tag("xml")
if v != "x" {
t.Errorf("Field's tag value of a non exported field with a tag should return 'x', got: %s", v)
}
v = s.Field("A").Tag("json")
if v != "" {
t.Errorf("Field's tag value of a existing field without a tag should return empty, got: %s", v)
}
}
func TestField_Value(t *testing.T) {
s := newStruct()
v := s.Field("A").Value()
val, ok := v.(string)
if !ok {
t.Errorf("Field's value of a A should be string")
}
if val != "gopher" {
t.Errorf("Field's value of a existing tag should return 'gopher', got: %s", val)
}
defer func() {
err := recover()
if err == nil {
t.Error("Value of a non exported field from the field should panic")
}
}()
// should panic
_ = s.Field("d").Value()
}
func TestField_IsEmbedded(t *testing.T) {
s := newStruct()
if !s.Field("Bar").IsEmbedded() {
t.Errorf("Fields 'Bar' field is an embedded field")
}
if s.Field("d").IsEmbedded() {
t.Errorf("Fields 'd' field is not an embedded field")
}
}
func TestField_IsExported(t *testing.T) {
s := newStruct()
if !s.Field("Bar").IsExported() {
t.Errorf("Fields 'Bar' field is an exported field")
}
if !s.Field("A").IsExported() {
t.Errorf("Fields 'A' field is an exported field")
}
if s.Field("d").IsExported() {
t.Errorf("Fields 'd' field is not an exported field")
}
}
func TestField_IsZero(t *testing.T) {
s := newStruct()
if s.Field("A").IsZero() {
t.Errorf("Fields 'A' field is an initialized field")
}
if !s.Field("B").IsZero() {
t.Errorf("Fields 'B' field is not an initialized field")
}
}
func TestField_Name(t *testing.T) {
s := newStruct()
if s.Field("A").Name() != "A" {
t.Errorf("Fields 'A' field should have the name 'A'")
}
}
func TestField_Field(t *testing.T) {
s := newStruct()
e := s.Field("Bar").Field("E")
val, ok := e.Value().(string)
if !ok {
t.Error("The value of the field 'e' inside 'Bar' struct should be string")
}
if val != "example" {
t.Errorf("The value of 'e' should be 'example, got: %s", val)
}
defer func() {
err := recover()
if err == nil {
t.Error("Field of a non existing nested struct should panic")
}
}()
_ = s.Field("Bar").Field("e")
}
func TestField_Fields(t *testing.T) {
s := newStruct()
fields := s.Field("Bar").Fields()
if len(fields) != 3 {
t.Errorf("We expect 3 fields in embedded struct, was: %d", len(fields))
}
}
func TestField_FieldOk(t *testing.T) {
s := newStruct()
b, ok := s.FieldOk("Bar")
if !ok {
t.Error("The field 'Bar' should exists.")
}
e, ok := b.FieldOk("E")
if !ok {
t.Error("The field 'E' should exists.")
}
val, ok := e.Value().(string)
if !ok {
t.Error("The value of the field 'e' inside 'Bar' struct should be string")
}
if val != "example" {
t.Errorf("The value of 'e' should be 'example, got: %s", val)
}
}

View File

@ -1,351 +0,0 @@
package structs
import (
"fmt"
"time"
)
func ExampleNew() {
type Server struct {
Name string
ID int32
Enabled bool
}
server := &Server{
Name: "Arslan",
ID: 123456,
Enabled: true,
}
s := New(server)
fmt.Printf("Name : %v\n", s.Name())
fmt.Printf("Values : %v\n", s.Values())
fmt.Printf("Value of ID : %v\n", s.Field("ID").Value())
// Output:
// Name : Server
// Values : [Arslan 123456 true]
// Value of ID : 123456
}
func ExampleMap() {
type Server struct {
Name string
ID int32
Enabled bool
}
s := &Server{
Name: "Arslan",
ID: 123456,
Enabled: true,
}
m := Map(s)
fmt.Printf("%#v\n", m["Name"])
fmt.Printf("%#v\n", m["ID"])
fmt.Printf("%#v\n", m["Enabled"])
// Output:
// "Arslan"
// 123456
// true
}
func ExampleMap_tags() {
// Custom tags can change the map keys instead of using the fields name
type Server struct {
Name string `structs:"server_name"`
ID int32 `structs:"server_id"`
Enabled bool `structs:"enabled"`
}
s := &Server{
Name: "Zeynep",
ID: 789012,
}
m := Map(s)
// access them by the custom tags defined above
fmt.Printf("%#v\n", m["server_name"])
fmt.Printf("%#v\n", m["server_id"])
fmt.Printf("%#v\n", m["enabled"])
// Output:
// "Zeynep"
// 789012
// false
}
func ExampleMap_omitNested() {
// By default field with struct types are processed too. We can stop
// processing them via "omitnested" tag option.
type Server struct {
Name string `structs:"server_name"`
ID int32 `structs:"server_id"`
Time time.Time `structs:"time,omitnested"` // do not convert to map[string]interface{}
}
const shortForm = "2006-Jan-02"
t, _ := time.Parse("2006-Jan-02", "2013-Feb-03")
s := &Server{
Name: "Zeynep",
ID: 789012,
Time: t,
}
m := Map(s)
// access them by the custom tags defined above
fmt.Printf("%v\n", m["server_name"])
fmt.Printf("%v\n", m["server_id"])
fmt.Printf("%v\n", m["time"].(time.Time))
// Output:
// Zeynep
// 789012
// 2013-02-03 00:00:00 +0000 UTC
}
func ExampleMap_omitEmpty() {
// By default field with struct types of zero values are processed too. We
// can stop processing them via "omitempty" tag option.
type Server struct {
Name string `structs:",omitempty"`
ID int32 `structs:"server_id,omitempty"`
Location string
}
// Only add location
s := &Server{
Location: "Tokyo",
}
m := Map(s)
// map contains only the Location field
fmt.Printf("%v\n", m)
// Output:
// map[Location:Tokyo]
}
func ExampleValues() {
type Server struct {
Name string
ID int32
Enabled bool
}
s := &Server{
Name: "Fatih",
ID: 135790,
Enabled: false,
}
m := Values(s)
fmt.Printf("Values: %+v\n", m)
// Output:
// Values: [Fatih 135790 false]
}
func ExampleValues_omitEmpty() {
// By default field with struct types of zero values are processed too. We
// can stop processing them via "omitempty" tag option.
type Server struct {
Name string `structs:",omitempty"`
ID int32 `structs:"server_id,omitempty"`
Location string
}
// Only add location
s := &Server{
Location: "Ankara",
}
m := Values(s)
// values contains only the Location field
fmt.Printf("Values: %+v\n", m)
// Output:
// Values: [Ankara]
}
func ExampleValues_tags() {
type Location struct {
City string
Country string
}
type Server struct {
Name string
ID int32
Enabled bool
Location Location `structs:"-"` // values from location are not included anymore
}
s := &Server{
Name: "Fatih",
ID: 135790,
Enabled: false,
Location: Location{City: "Ankara", Country: "Turkey"},
}
// Let get all values from the struct s. Note that we don't include values
// from the Location field
m := Values(s)
fmt.Printf("Values: %+v\n", m)
// Output:
// Values: [Fatih 135790 false]
}
func ExampleFields() {
type Access struct {
Name string
LastAccessed time.Time
Number int
}
s := &Access{
Name: "Fatih",
LastAccessed: time.Now(),
Number: 1234567,
}
fields := Fields(s)
for i, field := range fields {
fmt.Printf("[%d] %+v\n", i, field.Name())
}
// Output:
// [0] Name
// [1] LastAccessed
// [2] Number
}
func ExampleFields_nested() {
type Person struct {
Name string
Number int
}
type Access struct {
Person Person
HasPermission bool
LastAccessed time.Time
}
s := &Access{
Person: Person{Name: "fatih", Number: 1234567},
LastAccessed: time.Now(),
HasPermission: true,
}
// Let's get all fields from the struct s.
fields := Fields(s)
for _, field := range fields {
if field.Name() == "Person" {
fmt.Printf("Access.Person.Name: %+v\n", field.Field("Name").Value())
}
}
// Output:
// Access.Person.Name: fatih
}
func ExampleField() {
type Person struct {
Name string
Number int
}
type Access struct {
Person Person
HasPermission bool
LastAccessed time.Time
}
access := &Access{
Person: Person{Name: "fatih", Number: 1234567},
LastAccessed: time.Now(),
HasPermission: true,
}
// Create a new Struct type
s := New(access)
// Get the Field type for "Person" field
p := s.Field("Person")
// Get the underlying "Name field" and print the value of it
name := p.Field("Name")
fmt.Printf("Value of Person.Access.Name: %+v\n", name.Value())
// Output:
// Value of Person.Access.Name: fatih
}
func ExampleIsZero() {
type Server struct {
Name string
ID int32
Enabled bool
}
// Nothing is initalized
a := &Server{}
isZeroA := IsZero(a)
// Name and Enabled is initialized, but not ID
b := &Server{
Name: "Golang",
Enabled: true,
}
isZeroB := IsZero(b)
fmt.Printf("%#v\n", isZeroA)
fmt.Printf("%#v\n", isZeroB)
// Output:
// true
// false
}
func ExampleHasZero() {
// Let's define an Access struct. Note that the "Enabled" field is not
// going to be checked because we added the "structs" tag to the field.
type Access struct {
Name string
LastAccessed time.Time
Number int
Enabled bool `structs:"-"`
}
// Name and Number is not initialized.
a := &Access{
LastAccessed: time.Now(),
}
hasZeroA := HasZero(a)
// Name and Number is initialized.
b := &Access{
Name: "Fatih",
LastAccessed: time.Now(),
Number: 12345,
}
hasZeroB := HasZero(b)
fmt.Printf("%#v\n", hasZeroA)
fmt.Printf("%#v\n", hasZeroB)
// Output:
// true
// false
}

File diff suppressed because it is too large Load Diff

View File

@ -1,46 +0,0 @@
package structs
import "testing"
func TestParseTag_Name(t *testing.T) {
tags := []struct {
tag string
has bool
}{
{"", false},
{"name", true},
{"name,opt", true},
{"name , opt, opt2", false}, // has a single whitespace
{", opt, opt2", false},
}
for _, tag := range tags {
name, _ := parseTag(tag.tag)
if (name != "name") && tag.has {
t.Errorf("Parse tag should return name: %#v", tag)
}
}
}
func TestParseTag_Opts(t *testing.T) {
tags := []struct {
opts string
has bool
}{
{"name", false},
{"name,opt", true},
{"name , opt, opt2", false}, // has a single whitespace
{",opt, opt2", true},
{", opt3, opt4", false},
}
// search for "opt"
for _, tag := range tags {
_, opts := parseTag(tag.opts)
if opts.Has("opt") != tag.has {
t.Errorf("Tag opts should have opt: %#v", tag)
}
}
}

View File

@ -1,94 +0,0 @@
package errwrap
import (
"fmt"
"testing"
)
func TestWrappedError_impl(t *testing.T) {
var _ error = new(wrappedError)
}
func TestGetAll(t *testing.T) {
cases := []struct {
Err error
Msg string
Len int
}{
{},
{
fmt.Errorf("foo"),
"foo",
1,
},
{
fmt.Errorf("bar"),
"foo",
0,
},
{
Wrapf("bar", fmt.Errorf("foo")),
"foo",
1,
},
{
Wrapf("{{err}}", fmt.Errorf("foo")),
"foo",
2,
},
{
Wrapf("bar", Wrapf("baz", fmt.Errorf("foo"))),
"foo",
1,
},
}
for i, tc := range cases {
actual := GetAll(tc.Err, tc.Msg)
if len(actual) != tc.Len {
t.Fatalf("%d: bad: %#v", i, actual)
}
for _, v := range actual {
if v.Error() != tc.Msg {
t.Fatalf("%d: bad: %#v", i, actual)
}
}
}
}
func TestGetAllType(t *testing.T) {
cases := []struct {
Err error
Type interface{}
Len int
}{
{},
{
fmt.Errorf("foo"),
"foo",
0,
},
{
fmt.Errorf("bar"),
fmt.Errorf("foo"),
1,
},
{
Wrapf("bar", fmt.Errorf("foo")),
fmt.Errorf("baz"),
2,
},
{
Wrapf("bar", Wrapf("baz", fmt.Errorf("foo"))),
Wrapf("", nil),
0,
},
}
for i, tc := range cases {
actual := GetAllType(tc.Err, tc.Type)
if len(actual) != tc.Len {
t.Fatalf("%d: bad: %#v", i, actual)
}
}
}

View File

@ -1,82 +0,0 @@
package multierror
import (
"errors"
"testing"
)
func TestAppend_Error(t *testing.T) {
original := &Error{
Errors: []error{errors.New("foo")},
}
result := Append(original, errors.New("bar"))
if len(result.Errors) != 2 {
t.Fatalf("wrong len: %d", len(result.Errors))
}
original = &Error{}
result = Append(original, errors.New("bar"))
if len(result.Errors) != 1 {
t.Fatalf("wrong len: %d", len(result.Errors))
}
// Test when a typed nil is passed
var e *Error
result = Append(e, errors.New("baz"))
if len(result.Errors) != 1 {
t.Fatalf("wrong len: %d", len(result.Errors))
}
// Test flattening
original = &Error{
Errors: []error{errors.New("foo")},
}
result = Append(original, Append(nil, errors.New("foo"), errors.New("bar")))
if len(result.Errors) != 3 {
t.Fatalf("wrong len: %d", len(result.Errors))
}
}
func TestAppend_NilError(t *testing.T) {
var err error
result := Append(err, errors.New("bar"))
if len(result.Errors) != 1 {
t.Fatalf("wrong len: %d", len(result.Errors))
}
}
func TestAppend_NilErrorArg(t *testing.T) {
var err error
var nilErr *Error
result := Append(err, nilErr)
if len(result.Errors) != 0 {
t.Fatalf("wrong len: %d", len(result.Errors))
}
}
func TestAppend_NilErrorIfaceArg(t *testing.T) {
var err error
var nilErr error
result := Append(err, nilErr)
if len(result.Errors) != 0 {
t.Fatalf("wrong len: %d", len(result.Errors))
}
}
func TestAppend_NonError(t *testing.T) {
original := errors.New("foo")
result := Append(original, errors.New("bar"))
if len(result.Errors) != 2 {
t.Fatalf("wrong len: %d", len(result.Errors))
}
}
func TestAppend_NonError_Error(t *testing.T) {
original := errors.New("foo")
result := Append(original, Append(nil, errors.New("bar")))
if len(result.Errors) != 2 {
t.Fatalf("wrong len: %d", len(result.Errors))
}
}

View File

@ -1,48 +0,0 @@
package multierror
import (
"errors"
"fmt"
"reflect"
"strings"
"testing"
)
func TestFlatten(t *testing.T) {
original := &Error{
Errors: []error{
errors.New("one"),
&Error{
Errors: []error{
errors.New("two"),
&Error{
Errors: []error{
errors.New("three"),
},
},
},
},
},
}
expected := strings.TrimSpace(`
3 errors occurred:
* one
* two
* three
`)
actual := fmt.Sprintf("%s", Flatten(original))
if expected != actual {
t.Fatalf("expected: %s, got: %s", expected, actual)
}
}
func TestFlatten_nonError(t *testing.T) {
err := errors.New("foo")
actual := Flatten(err)
if !reflect.DeepEqual(actual, err) {
t.Fatalf("bad: %#v", actual)
}
}

View File

@ -1,38 +0,0 @@
package multierror
import (
"errors"
"testing"
)
func TestListFormatFuncSingle(t *testing.T) {
expected := `1 error occurred:
* foo`
errors := []error{
errors.New("foo"),
}
actual := ListFormatFunc(errors)
if actual != expected {
t.Fatalf("bad: %#v", actual)
}
}
func TestListFormatFuncMultiple(t *testing.T) {
expected := `2 errors occurred:
* foo
* bar`
errors := []error{
errors.New("foo"),
errors.New("bar"),
}
actual := ListFormatFunc(errors)
if actual != expected {
t.Fatalf("bad: %#v", actual)
}
}

View File

@ -1,70 +0,0 @@
package multierror
import (
"errors"
"reflect"
"testing"
)
func TestError_Impl(t *testing.T) {
var _ error = new(Error)
}
func TestErrorError_custom(t *testing.T) {
errors := []error{
errors.New("foo"),
errors.New("bar"),
}
fn := func(es []error) string {
return "foo"
}
multi := &Error{Errors: errors, ErrorFormat: fn}
if multi.Error() != "foo" {
t.Fatalf("bad: %s", multi.Error())
}
}
func TestErrorError_default(t *testing.T) {
expected := `2 errors occurred:
* foo
* bar`
errors := []error{
errors.New("foo"),
errors.New("bar"),
}
multi := &Error{Errors: errors}
if multi.Error() != expected {
t.Fatalf("bad: %s", multi.Error())
}
}
func TestErrorErrorOrNil(t *testing.T) {
err := new(Error)
if err.ErrorOrNil() != nil {
t.Fatalf("bad: %#v", err.ErrorOrNil())
}
err.Errors = []error{errors.New("foo")}
if v := err.ErrorOrNil(); v == nil {
t.Fatal("should not be nil")
} else if !reflect.DeepEqual(v, err) {
t.Fatalf("bad: %#v", v)
}
}
func TestErrorWrappedErrors(t *testing.T) {
errors := []error{
errors.New("foo"),
errors.New("bar"),
}
multi := &Error{Errors: errors}
if !reflect.DeepEqual(multi.Errors, multi.WrappedErrors()) {
t.Fatalf("bad: %s", multi.WrappedErrors())
}
}

View File

@ -1,33 +0,0 @@
package multierror
import (
"errors"
"testing"
)
func TestPrefix_Error(t *testing.T) {
original := &Error{
Errors: []error{errors.New("foo")},
}
result := Prefix(original, "bar")
if result.(*Error).Errors[0].Error() != "bar foo" {
t.Fatalf("bad: %s", result)
}
}
func TestPrefix_NilError(t *testing.T) {
var err error
result := Prefix(err, "bar")
if result != nil {
t.Fatalf("bad: %#v", result)
}
}
func TestPrefix_NonError(t *testing.T) {
original := errors.New("foo")
result := Prefix(original, "bar")
if result.Error() != "bar foo" {
t.Fatalf("bad: %s", result)
}
}

View File

@ -1,54 +0,0 @@
#!/usr/bin/env bash
#
# This script updates dependencies using a temporary directory. This is required
# to avoid any auxillary dependencies that sneak into GOPATH.
set -e
# Get the parent directory of where this script is.
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done
DIR="$(cd -P "$(dirname "$SOURCE")/.." && pwd)"
# Change into that directory
cd "$DIR"
# Get the name from the directory
NAME=${NAME:-"$(basename $(pwd))"}
# Announce
echo "==> Updating dependencies..."
echo "--> Making tmpdir..."
tmpdir=$(mktemp -d)
function cleanup {
rm -rf "${tmpdir}"
}
trap cleanup EXIT
export GOPATH="${tmpdir}"
export PATH="${tmpdir}/bin:$PATH"
mkdir -p "${tmpdir}/src/github.com/hashicorp"
pushd "${tmpdir}/src/github.com/hashicorp" &>/dev/null
echo "--> Copying ${NAME}..."
cp -R "$DIR" "${tmpdir}/src/github.com/hashicorp/${NAME}"
pushd "${tmpdir}/src/github.com/hashicorp/${NAME}" &>/dev/null
rm -rf vendor/
echo "--> Installing dependency manager..."
go get -u github.com/kardianos/govendor
govendor init
echo "--> Installing all dependencies (may take some time)..."
govendor fetch -v +outside
echo "--> Vendoring..."
govendor add +external
echo "--> Moving into place..."
vpath="${tmpdir}/src/github.com/hashicorp/${NAME}/vendor"
popd &>/dev/null
popd &>/dev/null
rm -rf vendor/
cp -R "${vpath}" .

View File

@ -1,82 +0,0 @@
package crypt
import (
"bytes"
"crypto/sha1"
"io/ioutil"
"os"
"testing"
)
var plain = [][]byte{
[]byte("Nö, ich trinke keinen Tee, ich bin Atheist. --- Helge Schneider"),
[]byte("I wish these damn scientists would leave intelligence to the experts. --- Gen. Richard Stillwell (CIA)"),
[]byte("I want to die peacefully in my sleep like my grandfather, not screaming in terror like his passengers. --- Charlie Hall"),
[]byte("NOTE 3: Each bit has the value either ZERO or ONE. --- ECMA-035 spec"),
[]byte("Writing about music is like dancing about architecture. --- Frank Zappa"),
[]byte("If you want to go somewhere, goto is the best way to get there. --- K Thompson"),
}
func TestEncryptDecrypt(t *testing.T) {
enc := bytes.NewBuffer(nil)
dec := bytes.NewBuffer(nil)
password := []byte("test password")
c := &Crypter{
HashFunc: sha1.New,
HashSize: sha1.Size,
Key: NewPbkdf2Key(password, 32),
}
defer c.Key.Reset()
for _, src := range plain {
enc.Reset()
dec.Reset()
err := c.Encrypt(enc, bytes.NewReader(src))
if err != nil {
t.Fatal(err)
}
err = c.Decrypt(dec, enc)
if err != nil {
t.Fatal(err)
}
if bytes.Compare(dec.Bytes(), src) != 0 {
t.Errorf("encrypt/decrypt error: want %q, got %q", string(src), string(dec.Bytes()))
}
}
}
func TestEncryptDecrypt1(t *testing.T) {
f, err := os.Open("crypt_test.go")
if err != nil {
t.Fatal(err)
}
defer f.Close()
encBuf := bytes.NewBuffer(nil)
password := []byte("test password")
c := &Crypter{
HashFunc: sha1.New,
HashSize: sha1.Size,
Key: NewPbkdf2Key(password, 32),
}
defer c.Key.Reset()
err = c.Encrypt(encBuf, f)
if err != nil {
t.Fatal(err)
}
decBuf := bytes.NewBuffer(nil)
err = c.Decrypt(decBuf, encBuf)
if err != nil {
t.Fatal(err)
}
src, err := ioutil.ReadFile("crypt_test.go")
if err != nil {
t.Fatal(err)
}
if bytes.Compare(decBuf.Bytes(), src) != 0 {
t.Errorf("encrypt/decrypt file error: crypt_test.go")
}
}

View File

@ -1,170 +0,0 @@
package main
import (
"bytes"
"crypto/sha1"
"flag"
"fmt"
"os"
"runtime"
"github.com/mars9/crypt"
"github.com/mars9/keyring"
"github.com/mars9/passwd"
)
var (
prompt = flag.Bool("p", false, "prompt to enter a passphrase")
decrypt = flag.Bool("d", false, "decrypt infile to oufile")
service = flag.String("s", "go-crypto", "keyring service name")
username = flag.String("u", os.Getenv("USER"), "keyring username")
initKeyring = flag.Bool("i", false, "intialize keyring")
)
func passphrase() ([]byte, error) {
if *prompt {
password, err := passwd.Get("Enter passphrase: ")
if err != nil {
return nil, fmt.Errorf("get passphrase: %v\n", err)
}
if !*decrypt {
confirm, err := passwd.Get("Confirm passphrase: ")
if err != nil {
return nil, fmt.Errorf("get passphrase: %v\n", err)
}
if !bytes.Equal(password, confirm) {
return nil, fmt.Errorf("Passphrase mismatch, try again.")
}
}
return password, nil
}
ring, err := keyring.New()
if err != nil {
return nil, err
}
return ring.Get(*service, *username)
}
func initialize() error {
password, err := passwd.Get("Enter passphrase: ")
if err != nil {
return fmt.Errorf("get passphrase: %v\n", err)
}
confirm, err := passwd.Get("Confirm passphrase: ")
if err != nil {
return fmt.Errorf("get passphrase: %v\n", err)
}
if !bytes.Equal(password, confirm) {
return fmt.Errorf("Passphrase mismatch, try again.")
}
ring, err := keyring.New()
if err != nil {
return err
}
return ring.Set(*service, *username, password)
}
func main() {
flag.Usage = usage
flag.Parse()
narg := flag.NArg()
if narg > 2 {
usage()
}
if runtime.GOOS == "windows" && narg == 0 {
usage()
}
if *initKeyring {
if err := initialize(); err != nil {
fmt.Fprintf(os.Stderr, "initialize keyring: %v", err)
os.Exit(1)
}
os.Exit(0)
}
password, err := passphrase()
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(3)
}
defer func() {
for i := range password {
password[i] = 0
}
}()
in := os.Stdin
out := os.Stdout
if narg > 0 {
in, err = os.Open(flag.Arg(0))
if err != nil {
fmt.Fprintf(os.Stderr, "open %s: %v\n", flag.Arg(0), err)
os.Exit(1)
}
defer in.Close()
if narg == 2 {
out, err = os.Create(flag.Arg(1))
if err != nil {
fmt.Fprintf(os.Stderr, "create %s: %v\n", flag.Arg(1), err)
os.Exit(1)
}
defer func() {
if err := out.Sync(); err != nil {
fmt.Fprintf(os.Stderr, "sync %s: %v\n", flag.Arg(1), err)
os.Exit(1)
}
if err := out.Close(); err != nil {
fmt.Fprintf(os.Stderr, "sync %s: %v\n", flag.Arg(1), err)
os.Exit(1)
}
}()
}
}
c := &crypt.Crypter{
HashFunc: sha1.New,
HashSize: sha1.Size,
Key: crypt.NewPbkdf2Key(password, 32),
}
if !*decrypt {
if err := c.Encrypt(out, in); err != nil {
fmt.Fprintf(os.Stderr, "encrypt: %v\n", err)
os.Exit(1)
}
} else {
if err := c.Decrypt(out, in); err != nil {
fmt.Fprintf(os.Stderr, "decrypt: %v\n", err)
os.Exit(1)
}
}
}
func usage() {
if runtime.GOOS == "windows" {
fmt.Fprintf(os.Stderr, "Usage: %s [options] infile [outfile]\n", os.Args[0])
} else {
fmt.Fprintf(os.Stderr, "Usage: %s [options] [infile] [[outfile]]\n", os.Args[0])
}
fmt.Fprint(os.Stderr, usageMsg)
fmt.Fprintf(os.Stderr, "\nOptions:\n")
flag.PrintDefaults()
os.Exit(2)
}
const usageMsg = `
Files are encrypted with AES (Rijndael) in cipher block counter mode
(CTR) and authenticate with HMAC-SHA. Encryption and HMAC keys are
derived from passphrase using PBKDF2.
If outfile is not specified, the de-/encrypted data is written to the
standard output and if infile is not specified, the de-/encrypted data
is read from standard input (reading standard input is not available
on windows).
`

View File

@ -1,16 +0,0 @@
package main
import (
"bufio"
"fmt"
"github.com/mattn/go-colorable"
)
func main() {
stdOut := bufio.NewWriter(colorable.NewColorableStdout())
fmt.Fprint(stdOut, "\x1B[3GMove to 3rd Column\n")
fmt.Fprint(stdOut, "\x1B[1;2HMove to 2nd Column on 1st Line\n")
stdOut.Flush()
}

View File

@ -1,16 +0,0 @@
package main
import (
"github.com/mattn/go-colorable"
"github.com/sirupsen/logrus"
)
func main() {
logrus.SetFormatter(&logrus.TextFormatter{ForceColors: true})
logrus.SetOutput(colorable.NewColorableStdout())
logrus.Info("succeeded")
logrus.Warn("not correct")
logrus.Error("something error")
logrus.Fatal("panic")
}

View File

@ -1,14 +0,0 @@
package main
import (
"fmt"
"os"
. "github.com/mattn/go-colorable"
)
func main() {
out := NewColorableStdout()
fmt.Fprint(out, "\x1B]0;TITLE Changed\007(See title and hit any key)")
var c [1]byte
os.Stdin.Read(c[:])
}

View File

@ -1,83 +0,0 @@
package colorable
import (
"bytes"
"os"
"runtime"
"testing"
)
// checkEncoding checks that colorable is output encoding agnostic as long as
// the encoding is a superset of ASCII. This implies that one byte not part of
// an ANSI sequence must give exactly one byte in output
func checkEncoding(t *testing.T, data []byte) {
// Send non-UTF8 data to colorable
b := bytes.NewBuffer(make([]byte, 0, 10))
if b.Len() != 0 {
t.FailNow()
}
// TODO move colorable wrapping outside the test
c := NewNonColorable(b)
c.Write(data)
if b.Len() != len(data) {
t.Fatalf("%d bytes expected, got %d", len(data), b.Len())
}
}
func TestEncoding(t *testing.T) {
checkEncoding(t, []byte{}) // Empty
checkEncoding(t, []byte(`abc`)) // "abc"
checkEncoding(t, []byte(`é`)) // "é" in UTF-8
checkEncoding(t, []byte{233}) // 'é' in Latin-1
}
func TestNonColorable(t *testing.T) {
var buf bytes.Buffer
want := "hello"
NewNonColorable(&buf).Write([]byte("\x1b[0m" + want + "\x1b[2J"))
got := buf.String()
if got != "hello" {
t.Fatalf("want %q but %q", want, got)
}
buf.Reset()
NewNonColorable(&buf).Write([]byte("\x1b["))
got = buf.String()
if got != "" {
t.Fatalf("want %q but %q", "", got)
}
}
func TestNonColorableNil(t *testing.T) {
paniced := false
func() {
defer func() {
recover()
paniced = true
}()
NewNonColorable(nil)
NewColorable(nil)
}()
if !paniced {
t.Fatalf("should panic")
}
}
func TestColorable(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skipf("skip this test on windows")
}
_, ok := NewColorableStdout().(*os.File)
if !ok {
t.Fatalf("should os.Stdout on UNIX")
}
_, ok = NewColorableStderr().(*os.File)
if !ok {
t.Fatalf("should os.Stdout on UNIX")
}
_, ok = NewColorable(os.Stdout).(*os.File)
if !ok {
t.Fatalf("should os.Stdout on UNIX")
}
}

View File

@ -1,18 +0,0 @@
package isatty_test
import (
"fmt"
"os"
"github.com/mattn/go-isatty"
)
func Example() {
if isatty.IsTerminal(os.Stdout.Fd()) {
fmt.Println("Is Terminal")
} else if isatty.IsCygwinTerminal(os.Stdout.Fd()) {
fmt.Println("Is Cygwin/MSYS2 Terminal")
} else {
fmt.Println("Is Not Terminal")
}
}

View File

@ -1,19 +0,0 @@
// +build !windows
package isatty
import (
"os"
"testing"
)
func TestTerminal(t *testing.T) {
// test for non-panic
IsTerminal(os.Stdout.Fd())
}
func TestCygwinPipeName(t *testing.T) {
if IsCygwinTerminal(os.Stdout.Fd()) {
t.Fatal("should be false always")
}
}

View File

@ -1,35 +0,0 @@
// +build windows
package isatty
import (
"testing"
)
func TestCygwinPipeName(t *testing.T) {
tests := []struct {
name string
result bool
}{
{``, false},
{`\msys-`, false},
{`\cygwin-----`, false},
{`\msys-x-PTY5-pty1-from-master`, false},
{`\cygwin-x-PTY5-from-master`, false},
{`\cygwin-x-pty2-from-toaster`, false},
{`\cygwin--pty2-from-master`, false},
{`\\cygwin-x-pty2-from-master`, false},
{`\cygwin-x-pty2-from-master-`, true}, // for the feature
{`\cygwin-e022582115c10879-pty4-from-master`, true},
{`\msys-e022582115c10879-pty4-to-master`, true},
{`\cygwin-e022582115c10879-pty4-to-master`, true},
}
for _, test := range tests {
want := test.result
got := isCygwinPipeName(test.name)
if want != got {
t.Fatalf("isatty(%q): got %v, want %v:", test.name, got, want)
}
}
}

View File

@ -1,185 +0,0 @@
package colorstring
import (
"os"
"testing"
)
func TestColor(t *testing.T) {
cases := []struct {
Input, Output string
}{
{
Input: "foo",
Output: "foo",
},
{
Input: "[blue]foo",
Output: "\033[34mfoo\033[0m",
},
{
Input: "foo[blue]foo",
Output: "foo\033[34mfoo\033[0m",
},
{
Input: "foo[what]foo",
Output: "foo[what]foo",
},
{
Input: "foo[_blue_]foo",
Output: "foo\033[44mfoo\033[0m",
},
{
Input: "foo[bold]foo",
Output: "foo\033[1mfoo\033[0m",
},
{
Input: "[blue]foo[bold]bar",
Output: "\033[34mfoo\033[1mbar\033[0m",
},
{
Input: "[underline]foo[reset]bar",
Output: "\033[4mfoo\033[0mbar\033[0m",
},
}
for _, tc := range cases {
actual := Color(tc.Input)
if actual != tc.Output {
t.Errorf(
"Input: %#v\n\nOutput: %#v\n\nExpected: %#v",
tc.Input,
actual,
tc.Output)
}
}
}
func TestColorPrefix(t *testing.T) {
cases := []struct {
Input, Output string
}{
{
Input: "foo",
Output: "",
},
{
Input: "[blue]foo",
Output: "[blue]",
},
{
Input: "[bold][blue]foo",
Output: "[bold][blue]",
},
{
Input: " [bold][blue]foo",
Output: "[bold][blue]",
},
}
for _, tc := range cases {
actual := ColorPrefix(tc.Input)
if actual != tc.Output {
t.Errorf(
"Input: %#v\n\nOutput: %#v\n\nExpected: %#v",
tc.Input,
actual,
tc.Output)
}
}
}
func TestColorizeColor_disable(t *testing.T) {
c := def
c.Disable = true
cases := []struct {
Input, Output string
}{
{
"[blue]foo",
"foo",
},
{
"[foo]bar",
"[foo]bar",
},
}
for _, tc := range cases {
actual := c.Color(tc.Input)
if actual != tc.Output {
t.Errorf(
"Input: %#v\n\nOutput: %#v\n\nExpected: %#v",
tc.Input,
actual,
tc.Output)
}
}
}
func TestColorizeColor_noReset(t *testing.T) {
c := def
c.Reset = false
input := "[blue]foo"
output := "\033[34mfoo"
actual := c.Color(input)
if actual != output {
t.Errorf(
"Input: %#v\n\nOutput: %#v\n\nExpected: %#v",
input,
actual,
output)
}
}
func TestConvenienceWrappers(t *testing.T) {
var length int
printInput := "[bold]Print:\t\t[default][red]R[green]G[blue]B[cyan]C[magenta]M[yellow]Y\n"
printlnInput := "[bold]Println:\t[default][red]R[green]G[blue]B[cyan]C[magenta]M[yellow]Y"
printfInput := "[bold]Printf:\t\t[default][red]R[green]G[blue]B[cyan]C[magenta]M[yellow]Y\n"
fprintInput := "[bold]Fprint:\t\t[default][red]R[green]G[blue]B[cyan]C[magenta]M[yellow]Y\n"
fprintlnInput := "[bold]Fprintln:\t[default][red]R[green]G[blue]B[cyan]C[magenta]M[yellow]Y"
fprintfInput := "[bold]Fprintf:\t[default][red]R[green]G[blue]B[cyan]C[magenta]M[yellow]Y\n"
// colorstring.Print
length, _ = Print(printInput)
assertOutputLength(t, printInput, 58, length)
// colorstring.Println
length, _ = Println(printlnInput)
assertOutputLength(t, printlnInput, 59, length)
// colorstring.Printf
length, _ = Printf(printfInput)
assertOutputLength(t, printfInput, 59, length)
// colorstring.Fprint
length, _ = Fprint(os.Stdout, fprintInput)
assertOutputLength(t, fprintInput, 59, length)
// colorstring.Fprintln
length, _ = Fprintln(os.Stdout, fprintlnInput)
assertOutputLength(t, fprintlnInput, 60, length)
// colorstring.Fprintf
length, _ = Fprintf(os.Stdout, fprintfInput)
assertOutputLength(t, fprintfInput, 59, length)
}
func assertOutputLength(t *testing.T, input string, expectedLength int, actualLength int) {
if actualLength != expectedLength {
t.Errorf("Input: %#v\n\n Output length: %d\n\n Expected: %d",
input,
actualLength,
expectedLength)
}
}

View File

@ -1,129 +0,0 @@
package homedir
import (
"os"
"os/user"
"path/filepath"
"testing"
)
func patchEnv(key, value string) func() {
bck := os.Getenv(key)
deferFunc := func() {
os.Setenv(key, bck)
}
if value != "" {
os.Setenv(key, value)
} else {
os.Unsetenv(key)
}
return deferFunc
}
func BenchmarkDir(b *testing.B) {
// We do this for any "warmups"
for i := 0; i < 10; i++ {
Dir()
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
Dir()
}
}
func TestDir(t *testing.T) {
u, err := user.Current()
if err != nil {
t.Fatalf("err: %s", err)
}
dir, err := Dir()
if err != nil {
t.Fatalf("err: %s", err)
}
if u.HomeDir != dir {
t.Fatalf("%#v != %#v", u.HomeDir, dir)
}
DisableCache = true
defer func() { DisableCache = false }()
defer patchEnv("HOME", "")()
dir, err = Dir()
if err != nil {
t.Fatalf("err: %s", err)
}
if u.HomeDir != dir {
t.Fatalf("%#v != %#v", u.HomeDir, dir)
}
}
func TestExpand(t *testing.T) {
u, err := user.Current()
if err != nil {
t.Fatalf("err: %s", err)
}
cases := []struct {
Input string
Output string
Err bool
}{
{
"/foo",
"/foo",
false,
},
{
"~/foo",
filepath.Join(u.HomeDir, "foo"),
false,
},
{
"",
"",
false,
},
{
"~",
u.HomeDir,
false,
},
{
"~foo/foo",
"",
true,
},
}
for _, tc := range cases {
actual, err := Expand(tc.Input)
if (err != nil) != tc.Err {
t.Fatalf("Input: %#v\n\nErr: %s", tc.Input, err)
}
if actual != tc.Output {
t.Fatalf("Input: %#v\n\nOutput: %#v", tc.Input, actual)
}
}
DisableCache = true
defer func() { DisableCache = false }()
defer patchEnv("HOME", "/custom/path/")()
expected := filepath.Join("/", "custom", "path", "foo/bar")
actual, err := Expand("~/foo/bar")
if err != nil {
t.Errorf("No error is expected, got: %v", err)
} else if actual != expected {
t.Errorf("Expected: %v; actual: %v", expected, actual)
}
}

View File

@ -1 +0,0 @@
.idea/

View File

@ -1,58 +0,0 @@
# base58 A Fast Implementation of Base58 encoding used in Bitcoin
[![GoDoc](https://godoc.org/github.com/mr-tron/base58/base58?status.svg)](https://godoc.org/github.com/mr-tron/base58/base58) [![Go Report Card](https://goreportcard.com/badge/github.com/mr-tron/base58)](https://goreportcard.com/report/github.com/mr-tron/base58)
Fast implementation of base58 encoding in Go (Golang).
Base algorithm is copied from https://github.com/trezor/trezor-crypto/blob/master/base58.c
To import library
```go
import (
"github.com/mr-tron/base58/base58"
)
```
# Example
```go
package main
import (
"fmt"
"os"
"github.com/mr-tron/base58/base58"
)
func main() {
exampleBase58Encoded := []string{
"1QCaxc8hutpdZ62iKZsn1TCG3nh7uPZojq",
"1DhRmSGnhPjUaVPAj48zgPV9e2oRhAQFUb",
"17LN2oPYRYsXS9TdYdXCCDvF2FegshLDU2",
"14h2bDLZSuvRFhUL45VjPHJcW667mmRAAn",
}
// If a base58 string is on the command line, then use that instead of the 4 exampels above.
if len(os.Args) > 1 {
exampleBase58Encoded = os.Args[1:]
}
for _, vv := range exampleBase58Encoded {
num, err := base58.Decode(vv)
if err != nil {
fmt.Printf("Demo %d, got error %s\n", err)
continue
}
chk := base58.Encode(num)
if vv == string(chk) {
fmt.Printf ( "Successfully decoded then re-encoded %s\n", vv )
} else {
fmt.Printf ( "Failed on %s\n", vv )
}
}
}
```

View File

@ -1,26 +0,0 @@
package base58
import "testing"
func TestBase58_test2(t *testing.T) {
testAddr := []string{
"1QCaxc8hutpdZ62iKZsn1TCG3nh7uPZojq",
"1DhRmSGnhPjUaVPAj48zgPV9e2oRhAQFUb",
"17LN2oPYRYsXS9TdYdXCCDvF2FegshLDU2",
"14h2bDLZSuvRFhUL45VjPHJcW667mmRAAn",
}
for ii, vv := range testAddr {
// num := Base58Decode([]byte(vv))
// chk := Base58Encode(num)
num, err := FastBase58Decoding(vv)
if err != nil {
t.Errorf("Test %d, expected success, got error %s\n", ii, err)
}
chk := FastBase58Encoding(num)
if vv != string(chk) {
t.Errorf("Test %d, expected=%s got=%s Address did base58 encode/decode correctly.", ii, vv, chk)
}
}
}

View File

@ -1,117 +0,0 @@
package base58
import (
"crypto/rand"
"encoding/hex"
"testing"
)
type testValues struct {
dec []byte
enc string
}
var n = 5000000
var testPairs = make([]testValues, 0, n)
func initTestPairs() {
if len(testPairs) > 0 {
return
}
// pre-make the test pairs, so it doesn't take up benchmark time...
data := make([]byte, 32)
for i := 0; i < n; i++ {
rand.Read(data)
testPairs = append(testPairs, testValues{dec: data, enc: FastBase58Encoding(data)})
}
}
func randAlphabet() *Alphabet {
// Permutes [0, 127] and returns the first 58 elements.
// Like (math/rand).Perm but using crypto/rand.
var randomness [128]byte
rand.Read(randomness[:])
var bts [128]byte
for i, r := range randomness {
j := int(r) % (i + 1)
bts[i] = bts[j]
bts[j] = byte(i)
}
return NewAlphabet(string(bts[:58]))
}
func TestFastEqTrivialEncodingAndDecoding(t *testing.T) {
for k := 0; k < 10; k++ {
testEncDecLoop(t, randAlphabet())
}
testEncDecLoop(t, BTCAlphabet)
testEncDecLoop(t, FlickrAlphabet)
}
func testEncDecLoop(t *testing.T, alph *Alphabet) {
for j := 1; j < 256; j++ {
var b = make([]byte, j)
for i := 0; i < 100; i++ {
rand.Read(b)
fe := FastBase58EncodingAlphabet(b, alph)
te := TrivialBase58EncodingAlphabet(b, alph)
if fe != te {
t.Errorf("encoding err: %#v", hex.EncodeToString(b))
}
fd, ferr := FastBase58DecodingAlphabet(fe, alph)
if ferr != nil {
t.Errorf("fast error: %v", ferr)
}
td, terr := TrivialBase58DecodingAlphabet(te, alph)
if terr != nil {
t.Errorf("trivial error: %v", terr)
}
if hex.EncodeToString(b) != hex.EncodeToString(td) {
t.Errorf("decoding err: %s != %s", hex.EncodeToString(b), hex.EncodeToString(td))
}
if hex.EncodeToString(b) != hex.EncodeToString(fd) {
t.Errorf("decoding err: %s != %s", hex.EncodeToString(b), hex.EncodeToString(fd))
}
}
}
}
func BenchmarkTrivialBase58Encoding(b *testing.B) {
initTestPairs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
TrivialBase58Encoding([]byte(testPairs[i].dec))
}
}
func BenchmarkFastBase58Encoding(b *testing.B) {
initTestPairs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
FastBase58Encoding(testPairs[i].dec)
}
}
func BenchmarkTrivialBase58Decoding(b *testing.B) {
initTestPairs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
TrivialBase58Decoding(testPairs[i].enc)
}
}
func BenchmarkFastBase58Decoding(b *testing.B) {
initTestPairs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
FastBase58Decoding(testPairs[i].enc)
}
}

View File

@ -1 +0,0 @@
cli

View File

@ -1,37 +0,0 @@
package main
import (
"fmt"
"os"
"github.com/mr-tron/base58/base58"
)
func main() {
exampleBase58Encoded := []string{
"1QCaxc8hutpdZ62iKZsn1TCG3nh7uPZojq",
"1DhRmSGnhPjUaVPAj48zgPV9e2oRhAQFUb",
"17LN2oPYRYsXS9TdYdXCCDvF2FegshLDU2",
"14h2bDLZSuvRFhUL45VjPHJcW667mmRAAn",
}
// If a base58 string is on the command line, then use that instead of the 4 exampels above.
if len(os.Args) > 1 {
exampleBase58Encoded = os.Args[1:]
}
for _, vv := range exampleBase58Encoded {
num, err := base58.Decode(vv)
if err != nil {
fmt.Printf("Demo %s, got error %s\n", vv, err)
continue
}
chk := base58.Encode(num)
if vv == string(chk) {
fmt.Printf("Successfully decoded then re-encoded %s\n", vv)
} else {
fmt.Printf("Failed on %s\n", vv)
}
}
}

View File

@ -1,112 +0,0 @@
package main
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"flag"
"fmt"
"io"
"io/ioutil"
"os"
"github.com/mr-tron/base58/base58"
)
func checkSum(b []byte) []byte {
sh1, sh2 := sha256.New(), sha256.New()
sh1.Write(b)
sh2.Write(sh1.Sum(nil))
return sh2.Sum(nil)
}
func main() {
var (
err error
bin []byte
help = flag.Bool("h", false, "display this message")
lnBreak = flag.Int("b", 76, "break encoded string into num character lines. Use 0 to disable line wrapping")
input = flag.String("i", "-", `input file (use: "-" for stdin)`)
output = flag.String("o", "-", `output file (use: "-" for stdout)`)
decode = flag.Bool("d", false, `decode input`)
check = flag.Bool("k", false, `use sha256 check`)
useError = flag.Bool("e", false, `write error to stderr`)
)
flag.Parse()
if *help {
flag.Usage()
os.Exit(0)
}
fin, fout := os.Stdin, os.Stdout
if *input != "-" {
if fin, err = os.Open(*input); err != nil {
fmt.Fprintf(os.Stderr, "input file err: %v\n", err)
os.Exit(1)
}
}
if *output != "-" {
if fout, err = os.Create(*output); err != nil {
fmt.Fprintf(os.Stderr, "output file err: %v\n", err)
os.Exit(1)
}
}
if bin, err = ioutil.ReadAll(fin); err != nil {
fmt.Fprintf(os.Stderr, "read input err: %v\n", err)
os.Exit(1)
}
if *decode {
decoded, err := base58.FastBase58Decoding(string(bin))
if err != nil {
fmt.Fprintf(os.Stderr, "decode input err: %v\n", err)
os.Exit(1)
}
var checkResult bool
if *check {
chk := len(decoded) - 4
decodedCk := decoded[chk:]
decoded = decoded[:chk]
sum := checkSum(decoded)
checkResult = hex.EncodeToString(sum[:4]) == hex.EncodeToString(decodedCk)
}
io.Copy(fout, bytes.NewReader(decoded))
if *check && !checkResult {
if *useError {
fmt.Fprintf(os.Stderr, "%t", false)
}
os.Exit(3)
}
os.Exit(0)
}
if *check {
sum := checkSum(bin)
bin = append(bin, sum[:4]...)
}
encoded := base58.FastBase58Encoding(bin)
if *lnBreak > 0 {
lines := (len(encoded) / *lnBreak) + 1
for i := 0; i < lines; i++ {
start := i * *lnBreak
end := start + *lnBreak
if i == lines-1 {
fmt.Fprintln(fout, encoded[start:])
return
}
fmt.Fprintln(fout, encoded[start:end])
}
}
fmt.Fprintln(fout, encoded)
}

View File

@ -1,59 +0,0 @@
// +build go1.7
package errors
import (
"fmt"
"testing"
stderrors "errors"
)
func noErrors(at, depth int) error {
if at >= depth {
return stderrors.New("no error")
}
return noErrors(at+1, depth)
}
func yesErrors(at, depth int) error {
if at >= depth {
return New("ye error")
}
return yesErrors(at+1, depth)
}
func BenchmarkErrors(b *testing.B) {
var toperr error
type run struct {
stack int
std bool
}
runs := []run{
{10, false},
{10, true},
{100, false},
{100, true},
{1000, false},
{1000, true},
}
for _, r := range runs {
part := "pkg/errors"
if r.std {
part = "errors"
}
name := fmt.Sprintf("%s-stack-%d", part, r.stack)
b.Run(name, func(b *testing.B) {
var err error
f := yesErrors
if r.std {
f = noErrors
}
b.ReportAllocs()
for i := 0; i < b.N; i++ {
err = f(0, r.stack)
}
b.StopTimer()
toperr = err
})
}
}

View File

@ -1,226 +0,0 @@
package errors
import (
"errors"
"fmt"
"io"
"reflect"
"testing"
)
func TestNew(t *testing.T) {
tests := []struct {
err string
want error
}{
{"", fmt.Errorf("")},
{"foo", fmt.Errorf("foo")},
{"foo", New("foo")},
{"string with format specifiers: %v", errors.New("string with format specifiers: %v")},
}
for _, tt := range tests {
got := New(tt.err)
if got.Error() != tt.want.Error() {
t.Errorf("New.Error(): got: %q, want %q", got, tt.want)
}
}
}
func TestWrapNil(t *testing.T) {
got := Wrap(nil, "no error")
if got != nil {
t.Errorf("Wrap(nil, \"no error\"): got %#v, expected nil", got)
}
}
func TestWrap(t *testing.T) {
tests := []struct {
err error
message string
want string
}{
{io.EOF, "read error", "read error: EOF"},
{Wrap(io.EOF, "read error"), "client error", "client error: read error: EOF"},
}
for _, tt := range tests {
got := Wrap(tt.err, tt.message).Error()
if got != tt.want {
t.Errorf("Wrap(%v, %q): got: %v, want %v", tt.err, tt.message, got, tt.want)
}
}
}
type nilError struct{}
func (nilError) Error() string { return "nil error" }
func TestCause(t *testing.T) {
x := New("error")
tests := []struct {
err error
want error
}{{
// nil error is nil
err: nil,
want: nil,
}, {
// explicit nil error is nil
err: (error)(nil),
want: nil,
}, {
// typed nil is nil
err: (*nilError)(nil),
want: (*nilError)(nil),
}, {
// uncaused error is unaffected
err: io.EOF,
want: io.EOF,
}, {
// caused error returns cause
err: Wrap(io.EOF, "ignored"),
want: io.EOF,
}, {
err: x, // return from errors.New
want: x,
}, {
WithMessage(nil, "whoops"),
nil,
}, {
WithMessage(io.EOF, "whoops"),
io.EOF,
}, {
WithStack(nil),
nil,
}, {
WithStack(io.EOF),
io.EOF,
}}
for i, tt := range tests {
got := Cause(tt.err)
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("test %d: got %#v, want %#v", i+1, got, tt.want)
}
}
}
func TestWrapfNil(t *testing.T) {
got := Wrapf(nil, "no error")
if got != nil {
t.Errorf("Wrapf(nil, \"no error\"): got %#v, expected nil", got)
}
}
func TestWrapf(t *testing.T) {
tests := []struct {
err error
message string
want string
}{
{io.EOF, "read error", "read error: EOF"},
{Wrapf(io.EOF, "read error without format specifiers"), "client error", "client error: read error without format specifiers: EOF"},
{Wrapf(io.EOF, "read error with %d format specifier", 1), "client error", "client error: read error with 1 format specifier: EOF"},
}
for _, tt := range tests {
got := Wrapf(tt.err, tt.message).Error()
if got != tt.want {
t.Errorf("Wrapf(%v, %q): got: %v, want %v", tt.err, tt.message, got, tt.want)
}
}
}
func TestErrorf(t *testing.T) {
tests := []struct {
err error
want string
}{
{Errorf("read error without format specifiers"), "read error without format specifiers"},
{Errorf("read error with %d format specifier", 1), "read error with 1 format specifier"},
}
for _, tt := range tests {
got := tt.err.Error()
if got != tt.want {
t.Errorf("Errorf(%v): got: %q, want %q", tt.err, got, tt.want)
}
}
}
func TestWithStackNil(t *testing.T) {
got := WithStack(nil)
if got != nil {
t.Errorf("WithStack(nil): got %#v, expected nil", got)
}
}
func TestWithStack(t *testing.T) {
tests := []struct {
err error
want string
}{
{io.EOF, "EOF"},
{WithStack(io.EOF), "EOF"},
}
for _, tt := range tests {
got := WithStack(tt.err).Error()
if got != tt.want {
t.Errorf("WithStack(%v): got: %v, want %v", tt.err, got, tt.want)
}
}
}
func TestWithMessageNil(t *testing.T) {
got := WithMessage(nil, "no error")
if got != nil {
t.Errorf("WithMessage(nil, \"no error\"): got %#v, expected nil", got)
}
}
func TestWithMessage(t *testing.T) {
tests := []struct {
err error
message string
want string
}{
{io.EOF, "read error", "read error: EOF"},
{WithMessage(io.EOF, "read error"), "client error", "client error: read error: EOF"},
}
for _, tt := range tests {
got := WithMessage(tt.err, tt.message).Error()
if got != tt.want {
t.Errorf("WithMessage(%v, %q): got: %q, want %q", tt.err, tt.message, got, tt.want)
}
}
}
// errors.New, etc values are not expected to be compared by value
// but the change in errors#27 made them incomparable. Assert that
// various kinds of errors have a functional equality operator, even
// if the result of that equality is always false.
func TestErrorEquality(t *testing.T) {
vals := []error{
nil,
io.EOF,
errors.New("EOF"),
New("EOF"),
Errorf("EOF"),
Wrap(io.EOF, "EOF"),
Wrapf(io.EOF, "EOF%d", 2),
WithMessage(nil, "whoops"),
WithMessage(io.EOF, "whoops"),
WithStack(io.EOF),
WithStack(nil),
}
for i := range vals {
for j := range vals {
_ = vals[i] == vals[j] // mustn't panic
}
}
}

View File

@ -1,205 +0,0 @@
package errors_test
import (
"fmt"
"github.com/pkg/errors"
)
func ExampleNew() {
err := errors.New("whoops")
fmt.Println(err)
// Output: whoops
}
func ExampleNew_printf() {
err := errors.New("whoops")
fmt.Printf("%+v", err)
// Example output:
// whoops
// github.com/pkg/errors_test.ExampleNew_printf
// /home/dfc/src/github.com/pkg/errors/example_test.go:17
// testing.runExample
// /home/dfc/go/src/testing/example.go:114
// testing.RunExamples
// /home/dfc/go/src/testing/example.go:38
// testing.(*M).Run
// /home/dfc/go/src/testing/testing.go:744
// main.main
// /github.com/pkg/errors/_test/_testmain.go:106
// runtime.main
// /home/dfc/go/src/runtime/proc.go:183
// runtime.goexit
// /home/dfc/go/src/runtime/asm_amd64.s:2059
}
func ExampleWithMessage() {
cause := errors.New("whoops")
err := errors.WithMessage(cause, "oh noes")
fmt.Println(err)
// Output: oh noes: whoops
}
func ExampleWithStack() {
cause := errors.New("whoops")
err := errors.WithStack(cause)
fmt.Println(err)
// Output: whoops
}
func ExampleWithStack_printf() {
cause := errors.New("whoops")
err := errors.WithStack(cause)
fmt.Printf("%+v", err)
// Example Output:
// whoops
// github.com/pkg/errors_test.ExampleWithStack_printf
// /home/fabstu/go/src/github.com/pkg/errors/example_test.go:55
// testing.runExample
// /usr/lib/go/src/testing/example.go:114
// testing.RunExamples
// /usr/lib/go/src/testing/example.go:38
// testing.(*M).Run
// /usr/lib/go/src/testing/testing.go:744
// main.main
// github.com/pkg/errors/_test/_testmain.go:106
// runtime.main
// /usr/lib/go/src/runtime/proc.go:183
// runtime.goexit
// /usr/lib/go/src/runtime/asm_amd64.s:2086
// github.com/pkg/errors_test.ExampleWithStack_printf
// /home/fabstu/go/src/github.com/pkg/errors/example_test.go:56
// testing.runExample
// /usr/lib/go/src/testing/example.go:114
// testing.RunExamples
// /usr/lib/go/src/testing/example.go:38
// testing.(*M).Run
// /usr/lib/go/src/testing/testing.go:744
// main.main
// github.com/pkg/errors/_test/_testmain.go:106
// runtime.main
// /usr/lib/go/src/runtime/proc.go:183
// runtime.goexit
// /usr/lib/go/src/runtime/asm_amd64.s:2086
}
func ExampleWrap() {
cause := errors.New("whoops")
err := errors.Wrap(cause, "oh noes")
fmt.Println(err)
// Output: oh noes: whoops
}
func fn() error {
e1 := errors.New("error")
e2 := errors.Wrap(e1, "inner")
e3 := errors.Wrap(e2, "middle")
return errors.Wrap(e3, "outer")
}
func ExampleCause() {
err := fn()
fmt.Println(err)
fmt.Println(errors.Cause(err))
// Output: outer: middle: inner: error
// error
}
func ExampleWrap_extended() {
err := fn()
fmt.Printf("%+v\n", err)
// Example output:
// error
// github.com/pkg/errors_test.fn
// /home/dfc/src/github.com/pkg/errors/example_test.go:47
// github.com/pkg/errors_test.ExampleCause_printf
// /home/dfc/src/github.com/pkg/errors/example_test.go:63
// testing.runExample
// /home/dfc/go/src/testing/example.go:114
// testing.RunExamples
// /home/dfc/go/src/testing/example.go:38
// testing.(*M).Run
// /home/dfc/go/src/testing/testing.go:744
// main.main
// /github.com/pkg/errors/_test/_testmain.go:104
// runtime.main
// /home/dfc/go/src/runtime/proc.go:183
// runtime.goexit
// /home/dfc/go/src/runtime/asm_amd64.s:2059
// github.com/pkg/errors_test.fn
// /home/dfc/src/github.com/pkg/errors/example_test.go:48: inner
// github.com/pkg/errors_test.fn
// /home/dfc/src/github.com/pkg/errors/example_test.go:49: middle
// github.com/pkg/errors_test.fn
// /home/dfc/src/github.com/pkg/errors/example_test.go:50: outer
}
func ExampleWrapf() {
cause := errors.New("whoops")
err := errors.Wrapf(cause, "oh noes #%d", 2)
fmt.Println(err)
// Output: oh noes #2: whoops
}
func ExampleErrorf_extended() {
err := errors.Errorf("whoops: %s", "foo")
fmt.Printf("%+v", err)
// Example output:
// whoops: foo
// github.com/pkg/errors_test.ExampleErrorf
// /home/dfc/src/github.com/pkg/errors/example_test.go:101
// testing.runExample
// /home/dfc/go/src/testing/example.go:114
// testing.RunExamples
// /home/dfc/go/src/testing/example.go:38
// testing.(*M).Run
// /home/dfc/go/src/testing/testing.go:744
// main.main
// /github.com/pkg/errors/_test/_testmain.go:102
// runtime.main
// /home/dfc/go/src/runtime/proc.go:183
// runtime.goexit
// /home/dfc/go/src/runtime/asm_amd64.s:2059
}
func Example_stackTrace() {
type stackTracer interface {
StackTrace() errors.StackTrace
}
err, ok := errors.Cause(fn()).(stackTracer)
if !ok {
panic("oops, err does not implement stackTracer")
}
st := err.StackTrace()
fmt.Printf("%+v", st[0:2]) // top two frames
// Example output:
// github.com/pkg/errors_test.fn
// /home/dfc/src/github.com/pkg/errors/example_test.go:47
// github.com/pkg/errors_test.Example_stackTrace
// /home/dfc/src/github.com/pkg/errors/example_test.go:127
}
func ExampleCause_printf() {
err := errors.Wrap(func() error {
return func() error {
return errors.Errorf("hello %s", fmt.Sprintf("world"))
}()
}(), "failed")
fmt.Printf("%v", err)
// Output: failed: hello world
}

View File

@ -1,535 +0,0 @@
package errors
import (
"errors"
"fmt"
"io"
"regexp"
"strings"
"testing"
)
func TestFormatNew(t *testing.T) {
tests := []struct {
error
format string
want string
}{{
New("error"),
"%s",
"error",
}, {
New("error"),
"%v",
"error",
}, {
New("error"),
"%+v",
"error\n" +
"github.com/pkg/errors.TestFormatNew\n" +
"\t.+/github.com/pkg/errors/format_test.go:26",
}, {
New("error"),
"%q",
`"error"`,
}}
for i, tt := range tests {
testFormatRegexp(t, i, tt.error, tt.format, tt.want)
}
}
func TestFormatErrorf(t *testing.T) {
tests := []struct {
error
format string
want string
}{{
Errorf("%s", "error"),
"%s",
"error",
}, {
Errorf("%s", "error"),
"%v",
"error",
}, {
Errorf("%s", "error"),
"%+v",
"error\n" +
"github.com/pkg/errors.TestFormatErrorf\n" +
"\t.+/github.com/pkg/errors/format_test.go:56",
}}
for i, tt := range tests {
testFormatRegexp(t, i, tt.error, tt.format, tt.want)
}
}
func TestFormatWrap(t *testing.T) {
tests := []struct {
error
format string
want string
}{{
Wrap(New("error"), "error2"),
"%s",
"error2: error",
}, {
Wrap(New("error"), "error2"),
"%v",
"error2: error",
}, {
Wrap(New("error"), "error2"),
"%+v",
"error\n" +
"github.com/pkg/errors.TestFormatWrap\n" +
"\t.+/github.com/pkg/errors/format_test.go:82",
}, {
Wrap(io.EOF, "error"),
"%s",
"error: EOF",
}, {
Wrap(io.EOF, "error"),
"%v",
"error: EOF",
}, {
Wrap(io.EOF, "error"),
"%+v",
"EOF\n" +
"error\n" +
"github.com/pkg/errors.TestFormatWrap\n" +
"\t.+/github.com/pkg/errors/format_test.go:96",
}, {
Wrap(Wrap(io.EOF, "error1"), "error2"),
"%+v",
"EOF\n" +
"error1\n" +
"github.com/pkg/errors.TestFormatWrap\n" +
"\t.+/github.com/pkg/errors/format_test.go:103\n",
}, {
Wrap(New("error with space"), "context"),
"%q",
`"context: error with space"`,
}}
for i, tt := range tests {
testFormatRegexp(t, i, tt.error, tt.format, tt.want)
}
}
func TestFormatWrapf(t *testing.T) {
tests := []struct {
error
format string
want string
}{{
Wrapf(io.EOF, "error%d", 2),
"%s",
"error2: EOF",
}, {
Wrapf(io.EOF, "error%d", 2),
"%v",
"error2: EOF",
}, {
Wrapf(io.EOF, "error%d", 2),
"%+v",
"EOF\n" +
"error2\n" +
"github.com/pkg/errors.TestFormatWrapf\n" +
"\t.+/github.com/pkg/errors/format_test.go:134",
}, {
Wrapf(New("error"), "error%d", 2),
"%s",
"error2: error",
}, {
Wrapf(New("error"), "error%d", 2),
"%v",
"error2: error",
}, {
Wrapf(New("error"), "error%d", 2),
"%+v",
"error\n" +
"github.com/pkg/errors.TestFormatWrapf\n" +
"\t.+/github.com/pkg/errors/format_test.go:149",
}}
for i, tt := range tests {
testFormatRegexp(t, i, tt.error, tt.format, tt.want)
}
}
func TestFormatWithStack(t *testing.T) {
tests := []struct {
error
format string
want []string
}{{
WithStack(io.EOF),
"%s",
[]string{"EOF"},
}, {
WithStack(io.EOF),
"%v",
[]string{"EOF"},
}, {
WithStack(io.EOF),
"%+v",
[]string{"EOF",
"github.com/pkg/errors.TestFormatWithStack\n" +
"\t.+/github.com/pkg/errors/format_test.go:175"},
}, {
WithStack(New("error")),
"%s",
[]string{"error"},
}, {
WithStack(New("error")),
"%v",
[]string{"error"},
}, {
WithStack(New("error")),
"%+v",
[]string{"error",
"github.com/pkg/errors.TestFormatWithStack\n" +
"\t.+/github.com/pkg/errors/format_test.go:189",
"github.com/pkg/errors.TestFormatWithStack\n" +
"\t.+/github.com/pkg/errors/format_test.go:189"},
}, {
WithStack(WithStack(io.EOF)),
"%+v",
[]string{"EOF",
"github.com/pkg/errors.TestFormatWithStack\n" +
"\t.+/github.com/pkg/errors/format_test.go:197",
"github.com/pkg/errors.TestFormatWithStack\n" +
"\t.+/github.com/pkg/errors/format_test.go:197"},
}, {
WithStack(WithStack(Wrapf(io.EOF, "message"))),
"%+v",
[]string{"EOF",
"message",
"github.com/pkg/errors.TestFormatWithStack\n" +
"\t.+/github.com/pkg/errors/format_test.go:205",
"github.com/pkg/errors.TestFormatWithStack\n" +
"\t.+/github.com/pkg/errors/format_test.go:205",
"github.com/pkg/errors.TestFormatWithStack\n" +
"\t.+/github.com/pkg/errors/format_test.go:205"},
}, {
WithStack(Errorf("error%d", 1)),
"%+v",
[]string{"error1",
"github.com/pkg/errors.TestFormatWithStack\n" +
"\t.+/github.com/pkg/errors/format_test.go:216",
"github.com/pkg/errors.TestFormatWithStack\n" +
"\t.+/github.com/pkg/errors/format_test.go:216"},
}}
for i, tt := range tests {
testFormatCompleteCompare(t, i, tt.error, tt.format, tt.want, true)
}
}
func TestFormatWithMessage(t *testing.T) {
tests := []struct {
error
format string
want []string
}{{
WithMessage(New("error"), "error2"),
"%s",
[]string{"error2: error"},
}, {
WithMessage(New("error"), "error2"),
"%v",
[]string{"error2: error"},
}, {
WithMessage(New("error"), "error2"),
"%+v",
[]string{
"error",
"github.com/pkg/errors.TestFormatWithMessage\n" +
"\t.+/github.com/pkg/errors/format_test.go:244",
"error2"},
}, {
WithMessage(io.EOF, "addition1"),
"%s",
[]string{"addition1: EOF"},
}, {
WithMessage(io.EOF, "addition1"),
"%v",
[]string{"addition1: EOF"},
}, {
WithMessage(io.EOF, "addition1"),
"%+v",
[]string{"EOF", "addition1"},
}, {
WithMessage(WithMessage(io.EOF, "addition1"), "addition2"),
"%v",
[]string{"addition2: addition1: EOF"},
}, {
WithMessage(WithMessage(io.EOF, "addition1"), "addition2"),
"%+v",
[]string{"EOF", "addition1", "addition2"},
}, {
Wrap(WithMessage(io.EOF, "error1"), "error2"),
"%+v",
[]string{"EOF", "error1", "error2",
"github.com/pkg/errors.TestFormatWithMessage\n" +
"\t.+/github.com/pkg/errors/format_test.go:272"},
}, {
WithMessage(Errorf("error%d", 1), "error2"),
"%+v",
[]string{"error1",
"github.com/pkg/errors.TestFormatWithMessage\n" +
"\t.+/github.com/pkg/errors/format_test.go:278",
"error2"},
}, {
WithMessage(WithStack(io.EOF), "error"),
"%+v",
[]string{
"EOF",
"github.com/pkg/errors.TestFormatWithMessage\n" +
"\t.+/github.com/pkg/errors/format_test.go:285",
"error"},
}, {
WithMessage(Wrap(WithStack(io.EOF), "inside-error"), "outside-error"),
"%+v",
[]string{
"EOF",
"github.com/pkg/errors.TestFormatWithMessage\n" +
"\t.+/github.com/pkg/errors/format_test.go:293",
"inside-error",
"github.com/pkg/errors.TestFormatWithMessage\n" +
"\t.+/github.com/pkg/errors/format_test.go:293",
"outside-error"},
}}
for i, tt := range tests {
testFormatCompleteCompare(t, i, tt.error, tt.format, tt.want, true)
}
}
func TestFormatGeneric(t *testing.T) {
starts := []struct {
err error
want []string
}{
{New("new-error"), []string{
"new-error",
"github.com/pkg/errors.TestFormatGeneric\n" +
"\t.+/github.com/pkg/errors/format_test.go:315"},
}, {Errorf("errorf-error"), []string{
"errorf-error",
"github.com/pkg/errors.TestFormatGeneric\n" +
"\t.+/github.com/pkg/errors/format_test.go:319"},
}, {errors.New("errors-new-error"), []string{
"errors-new-error"},
},
}
wrappers := []wrapper{
{
func(err error) error { return WithMessage(err, "with-message") },
[]string{"with-message"},
}, {
func(err error) error { return WithStack(err) },
[]string{
"github.com/pkg/errors.(func·002|TestFormatGeneric.func2)\n\t" +
".+/github.com/pkg/errors/format_test.go:333",
},
}, {
func(err error) error { return Wrap(err, "wrap-error") },
[]string{
"wrap-error",
"github.com/pkg/errors.(func·003|TestFormatGeneric.func3)\n\t" +
".+/github.com/pkg/errors/format_test.go:339",
},
}, {
func(err error) error { return Wrapf(err, "wrapf-error%d", 1) },
[]string{
"wrapf-error1",
"github.com/pkg/errors.(func·004|TestFormatGeneric.func4)\n\t" +
".+/github.com/pkg/errors/format_test.go:346",
},
},
}
for s := range starts {
err := starts[s].err
want := starts[s].want
testFormatCompleteCompare(t, s, err, "%+v", want, false)
testGenericRecursive(t, err, want, wrappers, 3)
}
}
func testFormatRegexp(t *testing.T, n int, arg interface{}, format, want string) {
got := fmt.Sprintf(format, arg)
gotLines := strings.SplitN(got, "\n", -1)
wantLines := strings.SplitN(want, "\n", -1)
if len(wantLines) > len(gotLines) {
t.Errorf("test %d: wantLines(%d) > gotLines(%d):\n got: %q\nwant: %q", n+1, len(wantLines), len(gotLines), got, want)
return
}
for i, w := range wantLines {
match, err := regexp.MatchString(w, gotLines[i])
if err != nil {
t.Fatal(err)
}
if !match {
t.Errorf("test %d: line %d: fmt.Sprintf(%q, err):\n got: %q\nwant: %q", n+1, i+1, format, got, want)
}
}
}
var stackLineR = regexp.MustCompile(`\.`)
// parseBlocks parses input into a slice, where:
// - incase entry contains a newline, its a stacktrace
// - incase entry contains no newline, its a solo line.
//
// Detecting stack boundaries only works incase the WithStack-calls are
// to be found on the same line, thats why it is optionally here.
//
// Example use:
//
// for _, e := range blocks {
// if strings.ContainsAny(e, "\n") {
// // Match as stack
// } else {
// // Match as line
// }
// }
//
func parseBlocks(input string, detectStackboundaries bool) ([]string, error) {
var blocks []string
stack := ""
wasStack := false
lines := map[string]bool{} // already found lines
for _, l := range strings.Split(input, "\n") {
isStackLine := stackLineR.MatchString(l)
switch {
case !isStackLine && wasStack:
blocks = append(blocks, stack, l)
stack = ""
lines = map[string]bool{}
case isStackLine:
if wasStack {
// Detecting two stacks after another, possible cause lines match in
// our tests due to WithStack(WithStack(io.EOF)) on same line.
if detectStackboundaries {
if lines[l] {
if len(stack) == 0 {
return nil, errors.New("len of block must not be zero here")
}
blocks = append(blocks, stack)
stack = l
lines = map[string]bool{l: true}
continue
}
}
stack = stack + "\n" + l
} else {
stack = l
}
lines[l] = true
case !isStackLine && !wasStack:
blocks = append(blocks, l)
default:
return nil, errors.New("must not happen")
}
wasStack = isStackLine
}
// Use up stack
if stack != "" {
blocks = append(blocks, stack)
}
return blocks, nil
}
func testFormatCompleteCompare(t *testing.T, n int, arg interface{}, format string, want []string, detectStackBoundaries bool) {
gotStr := fmt.Sprintf(format, arg)
got, err := parseBlocks(gotStr, detectStackBoundaries)
if err != nil {
t.Fatal(err)
}
if len(got) != len(want) {
t.Fatalf("test %d: fmt.Sprintf(%s, err) -> wrong number of blocks: got(%d) want(%d)\n got: %s\nwant: %s\ngotStr: %q",
n+1, format, len(got), len(want), prettyBlocks(got), prettyBlocks(want), gotStr)
}
for i := range got {
if strings.ContainsAny(want[i], "\n") {
// Match as stack
match, err := regexp.MatchString(want[i], got[i])
if err != nil {
t.Fatal(err)
}
if !match {
t.Fatalf("test %d: block %d: fmt.Sprintf(%q, err):\ngot:\n%q\nwant:\n%q\nall-got:\n%s\nall-want:\n%s\n",
n+1, i+1, format, got[i], want[i], prettyBlocks(got), prettyBlocks(want))
}
} else {
// Match as message
if got[i] != want[i] {
t.Fatalf("test %d: fmt.Sprintf(%s, err) at block %d got != want:\n got: %q\nwant: %q", n+1, format, i+1, got[i], want[i])
}
}
}
}
type wrapper struct {
wrap func(err error) error
want []string
}
func prettyBlocks(blocks []string, prefix ...string) string {
var out []string
for _, b := range blocks {
out = append(out, fmt.Sprintf("%v", b))
}
return " " + strings.Join(out, "\n ")
}
func testGenericRecursive(t *testing.T, beforeErr error, beforeWant []string, list []wrapper, maxDepth int) {
if len(beforeWant) == 0 {
panic("beforeWant must not be empty")
}
for _, w := range list {
if len(w.want) == 0 {
panic("want must not be empty")
}
err := w.wrap(beforeErr)
// Copy required cause append(beforeWant, ..) modified beforeWant subtly.
beforeCopy := make([]string, len(beforeWant))
copy(beforeCopy, beforeWant)
beforeWant := beforeCopy
last := len(beforeWant) - 1
var want []string
// Merge two stacks behind each other.
if strings.ContainsAny(beforeWant[last], "\n") && strings.ContainsAny(w.want[0], "\n") {
want = append(beforeWant[:last], append([]string{beforeWant[last] + "((?s).*)" + w.want[0]}, w.want[1:]...)...)
} else {
want = append(beforeWant, w.want...)
}
testFormatCompleteCompare(t, maxDepth, err, "%+v", want, false)
if maxDepth > 0 {
testGenericRecursive(t, err, want, list, maxDepth-1)
}
}
}

View File

@ -1,292 +0,0 @@
package errors
import (
"fmt"
"runtime"
"testing"
)
var initpc, _, _, _ = runtime.Caller(0)
func TestFrameLine(t *testing.T) {
var tests = []struct {
Frame
want int
}{{
Frame(initpc),
9,
}, {
func() Frame {
var pc, _, _, _ = runtime.Caller(0)
return Frame(pc)
}(),
20,
}, {
func() Frame {
var pc, _, _, _ = runtime.Caller(1)
return Frame(pc)
}(),
28,
}, {
Frame(0), // invalid PC
0,
}}
for _, tt := range tests {
got := tt.Frame.line()
want := tt.want
if want != got {
t.Errorf("Frame(%v): want: %v, got: %v", uintptr(tt.Frame), want, got)
}
}
}
type X struct{}
func (x X) val() Frame {
var pc, _, _, _ = runtime.Caller(0)
return Frame(pc)
}
func (x *X) ptr() Frame {
var pc, _, _, _ = runtime.Caller(0)
return Frame(pc)
}
func TestFrameFormat(t *testing.T) {
var tests = []struct {
Frame
format string
want string
}{{
Frame(initpc),
"%s",
"stack_test.go",
}, {
Frame(initpc),
"%+s",
"github.com/pkg/errors.init\n" +
"\t.+/github.com/pkg/errors/stack_test.go",
}, {
Frame(0),
"%s",
"unknown",
}, {
Frame(0),
"%+s",
"unknown",
}, {
Frame(initpc),
"%d",
"9",
}, {
Frame(0),
"%d",
"0",
}, {
Frame(initpc),
"%n",
"init",
}, {
func() Frame {
var x X
return x.ptr()
}(),
"%n",
`\(\*X\).ptr`,
}, {
func() Frame {
var x X
return x.val()
}(),
"%n",
"X.val",
}, {
Frame(0),
"%n",
"",
}, {
Frame(initpc),
"%v",
"stack_test.go:9",
}, {
Frame(initpc),
"%+v",
"github.com/pkg/errors.init\n" +
"\t.+/github.com/pkg/errors/stack_test.go:9",
}, {
Frame(0),
"%v",
"unknown:0",
}}
for i, tt := range tests {
testFormatRegexp(t, i, tt.Frame, tt.format, tt.want)
}
}
func TestFuncname(t *testing.T) {
tests := []struct {
name, want string
}{
{"", ""},
{"runtime.main", "main"},
{"github.com/pkg/errors.funcname", "funcname"},
{"funcname", "funcname"},
{"io.copyBuffer", "copyBuffer"},
{"main.(*R).Write", "(*R).Write"},
}
for _, tt := range tests {
got := funcname(tt.name)
want := tt.want
if got != want {
t.Errorf("funcname(%q): want: %q, got %q", tt.name, want, got)
}
}
}
func TestTrimGOPATH(t *testing.T) {
var tests = []struct {
Frame
want string
}{{
Frame(initpc),
"github.com/pkg/errors/stack_test.go",
}}
for i, tt := range tests {
pc := tt.Frame.pc()
fn := runtime.FuncForPC(pc)
file, _ := fn.FileLine(pc)
got := trimGOPATH(fn.Name(), file)
testFormatRegexp(t, i, got, "%s", tt.want)
}
}
func TestStackTrace(t *testing.T) {
tests := []struct {
err error
want []string
}{{
New("ooh"), []string{
"github.com/pkg/errors.TestStackTrace\n" +
"\t.+/github.com/pkg/errors/stack_test.go:172",
},
}, {
Wrap(New("ooh"), "ahh"), []string{
"github.com/pkg/errors.TestStackTrace\n" +
"\t.+/github.com/pkg/errors/stack_test.go:177", // this is the stack of Wrap, not New
},
}, {
Cause(Wrap(New("ooh"), "ahh")), []string{
"github.com/pkg/errors.TestStackTrace\n" +
"\t.+/github.com/pkg/errors/stack_test.go:182", // this is the stack of New
},
}, {
func() error { return New("ooh") }(), []string{
`github.com/pkg/errors.(func·009|TestStackTrace.func1)` +
"\n\t.+/github.com/pkg/errors/stack_test.go:187", // this is the stack of New
"github.com/pkg/errors.TestStackTrace\n" +
"\t.+/github.com/pkg/errors/stack_test.go:187", // this is the stack of New's caller
},
}, {
Cause(func() error {
return func() error {
return Errorf("hello %s", fmt.Sprintf("world"))
}()
}()), []string{
`github.com/pkg/errors.(func·010|TestStackTrace.func2.1)` +
"\n\t.+/github.com/pkg/errors/stack_test.go:196", // this is the stack of Errorf
`github.com/pkg/errors.(func·011|TestStackTrace.func2)` +
"\n\t.+/github.com/pkg/errors/stack_test.go:197", // this is the stack of Errorf's caller
"github.com/pkg/errors.TestStackTrace\n" +
"\t.+/github.com/pkg/errors/stack_test.go:198", // this is the stack of Errorf's caller's caller
},
}}
for i, tt := range tests {
x, ok := tt.err.(interface {
StackTrace() StackTrace
})
if !ok {
t.Errorf("expected %#v to implement StackTrace() StackTrace", tt.err)
continue
}
st := x.StackTrace()
for j, want := range tt.want {
testFormatRegexp(t, i, st[j], "%+v", want)
}
}
}
func stackTrace() StackTrace {
const depth = 8
var pcs [depth]uintptr
n := runtime.Callers(1, pcs[:])
var st stack = pcs[0:n]
return st.StackTrace()
}
func TestStackTraceFormat(t *testing.T) {
tests := []struct {
StackTrace
format string
want string
}{{
nil,
"%s",
`\[\]`,
}, {
nil,
"%v",
`\[\]`,
}, {
nil,
"%+v",
"",
}, {
nil,
"%#v",
`\[\]errors.Frame\(nil\)`,
}, {
make(StackTrace, 0),
"%s",
`\[\]`,
}, {
make(StackTrace, 0),
"%v",
`\[\]`,
}, {
make(StackTrace, 0),
"%+v",
"",
}, {
make(StackTrace, 0),
"%#v",
`\[\]errors.Frame{}`,
}, {
stackTrace()[:2],
"%s",
`\[stack_test.go stack_test.go\]`,
}, {
stackTrace()[:2],
"%v",
`\[stack_test.go:225 stack_test.go:272\]`,
}, {
stackTrace()[:2],
"%+v",
"\n" +
"github.com/pkg/errors.stackTrace\n" +
"\t.+/github.com/pkg/errors/stack_test.go:225\n" +
"github.com/pkg/errors.TestStackTraceFormat\n" +
"\t.+/github.com/pkg/errors/stack_test.go:276",
}, {
stackTrace()[:2],
"%#v",
`\[\]errors.Frame{stack_test.go:225, stack_test.go:284}`,
}}
for i, tt := range tests {
testFormatRegexp(t, i, tt.StackTrace, tt.format, tt.want)
}
}

View File

@ -1,5 +0,0 @@
language: go
go:
- 1.5
- tip

View File

@ -1,50 +0,0 @@
go-difflib
==========
[![Build Status](https://travis-ci.org/pmezard/go-difflib.png?branch=master)](https://travis-ci.org/pmezard/go-difflib)
[![GoDoc](https://godoc.org/github.com/pmezard/go-difflib/difflib?status.svg)](https://godoc.org/github.com/pmezard/go-difflib/difflib)
Go-difflib is a partial port of python 3 difflib package. Its main goal
was to make unified and context diff available in pure Go, mostly for
testing purposes.
The following class and functions (and related tests) have be ported:
* `SequenceMatcher`
* `unified_diff()`
* `context_diff()`
## Installation
```bash
$ go get github.com/pmezard/go-difflib/difflib
```
### Quick Start
Diffs are configured with Unified (or ContextDiff) structures, and can
be output to an io.Writer or returned as a string.
```Go
diff := UnifiedDiff{
A: difflib.SplitLines("foo\nbar\n"),
B: difflib.SplitLines("foo\nbaz\n"),
FromFile: "Original",
ToFile: "Current",
Context: 3,
}
text, _ := GetUnifiedDiffString(diff)
fmt.Printf(text)
```
would output:
```
--- Original
+++ Current
@@ -1,3 +1,3 @@
foo
-bar
+baz
```

View File

@ -1,426 +0,0 @@
package difflib
import (
"bytes"
"fmt"
"math"
"reflect"
"strings"
"testing"
)
func assertAlmostEqual(t *testing.T, a, b float64, places int) {
if math.Abs(a-b) > math.Pow10(-places) {
t.Errorf("%.7f != %.7f", a, b)
}
}
func assertEqual(t *testing.T, a, b interface{}) {
if !reflect.DeepEqual(a, b) {
t.Errorf("%v != %v", a, b)
}
}
func splitChars(s string) []string {
chars := make([]string, 0, len(s))
// Assume ASCII inputs
for i := 0; i != len(s); i++ {
chars = append(chars, string(s[i]))
}
return chars
}
func TestSequenceMatcherRatio(t *testing.T) {
s := NewMatcher(splitChars("abcd"), splitChars("bcde"))
assertEqual(t, s.Ratio(), 0.75)
assertEqual(t, s.QuickRatio(), 0.75)
assertEqual(t, s.RealQuickRatio(), 1.0)
}
func TestGetOptCodes(t *testing.T) {
a := "qabxcd"
b := "abycdf"
s := NewMatcher(splitChars(a), splitChars(b))
w := &bytes.Buffer{}
for _, op := range s.GetOpCodes() {
fmt.Fprintf(w, "%s a[%d:%d], (%s) b[%d:%d] (%s)\n", string(op.Tag),
op.I1, op.I2, a[op.I1:op.I2], op.J1, op.J2, b[op.J1:op.J2])
}
result := string(w.Bytes())
expected := `d a[0:1], (q) b[0:0] ()
e a[1:3], (ab) b[0:2] (ab)
r a[3:4], (x) b[2:3] (y)
e a[4:6], (cd) b[3:5] (cd)
i a[6:6], () b[5:6] (f)
`
if expected != result {
t.Errorf("unexpected op codes: \n%s", result)
}
}
func TestGroupedOpCodes(t *testing.T) {
a := []string{}
for i := 0; i != 39; i++ {
a = append(a, fmt.Sprintf("%02d", i))
}
b := []string{}
b = append(b, a[:8]...)
b = append(b, " i")
b = append(b, a[8:19]...)
b = append(b, " x")
b = append(b, a[20:22]...)
b = append(b, a[27:34]...)
b = append(b, " y")
b = append(b, a[35:]...)
s := NewMatcher(a, b)
w := &bytes.Buffer{}
for _, g := range s.GetGroupedOpCodes(-1) {
fmt.Fprintf(w, "group\n")
for _, op := range g {
fmt.Fprintf(w, " %s, %d, %d, %d, %d\n", string(op.Tag),
op.I1, op.I2, op.J1, op.J2)
}
}
result := string(w.Bytes())
expected := `group
e, 5, 8, 5, 8
i, 8, 8, 8, 9
e, 8, 11, 9, 12
group
e, 16, 19, 17, 20
r, 19, 20, 20, 21
e, 20, 22, 21, 23
d, 22, 27, 23, 23
e, 27, 30, 23, 26
group
e, 31, 34, 27, 30
r, 34, 35, 30, 31
e, 35, 38, 31, 34
`
if expected != result {
t.Errorf("unexpected op codes: \n%s", result)
}
}
func ExampleGetUnifiedDiffCode() {
a := `one
two
three
four
fmt.Printf("%s,%T",a,b)`
b := `zero
one
three
four`
diff := UnifiedDiff{
A: SplitLines(a),
B: SplitLines(b),
FromFile: "Original",
FromDate: "2005-01-26 23:30:50",
ToFile: "Current",
ToDate: "2010-04-02 10:20:52",
Context: 3,
}
result, _ := GetUnifiedDiffString(diff)
fmt.Println(strings.Replace(result, "\t", " ", -1))
// Output:
// --- Original 2005-01-26 23:30:50
// +++ Current 2010-04-02 10:20:52
// @@ -1,5 +1,4 @@
// +zero
// one
// -two
// three
// four
// -fmt.Printf("%s,%T",a,b)
}
func ExampleGetContextDiffCode() {
a := `one
two
three
four
fmt.Printf("%s,%T",a,b)`
b := `zero
one
tree
four`
diff := ContextDiff{
A: SplitLines(a),
B: SplitLines(b),
FromFile: "Original",
ToFile: "Current",
Context: 3,
Eol: "\n",
}
result, _ := GetContextDiffString(diff)
fmt.Print(strings.Replace(result, "\t", " ", -1))
// Output:
// *** Original
// --- Current
// ***************
// *** 1,5 ****
// one
// ! two
// ! three
// four
// - fmt.Printf("%s,%T",a,b)
// --- 1,4 ----
// + zero
// one
// ! tree
// four
}
func ExampleGetContextDiffString() {
a := `one
two
three
four`
b := `zero
one
tree
four`
diff := ContextDiff{
A: SplitLines(a),
B: SplitLines(b),
FromFile: "Original",
ToFile: "Current",
Context: 3,
Eol: "\n",
}
result, _ := GetContextDiffString(diff)
fmt.Printf(strings.Replace(result, "\t", " ", -1))
// Output:
// *** Original
// --- Current
// ***************
// *** 1,4 ****
// one
// ! two
// ! three
// four
// --- 1,4 ----
// + zero
// one
// ! tree
// four
}
func rep(s string, count int) string {
return strings.Repeat(s, count)
}
func TestWithAsciiOneInsert(t *testing.T) {
sm := NewMatcher(splitChars(rep("b", 100)),
splitChars("a"+rep("b", 100)))
assertAlmostEqual(t, sm.Ratio(), 0.995, 3)
assertEqual(t, sm.GetOpCodes(),
[]OpCode{{'i', 0, 0, 0, 1}, {'e', 0, 100, 1, 101}})
assertEqual(t, len(sm.bPopular), 0)
sm = NewMatcher(splitChars(rep("b", 100)),
splitChars(rep("b", 50)+"a"+rep("b", 50)))
assertAlmostEqual(t, sm.Ratio(), 0.995, 3)
assertEqual(t, sm.GetOpCodes(),
[]OpCode{{'e', 0, 50, 0, 50}, {'i', 50, 50, 50, 51}, {'e', 50, 100, 51, 101}})
assertEqual(t, len(sm.bPopular), 0)
}
func TestWithAsciiOnDelete(t *testing.T) {
sm := NewMatcher(splitChars(rep("a", 40)+"c"+rep("b", 40)),
splitChars(rep("a", 40)+rep("b", 40)))
assertAlmostEqual(t, sm.Ratio(), 0.994, 3)
assertEqual(t, sm.GetOpCodes(),
[]OpCode{{'e', 0, 40, 0, 40}, {'d', 40, 41, 40, 40}, {'e', 41, 81, 40, 80}})
}
func TestWithAsciiBJunk(t *testing.T) {
isJunk := func(s string) bool {
return s == " "
}
sm := NewMatcherWithJunk(splitChars(rep("a", 40)+rep("b", 40)),
splitChars(rep("a", 44)+rep("b", 40)), true, isJunk)
assertEqual(t, sm.bJunk, map[string]struct{}{})
sm = NewMatcherWithJunk(splitChars(rep("a", 40)+rep("b", 40)),
splitChars(rep("a", 44)+rep("b", 40)+rep(" ", 20)), false, isJunk)
assertEqual(t, sm.bJunk, map[string]struct{}{" ": struct{}{}})
isJunk = func(s string) bool {
return s == " " || s == "b"
}
sm = NewMatcherWithJunk(splitChars(rep("a", 40)+rep("b", 40)),
splitChars(rep("a", 44)+rep("b", 40)+rep(" ", 20)), false, isJunk)
assertEqual(t, sm.bJunk, map[string]struct{}{" ": struct{}{}, "b": struct{}{}})
}
func TestSFBugsRatioForNullSeqn(t *testing.T) {
sm := NewMatcher(nil, nil)
assertEqual(t, sm.Ratio(), 1.0)
assertEqual(t, sm.QuickRatio(), 1.0)
assertEqual(t, sm.RealQuickRatio(), 1.0)
}
func TestSFBugsComparingEmptyLists(t *testing.T) {
groups := NewMatcher(nil, nil).GetGroupedOpCodes(-1)
assertEqual(t, len(groups), 0)
diff := UnifiedDiff{
FromFile: "Original",
ToFile: "Current",
Context: 3,
}
result, err := GetUnifiedDiffString(diff)
assertEqual(t, err, nil)
assertEqual(t, result, "")
}
func TestOutputFormatRangeFormatUnified(t *testing.T) {
// Per the diff spec at http://www.unix.org/single_unix_specification/
//
// Each <range> field shall be of the form:
// %1d", <beginning line number> if the range contains exactly one line,
// and:
// "%1d,%1d", <beginning line number>, <number of lines> otherwise.
// If a range is empty, its beginning line number shall be the number of
// the line just before the range, or 0 if the empty range starts the file.
fm := formatRangeUnified
assertEqual(t, fm(3, 3), "3,0")
assertEqual(t, fm(3, 4), "4")
assertEqual(t, fm(3, 5), "4,2")
assertEqual(t, fm(3, 6), "4,3")
assertEqual(t, fm(0, 0), "0,0")
}
func TestOutputFormatRangeFormatContext(t *testing.T) {
// Per the diff spec at http://www.unix.org/single_unix_specification/
//
// The range of lines in file1 shall be written in the following format
// if the range contains two or more lines:
// "*** %d,%d ****\n", <beginning line number>, <ending line number>
// and the following format otherwise:
// "*** %d ****\n", <ending line number>
// The ending line number of an empty range shall be the number of the preceding line,
// or 0 if the range is at the start of the file.
//
// Next, the range of lines in file2 shall be written in the following format
// if the range contains two or more lines:
// "--- %d,%d ----\n", <beginning line number>, <ending line number>
// and the following format otherwise:
// "--- %d ----\n", <ending line number>
fm := formatRangeContext
assertEqual(t, fm(3, 3), "3")
assertEqual(t, fm(3, 4), "4")
assertEqual(t, fm(3, 5), "4,5")
assertEqual(t, fm(3, 6), "4,6")
assertEqual(t, fm(0, 0), "0")
}
func TestOutputFormatTabDelimiter(t *testing.T) {
diff := UnifiedDiff{
A: splitChars("one"),
B: splitChars("two"),
FromFile: "Original",
FromDate: "2005-01-26 23:30:50",
ToFile: "Current",
ToDate: "2010-04-12 10:20:52",
Eol: "\n",
}
ud, err := GetUnifiedDiffString(diff)
assertEqual(t, err, nil)
assertEqual(t, SplitLines(ud)[:2], []string{
"--- Original\t2005-01-26 23:30:50\n",
"+++ Current\t2010-04-12 10:20:52\n",
})
cd, err := GetContextDiffString(ContextDiff(diff))
assertEqual(t, err, nil)
assertEqual(t, SplitLines(cd)[:2], []string{
"*** Original\t2005-01-26 23:30:50\n",
"--- Current\t2010-04-12 10:20:52\n",
})
}
func TestOutputFormatNoTrailingTabOnEmptyFiledate(t *testing.T) {
diff := UnifiedDiff{
A: splitChars("one"),
B: splitChars("two"),
FromFile: "Original",
ToFile: "Current",
Eol: "\n",
}
ud, err := GetUnifiedDiffString(diff)
assertEqual(t, err, nil)
assertEqual(t, SplitLines(ud)[:2], []string{"--- Original\n", "+++ Current\n"})
cd, err := GetContextDiffString(ContextDiff(diff))
assertEqual(t, err, nil)
assertEqual(t, SplitLines(cd)[:2], []string{"*** Original\n", "--- Current\n"})
}
func TestOmitFilenames(t *testing.T) {
diff := UnifiedDiff{
A: SplitLines("o\nn\ne\n"),
B: SplitLines("t\nw\no\n"),
Eol: "\n",
}
ud, err := GetUnifiedDiffString(diff)
assertEqual(t, err, nil)
assertEqual(t, SplitLines(ud), []string{
"@@ -0,0 +1,2 @@\n",
"+t\n",
"+w\n",
"@@ -2,2 +3,0 @@\n",
"-n\n",
"-e\n",
"\n",
})
cd, err := GetContextDiffString(ContextDiff(diff))
assertEqual(t, err, nil)
assertEqual(t, SplitLines(cd), []string{
"***************\n",
"*** 0 ****\n",
"--- 1,2 ----\n",
"+ t\n",
"+ w\n",
"***************\n",
"*** 2,3 ****\n",
"- n\n",
"- e\n",
"--- 3 ----\n",
"\n",
})
}
func TestSplitLines(t *testing.T) {
allTests := []struct {
input string
want []string
}{
{"foo", []string{"foo\n"}},
{"foo\nbar", []string{"foo\n", "bar\n"}},
{"foo\nbar\n", []string{"foo\n", "bar\n", "\n"}},
}
for _, test := range allTests {
assertEqual(t, SplitLines(test.input), test.want)
}
}
func benchmarkSplitLines(b *testing.B, count int) {
str := strings.Repeat("foo\n", count)
b.ResetTimer()
n := 0
for i := 0; i < b.N; i++ {
n += len(SplitLines(str))
}
}
func BenchmarkSplitLines100(b *testing.B) {
benchmarkSplitLines(b, 100)
}
func BenchmarkSplitLines10000(b *testing.B) {
benchmarkSplitLines(b, 10000)
}

24
vendor/github.com/schollz/bytetoword/LICENSE generated vendored Normal file
View File

@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
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 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.
For more information, please refer to <http://unlicense.org>

18
vendor/github.com/schollz/bytetoword/README.md generated vendored Normal file
View File

@ -0,0 +1,18 @@
# bytetoword
This will convert Go bytes to words. Every word is for one byte.
The word list is generated using
```
curl https://raw.githubusercontent.com/schollz/BandGenerator/master/dictionary.txt > dictionary.txt
curl https://raw.githubusercontent.com/dwyl/english-words/master/words.txt >> dictionary.txt
python3 run.py
```
and then copy-paste the `words.txt` into `words.go`.
## License
Unlicense

65848
vendor/github.com/schollz/bytetoword/bytetoword.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

35
vendor/github.com/schollz/bytetoword/run.py generated vendored Normal file
View File

@ -0,0 +1,35 @@
import random
words = []
with open("dictionary.txt","rb") as f:
for line in f:
words.append(line.split(b"(")[0].strip().lower())
words = list(set(words))
print(len(words))
word_lengths = {}
word_skips = list(b" !@#$%^&*()_+-=[]{};':\<>?,./"+b'"')
for word in words:
if len(word) < 2:
continue
skip_word = False
for w in word_skips:
if w in word:
skip_word = True
break
if skip_word:
continue
word_lengths[word] = len(word)
print(len(word_lengths))
import operator
possible_words = []
for t in sorted(word_lengths.items(), key=operator.itemgetter(1)):
possible_words.append(t[0])
if len(possible_words) > 65536+256:
break
random.shuffle(possible_words)
with open('words.txt','wb') as f:
f.write((b"\n").join(possible_words))
# https://play.golang.org/p/VMtD2WfmH4D

View File

@ -1,38 +0,0 @@
package main
import (
"encoding/hex"
"io"
)
const bufsize = 256
type hexdump struct {
w io.Writer
buf [bufsize]byte
}
func hexoutput(w io.Writer) io.WriteCloser {
return &hexdump{w: w}
}
func (h *hexdump) Write(data []byte) (n int, err error) {
for n < len(data) {
amt := len(data) - n
if hex.EncodedLen(amt) > bufsize {
amt = hex.DecodedLen(bufsize)
}
nn := hex.Encode(h.buf[:], data[n:n+amt])
_, err := h.w.Write(h.buf[:nn])
n += amt
if err != nil {
return n, err
}
}
return n, nil
}
func (h *hexdump) Close() error {
_, err := h.w.Write([]byte{'\n'})
return err
}

View File

@ -1,51 +0,0 @@
package main
import (
"flag"
"io"
"log"
"os"
"path"
"bitbucket.org/dchapes/mnemonicode"
)
func main() {
log.SetFlags(0)
log.SetPrefix(path.Base(os.Args[0]) + ": ")
hexFlag := flag.Bool("x", false, "hex output")
verboseFlag := flag.Bool("v", false, "verbose")
flag.Parse()
if flag.NArg() > 0 {
flag.Usage()
os.Exit(2)
}
output := io.WriteCloser(os.Stdout)
if *hexFlag {
output = hexoutput(output)
}
var n int64
var err error
if true {
dec := mnemonicode.NewDecoder(os.Stdin)
n, err = io.Copy(output, dec)
} else {
w := mnemonicode.NewDecodeWriter(output)
n, err = io.Copy(w, os.Stdin)
if err != nil {
log.Fatal(err)
}
err = w.Close()
}
if err != nil {
log.Fatal(err)
}
if *verboseFlag {
log.Println("bytes decoded:", n)
}
if err = output.Close(); err != nil {
log.Fatal(err)
}
}

View File

@ -1,66 +0,0 @@
package main
import (
"encoding/hex"
"unicode"
"unicode/utf8"
"golang.org/x/text/transform"
)
type hexinput bool
func (h *hexinput) Reset() {
*h = false
}
func (h *hexinput) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
for r, sz := rune(0), 0; len(src) > 0; src = src[sz:] {
if r = rune(src[0]); r < utf8.RuneSelf {
sz = 1
} else {
r, sz = utf8.DecodeRune(src)
if sz == 1 {
// Invalid rune.
if !atEOF && !utf8.FullRune(src) {
err = transform.ErrShortSrc
break
}
// Just ignore it
nSrc++
continue
}
}
if unicode.IsSpace(r) {
nSrc += sz
continue
}
if sz > 1 {
err = hex.InvalidByteError(src[0]) // XXX
break
}
if len(src) < 2 {
err = transform.ErrShortSrc
break
}
if nDst+1 > len(dst) {
err = transform.ErrShortDst
break
}
sz = 2
nSrc += 2
if !*h {
*h = true
if r == '0' && (src[1] == 'x' || src[1] == 'X') {
continue
}
}
if _, err = hex.Decode(dst[nDst:], src[:2]); err != nil {
break
}
nDst++
}
return
}

View File

@ -1,118 +0,0 @@
package main
import (
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"path"
"strconv"
"golang.org/x/text/transform"
"bitbucket.org/dchapes/mnemonicode"
)
type quoted string
func (q quoted) Get() interface{} { return string(q) }
func (q quoted) String() string { return strconv.Quote(string(q)) }
func (q *quoted) Set(s string) (err error) {
if s, err = strconv.Unquote(`"` + s + `"`); err == nil {
*q = quoted(s)
}
return
}
type quotedRune rune
func (qr quotedRune) Get() interface{} { return rune(qr) }
func (qr quotedRune) String() string { return strconv.QuoteRune(rune(qr)) }
func (qr *quotedRune) Set(s string) error {
r, _, x, err := strconv.UnquoteChar(s, 0)
if err != nil {
return err
}
if x != "" {
return fmt.Errorf("more than a single rune")
}
*qr = quotedRune(r)
return nil
}
func main() {
log.SetFlags(0)
log.SetPrefix(path.Base(os.Args[0]) + ": ")
vlog := log.New(os.Stderr, log.Prefix(), log.Flags())
config := mnemonicode.NewDefaultConfig()
prefix := quoted(config.LinePrefix)
suffix := quoted(config.LineSuffix)
wordsep := quoted(config.WordSeparator)
groupsep := quoted(config.GroupSeparator)
pad := quotedRune(config.WordPadding)
flag.Var(&prefix, "prefix", "prefix each line with `string`")
flag.Var(&suffix, "suffix", "suffix each line with `string`")
flag.Var(&wordsep, "word", "separate each word with `wsep`")
flag.Var(&groupsep, "group", "separate each word group with `gsep`")
words := flag.Uint("words", config.WordsPerGroup, "words per group")
groups := flag.Uint("groups", config.GroupsPerLine, "groups per line")
nopad := flag.Bool("nopad", false, "do not pad words")
flag.Var(&pad, "pad", "pad shorter words with `rune`")
hexin := flag.Bool("x", false, "hex input")
verbose := flag.Bool("v", false, "verbose")
flag.Parse()
if flag.NArg() > 0 {
flag.Usage()
os.Exit(2)
}
if !*verbose {
vlog.SetOutput(ioutil.Discard)
}
config.LinePrefix = prefix.Get().(string)
config.LineSuffix = suffix.Get().(string)
config.GroupSeparator = groupsep.Get().(string)
config.WordSeparator = wordsep.Get().(string)
config.WordPadding = pad.Get().(rune)
if *words > 0 {
config.WordsPerGroup = *words
}
if *groups > 0 {
config.GroupsPerLine = *groups
}
if *nopad {
config.WordPadding = 0
}
vlog.Println("Wordlist ver", mnemonicode.WordListVersion)
input := io.Reader(os.Stdin)
if *hexin {
input = transform.NewReader(input, new(hexinput))
}
var n int64
var err error
if true {
enc := mnemonicode.NewEncoder(os.Stdout, config)
n, err = io.Copy(enc, input)
if err != nil {
log.Fatal(err)
}
err = enc.Close()
} else {
r := mnemonicode.NewEncodeReader(input, config)
n, err = io.Copy(os.Stdout, r)
}
if err != nil {
log.Fatal(err)
}
fmt.Println()
vlog.Println("bytes encoded:", n)
}

View File

@ -1,40 +0,0 @@
package mnemonicode_test
import (
"bytes"
"io"
"strings"
"testing"
"bitbucket.org/dchapes/mnemonicode"
)
func TestIssue002(t *testing.T) {
buf := &bytes.Buffer{}
// Code from:
const issue = `https://bitbucket.org/dchapes/mnemonicode/issues/2`
config := mnemonicode.NewDefaultConfig()
config.GroupsPerLine = 1
config.LineSuffix = "\n"
config.GroupSeparator = "\n"
config.WordPadding = 0
config.WordsPerGroup = 1
config.WordSeparator = "\n"
src := strings.NewReader("abcdefgh")
r := mnemonicode.NewEncodeReader(src, config)
//io.Copy(os.Stdout, r)
io.Copy(buf, r)
// Note, in the issue the expected trailing newline is missing.
const expected = ` bogart
atlas
safari
airport
cabaret
shock
`
if s := buf.String(); s != expected {
t.Errorf("%v\n\tgave %q\n\twant%q", issue, s, expected)
}
}

View File

@ -1,238 +0,0 @@
package mnemonicode
import (
"bytes"
"encoding/hex"
"fmt"
"strings"
"testing"
"golang.org/x/text/transform"
)
func TestWordsReq(t *testing.T) {
for i, n := range []int{0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10} {
r := WordsRequired(i)
if r != n {
t.Errorf("WordsRequired(%d) returned %d, expected %d", i, r, n)
}
}
}
var testData = []struct {
hex string
words []string
}{
{"01", []string{"acrobat"}},
{"0102", []string{"opera", "academy"}},
{"010203", []string{"kayak", "cement", "ego"}},
{"01020304", []string{"papa", "twist", "alpine"}},
{"0102030405", []string{"papa", "twist", "alpine", "admiral"}},
{"010203040506", []string{"papa", "twist", "alpine", "shine", "academy"}},
{"01020304050607", []string{"papa", "twist", "alpine", "chess", "flute", "ego"}},
{"0102030405060708", []string{"papa", "twist", "alpine", "content", "sailor", "athena"}},
{"00", []string{"academy"}},
{"5A06", []string{"academy", "acrobat"}},
{"FE5D28", []string{"academy", "acrobat", "fax"}},
{"A2B55000", []string{"academy", "acrobat", "active"}},
{"A2B5500003", []string{"academy", "acrobat", "active", "actor"}},
{"A2B550006B19", []string{"academy", "acrobat", "active", "actor", "adam"}},
{"A2B550000F7128", []string{"academy", "acrobat", "active", "actor", "adam", "fax"}},
{"A2B550009FCFC900", []string{"academy", "acrobat", "active", "actor", "adam", "admiral"}},
{"FF", []string{"exact"}},
{"FFFF", []string{"nevada", "archive"}},
{"FFFFFF", []string{"claudia", "photo", "yes"}},
{"FFFFFFFF", []string{"natural", "analyze", "verbal"}},
{"123456789ABCDEF123456789ABCDEF012345", []string{
"plastic", "roger", "vincent", "pilgrim", "flame", "secure", "apropos", "polka", "earth", "radio", "modern", "aladdin", "marion", "airline"}},
}
func compareWordList(tb testing.TB, expected, got []string, args ...interface{}) {
fail := false
if len(expected) != len(got) {
fail = true
}
for i := 0; !fail && i < len(expected); i++ {
fail = expected[i] != got[i]
}
if fail {
prefix := ""
if len(args) > 0 {
prefix += fmt.Sprintln(args...)
prefix = prefix[:len(prefix)-1] + ": "
}
tb.Errorf("%vexpected %v, got %v", prefix, expected, got)
}
}
func TestEncodeWordList(t *testing.T) {
var result []string
for i, d := range testData {
raw, err := hex.DecodeString(d.hex)
if err != nil {
t.Fatal("bad test data:", i, err)
}
result = EncodeWordList(result, raw)
compareWordList(t, d.words, result, i, d.hex)
result = result[:0]
}
}
func TestDecodeWordList(t *testing.T) {
var result []byte
var err error
for i, d := range testData {
raw, _ := hex.DecodeString(d.hex)
result, err = DecodeWordList(result, d.words)
if err != nil {
t.Errorf("%2d %v failed: %v", i, d.words, err)
continue
}
if !bytes.Equal(raw, result) {
t.Errorf("%2d %v expected %v got %v", i, d.words, raw, result)
}
result = result[:0]
}
}
func TestEncodeTransformer(t *testing.T) {
cfg := NewDefaultConfig()
cfg.GroupSeparator = " "
enc := NewEncodeTransformer(cfg)
for i, d := range testData {
raw, err := hex.DecodeString(d.hex)
if err != nil {
t.Fatal("bad test data:", i, err)
}
result, _, err := transform.Bytes(enc, raw)
if err != nil {
t.Errorf("%2d %v failed: %v", i, d.words, err)
continue
}
//t.Logf("%q", result)
words := strings.Fields(string(result))
compareWordList(t, d.words, words, i, d.hex)
}
}
func TestDecodeTransformer(t *testing.T) {
dec := NewDecodeTransformer()
for i, d := range testData {
raw, _ := hex.DecodeString(d.hex)
words := strings.Join(d.words, " ")
result, _, err := transform.Bytes(dec, []byte(words))
if err != nil {
t.Errorf("%2d %v failed: %v", i, d.words, err)
continue
}
if !bytes.Equal(raw, result) {
t.Errorf("%2d %v expected %v got %v", i, d.words, raw, result)
}
}
}
func TestEncodeFormatting(t *testing.T) {
raw, _ := hex.DecodeString(testData[20].hex)
input := string(raw)
//words := testData[20].words
tests := []struct {
cfg *Config
formatted string
}{
{nil, "plastic roger vincent - pilgrim flame secure - apropos polka earth \nradio modern aladdin - marion airline"},
{&Config{
LinePrefix: "{P}",
LineSuffix: "{S}\n",
WordSeparator: "{w}",
GroupSeparator: "{g}",
WordsPerGroup: 2,
GroupsPerLine: 2,
WordPadding: '·',
},
`{P}plastic{w}roger··{g}vincent{w}pilgrim{S}
{P}flame··{w}secure·{g}apropos{w}polka··{S}
{P}earth··{w}radio··{g}modern·{w}aladdin{S}
{P}marion·{w}airline`},
}
for i, d := range tests {
enc := NewEncodeTransformer(d.cfg)
result, _, err := transform.String(enc, input)
if err != nil {
t.Errorf("%2d transform failed: %v", i, err)
continue
}
if result != d.formatted {
t.Errorf("%2d expected:\n%q\ngot:\n%q", i, d.formatted, result)
}
}
}
func BenchmarkEncodeWordList(b *testing.B) {
// the list of all known words (except the short end words)
data, err := DecodeWordList(nil, wordList[:base])
if err != nil {
b.Fatal("DecodeWordList failed:", err)
}
b.SetBytes(int64(len(data)))
b.ReportAllocs()
b.ResetTimer()
var words []string
for i := 0; i < b.N; i++ {
words = EncodeWordList(words[:0], data)
}
}
func BenchmarkDencodeWordList(b *testing.B) {
b.ReportAllocs()
var buf []byte
var err error
// decode the list of all known words (except the short end words)
for i := 0; i < b.N; i++ {
buf, err = DecodeWordList(buf[:0], wordList[:base])
if err != nil {
b.Fatal("DecodeWordList failed:", err)
}
}
b.SetBytes(int64(len(buf)))
}
func BenchmarkEncodeTransformer(b *testing.B) {
// the list of all known words (except the short end words)
data, err := DecodeWordList(nil, wordList[:base])
if err != nil {
b.Fatal("DecodeWordList failed:", err)
}
enc := NewEncodeTransformer(nil)
b.SetBytes(int64(len(data)))
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _, err := transform.Bytes(enc, data)
if err != nil {
b.Fatal("encode transformer error:", err)
}
}
}
func BenchmarkDecodeTransformer(b *testing.B) {
data, err := DecodeWordList(nil, wordList[:base])
if err != nil {
b.Fatal("DecodeWordList failed:", err)
}
enc := NewEncodeTransformer(nil)
words, _, err := transform.Bytes(enc, data)
if err != nil {
b.Fatal("encode transformer error:", err)
}
b.SetBytes(int64(len(data)))
dec := NewDecodeTransformer()
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _, err := transform.Bytes(dec, words)
if err != nil {
b.Fatal("decode transformer error:", err)
}
}
}

View File

@ -1,75 +0,0 @@
package main
import (
"fmt"
"log"
math_rand "math/rand"
"time"
"github.com/schollz/peerdiscovery"
"github.com/schollz/progressbar"
)
func main() {
fmt.Println("Scanning for 10 seconds to find LAN peers")
// show progress bar
go func() {
bar := progressbar.New(10)
for i := 0; i < 10; i++ {
bar.Add(1)
time.Sleep(1 * time.Second)
}
fmt.Print("\n")
}()
// discover peers
discoveries, err := peerdiscovery.Discover(peerdiscovery.Settings{
Limit: -1,
Payload: []byte(randStringBytesMaskImprSrc(10)),
Delay: 500 * time.Millisecond,
TimeLimit: 10 * time.Second,
})
// print out results
if err != nil {
log.Fatal(err)
} else {
if len(discoveries) > 0 {
fmt.Printf("Found %d other computers\n", len(discoveries))
for i, d := range discoveries {
fmt.Printf("%d) '%s' with payload '%s'\n", i, d.Address, d.Payload)
}
} else {
fmt.Println("Found no devices. You need to run this on another computer at the same time.")
}
}
}
// src is seeds the random generator for generating random strings
var src = math_rand.NewSource(time.Now().UnixNano())
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
const (
letterIdxBits = 6 // 6 bits to represent a letter index
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
)
// RandStringBytesMaskImprSrc prints a random string
func randStringBytesMaskImprSrc(n int) string {
b := make([]byte, n)
// A src.Int63() generates 63 random bits, enough for letterIdxMax characters!
for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; {
if remain == 0 {
cache, remain = src.Int63(), letterIdxMax
}
if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
b[i] = letterBytes[idx]
i--
}
cache >>= letterIdxBits
remain--
}
return string(b)
}

Some files were not shown because too many files have changed in this diff Show More