summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2024-08-05 16:51:41 -0300
committerEuAndreh <eu@euandre.org>2024-08-05 16:51:41 -0300
commit27f3f26e8ffa52aed694a0d6d17efcdd8278ba6f (patch)
tree89a881998c208e46bf0b81c95361b2e0b363b12e
parentMakefile: Build with "go tool compile" and "go tool link" (diff)
downloadgobang-27f3f26e8ffa52aed694a0d6d17efcdd8278ba6f.tar.gz
gobang-27f3f26e8ffa52aed694a0d6d17efcdd8278ba6f.tar.xz
Start using TestStart() and Testing()
-rw-r--r--Makefile25
-rw-r--r--src/gobang.go207
-rw-r--r--tests/gobang.go115
-rw-r--r--tests/gobang_main.go2
4 files changed, 206 insertions, 143 deletions
diff --git a/Makefile b/Makefile
index cba5d37..b6085d4 100644
--- a/Makefile
+++ b/Makefile
@@ -22,7 +22,7 @@ LDLIBS =
.SUFFIXES:
-.SUFFIXES: .go .a .bin
+.SUFFIXES: .go .a .bin .bin-check
@@ -30,14 +30,14 @@ all:
include deps.mk
-sources = \
- src/$(NAME).go \
-
objects = \
src/$(NAME).a \
tests/$(NAME).a \
tests/$(NAME)_main.a \
+sources = \
+ src/$(NAME).go \
+
derived-assets = \
$(objects) \
@@ -69,8 +69,13 @@ $(objects): Makefile
-check-unit: tests/$(NAME)_main.bin
- ./tests/$(NAME)_main.bin
+tests.bin-check = \
+ tests/$(NAME)_main.bin-check \
+
+$(tests.bin-check): tests/$(NAME)_main.bin
+ $(EXEC)$*.bin
+
+check-unit: $(tests.bin-check)
integration-tests = \
@@ -95,8 +100,8 @@ clean:
## ensures that all installable artifacts are crafted beforehand.
install: all
mkdir -p \
- '$(DESTDIR)$(GOLIBDIR)' \
- '$(DESTDIR)$(SRCDIR)' \
+ '$(DESTDIR)$(GOLIBDIR)' \
+ '$(DESTDIR)$(SRCDIR)' \
cp src/$(NAME).a '$(DESTDIR)$(GOLIBDIR)'
cp $(sources) '$(DESTDIR)$(SRCDIR)'
@@ -106,8 +111,8 @@ install: all
## A dedicated test asserts that this is always true.
uninstall:
rm -rf \
- '$(DESTDIR)$(GOLIBDIR)'/$(NAME).a \
- '$(DESTDIR)$(SRCDIR)' \
+ '$(DESTDIR)$(GOLIBDIR)'/$(NAME).a \
+ '$(DESTDIR)$(SRCDIR)' \
ALWAYS:
diff --git a/src/gobang.go b/src/gobang.go
index 4ce13ff..4775dfc 100644
--- a/src/gobang.go
+++ b/src/gobang.go
@@ -19,19 +19,18 @@ import (
"strings"
"sync"
"syscall"
- "testing"
"time"
)
-type LogLevel int8
+type logLevel int8
const (
- LevelNone LogLevel = 0
- LevelError LogLevel = 1
- LevelWarning LogLevel = 2
- LevelInfo LogLevel = 3
- LevelDebug LogLevel = 4
+ LevelNone logLevel = 0
+ LevelError logLevel = 1
+ LevelWarning logLevel = 2
+ LevelInfo logLevel = 3
+ LevelDebug logLevel = 4
)
const lengthUUID = 16
@@ -52,7 +51,15 @@ type CopyResult struct {
-const MaxInt = int((^uint(0)) >> 1)
+const maxInt = int((^uint(0)) >> 1)
+
+const (
+ scrypt_N = 32768
+ scrypt_r = 8
+ scrypt_p = 1
+ scryptSaltMinLength = 32
+ scryptDesiredLength = 32
+)
@@ -62,14 +69,17 @@ const MaxInt = int((^uint(0)) >> 1)
//
// 52 bits of time in milliseconds since epoch
// 12 bits of (fractional nanoseconds) >> 8
+
var lastV7Time int64
-var timeMu sync.Mutex
+var timeMutex sync.Mutex
+
+
+// Local variables
-// Global variables
var (
- Level LogLevel = LevelInfo
- EmitMetric bool = true
- Hostname string
+ level logLevel = LevelInfo
+ emitMetric bool = true
+ hostname string
)
@@ -104,7 +114,7 @@ var (
//
// Using a higher iteration count will increase the cost of an exhaustive
// search but will also make derivation proportionally slower.
-func PBKDF2Key(
+func _PBKDF2Key(
password []byte,
salt []byte,
iter int,
@@ -127,7 +137,7 @@ func PBKDF2Key(
buf[0] = byte(block >> 24)
buf[1] = byte(block >> 16)
buf[2] = byte(block >> 8)
- buf[3] = byte(block)
+ buf[3] = byte(block >> 0)
prf.Write(buf[:4])
dk = prf.Sum(dk)
T := dk[len(dk) - hashLen:]
@@ -341,7 +351,7 @@ func smix(b []byte, r int, N int, v []uint32, xy []uint32) {
// and p=1. The parameters N, r, and p should be increased as memory latency and
// CPU parallelism increases; consider setting N to the highest power of 2 you
// can derive within 100 milliseconds. Remember to get a good random salt.
-func Scrypt(
+func scrypt(
password []byte,
salt []byte,
N int,
@@ -353,35 +363,35 @@ func Scrypt(
return nil, errors.New("scrypt: N must be > 1 and a power of 2")
}
if ((uint64(r) * uint64(p)) >= (1 << 30)) ||
- r > MaxInt / 128 / p ||
- r > MaxInt / 256 ||
- N > MaxInt / 128 / r {
+ r > maxInt / 128 / p ||
+ r > maxInt / 256 ||
+ N > maxInt / 128 / r {
return nil, errors.New("scrypt: parameters are too large")
}
xy := make([]uint32, 64 * r)
v := make([]uint32, 32 * N * r)
- b := PBKDF2Key(password, salt, 1, p * 128 * r, sha256.New)
+ b := _PBKDF2Key(password, salt, 1, p * 128 * r, sha256.New)
for i := 0; i < p; i++ {
smix(b[i * 128 * r:], r, N, v, xy)
}
- return PBKDF2Key(password, b, 1, keyLen, sha256.New), nil
+ return _PBKDF2Key(password, b, 1, keyLen, sha256.New), nil
}
-func CopyData(
- c chan CopyResult,
- label string,
- from io.Reader,
- to io.WriteCloser,
-) {
- written, err := io.Copy(to, from)
- c <- CopyResult {
- Written: written,
- Err: err,
- Label: label,
- }
+func Salt() []byte {
+ var buf [scryptSaltMinLength]byte
+ _, err := io.ReadFull(rand.Reader, buf[:])
+ FatalIf(err)
+ return buf[:]
+}
+
+func Hash(password []byte, salt []byte) []byte{
+ Assert(len(salt) >= scryptSaltMinLength, "salt is too small")
+ hash, err := scrypt(password, salt, scrypt_N, scrypt_r, scrypt_p, scryptDesiredLength)
+ FatalIf(err)
+ return hash
}
// FIXME: finish rewriting
@@ -397,8 +407,8 @@ func getV7Time(nano int64) (int64, int64) {
seq := (nano - (milli * nanoPerMilli)) >> 8
now := milli << (12 + seq)
- timeMu.Lock()
- defer timeMu.Unlock()
+ timeMutex.Lock()
+ defer timeMutex.Unlock()
if now <= lastV7Time {
now = lastV7Time + 1
milli = now >> 12
@@ -460,7 +470,7 @@ func (uuid UUID) ToString() string {
}
func Debug(message string, type_ string, args ...any) {
- if Level < LevelDebug {
+ if level < LevelDebug {
return
}
@@ -478,7 +488,7 @@ func Debug(message string, type_ string, args ...any) {
}
func Info(message string, type_ string, args ...any) {
- if Level < LevelInfo {
+ if level < LevelInfo {
return
}
@@ -496,7 +506,7 @@ func Info(message string, type_ string, args ...any) {
}
func Warning(message string, type_ string, args ...any) {
- if Level < LevelWarning {
+ if level < LevelWarning {
return
}
@@ -514,7 +524,7 @@ func Warning(message string, type_ string, args ...any) {
}
func Error(message string, type_ string, args ...any) {
- if Level < LevelError {
+ if level < LevelError {
return
}
@@ -532,7 +542,7 @@ func Error(message string, type_ string, args ...any) {
}
func Metric(type_ string, label string, args ...any) {
- if !EmitMetric {
+ if !emitMetric {
return
}
@@ -602,35 +612,69 @@ func MakeCounter(label string) func(...any) {
}
}
-func ErrorIf(t *testing.T, err error) {
+func ErrorIf(err error) {
if err != nil {
- t.Errorf("Unexpected error: %#v\n", err)
+ fmt.Fprintf(os.Stderr, "Unexpected error: %#v\n", err)
+ os.Exit(1)
}
}
-func ErrorNil(t *testing.T, err error) {
+func ErrorNil(err error) {
if err == nil {
- t.Errorf("Expected error, got nil\n")
+ fmt.Fprintf(os.Stderr, "Expected error, got nil\n")
+ os.Exit(1)
+ }
+}
+
+func showColour() bool {
+ return os.Getenv("NO_COLOUR") == ""
+}
+
+func TestStart(name string) {
+ fmt.Fprintf(os.Stderr, "%s:\n", name)
+}
+
+func Testing(message string, body func()) {
+ if showColour() {
+ fmt.Fprintf(os.Stderr, "\033[0;33mtesting\033[0m: %s... ", message)
+ body()
+ fmt.Fprint(os.Stderr, "\033[0;32mOK\033[0m.\n")
+ } else {
+ fmt.Fprintf(os.Stderr, "testing: %s...", message)
+ body()
+ fmt.Fprint(os.Stderr, " OK.\n")
}
}
-func AssertEqual(t *testing.T, given any, expected any) {
+func AssertEqual(given any, expected any) {
if !reflect.DeepEqual(given, expected) {
- t.Errorf("given != expected\n")
- t.Errorf("given: %#v\n", given)
- t.Errorf("expected: %#v\n", expected)
+ if showColour() {
+ fmt.Fprintf(os.Stderr, "\033[0;31mERR\033[0m.\n")
+ } else {
+ fmt.Fprintf(os.Stderr, "ERR.\n")
+ }
+ fmt.Fprintf(os.Stderr, "given != expected\n")
+ fmt.Fprintf(os.Stderr, "given: %#v\n", given)
+ fmt.Fprintf(os.Stderr, "expected: %#v\n", expected)
+ os.Exit(1)
}
}
-func AssertEqualI(t *testing.T, i int, given any, expected any) {
+func AssertEqualI(i int, given any, expected any) {
if !reflect.DeepEqual(given, expected) {
- t.Errorf("given != expected (i = %d)\n", i)
- t.Errorf("given: %#v\n", given)
- t.Errorf("expected: %#v\n", expected)
+ if showColour() {
+ fmt.Fprintf(os.Stderr, "\033[0;31mERR\033[0m.\n")
+ } else {
+ fmt.Fprintf(os.Stderr, "ERR.\n")
+ }
+ fmt.Fprintf(os.Stderr, "given != expected (i = %d)\n", i)
+ fmt.Fprintf(os.Stderr, "given: %#v\n", given)
+ fmt.Fprintf(os.Stderr, "expected: %#v\n", expected)
+ os.Exit(1)
}
}
-func SetLoggerOutput(w io.Writer) {
+func setLoggerOutput(w io.Writer) {
slog.SetDefault(slog.New(slog.NewJSONHandler(w, &slog.HandlerOptions {
AddSource: true,
})).With(
@@ -643,47 +687,47 @@ func SetLoggerOutput(w io.Writer) {
))
}
-func LevelFromString(name string) (bool, LogLevel) {
- level := strings.ToUpper(name)
+func levelFromString(name string) (bool, logLevel) {
+ label := strings.ToUpper(name)
- if level == "NONE" {
+ if label == "NONE" {
return true, LevelNone
}
- if level == "ERROR" {
+ if label == "ERROR" {
return true, LevelError
}
- if level == "WARNING" {
+ if label == "WARNING" {
return true, LevelWarning
}
- if level == "INFO" {
+ if label == "INFO" {
return true, LevelInfo
}
- if level == "DEBUG" {
+ if label == "DEBUG" {
return true, LevelDebug
}
- return false, Level
+ return false, level
}
-func SetLogLevel() {
- ok, level := LevelFromString(os.Getenv("LOG_LEVEL"))
+func setLogLevel() {
+ ok, envLevel := levelFromString(os.Getenv("LOG_LEVEL"))
if ok {
- Level = level
+ level = envLevel
}
}
-func SetMetric() {
+func setMetric() {
if os.Getenv("NO_METRIC") != "" {
- EmitMetric = false
+ emitMetric = false
}
}
-func SetTraceback() {
+func setTraceback() {
if os.Getenv("GOTRACEBACK") == "" {
debug.SetTraceback("crash")
}
@@ -705,21 +749,26 @@ func FatalIf(err error) {
}
}
-func SetHostname() {
- var err error
- Hostname, err = os.Hostname()
- FatalIf(err)
+func Assert(condition bool, message string) {
+ if !condition {
+ Fatal(errors.New(message))
+ }
}
-func Init() {
- SetLoggerOutput(os.Stdout)
- SetLogLevel()
- SetMetric()
- SetTraceback()
- SetHostname()
+func Unreachable() {
+ Assert(false, "Unreachable code was reached")
}
+func setHostname() {
+ var err error
+ hostname, err = os.Hostname()
+ FatalIf(err)
+}
-func Main() {
- fmt.Println(NewUUID().ToString())
+func Init() {
+ setLoggerOutput(os.Stdout)
+ setLogLevel()
+ setMetric()
+ setTraceback()
+ setHostname()
}
diff --git a/tests/gobang.go b/tests/gobang.go
index 3abdf6f..61168d6 100644
--- a/tests/gobang.go
+++ b/tests/gobang.go
@@ -9,7 +9,6 @@ import (
"fmt"
"hash"
"log/slog"
- "testing"
)
@@ -141,30 +140,29 @@ var sha256TestVectors = []pbkdfTestVector {
},
}
-func testHash(
- t *testing.T,
- h func() hash.Hash,
- hashName string,
- vectors []pbkdfTestVector,
-) {
+func testHash(h func() hash.Hash, hashName string, vectors []pbkdfTestVector) {
for i, v := range vectors {
- out := PBKDF2Key(
+ out := _PBKDF2Key(
[]byte(v.password),
[]byte(v.salt),
v.iter,
len(v.output),
h,
)
- AssertEqualI(t, i, out, v.output)
+ AssertEqualI(i, out, v.output)
}
}
-func TestWithHMACSHA1(t *testing.T) {
- testHash(t, sha1.New, "SHA1", sha1TestVectors)
-}
+func test__PBKDF() {
+ TestStart("_PBKDF()")
+
+ Testing("HMAC with SHA1", func() {
+ testHash(sha1.New, "SHA1", sha1TestVectors)
+ })
-func TestWithHMACSHA256(t *testing.T) {
- testHash(t, sha256.New, "SHA256", sha256TestVectors)
+ Testing("HMAC with SHA256", func() {
+ testHash(sha256.New, "SHA256", sha256TestVectors)
+ })
}
type scryptTestVector struct {
@@ -284,7 +282,7 @@ var good = []scryptTestVector {
// },
}
-const halfMax = MaxInt / 2
+const halfMax = maxInt / 2
var bad = []scryptTestVector {
{"p", "s", 0, 1, 1, nil}, // N == 0
{"p", "s", 1, 1, 1, nil}, // N == 1
@@ -292,46 +290,53 @@ var bad = []scryptTestVector {
{"p", "s", 16, halfMax, halfMax, nil}, // p * r too large
}
-func TestKey(t *testing.T) {
- for i, v := range good {
- k, err := Scrypt(
- []byte(v.password),
- []byte(v.salt),
- v.N,
- v.r,
- v.p,
- len(v.output),
- )
- ErrorIf(t, err)
- AssertEqualI(t, i, k, v.output)
- }
- for _, v := range bad {
- _, err := Scrypt(
- []byte(v.password),
- []byte(v.salt),
- v.N,
- v.r,
- v.p,
- 32,
- )
- ErrorNil(t, err)
- }
-}
+func test_scrypt() {
+ TestStart("scrypt()")
-func TestExample(t *testing.T) {
- const expected = "lGnMz8io0AUkfzn6Pls1qX20Vs7PGN6sbYQ2TQgY12M="
- // DO NOT use this salt value; generate your own random salt. 8 bytes is
- // a good length.
- salt := []byte{0xc8, 0x28, 0xf2, 0x58, 0xa7, 0x6a, 0xad, 0x7b}
+ Testing("good hashes", func() {
+ for i, v := range good {
+ k, err := scrypt(
+ []byte(v.password),
+ []byte(v.salt),
+ v.N,
+ v.r,
+ v.p,
+ len(v.output),
+ )
+ ErrorIf(err)
+ AssertEqualI(i, k, v.output)
+ }
+ })
- dk, err := Scrypt([]byte("some password"), salt, 1<<15, 8, 1, 32)
- ErrorIf(t, err)
+ Testing("bad hashes", func() {
+ for _, v := range bad {
+ _, err := scrypt(
+ []byte(v.password),
+ []byte(v.salt),
+ v.N,
+ v.r,
+ v.p,
+ 32,
+ )
+ ErrorNil(err)
+ }
+ })
- given := base64.StdEncoding.EncodeToString(dk)
- AssertEqual(t, given, expected)
+ Testing("example value", func() {
+ const expected = "lGnMz8io0AUkfzn6Pls1qX20Vs7PGN6sbYQ2TQgY12M="
+ // DO NOT use this salt value; generate your own random salt. 8 bytes is
+ // a good length.
+ salt := []byte{0xc8, 0x28, 0xf2, 0x58, 0xa7, 0x6a, 0xad, 0x7b}
+
+ dk, err := scrypt([]byte("some password"), salt, 1<<15, 8, 1, 32)
+ ErrorIf(err)
+
+ given := base64.StdEncoding.EncodeToString(dk)
+ AssertEqual(given, expected)
+ })
}
-func TestSetLoggerOutput(t *testing.T) {
+func TestSetLoggerOutput() {
return
type entry struct {
msg string `json:"msg"`
@@ -346,13 +351,17 @@ func TestSetLoggerOutput(t *testing.T) {
// fmt.Println(e)
err := json.Unmarshal([]byte(s), &e)
if err != nil {
- t.Fail()
+ // t.Fail()
// Mmain()
- Main()
}
if e.msg != "the message" {
- t.Fail()
+ // t.Fail()
}
fmt.Println(1)
// fmt.Println(e)
}
+
+func MainTest() {
+ test__PBKDF()
+ test_scrypt()
+}
diff --git a/tests/gobang_main.go b/tests/gobang_main.go
index d5cb7f2..2dcbdf0 100644
--- a/tests/gobang_main.go
+++ b/tests/gobang_main.go
@@ -3,5 +3,5 @@ package main
import "gobang"
func main() {
- gobang.Main()
+ gobang.MainTest()
}