Skip to content

Commit

Permalink
Added support for environment variables. Added tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
dsoprea committed Jan 12, 2018
1 parent a3427f4 commit de3b4fb
Show file tree
Hide file tree
Showing 3 changed files with 213 additions and 7 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,13 @@ Note that using a parser this way returns the desired type directly (not as a `i

## Utilities

We also include a convenience function to parse values from an HTTP request
We also include a convenience function to parse values from an HTTP request
(query arguments or body data):

```go
// func ParseRequestArg(r *http.Request, name string, kindName string, required bool) (value interface{})
parse.ParseRequestArg(r, "varname", "float64", true).(float64)
// func FromRequest(r *http.Request, name string, kindName string, required bool) (value interface{})
v := parse.FromRequest(r, "varname", "float64", true).(float64)

// func FromEnviron(name string, kindName string, required bool) (value interface{})
v := parse.FromEnviron("varname", "float64", true).(float64)
```
22 changes: 18 additions & 4 deletions parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package parse
import (
"net/http"

"os"
"fmt"
"reflect"
"time"
Expand Down Expand Up @@ -49,7 +50,7 @@ var (
}

stringType = reflect.TypeOf("")

t = time.Time{}

KindNameZeroType = map[string]reflect.Type {
Expand Down Expand Up @@ -143,9 +144,8 @@ func Parse(valueRaw interface{}, toKindName string) interface{} {
return parsed[0].Interface()
}

// ParseRequestArg A convenience function to parse values from an incoming
// request.
func ParseRequestArg(r *http.Request, name string, kindName string, required bool) (value interface{}) {
// FromRequest parses values from an HTTP request.
func FromRequest(r *http.Request, name string, kindName string, required bool) (value interface{}) {
valueRaw := r.FormValue(name)
if valueRaw == "" {
if required == true {
Expand All @@ -157,3 +157,17 @@ func ParseRequestArg(r *http.Request, name string, kindName string, required boo

return Parse(valueRaw, kindName)
}

// FromEnviron parses values from the environment
func FromEnviron(name string, kindName string, required bool) (value interface{}) {
valueRaw := os.Getenv(name)
if valueRaw == "" {
if required == true {
log.Panic(fmt.Errorf("environment argument empty or omitted: [%s]", name))
} else {
return nil
}
}

return Parse(valueRaw, kindName)
}
189 changes: 189 additions & 0 deletions parse_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
package parse

import (
"testing"
"os"

"net/http"
"net/url"
)

const (
testEnvironmentKey = "_MULTIPARSE_TEST"
)

func TestFromRequest_String_Required_Hit(t *testing.T) {
req, err := http.NewRequest("GET", "http://example.com", nil)
if err != nil {
t.Fatalf("Could not fabricate request: [%s]", err)
}

req.Form = url.Values{}
req.Form.Add("SomeKey", "SomeValue")

actual := FromRequest(req, "SomeKey", "string", true)
expected := "SomeValue"

if actual != expected {
t.Fatalf("Actual value does not equal expected value: [%s] != [%s]",
actual, expected)
}
}

func TestFromRequest_String_Required_Miss(t *testing.T) {
defer func() {
errRaw := recover()
if errRaw == nil {
t.Fatalf("Did not get error for missing but required variable.")
}

err := errRaw.(error)

if err.Error() != "query argument empty or omitted: [SomeKey]" {
t.Fatalf("There was an error for a missing but required query argument but it was not the right error: [%v]", err)
}
}()

req, err := http.NewRequest("GET", "http://example.com", nil)
if err != nil {
t.Fatalf("Could not fabricate request: [%s]", err)
}

FromRequest(req, "SomeKey", "string", true)
}

func TestFromRequest_String_Optional_Hit(t *testing.T) {
req, err := http.NewRequest("GET", "http://example.com", nil)
if err != nil {
t.Fatalf("Could not fabricate request: [%s]", err)
}

req.Form = url.Values{}
req.Form.Add("SomeKey", "SomeValue")

actual := FromRequest(req, "SomeKey", "string", false)
expected := "SomeValue"

if actual != expected {
t.Fatalf("Actual value does not equal expected value: [%s] != [%s]",
actual, expected)
}
}

func TestFromRequest_String_Optional_Miss(t *testing.T) {
req, err := http.NewRequest("GET", "http://example.com", nil)
if err != nil {
t.Fatalf("Could not fabricate request: [%s]", err)
}

recovered := FromRequest(req, "SomeKey", "string", false)
if recovered != nil {
t.Fatalf("Read value should've been nil: [%s]", recovered)
}
}

func TestFromRequest_Uint64(t *testing.T) {
req, err := http.NewRequest("GET", "http://example.com", nil)
if err != nil {
t.Fatalf("Could not fabricate request: [%s]", err)
}

valueRaw := "123"

req.Form = url.Values{}
req.Form.Add("SomeKey", valueRaw)

recovered := FromRequest(req, "SomeKey", "uint64", false)
if recovered != uint64(123) {
t.Fatalf("Read value does not equal written UINT64 value: [%v] != [%s]",
recovered, valueRaw)
}
}

func TestFromEnviron_String_Required_Hit(t *testing.T) {
value := "SOME-VALUE"

os.Unsetenv(testEnvironmentKey)

err := os.Setenv(testEnvironmentKey, value)
if err != nil {
t.Fatalf("Could not set variable: %v", err)
}

defer func() {
os.Unsetenv(testEnvironmentKey)
}()

recovered := FromEnviron(testEnvironmentKey, "string", true)
if recovered != value {
t.Fatalf("Read value does not equal written value: [%s] != [%s]",
recovered, value)
}
}

func TestFromEnviron_String_Required_Miss(t *testing.T) {
defer func() {
errRaw := recover()
if errRaw == nil {
t.Fatalf("Did not get error for missing but required variable.")
}

err := errRaw.(error)

if err.Error() != "environment argument empty or omitted: [_MULTIPARSE_TEST]" {
t.Fatalf("There was an error for a missing but required variable but it was not the right error: [%v]", err)
}
}()

os.Unsetenv(testEnvironmentKey)
FromEnviron(testEnvironmentKey, "string", true)
}

func TestFromEnviron_String_Optional_Hit(t *testing.T) {
value := "SOME-VALUE2"

os.Unsetenv(testEnvironmentKey)

err := os.Setenv(testEnvironmentKey, value)
if err != nil {
t.Fatalf("Could not set variable: %v", err)
}

defer func() {
os.Unsetenv(testEnvironmentKey)
}()

recovered := FromEnviron(testEnvironmentKey, "string", false)
if recovered != value {
t.Fatalf("Read value does not equal written STRING value: [%s] != [%s]",
recovered, value)
}
}

func TestFromEnviron_String_Optional_Miss(t *testing.T) {
recovered := FromEnviron(testEnvironmentKey, "string", false)
if recovered != nil {
t.Fatalf("Read value should've been nil: [%s]", recovered)
}
}

func TestFromEnviron_Uint64(t *testing.T) {
value := "123"

os.Unsetenv(testEnvironmentKey)

err := os.Setenv(testEnvironmentKey, value)
if err != nil {
t.Fatalf("Could not set variable: %v", err)
}

defer func() {
os.Unsetenv(testEnvironmentKey)
}()

recovered := FromEnviron(testEnvironmentKey, "uint64", false)
if recovered != uint64(123) {
t.Fatalf("Read value does not equal written UINT64 value: [%v] != [%s]",
recovered, value)
}
}

0 comments on commit de3b4fb

Please sign in to comment.