package main
import (
"flag"
"fmt"
)
func main() {
passArguments()
}
func passArguments() string {
username := flag.String("user", "root", "Username for this server")
flag.Parse()
fmt.Printf("Your username is %q.", *username)
usernameToString := *username
return usernameToString
}
Passing an argument to the compiled code:
./args -user=bla
results in:
Your username is "bla"
the username that has been passed is displayed.
Aim: in order to prevent that the code needs to be build and run manually every time to test the code the aim is to write a test that is able to test the passing of arguments.
Attempt
Running the following test:
package main
import (
"os"
"testing"
)
func TestArgs(t *testing.T) {
expected := "bla"
os.Args = []string{"-user=bla"}
actual := passArguments()
if actual != expected {
t.Errorf("Test failed, expected: '%s', got: '%s'", expected, actual)
}
}
results in:
Your username is "root".Your username is "root".--- FAIL: TestArgs (0.00s)
args_test.go:15: Test failed, expected: 'bla', got: 'root'
FAIL
coverage: 87.5% of statements
FAIL tool 0.008s
Problem
It looks like that the os.Args = []string{"-user=bla is not able to pass this argument to the function as the outcome is root instead of bla
Per my comment, the very first value in os.Args is a (path to) executable itself, so os.Args = []string{"cmd", "-user=bla"} should fix your issue. You can take a look at flag test from the standard package where they're doing something similar.
Also, as os.Args is a "global variable", it might be a good idea to keep the state from before the test and restore it after. Similarly to the linked test:
oldArgs := os.Args
defer func() { os.Args = oldArgs }()
This might be useful where other tests are, for example, examining the real arguments passed when evoking go test.
This is old enough but still searched out, while it seems out dated.
Because Go 1.13 changed sth.
I find this change helpful, putting flag.*() in init() and flag.Parse() in Test*()
-args cannot take -<test-args>=<val> after it, but only <test-args>, otherwise the test-args will be taken as go test's command line parameter, instead of your Test*'s
Related
I read stdin and stderr from the command-line using:
fun runCommand(vararg commands: String): Pair<String, String> {
val proc = Runtime.getRuntime().exec(commands)
val stdIn = BufferedReader(InputStreamReader(proc.inputStream))
val stdErr = BufferedReader(InputStreamReader(proc.errorStream))
val p = Pair(stdIn.use(BufferedReader::readText).trim(), stdErr.use(BufferedReader::readText).trim())
stdIn.close();
stdErr.close();
return p;
}
This gives me a Pair of <String, String> with the output of stdin and stderr.
However, no matter how I try to compare these Strings to another String, the comparison always returns false.
Things I've tried:
runCommand("nordvpn", "account").first.compareTo("You are not logged in.")
runCommand("nordvpn", "account").first == "You are not logged in."
runCommand("nordvpn", "account").first.equals("You are not logged in.")
Might this have something to do with the encoding?
Or am I just reading the output incorrectly?
Any help would be appreciated!
Thanks to #gidds' comment I was able to find that for some reason the output of the command (stdout) had "-CR SP SP CR" (- CarriageReturn Space Space CarriageReturn" prepended, which I removed with a simple String.drop(5).
Edit: After some more thinking, I assume that the aforementioned charts were responsible for making the output of the command in the terminal colored (yellow)
I am trying to create a table from a struct using the following code. It had initially worked by hard coding the credentials to test. Once changing to env vars, I wanted to test that the tables and schemas would get created as expected.
So far I have tried:
Removing the tables from the db, running "go run main.go".
Result: Established connection successfully to the db, but tables do not get created.
Deleting the database, recreating the database using psql "CREATE DATABASE" command, and running "go run main.go"
Result: Established connection successfully to the db, but tables do not get created.
Use AutoMigrate, but was not able to successfully create the tables.
Debug: When I run it in debug mode, the debug console displays that its connected, i see no indication of any errors. I have not been coding for many years, still in the learning process.
Below are 2 files, main.go and api.go (opens db)
MAIN.GO
import (
"fmt"
"log"
"net/http"
"time"
"github.com/gorilla/handlers"
"gitlab......"
_ "gitlab....."
)
var err error
func main() {
api := controllers.API{}
// Using env vars from a config file
api.Initialize("user=%s password=%s dbname=%s port=%s sslmode=disable")
// BIND TO A PORT AND PASS OUR ROUTER IN
log.Fatal(http.ListenAndServe(":8000", handlers.CORS()(api.Router)))
if err != nil {
panic(err.Error())
}
// Models
type Application struct {
ID string `json:"id" gorm:"primary_key"`
CreatedAt time.Time `json:"-"`
UpdatedAt time.Time `json:"-"`
Name string `json:"name"`
Ci string `json:"ci"`
// CREATE TABLES AND SCHEMA IF TABLES DO NOT EXIST
if !api.Database.HasTable(&Application{}) {
api.Database.CreateTable(&Application{})
}
API.GO
func (api *API) Initialize(opts string) {
// Initialize DB
dbinfo := fmt.Sprintf("user=%s password=%s dbname=%s port=%s sslmode=disable",
config.DB_USER, config.DB_PASSWORD, config.DB_NAME, config.PORT)
api.Database, err = gorm.Open("postgres", dbinfo)
if err != nil {
log.Print("failed to connect to the database")
log.Fatal(err)
}
fmt.Println("Connection established")
log.Printf("Postgres started at %s PORT", config.PORT)
}
I have already created the database, and am able to establish a connection to the database. Just can not get the tables created.
Ideas?
When I try to use database/sql in this way it compiles and works:
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
But if I try to use postgres specific connectors it doesn't even compile:
import(
"database/sql"
_ "github.com/lib/pq"
)
import(
"database/sql"
_ "github.com/jbarham/gopgsqldriver"
)
both fail with the error
sql: unknown driver "mysql" (forgotten import?)
I have done go get for both of these packages, and am really not sure why it is not compiling
Are you doing
db, err := sql.Open("mysql",
later on? When you import "github.com/lib/pq" for example, it registers itself by calling sql.Register, and then in the source of sql.Open you have:
func Open(driverName, dataSourceName string) (*DB, error) {
driversMu.RLock()
driveri, ok := drivers[driverName]
driversMu.RUnlock()
if !ok {
return nil, fmt.Errorf("sql: unknown driver %q (forgotten import?)", driverName)
}
}
So, since you are no longer importing mysql, you need to change sql.Open to use the pq driver (or whichever one you end up picking).
In my Perl 6 script, I want to do a (preferably non-blocking) check of standard input to see if data is available. If this is the case, then I want to process it, otherwise I want to do other stuff.
Example (consumer.p6):
#!/usr/bin/perl6
use v6.b;
use fatal;
sub MAIN() returns UInt:D {
while !$*IN.eof {
if some_fancy_check_for_STDIN() { #TODO: this needs to be done.
for $*IN.lines -> $line {
say "Process '$line'";
}
}
say "Do something Else.";
}
say "I'm done.";
return 0;
}
As a STDIN-Generator I wrote another Perl6 script (producer.p6):
#!/usr/bin/perl6
use v6.b;
use fatal;
sub MAIN() returns UInt:D {
$*OUT.say("aaaa aaa");
sleep-until now+2;
$*OUT.say("nbbasdf");
sleep-until now+2;
$*OUT.say("xxxxx");
sleep-until now+2;
return 0;
}
If consumer.p6 works as expected, it should produce the following output, if called via ./producer.p6 | ./consumer.p6:
Process 'aaaa aaa'
Do something Else.
Process 'nbbasdf'
Do something Else.
Process 'xxxxx'
Do something Else.
I'm done.
But actually, it produces the following output (if the if condition is commented out):
Process 'aaaa aaa'
Process 'nbbasdf'
Process 'xxxxx'
Do something Else.
I'm done.
You are using an old version of Perl 6, as v6.b is from before the official release of the language.
So some of what I have below may need a newer version to work.
Also why are you using sleep-until now+2 instead of sleep 2?
One way to do this is to turn the .lines into a Channel, then you can use .poll.
#!/usr/bin/env perl6
use v6.c;
sub MAIN () {
# convert it into a Channel so we can poll it
my $lines = $*IN.Supply.lines.Channel;
my $running = True;
$lines.closed.then: {$running = False}
while $running {
with $lines.poll() -> $line {
say "Process '$line'";
}
say "Do something Else.";
sleep ½;
}
say "I'm done.";
}
Note that the code above blocks at the my $lines = … line currently; so it doesn't start doing something until the first line comes in. To get around that you could do the following
my $lines = supply {
# unblock the $*IN.Supply.lines call
whenever start $*IN.Supply {
whenever .lines { .emit }
}
}.Channel;
How can I write a message to Stderr without using log?
A comment in this SO post shows how to do it with log: log.Println("Message"), but what if I don't want a timestamp?
Is the following good Go?
os.Stderr.WriteString("Message")
If you don't want timestamps, just create a new log.Logger with flag set to 0:
l := log.New(os.Stderr, "", 0)
l.Println("log msg")
EDIT:
Is the following good Go?
os.Stderr.WriteString("Message")
This is acceptable, and you can also use fmt.Fprintf and friends to get formatted output:
fmt.Fprintf(os.Stderr, "number of foo: %d", nFoo)
Using the fmt package, you can choose to write to stderr this way:
import "fmt"
import "os"
func main() {
fmt.Fprintln(os.Stderr, "hello world")
}
The Go builtin functions print and println print to stderr. So if you simply want to output some text to stderr you can do
package main
func main() {
println("Hello stderr!")
}
Documentation: https://golang.org/pkg/builtin/#print
os.Stderr is an io.Writer, so you can use it in any function which accepts an io.Writer. Here are a few examples:
str := "Message"
fmt.Fprintln(os.Stderr, str)
io.WriteString(os.Stderr, str)
io.Copy(os.Stderr, bytes.NewBufferString(str))
os.Stderr.Write([]byte(str))
It all depends on how exactly you have the string you want to print (i.e. if you want to format it first, if you have it as an io.Reader, if you have it as a byte slice...). And there can be a lot more ways.
By default the logger flags are set to Ldate | Ltime. You can change the logger format to any of the following (from the golang log documentation):
Ldate = 1 << iota // the date in the local time zone: 2009/01/23
Ltime // the time in the local time zone: 01:23:23
Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime.
Llongfile // full file name and line number: /a/b/c/d.go:23
Lshortfile // final file name element and line number: d.go:23. overrides Llongfile
LUTC // if Ldate or Ltime is set, use UTC rather than the local time zone
LstdFlags = Ldate | Ltime // initial values for the standard logger
For example, flags Ldate | Ltime (or LstdFlags) produce,
2009/01/23 01:23:23 message
While flags Ldate | Ltime | Lmicroseconds | Llongfile produce,
2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message
You can also set the default logger to not print anything by setting the flag to 0:
log.SetFlags(0)
use SetOutput function, set output stream to os.Stdout
import (
"log"
"os"
)
func init() {
log.SetOutput(os.Stdout)
}
func main() {
log.Println("Gene Story SNP File Storage Server Started.")
}