panic: testing: Verbose called before Init - go

Trying to run
https://github.com/adonovan/gopl.io/blob/master/ch8/cake/cake_test.go
but got
panic: testing: Verbose called before Init
goroutine 1 [running]:
testing.Verbose(...)
/usr/lib/go-1.17/src/testing/testing.go:453
.../cake_test.init()
It says the error comes from cake_test.init(), yet the cake_test.go file doesn't contain init():
$ grep init cake_test.go | wc
0 0 0
What exactly is the problem?

This happens because the testing package itself has a init to process test flags and you are callind Verbose to create a global variable
https://cs.opensource.google/go/go/+/refs/tags/go1.18:src/testing/testing.go;l=548
To avoid this you can:
Use a ponter to function to capture testing.Verbose and use inside functions, after all initializations ( Verbose will be type func() bool) but I think this is complex
Add a helper that creates a new default on each test with a safe call to testing.Verbose
Create a constructor (instead a test helper) that fill with the most common options and you can set the value of Verbose on each test
Create a two constructors, a second one that receive the value of Verbose
Also, Consider create a method Debug with same signature of Println, to call fmt.Println if Verbose is true
If you have a constructor, you can create a second field: Logger, with is a ponter to function with same signature as Println and you initialize with fmt.Println and in the tests you can set as t.Log to have a better experience
Of course perhaps some suggestions are more advanced than others, feel free to play a little bit and choose the best ones

Related

golang test fails on flags parse for test.v

In my go program, the main method does:
port := flag.Int("port", 8080, "Port number to start service on")
flag.Parse()
I have a dummy test that looks as:
func TestName(t *testing.T) {
fmt.Println("Hello there")
}
when I run my tests (from the goland or the command line) I got the following error stuck:
/usr/local/go/bin/go tool test2json -t /private/var/folders/7v/p2t5phhn6cn9hqwjnn_p95_80000gn/T/___TestName_in_github_tools....test -test.v -test.paniconexit0 -test.run ^\QTestName\E$
flag provided but not defined: -test.v
Usage of /private/var/folders/7v/p2t5phhn6cn9hqwjnn_p95_80000gn/T/___TestName_in_github_tools.....test:
-port int
Port number to start service on (default 8080)
When I remove the lines of the flag in the main, the test executes normally
Any idea on how to fix this, please?
Thanks in advance
When you run go test, go actually compiles your code into an executable, and executes it.
If you add options to go test -- for example : go test -v -- these options are actually passed to the test executable, prefixed with test -- so -v is turned into -test.v.
(this is a reason why several comments ask for the exact command line you use to run your tests : since the error is about -test.v, there probably is something that adds -v to some go test ... invocation)
It looks like flag.Parse() is trying to parse some arguments which are actually intended for your test executable, not for your code.
This is probably because it is called too early, before the test executable has had a chance to alter the os.Args slice to remove some specific flags.
Check what triggers a call to flag.Parse() : if it is executed from an init() block, this would count as "too early".
The behavior of go test options is documented in go help testflag :
Each of these flags is also recognized with an optional 'test.' prefix,
as in -test.v. When invoking the generated test binary (the result of
'go test -c') directly, however, the prefix is mandatory.
The 'go test' command rewrites or removes recognized flags,
as appropriate, both before and after the optional package list,
before invoking the test binary.
For instance, the command
go test -v -myflag testdata -cpuprofile=prof.out -x
will compile the test binary and then run it as
pkg.test -test.v -myflag testdata -test.cpuprofile=prof.out

inspec - i want to output structured data to be parsed by another function

I have a inspec test, this is great:
inspec exec scratchpad/profiles/forum_profile --reporter yaml
Trouble is I want to run this in a script and output this to an array
I cannot find the documentation that indicated what method i need to use to simulate the same
I do this
def my_func
http_checker = Inspec::Runner.new()
http_checker.add_target('scratchpad/profiles/forum_profile')
http_checker.run
puts http_checker.report
So the report method seems to give me load of the equivalent type and much more - does anyone have any documentation or advice on returning the same output as the --reporter yaml type response but in a script? I want to parse the response so I can share output with another function
I've never touched inspec, so take the following with a grain of salt, but according to https://github.com/inspec/inspec/blob/master/lib/inspec/runner.rb#L140, you can provide reporter option while instantiating the runner. Looking at https://github.com/inspec/inspec/blob/master/lib/inspec/reporters.rb#L11 I think it should be smth. like ["yaml", {}]. So, could you please try
# ...
http_checker = Inspec::Runner.new(reporter: ["yaml", {}])
# ...
(chances are it will give you the desired output)

Julia: Having a function f() containing the macro #printf, how can I access the output outside f()?

In the Julia NMF package a verbose option provides information on convergence using the #printf macro.
How can I access this output without rewriting the NMF package io?
To rephrase, having a function f() containing the macro #printf, how can I access the output outside f()?
This does seem like useful functionality to have: I would suggest that you file an issue with the package.
However, as a quick hack, something like the following should work:
oldout = STDOUT
(rd,wr) = redirect_stdout()
start_reading(rd)
# call your function here
flush_cstdio()
redirect_stdout(oldout)
close(wr)
s = readall(rd)
close(rd)
s

