Giter Site home page Giter Site logo

gencheck's Introduction

gencheck

CircleCI Coverage Status Go Report Card

Validation generation for go.

Built-in validations

See Validations

How it works

gencheck was built using the idea of zencoder/gokay, but uses templates to create validations for a struct.

gencheck will use the valid tag within a struct to generate a Validate() method, which is will store in a file_validators.go file next to the input file.

gencheck's Validate() method will return a ValidationErrors type, which is an array of FieldErrors.

Given the struct:

type MyStruct struct{
	MyField string `valid:"required"`
}

A Validate method is generated:

func (s MyStruct) Validate() error {
	var vErrors gencheck.ValidationErrors

	// BEGIN MyField Validations
	// required
	if s.MyField == "" {
		vErrors = append(vErrors, gencheck.NewFieldError("MyStruct", "MyField", "required", errors.New("is required")))
	}
	// END MyField Validations

	if len(vErrors) > 0 {
		return vErrors
	}
	return nil
}

Installing

First use go get to install the latest version of the library.

go get -v github.com/abice/gencheck/gencheck

Normally the above command will build and install the binary, but just to be sure it is installed in your GOPATH for use on the command line, or build args:

go install github.com/abice/gencheck/gencheck

Running

Command line

gencheck -f=file.go -t="SomeTemplate.tmpl" --template="SomeOtherTemplate.tmpl" -d="some/dir" --template-dir="some/dir/that/has/templates"

Using with go generate

Add a //go:generate tag to the top of your file that you want to generate for, including the file name.

//go:generate gencheck -f=this_file.go

Adding Validations

Add validations to valid tag in struct def:

type ExampleStruct struct {
	HexStringPtr            *string `valid:"len=16,notnil,hex"`
	HexString               string  `valid:"len=12,hex"`
	CanBeNilWithConstraints *string `valid:"len=12"`
}

Tag syntax

Validation tags are comma separated, with any validation parameter specified after an equal sign.

valid:"ValidationName1,ValidationName2=vn2param"

In the above example, the hex and notnil Validations are parameterless, whereas len requires 1 parameter.

Time comparisons

Since the addition of gt(e) and lt(e), there are now comparisons for time.Time values. If no arguments are specified to those, then it calculates whether the field time is After and Before time.Now().UTC() respectively. You can specify a parameter for those validations if you choose. The parameter will be interpreted as the offset to use with respect to time.Now().UTC() by utilizing the Add() function.

requestTime time.Time `valid:"gte=-1*time.Second"`
tGteTimeVal := time.Now().UTC().Add(-1 * time.Second)
if s.GteTimeVal.Before(tGteTimeVal) {
	vErrors = append(vErrors, gencheck.NewFieldError("Test", "GteTimeVal", "gte", fmt.Errorf("is before %s", tGteTimeVal)))
}

Fail Fast flag

The fail fast flag is a built-in validation flag that will allow you to return immediately on an invalid check. This allows you to not waste time checking the rest of the struct if a vital field is wrong. It can be placed anywhere within the valid tag, and will be applied to all rules within that field.

There is also a --failfast flag on the cli that will allow you to make all validations within all structs found in the files to be fail fast.

Writing your own Validations

gencheck allows developers to write and attach their own Validation templates to the generator.

  1. Write a template that creates a validation for a given field making sure to define the template as the validation tag you want to use:

    {{define "mycheck" -}}
    if err := gencheck.IsUUID({{.Param}}, {{if not (IsPtr . )}}&{{end}}s.{{.FieldName}}); err != nil {
      {{ AddError . "err" }}
    }
    {{end -}}
    
  2. Import that template when running gencheck

  3. Write tests for your struct's constraints

  4. Add valid tags to your struct fields

  5. Run gencheck: gencheck -f=file.go -t=MyTemplate

NOTES:

  • In your template, the . pipeline is an instance of the generator.Validation struct.
  • The template functions from Sprig have been included.
  • There are some custom functions provided for you to help in determining the ast field type
  • isPtr
  • addError
  • isNullable
  • isMap
  • isArray
  • isStruct
  • isStructPtr
  • isStructPtr
  • generationError
    • Allows you to fail code generation with a specific error message

More Examples

Useless Benchmarks

I know benchmarks are always skewed to show what the creators want you to see, but here's a quick benchmark of the cost of using validation to check.

I've also added some comparison benchmark output from the ./internal/benchmark_test.go to compare the different options with gencheck and how it holds up to the go playground validator.

BenchmarkReflectionInt-8      	20000000	       104 ns/op
BenchmarkEmptyInt-8           	2000000000	         0.29 ns/op
BenchmarkReflectionStruct-8   	 5000000	       262 ns/op
BenchmarkEmptyStruct-8        	50000000	        28.3 ns/op
BenchmarkReflectionString-8   	10000000	       159 ns/op
BenchmarkEmptyString-8        	200000000	         9.49 ns/op

Benchmarks using fail fast flag

BenchmarkValidString-8            	300000000	         5.02 ns/op
BenchmarkFailing1TestString-8     	10000000	       158 ns/op
BenchmarkFailing2TestString-8     	10000000	       159 ns/op
BenchmarkFailingAllTestString-8   	10000000	       164 ns/op

Benchmarks without fail fast flag and preallocated capacity for errors

BenchmarkValidString-8            	20000000	        68.7 ns/op
BenchmarkFailing1TestString-8     	10000000	       189 ns/op
BenchmarkFailing2TestString-8     	 5000000	       272 ns/op
BenchmarkFailingAllTestString-8   	 3000000	       418 ns/op

Development

Dependencies

Tested on go 1.7.3.

Build and run unit tests

make test

TODO

  • Testing for templates
  • Prevent duplicate validations on the same field
  • Update Required tag to error out on numerical or boolean fields
  • Support for sub-validations? Struct fields: generated code will call static Validate method on any field that implements Validateable interface Maybe use a deep check
  • Readme info for what information is available within the templates.
  • Contains for other slice types.
  • Contains for maps.
  • Add support for build tags for generated file.
  • Cross field validation (i.e. x.start <= x.end)

CI

This library builds on Circle CI, here.

License

Apache License Version 2.0

gencheck's People

Contributors

abice avatar jesse0michael avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

jesse0michael

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.