In service A I have a string that get hashed like this:
fun String.toHash(): Long {
var hashCode = this.hashCode().toLong()
if (hashCode < 0L) {
hashCode *= -1
}
return hashCode
}
I want to replicate this code in service B written in Golang so for the same word I get the exact same hash. For what I understand from Kotlin's documentation the hash applied returns a 64bit integer. So in Go I am doing this:
func hash(s string) int64 {
h := fnv.New64()
h.Write([]byte(s))
v := h.Sum64()
return int64(v)
}
But while unit testing this I do not get the same value. I get:
func Test_hash(t *testing.T) {
tests := []struct {
input string
output int64
}{
{input: "papafritas", output: 1079370635},
}
for _, test := range tests {
got := hash(test.input)
assert.Equal(t, test.output, got)
}
}
Result:
7841672725449611742
Am I doing something wrong?
Java and therefore Kotlin uses different hash function than Go.
Possible options are:
Use a standard hash function.
Reimplement Java hashCode for Strings in Go.
What is it about Iterable.fold(...) in Kotlin that allows me to put the operation function after the closing parentheses?
val numbers = listOf(5, 2, 10, 4)
// operation function passed as the second param of fold
val sumDoubled1 = numbers.fold(0, { sum, n -> sum + n * 2 })
println(sumDoubled1)
// operation function after the closing paren of fold
val sumDoubled2 = numbers.fold(0) { sum, n -> sum + n * 2 }
println(sumDoubled2)
Further to Pavneet's answer, the rationale behind this that it allows you to write what look like language extensions. For example:
repeat (10) {
// Do something
}
That looks like a new type of loop structure; but it's really just a function called repeat() that takes two parameters; an integer, and a lambda.
Also, if the lambda is the only parameter, you can omit the parens entirely, e.g.:
repeatForever {
// Do something
}
(repeat() is in the standard library; repeatForever() is left as an exercise for the reader :-)
The ability to neaten some inline method calls, such as someValue.takeIf{ it > 0 } is just a nice side-effect of that.
It is called Passing trailing lambdas means, if a methods takes last parameter input as function(aka method literal) then it can be placed outside that method call though you can also place it inside the brackets as well. A simple example would be:
fun main() {
processInput("Lambda", { println(it) })
processInput("Passing trailing lambda") { println(it) }
processInput("Passing trailing lambda with named param") { input -> println(input) }
}
fun processInput(input:String, method:(str:String)->Unit){
method(input.toUpperCase()) // additional logic
}
Output:
LAMBDA
PASSING TRAILING LAMBDA
PASSING TRAILING LAMBDA WITH NAMED PARAM
I want to write tests first, then write code that makes the tests pass.
I can write tests functions like this:
func TestCheckPassword(t *testing.T) {
isCorrect := CheckPasswordHash("test", "$2a$14$rz.gZgh9CHhXQEfLfuSeRuRrR5uraTqLChRW7/Il62KNOQI9vjO2S")
if isCorrect != true {
t.Errorf("Password is wrong")
}
}
But I'd like to have more descriptive information for each test function.
For example, I am thinking about creating auth module for my app.
Now, in plain English, I can easily describe my requirements for this module:
It should accept a non-empty string as input.
String must be from 6 to 48 characters long.
Function should return true if password string fits provided hash string and false if not.
What's the way to put this information that is understandable by a non-tech business person into tests besides putting them into comments?
In Go, a common way of writing tests to perform related checks is to create a slice of test cases (which is referred to as the "table" and the method as "table-driven tests"), which we simply loop over and execute one-by-one.
A test case may have arbitrary properties, which is usually modeled by an anonymous struct.
If you want to provide a description for test cases, you can add an additional field to the struct describing a test case. This will serve both as documentation of the test case and as (part of the) output in case the test case would fail.
For simplicity, let's test the following simple Abs() function:
func Abs(x int) int {
if x < 0 {
return -x
}
return x
}
The implementation seems to be right and complete. If we'd want to write tests for this, normally we would add 2 test cases to cover the 2 possible branches: test when x is negative (x < 0), and when x is non-negative. In reality, it's often handy and recommended to also test the special 0 input and the corner cases: the min and max values of the input.
If we think about it, this Abs() function won't even give a correct result when called with the minimum value of int32, because that is -2147483648, and its absolute value is 2147483648 which doesn't fit into int32 because max value of int32 is: 2147483647. So the above implementation will overflow and incorrectly give the negative min value as the absolute of the negative min.
The test function that lists cases for each possible branches plus includes 0 and the corner cases, with descriptions:
func TestAbs(t *testing.T) {
cases := []struct {
desc string // Description of the test case
x int32 // Input value
exp int32 // Expected output value
}{
{
desc: "Abs of positive numbers is the same",
x: 1,
exp: 1,
},
{
desc: "Abs of 0 is 0",
x: 0,
exp: 0,
},
{
desc: "Abs of negative numbers is -x",
x: -1,
exp: 1,
},
{
desc: "Corner case testing MaxInt32",
x: math.MaxInt32,
exp: math.MaxInt32,
},
{
desc: "Corner case testing MinInt32, which overflows",
x: math.MinInt32,
exp: math.MinInt32,
},
}
for _, c := range cases {
got := Abs(c.x)
if got != c.exp {
t.Errorf("Expected: %d, got: %d, test case: %s", c.exp, got, c.desc)
}
}
}
In Go, the idiomatic way to write these kinds of tests is:
func TestCheckPassword(t *testing.T) {
tcs := []struct {
pw string
hash string
want bool
}{
{"test", "$2a$14$rz.gZgh9CHhXQEfLfuSeRuRrR5uraTqLChRW7/Il62KNOQI9vjO2S", true},
{"foo", "$2a$14$rz.gZgh9CHhXQEfLfuSeRuRrR5uraTqLChRW7/Il62KNOQI9vjO2S", false},
{"", "$2a$14$rz.gZgh9CHhXQEfLfuSeRuRrR5uraTqLChRW7/Il62KNOQI9vjO2S", false},
}
for _, tc := range tests {
got := CheckPasswordHash(tc.pw, tc.hash)
if got != tc.want {
t.Errorf("CheckPasswordHash(%q, %q) = %v, want %v", tc.pw, tc.hash, got, want)
}
}
}
This is called "table-driven testing". You create a table of inputs and expected outputs, you iterate over that table and call your function and if the expected output does not match what you want, you write an error message describing the failure.
If what you want isn't as simple as comparing a return against a golden value - for example, you want to check that either an error, or a value is returned, or that a well-formed hash+salt is returned, but don't care what salt is used (as that's not part of the API), you'd write additional code for that - in the end, you simply write down what properties the result should have, add some if's to check that and provide a descriptive error message if the result is not as expected. So, say:
func Hash(pw string) (hash string, err error) {
// Validate input, create salt, hash thing…
}
func TestHash(t *testing.T) {
tcs := []struct{
pw string
wantError bool
}{
{"", true},
{"foo", true},
{"foobar", false},
{"foobarbaz", true},
}
for _, tc := range tcs {
got, err := Hash(tc.pw)
if err != nil {
if !tc.wantError {
t.Errorf("Hash(%q) = %q, %v, want _, nil", tc.pw, got, err)
}
continue
}
if len(got) != 52 {
t.Errorf("Hash(%q) = %q, want 52 character string", tc.pw, got)
}
if !CheckPasswordHash(tc.pw, got) {
t.Errorf("CheckPasswordHash(Hash(%q)) = false, want true", tc.pw)
}
}
}
If you want a test suite with descriptive texts and contexts (like rspec for ruby) you should check out ginko: https://onsi.github.io/ginkgo/
I have a tree of structs which I'd like to test using testing/quick, but constraining it to within my invariants.
This example code works:
var rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
type X struct {
HasChildren bool
Children []*X
}
func TestSomething(t *testing.T) {
x, _ := quick.Value(reflect.TypeOf(X{}), rnd)
_ = x
// test some stuff here
}
But we hold HasChildren = true whenever len(Children) > 0 as an invariant, so it'd be better to ensure that whatever quick.Value() generates respects that (rather than finding "bugs" that don't actually exist).
I figured I could define a Generate function which uses quick.Value() to populate all the variable members:
func (X) Generate(rand *rand.Rand, size int) reflect.Value {
x := X{}
throwaway, _ := quick.Value(reflect.TypeOf([]*X{}), rand)
x.Children = throwaway.Interface().([]*X)
if len(x.Children) > 0 {
x.HasChildren = true
} else {
x.HasChildren = false
}
return reflect.ValueOf(x)
}
But this is panicking:
panic: value method main.X.Generate called using nil *X pointer [recovered]
And when I change Children from []*X to []X, it dies with a stack overflow.
The documentation is very thin on examples, and I'm finding almost nothing in web searches either.
How can this be done?
Looking at the testing/quick source code it seems that you can't create recursive custom generators and at the same time reuse the quick library facilities to generate the array part of the struct, because the size parameter, that is designed to limit the number of recursive calls, cannot be passed back into quick.Value(...)
https://golang.org/src/testing/quick/quick.go (see around line 50)
in your case this lead to an infinite tree that quickly "explodes" with 1..50 leafs at each level (that's the reason for the stack overflow).
If the function quick.sizedValue() had been public we could have used it to accomplish your task, but unfortunately this is not the case.
BTW since HasChildren is an invariant, can't you simply make it a struct method?
type X struct {
Children []*X
}
func (me *X) HasChildren() bool {
return len(me.Children) > 0
}
func main() {
.... generate X ....
if x.HasChildren() {
.....
}
}
Disclaimer: I wish you a merry XMas and I hope my question does not disturb you!
sample.go:
package main
import(
"fmt"
"os"
)
type sample struct {
value int64
}
func (s sample) useful() {
if s.value == 0 {
fmt.Println("Error: something is wrong!")
os.Exit(1)
} else {
fmt.Println("May the force be with you!")
}
}
func main() {
s := sample{42}
s.useful()
s.value = 0
s.useful()
}
// output:
// May the force be with you!
// Error: something is wrong!
// exit status 1
I did a lot of research on how to use interfaces in golang testing. But so far I was not able to wrap my head around this completely. At least I can not see how interfaces help me when I need to "mock" (apologies for using this word) golang std. library packages like "fmt".
I came up with two scenarios:
use os/exec to test the command line interface
wrap fmt package so I have control and am able to check the output strings
I do not like both scenarios:
I experience going through the actual command line a convoluted and not-performant (see below). Might have portability issues, too.
I believe this is the way to go but I fear that wrapping the fmt package might be a lot of work (at least wrapping the time package for testing turned out a non-trivial task (https://github.com/finklabs/ttime)).
Actual Question here: Is there another (better/simpler/idiomatic) way?
Note: I want to do this in pure golang, I am not interested in the next testing framework.
cli_test.go:
package main
import(
"os/exec"
"testing"
)
func TestCli(t *testing.T) {
out, err := exec.Command("go run sample.go").Output()
if err != nil {
t.Fatal(err)
}
if string(out) != "May the force be with you!\nError: this is broken and not useful!\nexit status 1" {
t.Fatal("There is something wrong with the CLI")
}
}
Chapter 11 of Kerningham's Book gives a good solution to this question.
The trick is to change the calls to fmt.Printline() to calls to
fmt.Fprint(out, ...) where out is initialised to os.Stdout
This can be overwritten in the test harness to new(bytes.Buffer) allowing the
test to capture the output.
See https://github.com/adonovan/gopl.io/blob/master/ch11/echo/echo.go and
https://github.com/adonovan/gopl.io/blob/master/ch11/echo/echo_test.go
edited by OP...
sample.go:
package main
import(
"fmt"
"os"
"io"
)
var out io.Writer = os.Stdout // modified during testing
var exit func(code int) = os.Exit
type sample struct {
value int64
}
func (s sample) useful() {
if s.value == 0 {
fmt.Fprint(out, "Error: something is wrong!\n")
exit(1)
} else {
fmt.Fprint(out, "May the force be with you!\n")
}
}
func main() {
s := sample{42}
s.useful()
s.value = 0
s.useful()
}
// output:
// May the force be with you!
// Error: this is broken and not useful!
// exit status 1
cli_test.go:
package main
import(
"bytes"
"testing"
)
func TestUsefulPositive(t *testing.T) {
bak := out
out = new(bytes.Buffer)
defer func() { out = bak }()
s := sample{42}
s.useful()
if out.(*bytes.Buffer).String() != "May the force be with you!\n" {
t.Fatal("There is something wrong with the CLI")
}
}
func TestUsefulNegative(t *testing.T) {
bak := out
out = new(bytes.Buffer)
defer func() { out = bak }()
code := 0
osexit := exit
exit = func(c int) { code = c }
defer func() { exit = osexit }()
s := sample{0}
s.useful()
if out.(*bytes.Buffer).String() != "Error: something is wrong!\n" {
t.Fatal("There is something wrong with the CLI")
}
if code != 1 {
t.Fatal("Wrong exit code!")
}
}
Am I missing something here or are you talking of testable examples?
Basically, it works like this: In a *_test.go file, you need to adhere to the convention Example[[T][_M]] where T is a placeholder for the type and M a placeholder for the method you want to display the testable example as example code in the Godoc. If the function is just called Example(), the code will be shown as a package example.
Below the last line of the code of your example, you can put a comment like this
// Output:
// Foo
Now go test will make sure that the testable example function either exactly puts out everything below // Output: (including whitespace) or it will make the test fail.
Here is an actual example for an testable example
func ExampleMongoStore_Get() {
sessionId := "ExampleGetSession"
data, err := ms.Get(sessionId)
if err == sessionmw.ErrSessionNotFound {
fmt.Printf("Session '%s' not found\n", sessionId)
data = make(map[string]interface{})
data["foo"] = "bar"
ms.Save(sessionId, data)
}
loaded, _ := ms.Get(sessionId)
fmt.Printf("Loaded value '%s' for key '%s' in session '%s'",
loaded["foo"],
"foo", sessionId)
// Output:
// Session 'ExampleGetSession' not found
// Loaded value 'bar' for key 'foo' in session 'ExampleGetSession'
}
Edit: Have a look at the output of above example at godoc.org