go test flag: flag provided but not defined

Hi I am using a flag when testing in go:
file_test.go
var ip = flag.String("ip", "noip", "test")
I am only using this in one test file. And it works fine when only testing that one test file, but when I run:
go test ./... -ip 127.0.0.1 alle of the other test file saying: flag provided but not defined.
Have you seen this?
Regards
flag.Parse() is being called before your flag is defined.
You have to make sure that all flag definitions happen before calling flag.Parse(), usually by defining all flags inside init() functions.
If you've migrated to golang 13, it changed the order of the test initializer,
so it could lead to something like
flag provided but not defined: -test.timeout
as a possible workaround, you can use
var _ = func() bool {
testing.Init()
return true
}()
that would call test initialization before the application one. More info can be found on the original thread:
https://github.com/golang/go/issues/31859#issuecomment-489889428
do not call flag.Parse() in any init()
I'm very late to the party; but is this broken (again) on Go 1.19.5?
I hit the same errors reported on this thread and the same solution reported above (https://github.com/golang/go/issues/31859#issuecomment-489889428) fixes it.
I see a call to flags.Parse() was added back in go_test.go in v1.18
https://go.googlesource.com/go/+/f7248f05946c1804b5519d0b3eb0db054dc9c5d6%5E%21/src/cmd/go/go_test.go
I am only just learning Go so it'd be nice to have some verification from people more skilled before I report this elsewhere.
If you get this, when running command via docker-compose then you do incorrect quoting. Eg.
services:
app:
...
image: kumina/openvpn-exporter:latest
command: [
"--openvpn.status_paths", "/etc/openvpn_exporter/openvpn-status.log",
"--openvpn.status_paths /etc/openvpn_exporter/openvpn-status.log",
]
First is correct, second is wrong, because whole line counted as one parameter. You need to split them by passing two separate strings, like in first line.

flag package in Go - do I have to always set default value?

Is it possible not to set default value in flag package in Go? For example, in flag package you can write out the following line:
filename := flag.String("file", "test.csv", "Filename to cope with")
In the above code, I don't want to necessarily set default value, which is test.csv in this case, and instead always make users specify their own filename, and if it's not specified then I want to cause an error and exit the program.
One of the way I came up with is that I first check the value of filename after doing flag.Parse(), and if that value is test.csv then I have the program exits with the appropriate error message. However, I don't want to write such redundant code if it can be evaded - and even if it can't, I'd like to hear any better way to cope with the issue here.
You can do those kind of operations in Python's argparse module by the way - I just want to implement the similar thing if I can...
Also, can I implement both short and long arguments (in other words both -f and -file argument?) in flag package?
Thanks.
I think it's idiomatic to design your flag values in such a way which implies "not present" when equal to the zero value of their respective types. For example:
optFile := flag.String("file", "", "Source file")
flag.Parse()
fn := *optFile
if fn == "" {
fn = "/dev/stdin"
}
f, err := os.Open(fn)
...
Ad the 2nd question: IINM, the flag package by design doesn't distinguish between -flag and --flag. IOW, you can have both -f and --file in your flag set and write any version of - or -- before both f and file. However, considering another defined flag -g, the flag package will not recognize -gf foo as being equvalent of -g -f foo.
When I have a flag that cannot have a default value I often use the value REQUIRED or something similar. I find this makes the --help easier to read.
As for why it wasn't baked in, I suspect it just wasn't considered important enough. The default wouldn't fit every need. However, the --help flag is similar; it doesn't fit every need, but it's good enough most of the time.
That's not to say the required flags are a bad idea. If you're passionate enough a flagutil package could be nice. Wrap the current flag api, make Parse return an error that describes the missing flag and add a RequiredInt and RequiredIntVar etc. If it turns out to be useful / popular it could be merged with the official flag package.
This is how I implemented command argument parser.
Since there are already plenty of similar projects, I decided not to add more choices without strong impetus.
Here is an example of how it can be used, which might inspired somebody, or someone might be interested.
# minarg.go
package main
import (
"fmt"
"self/argp"
)
func main() {
p := argp.New(nil)
p.Bool("continue",nil,"-v","-g")
f := func(m, arg string) {
switch m {
case "__init__":
case "__defer__":
p.Set("server", p.GetString("-s") + ":" + p.GetString("-p"))
default:
arg, _ := p.Shift()
p.Set(m, arg)
}
}
p.Mode(f,"__init__","__defer__","-s","-p","-nstat","-n")
p.Default("-s","127.0.0.1", "-p","1080", "-nstat","100", "-n","5")
p.Env("-s","SERVER", "-p","PORT")
p.Parse()
fmt.Println(p.Vars)
}
The output is
$ go run minarg.go
&map[-g:{false continue <nil>} -n:5 -nstat:100 -p:1080 -s:127.0.0.1 -v:{false continue <nil>} server:127.0.0.1:1080]
$ export PORT=80
$ go run minarg.go -s 0.0.0.0 -n 3 -vg
&map[-g:{true continue <nil>} -n:3 -nstat:100 -p:80 -s:0.0.0.0 -v:{true continue <nil>} server:0.0.0.0:80]

Resources