Commit 51fd99e3 authored by Jeromy's avatar Jeromy
Browse files

extract from 0.4.0

parent 5a0162c7
package testutil
import (
"math/rand"
"sync"
"time"
)
var SeededRand *rand.Rand
func init() {
SeededRand = NewSeededRand(time.Now().UTC().UnixNano())
}
func NewSeededRand(seed int64) *rand.Rand {
src := rand.NewSource(seed)
return rand.New(&LockedRandSource{src: src})
}
type LockedRandSource struct {
lk sync.Mutex
src rand.Source
}
func (r *LockedRandSource) Int63() (n int64) {
r.lk.Lock()
n = r.src.Int63()
r.lk.Unlock()
return
}
func (r *LockedRandSource) Seed(seed int64) {
r.lk.Lock()
r.src.Seed(seed)
r.lk.Unlock()
}
package util
import "time"
var TimeFormatIpfs = time.RFC3339Nano
func ParseRFC3339(s string) (time.Time, error) {
t, err := time.Parse(TimeFormatIpfs, s)
if err != nil {
return time.Time{}, err
}
return t.UTC(), nil
}
func FormatRFC3339(t time.Time) string {
return t.UTC().Format(TimeFormatIpfs)
}
package util
import (
"testing"
"time"
)
func TestTimeFormatParseInversion(t *testing.T) {
v, err := ParseRFC3339(FormatRFC3339(time.Now()))
if err != nil {
t.Fatal(err)
}
if v.Location() != time.UTC {
t.Fatal("Time should be UTC")
}
}
// Package util implements various utility functions used within ipfs
// that do not currently have a better place to live.
package util
import (
"errors"
"io"
"math/rand"
"os"
"path/filepath"
"runtime/debug"
"strings"
"time"
b58 "github.com/jbenet/go-base58"
mh "github.com/jbenet/go-multihash"
)
// Debug is a global flag for debugging.
var Debug bool
// ErrNotImplemented signifies a function has not been implemented yet.
var ErrNotImplemented = errors.New("Error: not implemented yet.")
// ErrTimeout implies that a timeout has been triggered
var ErrTimeout = errors.New("Error: Call timed out.")
// ErrSeErrSearchIncomplete implies that a search type operation didnt
// find the expected node, but did find 'a' node.
var ErrSearchIncomplete = errors.New("Error: Search Incomplete.")
// ErrCast is returned when a cast fails AND the program should not panic.
func ErrCast() error {
debug.PrintStack()
return errCast
}
var errCast = errors.New("cast error")
// ExpandPathnames takes a set of paths and turns them into absolute paths
func ExpandPathnames(paths []string) ([]string, error) {
var out []string
for _, p := range paths {
abspath, err := filepath.Abs(p)
if err != nil {
return nil, err
}
out = append(out, abspath)
}
return out, nil
}
type randGen struct {
rand.Rand
}
func NewTimeSeededRand() io.Reader {
src := rand.NewSource(time.Now().UnixNano())
return &randGen{
Rand: *rand.New(src),
}
}
func NewSeededRand(seed int64) io.Reader {
src := rand.NewSource(seed)
return &randGen{
Rand: *rand.New(src),
}
}
func (r *randGen) Read(p []byte) (n int, err error) {
for i := 0; i < len(p); i++ {
p[i] = byte(r.Rand.Intn(255))
}
return len(p), nil
}
// GetenvBool is the way to check an env var as a boolean
func GetenvBool(name string) bool {
v := strings.ToLower(os.Getenv(name))
return v == "true" || v == "t" || v == "1"
}
// MultiErr is a util to return multiple errors
type MultiErr []error
func (m MultiErr) Error() string {
if len(m) == 0 {
return "no errors"
}
s := "Multiple errors: "
for i, e := range m {
if i != 0 {
s += ", "
}
s += e.Error()
}
return s
}
func Partition(subject string, sep string) (string, string, string) {
if i := strings.Index(subject, sep); i != -1 {
return subject[:i], subject[i : i+len(sep)], subject[i+len(sep):]
}
return subject, "", ""
}
func RPartition(subject string, sep string) (string, string, string) {
if i := strings.LastIndex(subject, sep); i != -1 {
return subject[:i], subject[i : i+len(sep)], subject[i+len(sep):]
}
return subject, "", ""
}
// Hash is the global IPFS hash function. uses multihash SHA2_256, 256 bits
func Hash(data []byte) mh.Multihash {
h, err := mh.Sum(data, mh.SHA2_256, -1)
if err != nil {
// this error can be safely ignored (panic) because multihash only fails
// from the selection of hash function. If the fn + length are valid, it
// won't error.
panic("multihash failed to hash using SHA2_256.")
}
return h
}
// IsValidHash checks whether a given hash is valid (b58 decodable, len > 0)
func IsValidHash(s string) bool {
out := b58.Decode(s)
if out == nil || len(out) == 0 {
return false
}
_, err := mh.Cast(out)
if err != nil {
return false
}
return true
}
// XOR takes two byte slices, XORs them together, returns the resulting slice.
func XOR(a, b []byte) []byte {
c := make([]byte, len(a))
for i := 0; i < len(a); i++ {
c[i] = a[i] ^ b[i]
}
return c
}
package util
import (
"bytes"
"testing"
)
func TestXOR(t *testing.T) {
cases := [][3][]byte{
{
{0xFF, 0xFF, 0xFF},
{0xFF, 0xFF, 0xFF},
{0x00, 0x00, 0x00},
},
{
{0x00, 0xFF, 0x00},
{0xFF, 0xFF, 0xFF},
{0xFF, 0x00, 0xFF},
},
{
{0x55, 0x55, 0x55},
{0x55, 0xFF, 0xAA},
{0x00, 0xAA, 0xFF},
},
}
for _, c := range cases {
r := XOR(c[0], c[1])
if !bytes.Equal(r, c[2]) {
t.Error("XOR failed")
}
}
}
func BenchmarkHash256K(b *testing.B) {
buf := make([]byte, 256*1024)
NewTimeSeededRand().Read(buf)
b.SetBytes(int64(256 * 1024))
b.ResetTimer()
for i := 0; i < b.N; i++ {
Hash(buf)
}
}
func BenchmarkHash512K(b *testing.B) {
buf := make([]byte, 512*1024)
NewTimeSeededRand().Read(buf)
b.SetBytes(int64(512 * 1024))
b.ResetTimer()
for i := 0; i < b.N; i++ {
Hash(buf)
}
}
func BenchmarkHash1M(b *testing.B) {
buf := make([]byte, 1024*1024)
NewTimeSeededRand().Read(buf)
b.SetBytes(int64(1024 * 1024))
b.ResetTimer()
for i := 0; i < b.N; i++ {
Hash(buf)
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment