-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add file generator #37
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,19 +6,21 @@ import ( | |
"io/ioutil" | ||
"os" | ||
"os/exec" | ||
"path" | ||
"path/filepath" | ||
"runtime" | ||
"testing" | ||
|
||
"reflect" | ||
"strings" | ||
|
||
"github.com/kr/pretty" | ||
) | ||
|
||
var update = flag.Bool("update", false, "update golden files") | ||
|
||
var binaryName = "fakedata" | ||
const binaryName = "fakedata" | ||
|
||
var binaryPath string | ||
|
||
func diff(expected, actual interface{}) []string { | ||
return pretty.Diff(expected, actual) | ||
|
@@ -54,49 +56,130 @@ func TestCliArgs(t *testing.T) { | |
name string | ||
args []string | ||
fixture string | ||
match func(string, string) bool | ||
}{ | ||
{"no arguments", []string{}, "help.golden"}, | ||
{"list generators", []string{"-g"}, "generators.golden"}, | ||
{"default format", []string{"int,42..42", "enum,foo..foo"}, "default-format.golden"}, | ||
{"unknown generators", []string{"madeupgenerator", "anothermadeupgenerator"}, "unknown-generators.golden"}, | ||
{"default format with limit short", []string{"-l=5", "int,42..42", "enum,foo..foo"}, "default-format-with-limit.golden"}, | ||
{"default format with limit", []string{"--limit=5", "int,42..42", "enum,foo..foo"}, "default-format-with-limit.golden"}, | ||
{"csv format short", []string{"-f=csv", "int,42..42", "enum,foo..foo"}, "csv-format.golden"}, | ||
{"csv format", []string{"--format=csv", "int,42..42", "enum,foo..foo"}, "csv-format.golden"}, | ||
{"tab format", []string{"-f=tab", "int,42..42", "enum,foo..foo"}, "tab-format.golden"}, | ||
{"sql format", []string{"-f=sql", "int,42..42", "enum,foo..foo"}, "sql-format.golden"}, | ||
{"sql format with keys", []string{"-f=sql", "age=int,42..42", "name=enum,foo..foo"}, "sql-format-with-keys.golden"}, | ||
{"sql format with table name", []string{"-f=sql", "-t=USERS", "int,42..42", "enum,foo..foo"}, "sql-format-with-table-name.golden"}, | ||
{ | ||
name: "no arguments", | ||
args: []string{}, | ||
fixture: "help.golden", | ||
}, | ||
{ | ||
name: "list generators", | ||
args: []string{"-g"}, | ||
fixture: "generators.golden", | ||
}, | ||
{ | ||
name: "default format", | ||
args: []string{"int,42..42", "enum,foo..foo"}, | ||
fixture: "default-format.golden", | ||
}, | ||
{ | ||
name: "unknown generators", | ||
args: []string{"madeupgenerator", "anothermadeupgenerator"}, | ||
fixture: "unknown-generators.golden", | ||
}, | ||
{ | ||
name: "default format with limit short", | ||
args: []string{"-l=5", "int,42..42", "enum,foo..foo"}, | ||
fixture: "default-format-with-limit.golden", | ||
}, | ||
{ | ||
name: "default format with limit", | ||
args: []string{"--limit=5", "int,42..42", "enum,foo..foo"}, | ||
fixture: "default-format-with-limit.golden", | ||
}, | ||
{ | ||
name: "csv format short", | ||
args: []string{"-f=csv", "int,42..42", "enum,foo..foo"}, | ||
fixture: "csv-format.golden", | ||
}, | ||
{ | ||
name: "csv format", | ||
args: []string{"--format=csv", "int,42..42", "enum,foo..foo"}, | ||
fixture: "csv-format.golden", | ||
}, | ||
{ | ||
name: "tab format", | ||
args: []string{"-f=tab", "int,42..42", "enum,foo..foo"}, | ||
fixture: "tab-format.golden", | ||
}, | ||
{ | ||
name: "sql format", | ||
args: []string{"-f=sql", "int,42..42", "enum,foo..foo"}, | ||
fixture: "sql-format.golden", | ||
}, | ||
{ | ||
name: "sql format with keys", | ||
args: []string{"-f=sql", "age=int,42..42", "name=enum,foo..foo"}, | ||
fixture: "sql-format-with-keys.golden", | ||
}, | ||
{ | ||
name: "sql format with table name", | ||
args: []string{"-f=sql", "-t=USERS", "int,42..42", "enum,foo..foo"}, | ||
fixture: "sql-format-with-table-name.golden", | ||
}, | ||
{ | ||
name: "file generator", | ||
args: []string{"file,integration/file.golden"}, | ||
fixture: "file.golden", | ||
match: func(actual, expected string) bool { | ||
for _, line := range strings.Split(actual, "\n") { | ||
if !strings.Contains(expected+"\n", line+"\n") { | ||
return false | ||
} | ||
} | ||
return true | ||
}, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
dir, err := os.Getwd() | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
cmd := exec.Command(path.Join(dir, binaryName), tt.args...) | ||
cmd := exec.Command(binaryPath, tt.args...) | ||
output, err := cmd.CombinedOutput() | ||
if err != nil { | ||
t.Fatal(err) | ||
t.Fatal(err, "\n", string(output)) | ||
} | ||
|
||
if *update { | ||
writeFixture(t, tt.fixture, output) | ||
} | ||
|
||
actual := string(output) | ||
|
||
expected := loadFixture(t, tt.fixture) | ||
|
||
if !reflect.DeepEqual(actual, expected) { | ||
if tt.match != nil { | ||
if !tt.match(actual, expected) { | ||
t.Fatalf("values do not match: \n%v\n%v", actual, expected) | ||
} | ||
} else if !reflect.DeepEqual(actual, expected) { | ||
t.Fatalf("diff: %v", diff(expected, actual)) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestCliErr(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
args []string | ||
}{ | ||
{"no file", []string{"file"}}, | ||
{"no file,", []string{"file,"}}, | ||
{"no file,''", []string{"file,''"}}, | ||
{`no file,""`, []string{`file,""`}}, | ||
{"file does not exist", []string{`file,'this file does not exist.txt'`}}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
if err := exec.Command(binaryPath, tt.args...).Run(); err == nil { | ||
t.Fatalf("expected to fail with args: %v", tt.args) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestMain(m *testing.M) { | ||
err := os.Chdir("..") | ||
if err != nil { | ||
|
@@ -109,6 +192,11 @@ func TestMain(m *testing.M) { | |
fmt.Printf("could not make binary for %s: %v", binaryName, err) | ||
os.Exit(1) | ||
} | ||
binaryPath, err = filepath.Abs(binaryName) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only need to get the path once. |
||
if err != nil { | ||
fmt.Printf("could not get binary path: %v", err) | ||
os.Exit(1) | ||
} | ||
|
||
os.Exit(m.Run()) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
one | ||
two | ||
three | ||
four | ||
five | ||
six | ||
seven | ||
eight | ||
nine | ||
ten |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ package fakedata | |
|
||
import ( | ||
"fmt" | ||
"io/ioutil" | ||
"log" | ||
"math/rand" | ||
"sort" | ||
|
@@ -177,6 +178,27 @@ var enum = func(column Column) string { | |
return withEnum(enum)(column) | ||
} | ||
|
||
var fileCache map[string][]string | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nice! As the program works right now I think this is a cool approach. It's interesting to notice that this is needed because the design of the program is still suboptimal. Right now, all the Constraints are computed for every single row which makes no sense from a perf perspective :D. I've been wanting to start working on it for a while (but only because it's fun!) but I had no real reason. Now that I see this I feel more compelled to start working on that too. It was only a digression though (kind of a way for me to start thinking about this more concretely). I think what you did here is pretty good for the current design There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @lucapette sure, while adding this I was wondering about the same thing :D |
||
|
||
var file = func(column Column) string { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @lucapette is there a reason you put the functions in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's funny. I think it's literally "historical reasons" even though the project is so young. I started it off an existing codebase and evolved the design in a direction I liked more. So long story short, there's no good reason right now. I'll put in a small gardening/good first patch issue for it. I think it's good we keep it consistent right now though so I appreciate you followed existing style. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
p := column.Constraints | ||
if p == "" { | ||
log.Fatalf("%s: no file path given", column.Name) | ||
} | ||
// Try to get file from cache | ||
f := fileCache[p] | ||
// Load file if cache is empty | ||
if f == nil { | ||
content, err := ioutil.ReadFile(p) | ||
if err != nil { | ||
log.Fatalf("%s: no readable file found at '%s'", column.Name, p) | ||
} | ||
f = strings.Split(string(content), "\n") | ||
} | ||
// Return random line | ||
return f[rand.Intn(len(f))] | ||
} | ||
|
||
func init() { | ||
generators = make(map[string]Generator) | ||
|
||
|
@@ -332,4 +354,10 @@ func init() { | |
Desc: `a random value from an enum. Defaults to "foo..bar..baz"`, | ||
Func: enum, | ||
} | ||
|
||
generators["file"] = Generator{ | ||
Name: "file", | ||
Desc: `Read a random line from a file. Pass filepath with 'file,path/to/file.txt'.`, | ||
Func: file, | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These don't fit into the table above.