Compare commits
No commits in common. 'master' and 'v4' have entirely different histories.
@ -1 +0,0 @@ |
|||||||
* @go-playground/validator-maintainers |
|
@ -1,9 +0,0 @@ |
|||||||
# Contribution Guidelines |
|
||||||
|
|
||||||
## Quality Standard |
|
||||||
|
|
||||||
To ensure the continued stability of this package, tests are required that cover the change in order for a pull request to be merged. |
|
||||||
|
|
||||||
## Reporting issues |
|
||||||
|
|
||||||
Please open an issue or join the gitter chat [![Join the chat at https://gitter.im/go-playground/validator](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-playground/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) for any issues, questions or possible enhancements to the package. |
|
@ -1,16 +0,0 @@ |
|||||||
- [ ] I have looked at the documentation [here](https://pkg.go.dev/github.com/go-playground/validator/v10#section-documentation) first? |
|
||||||
- [ ] I have looked at the examples provided that may showcase my question [here](/_examples)? |
|
||||||
|
|
||||||
### Package version eg. v9, v10: |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Issue, Question or Enhancement: |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Code sample, to showcase or reproduce: |
|
||||||
|
|
||||||
```go |
|
||||||
|
|
||||||
``` |
|
@ -1,7 +0,0 @@ |
|||||||
## Fixes Or Enhances |
|
||||||
|
|
||||||
|
|
||||||
**Make sure that you've checked the boxes below before you submit PR:** |
|
||||||
- [ ] Tests exist or have been written that cover this particular change. |
|
||||||
|
|
||||||
@go-playground/validator-maintainers |
|
@ -1,51 +0,0 @@ |
|||||||
on: |
|
||||||
push: |
|
||||||
branches: |
|
||||||
- master |
|
||||||
pull_request: |
|
||||||
name: Test |
|
||||||
jobs: |
|
||||||
test: |
|
||||||
strategy: |
|
||||||
matrix: |
|
||||||
go-version: [1.19.x] |
|
||||||
os: [ubuntu-latest, macos-latest, windows-latest] |
|
||||||
runs-on: ${{ matrix.os }} |
|
||||||
steps: |
|
||||||
- name: Install Go |
|
||||||
uses: actions/setup-go@v3 |
|
||||||
with: |
|
||||||
go-version: ${{ matrix.go-version }} |
|
||||||
|
|
||||||
- name: Checkout code |
|
||||||
uses: actions/checkout@v3 |
|
||||||
|
|
||||||
- name: Restore Cache |
|
||||||
uses: actions/cache@v3 |
|
||||||
with: |
|
||||||
path: ~/go/pkg/mod |
|
||||||
key: ${{ runner.os }}-v1-go-${{ hashFiles('**/go.sum') }} |
|
||||||
restore-keys: | |
|
||||||
${{ runner.os }}-v1-go- |
|
||||||
|
|
||||||
- name: Test |
|
||||||
run: go test -race -covermode=atomic -coverprofile="profile.cov" ./... |
|
||||||
|
|
||||||
- name: Send Coverage |
|
||||||
if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.19.x' |
|
||||||
uses: shogo82148/actions-goveralls@v1 |
|
||||||
with: |
|
||||||
path-to-profile: profile.cov |
|
||||||
|
|
||||||
golangci: |
|
||||||
name: lint |
|
||||||
runs-on: ubuntu-latest |
|
||||||
steps: |
|
||||||
- uses: actions/setup-go@v3 |
|
||||||
with: |
|
||||||
go-version: 1.19.x |
|
||||||
- uses: actions/checkout@v3 |
|
||||||
- name: golangci-lint |
|
||||||
uses: golangci/golangci-lint-action@v3 |
|
||||||
with: |
|
||||||
version: v1.50.1 |
|
@ -0,0 +1,16 @@ |
|||||||
|
language: go |
||||||
|
|
||||||
|
notificaitons: |
||||||
|
email: |
||||||
|
recipients: bluesuncorp01@gmail.com |
||||||
|
on_success: change |
||||||
|
on_failure: always |
||||||
|
|
||||||
|
before_script: |
||||||
|
- go get gopkg.in/check.v1 |
||||||
|
|
||||||
|
go: |
||||||
|
- 1.2 |
||||||
|
- 1.3 |
||||||
|
- 1.4 |
||||||
|
- tip |
@ -1,16 +0,0 @@ |
|||||||
## Maintainers Guide |
|
||||||
|
|
||||||
### Semantic Versioning |
|
||||||
Semantic versioning as defined [here](https://semver.org) must be strictly adhered to. |
|
||||||
|
|
||||||
### External Dependencies |
|
||||||
Any new external dependencies MUST: |
|
||||||
- Have a compatible LICENSE present. |
|
||||||
- Be actively maintained. |
|
||||||
- Be approved by @go-playground/admins |
|
||||||
|
|
||||||
### PR Merge Requirements |
|
||||||
- Up-to-date branch. |
|
||||||
- Passing tests and linting. |
|
||||||
- CODEOWNERS approval. |
|
||||||
- Tests that cover both the Happy and Unhappy paths. |
|
@ -1,18 +0,0 @@ |
|||||||
GOCMD=GO111MODULE=on go
|
|
||||||
|
|
||||||
linters-install: |
|
||||||
@golangci-lint --version >/dev/null 2>&1 || { \
|
|
||||||
echo "installing linting tools..."; \
|
|
||||||
curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s v1.41.1; \
|
|
||||||
}
|
|
||||||
|
|
||||||
lint: linters-install |
|
||||||
golangci-lint run
|
|
||||||
|
|
||||||
test: |
|
||||||
$(GOCMD) test -cover -race ./...
|
|
||||||
|
|
||||||
bench: |
|
||||||
$(GOCMD) test -bench=. -benchmem ./...
|
|
||||||
|
|
||||||
.PHONY: test lint linters-install |
|
@ -1,348 +1,43 @@ |
|||||||
Package validator |
Package go-validate-yourself |
||||||
================= |
================ |
||||||
<img align="right" src="https://raw.githubusercontent.com/go-playground/validator/v10/logo.png">[![Join the chat at https://gitter.im/go-playground/validator](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-playground/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) |
[![Build Status](https://travis-ci.org/bluesuncorp/go-validate-yourself.svg?branch=v4)](https://travis-ci.org/bluesuncorp/go-validate-yourself) |
||||||
![Project status](https://img.shields.io/badge/version-10.12.0-green.svg) |
[![GoDoc](https://godoc.org/gopkg.in/bluesuncorp/go-validate-yourself.v4?status.svg)](https://godoc.org/gopkg.in/bluesuncorp/go-validate-yourself.v4) |
||||||
[![Build Status](https://travis-ci.org/go-playground/validator.svg?branch=master)](https://travis-ci.org/go-playground/validator) |
|
||||||
[![Coverage Status](https://coveralls.io/repos/go-playground/validator/badge.svg?branch=master&service=github)](https://coveralls.io/github/go-playground/validator?branch=master) |
|
||||||
[![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/validator)](https://goreportcard.com/report/github.com/go-playground/validator) |
|
||||||
[![GoDoc](https://godoc.org/github.com/go-playground/validator?status.svg)](https://pkg.go.dev/github.com/go-playground/validator/v10) |
|
||||||
![License](https://img.shields.io/dub/l/vibe-d.svg) |
|
||||||
|
|
||||||
Package validator implements value validations for structs and individual fields based on tags. |
Package validator implements value validations for structs and individual fields based on tags. |
||||||
|
|
||||||
It has the following **unique** features: |
|
||||||
|
|
||||||
- Cross Field and Cross Struct validations by using validation tags or custom validators. |
|
||||||
- Slice, Array and Map diving, which allows any or all levels of a multidimensional field to be validated. |
|
||||||
- Ability to dive into both map keys and values for validation |
|
||||||
- Handles type interface by determining it's underlying type prior to validation. |
|
||||||
- Handles custom field types such as sql driver Valuer see [Valuer](https://golang.org/src/database/sql/driver/types.go?s=1210:1293#L29) |
|
||||||
- Alias validation tags, which allows for mapping of several validations to a single tag for easier defining of validations on structs |
|
||||||
- Extraction of custom defined Field Name e.g. can specify to extract the JSON name while validating and have it available in the resulting FieldError |
|
||||||
- Customizable i18n aware error messages. |
|
||||||
- Default validator for the [gin](https://github.com/gin-gonic/gin) web framework; upgrading from v8 to v9 in gin see [here](https://github.com/go-playground/validator/tree/master/_examples/gin-upgrading-overriding) |
|
||||||
|
|
||||||
Installation |
Installation |
||||||
------------ |
============ |
||||||
|
|
||||||
Use go get. |
|
||||||
|
|
||||||
go get github.com/go-playground/validator/v10 |
|
||||||
|
|
||||||
Then import the validator package into your own code. |
|
||||||
|
|
||||||
import "github.com/go-playground/validator/v10" |
|
||||||
|
|
||||||
Error Return Value |
|
||||||
------- |
|
||||||
|
|
||||||
Validation functions return type error |
|
||||||
|
|
||||||
They return type error to avoid the issue discussed in the following, where err is always != nil: |
|
||||||
|
|
||||||
* http://stackoverflow.com/a/29138676/3158232 |
|
||||||
* https://github.com/go-playground/validator/issues/134 |
|
||||||
|
|
||||||
Validator returns only InvalidValidationError for bad validation input, nil or ValidationErrors as type error; so, in your code all you need to do is check if the error returned is not nil, and if it's not check if error is InvalidValidationError ( if necessary, most of the time it isn't ) type cast it to type ValidationErrors like so: |
|
||||||
|
|
||||||
```go |
Just use go get. |
||||||
err := validate.Struct(mystruct) |
|
||||||
validationErrors := err.(validator.ValidationErrors) |
|
||||||
``` |
|
||||||
|
|
||||||
Usage and documentation |
go get gopkg.in/bluesuncorp/go-validate-yourself.v4 |
||||||
------ |
|
||||||
|
|
||||||
Please see https://pkg.go.dev/github.com/go-playground/validator/v10 for detailed usage docs. |
or to update |
||||||
|
|
||||||
##### Examples: |
go get -u gopkg.in/bluesuncorp/go-validate-yourself.v4 |
||||||
|
|
||||||
- [Simple](https://github.com/go-playground/validator/blob/master/_examples/simple/main.go) |
And then just import the package into your own code. |
||||||
- [Custom Field Types](https://github.com/go-playground/validator/blob/master/_examples/custom/main.go) |
|
||||||
- [Struct Level](https://github.com/go-playground/validator/blob/master/_examples/struct-level/main.go) |
|
||||||
- [Translations & Custom Errors](https://github.com/go-playground/validator/blob/master/_examples/translations/main.go) |
|
||||||
- [Gin upgrade and/or override validator](https://github.com/go-playground/validator/tree/v9/_examples/gin-upgrading-overriding) |
|
||||||
- [wash - an example application putting it all together](https://github.com/bluesuncorp/wash) |
|
||||||
|
|
||||||
Baked-in Validations |
import "gopkg.in/bluesuncorp/go-validate-yourself.v4" |
||||||
------ |
|
||||||
|
|
||||||
### Fields: |
Usage |
||||||
|
===== |
||||||
|
|
||||||
| Tag | Description | |
Please see http://godoc.org/gopkg.in/bluesuncorp/go-validate-yourself.v4 for detailed usage docs. |
||||||
| - | - | |
|
||||||
| eqcsfield | Field Equals Another Field (relative)| |
|
||||||
| eqfield | Field Equals Another Field | |
|
||||||
| fieldcontains | Check the indicated characters are present in the Field | |
|
||||||
| fieldexcludes | Check the indicated characters are not present in the field | |
|
||||||
| gtcsfield | Field Greater Than Another Relative Field | |
|
||||||
| gtecsfield | Field Greater Than or Equal To Another Relative Field | |
|
||||||
| gtefield | Field Greater Than or Equal To Another Field | |
|
||||||
| gtfield | Field Greater Than Another Field | |
|
||||||
| ltcsfield | Less Than Another Relative Field | |
|
||||||
| ltecsfield | Less Than or Equal To Another Relative Field | |
|
||||||
| ltefield | Less Than or Equal To Another Field | |
|
||||||
| ltfield | Less Than Another Field | |
|
||||||
| necsfield | Field Does Not Equal Another Field (relative) | |
|
||||||
| nefield | Field Does Not Equal Another Field | |
|
||||||
|
|
||||||
### Network: |
Contributing |
||||||
|
============ |
||||||
|
|
||||||
| Tag | Description | |
There will be a development branch for each version of this package i.e. v1-development, please |
||||||
| - | - | |
make your pull requests against those branches. |
||||||
| cidr | Classless Inter-Domain Routing CIDR | |
|
||||||
| cidrv4 | Classless Inter-Domain Routing CIDRv4 | |
|
||||||
| cidrv6 | Classless Inter-Domain Routing CIDRv6 | |
|
||||||
| datauri | Data URL | |
|
||||||
| fqdn | Full Qualified Domain Name (FQDN) | |
|
||||||
| hostname | Hostname RFC 952 | |
|
||||||
| hostname_port | HostPort | |
|
||||||
| hostname_rfc1123 | Hostname RFC 1123 | |
|
||||||
| ip | Internet Protocol Address IP | |
|
||||||
| ip4_addr | Internet Protocol Address IPv4 | |
|
||||||
| ip6_addr | Internet Protocol Address IPv6 | |
|
||||||
| ip_addr | Internet Protocol Address IP | |
|
||||||
| ipv4 | Internet Protocol Address IPv4 | |
|
||||||
| ipv6 | Internet Protocol Address IPv6 | |
|
||||||
| mac | Media Access Control Address MAC | |
|
||||||
| tcp4_addr | Transmission Control Protocol Address TCPv4 | |
|
||||||
| tcp6_addr | Transmission Control Protocol Address TCPv6 | |
|
||||||
| tcp_addr | Transmission Control Protocol Address TCP | |
|
||||||
| udp4_addr | User Datagram Protocol Address UDPv4 | |
|
||||||
| udp6_addr | User Datagram Protocol Address UDPv6 | |
|
||||||
| udp_addr | User Datagram Protocol Address UDP | |
|
||||||
| unix_addr | Unix domain socket end point Address | |
|
||||||
| uri | URI String | |
|
||||||
| url | URL String | |
|
||||||
| http_url | HTTP URL String | |
|
||||||
| url_encoded | URL Encoded | |
|
||||||
| urn_rfc2141 | Urn RFC 2141 String | |
|
||||||
|
|
||||||
### Strings: |
If changes are breaking please create an issue, for discussion and create a pull request against |
||||||
|
the highest development branch for example this package has a v1 and v1-development branch |
||||||
|
however, there will also be a v2-development brach even though v2 doesn't exist yet. |
||||||
|
|
||||||
| Tag | Description | |
I strongly encourage everyone whom creates a custom validation function to contribute them and |
||||||
| - | - | |
help make this package even better. |
||||||
| alpha | Alpha Only | |
|
||||||
| alphanum | Alphanumeric | |
|
||||||
| alphanumunicode | Alphanumeric Unicode | |
|
||||||
| alphaunicode | Alpha Unicode | |
|
||||||
| ascii | ASCII | |
|
||||||
| boolean | Boolean | |
|
||||||
| contains | Contains | |
|
||||||
| containsany | Contains Any | |
|
||||||
| containsrune | Contains Rune | |
|
||||||
| endsnotwith | Ends Not With | |
|
||||||
| endswith | Ends With | |
|
||||||
| excludes | Excludes | |
|
||||||
| excludesall | Excludes All | |
|
||||||
| excludesrune | Excludes Rune | |
|
||||||
| lowercase | Lowercase | |
|
||||||
| multibyte | Multi-Byte Characters | |
|
||||||
| number | Number | |
|
||||||
| numeric | Numeric | |
|
||||||
| printascii | Printable ASCII | |
|
||||||
| startsnotwith | Starts Not With | |
|
||||||
| startswith | Starts With | |
|
||||||
| uppercase | Uppercase | |
|
||||||
|
|
||||||
### Format: |
|
||||||
| Tag | Description | |
|
||||||
| - | - | |
|
||||||
| base64 | Base64 String | |
|
||||||
| base64url | Base64URL String | |
|
||||||
| base64rawurl | Base64RawURL String | |
|
||||||
| bic | Business Identifier Code (ISO 9362) | |
|
||||||
| bcp47_language_tag | Language tag (BCP 47) | |
|
||||||
| btc_addr | Bitcoin Address | |
|
||||||
| btc_addr_bech32 | Bitcoin Bech32 Address (segwit) | |
|
||||||
| credit_card | Credit Card Number | |
|
||||||
| mongodb | MongoDB ObjectID | |
|
||||||
| cron | Cron | |
|
||||||
| datetime | Datetime | |
|
||||||
| e164 | e164 formatted phone number | |
|
||||||
| email | E-mail String |
|
||||||
| eth_addr | Ethereum Address | |
|
||||||
| hexadecimal | Hexadecimal String | |
|
||||||
| hexcolor | Hexcolor String | |
|
||||||
| hsl | HSL String | |
|
||||||
| hsla | HSLA String | |
|
||||||
| html | HTML Tags | |
|
||||||
| html_encoded | HTML Encoded | |
|
||||||
| isbn | International Standard Book Number | |
|
||||||
| isbn10 | International Standard Book Number 10 | |
|
||||||
| isbn13 | International Standard Book Number 13 | |
|
||||||
| iso3166_1_alpha2 | Two-letter country code (ISO 3166-1 alpha-2) | |
|
||||||
| iso3166_1_alpha3 | Three-letter country code (ISO 3166-1 alpha-3) | |
|
||||||
| iso3166_1_alpha_numeric | Numeric country code (ISO 3166-1 numeric) | |
|
||||||
| iso3166_2 | Country subdivision code (ISO 3166-2) | |
|
||||||
| iso4217 | Currency code (ISO 4217) | |
|
||||||
| json | JSON | |
|
||||||
| jwt | JSON Web Token (JWT) | |
|
||||||
| latitude | Latitude | |
|
||||||
| longitude | Longitude | |
|
||||||
| luhn_checksum | Luhn Algorithm Checksum (for strings and (u)int) | |
|
||||||
| postcode_iso3166_alpha2 | Postcode | |
|
||||||
| postcode_iso3166_alpha2_field | Postcode | |
|
||||||
| rgb | RGB String | |
|
||||||
| rgba | RGBA String | |
|
||||||
| ssn | Social Security Number SSN | |
|
||||||
| timezone | Timezone | |
|
||||||
| uuid | Universally Unique Identifier UUID | |
|
||||||
| uuid3 | Universally Unique Identifier UUID v3 | |
|
||||||
| uuid3_rfc4122 | Universally Unique Identifier UUID v3 RFC4122 | |
|
||||||
| uuid4 | Universally Unique Identifier UUID v4 | |
|
||||||
| uuid4_rfc4122 | Universally Unique Identifier UUID v4 RFC4122 | |
|
||||||
| uuid5 | Universally Unique Identifier UUID v5 | |
|
||||||
| uuid5_rfc4122 | Universally Unique Identifier UUID v5 RFC4122 | |
|
||||||
| uuid_rfc4122 | Universally Unique Identifier UUID RFC4122 | |
|
||||||
| md4 | MD4 hash | |
|
||||||
| md5 | MD5 hash | |
|
||||||
| sha256 | SHA256 hash | |
|
||||||
| sha384 | SHA384 hash | |
|
||||||
| sha512 | SHA512 hash | |
|
||||||
| ripemd128 | RIPEMD-128 hash | |
|
||||||
| ripemd128 | RIPEMD-160 hash | |
|
||||||
| tiger128 | TIGER128 hash | |
|
||||||
| tiger160 | TIGER160 hash | |
|
||||||
| tiger192 | TIGER192 hash | |
|
||||||
| semver | Semantic Versioning 2.0.0 | |
|
||||||
| ulid | Universally Unique Lexicographically Sortable Identifier ULID | |
|
||||||
| cve | Common Vulnerabilities and Exposures Identifier (CVE id) | |
|
||||||
|
|
||||||
### Comparisons: |
|
||||||
| Tag | Description | |
|
||||||
| - | - | |
|
||||||
| eq | Equals | |
|
||||||
| eq_ignore_case | Equals ignoring case | |
|
||||||
| gt | Greater than| |
|
||||||
| gte | Greater than or equal | |
|
||||||
| lt | Less Than | |
|
||||||
| lte | Less Than or Equal | |
|
||||||
| ne | Not Equal | |
|
||||||
| ne_ignore_case | Not Equal ignoring case | |
|
||||||
|
|
||||||
### Other: |
|
||||||
| Tag | Description | |
|
||||||
| - | - | |
|
||||||
| dir | Existing Directory | |
|
||||||
| dirpath | Directory Path | |
|
||||||
| file | Existing File | |
|
||||||
| filepath | File Path | |
|
||||||
| isdefault | Is Default | |
|
||||||
| len | Length | |
|
||||||
| max | Maximum | |
|
||||||
| min | Minimum | |
|
||||||
| oneof | One Of | |
|
||||||
| required | Required | |
|
||||||
| required_if | Required If | |
|
||||||
| required_unless | Required Unless | |
|
||||||
| required_with | Required With | |
|
||||||
| required_with_all | Required With All | |
|
||||||
| required_without | Required Without | |
|
||||||
| required_without_all | Required Without All | |
|
||||||
| excluded_if | Excluded If | |
|
||||||
| excluded_unless | Excluded Unless | |
|
||||||
| excluded_with | Excluded With | |
|
||||||
| excluded_with_all | Excluded With All | |
|
||||||
| excluded_without | Excluded Without | |
|
||||||
| excluded_without_all | Excluded Without All | |
|
||||||
| unique | Unique | |
|
||||||
|
|
||||||
#### Aliases: |
|
||||||
| Tag | Description | |
|
||||||
| - | - | |
|
||||||
| iscolor | hexcolor\|rgb\|rgba\|hsl\|hsla | |
|
||||||
| country_code | iso3166_1_alpha2\|iso3166_1_alpha3\|iso3166_1_alpha_numeric | |
|
||||||
|
|
||||||
Benchmarks |
|
||||||
------ |
|
||||||
###### Run on MacBook Pro (15-inch, 2017) go version go1.10.2 darwin/amd64 |
|
||||||
```go |
|
||||||
goos: darwin |
|
||||||
goarch: amd64 |
|
||||||
pkg: github.com/go-playground/validator |
|
||||||
BenchmarkFieldSuccess-8 20000000 83.6 ns/op 0 B/op 0 allocs/op |
|
||||||
BenchmarkFieldSuccessParallel-8 50000000 26.8 ns/op 0 B/op 0 allocs/op |
|
||||||
BenchmarkFieldFailure-8 5000000 291 ns/op 208 B/op 4 allocs/op |
|
||||||
BenchmarkFieldFailureParallel-8 20000000 107 ns/op 208 B/op 4 allocs/op |
|
||||||
BenchmarkFieldArrayDiveSuccess-8 2000000 623 ns/op 201 B/op 11 allocs/op |
|
||||||
BenchmarkFieldArrayDiveSuccessParallel-8 10000000 237 ns/op 201 B/op 11 allocs/op |
|
||||||
BenchmarkFieldArrayDiveFailure-8 2000000 859 ns/op 412 B/op 16 allocs/op |
|
||||||
BenchmarkFieldArrayDiveFailureParallel-8 5000000 335 ns/op 413 B/op 16 allocs/op |
|
||||||
BenchmarkFieldMapDiveSuccess-8 1000000 1292 ns/op 432 B/op 18 allocs/op |
|
||||||
BenchmarkFieldMapDiveSuccessParallel-8 3000000 467 ns/op 432 B/op 18 allocs/op |
|
||||||
BenchmarkFieldMapDiveFailure-8 1000000 1082 ns/op 512 B/op 16 allocs/op |
|
||||||
BenchmarkFieldMapDiveFailureParallel-8 5000000 425 ns/op 512 B/op 16 allocs/op |
|
||||||
BenchmarkFieldMapDiveWithKeysSuccess-8 1000000 1539 ns/op 480 B/op 21 allocs/op |
|
||||||
BenchmarkFieldMapDiveWithKeysSuccessParallel-8 3000000 613 ns/op 480 B/op 21 allocs/op |
|
||||||
BenchmarkFieldMapDiveWithKeysFailure-8 1000000 1413 ns/op 721 B/op 21 allocs/op |
|
||||||
BenchmarkFieldMapDiveWithKeysFailureParallel-8 3000000 575 ns/op 721 B/op 21 allocs/op |
|
||||||
BenchmarkFieldCustomTypeSuccess-8 10000000 216 ns/op 32 B/op 2 allocs/op |
|
||||||
BenchmarkFieldCustomTypeSuccessParallel-8 20000000 82.2 ns/op 32 B/op 2 allocs/op |
|
||||||
BenchmarkFieldCustomTypeFailure-8 5000000 274 ns/op 208 B/op 4 allocs/op |
|
||||||
BenchmarkFieldCustomTypeFailureParallel-8 20000000 116 ns/op 208 B/op 4 allocs/op |
|
||||||
BenchmarkFieldOrTagSuccess-8 2000000 740 ns/op 16 B/op 1 allocs/op |
|
||||||
BenchmarkFieldOrTagSuccessParallel-8 3000000 474 ns/op 16 B/op 1 allocs/op |
|
||||||
BenchmarkFieldOrTagFailure-8 3000000 471 ns/op 224 B/op 5 allocs/op |
|
||||||
BenchmarkFieldOrTagFailureParallel-8 3000000 414 ns/op 224 B/op 5 allocs/op |
|
||||||
BenchmarkStructLevelValidationSuccess-8 10000000 213 ns/op 32 B/op 2 allocs/op |
|
||||||
BenchmarkStructLevelValidationSuccessParallel-8 20000000 91.8 ns/op 32 B/op 2 allocs/op |
|
||||||
BenchmarkStructLevelValidationFailure-8 3000000 473 ns/op 304 B/op 8 allocs/op |
|
||||||
BenchmarkStructLevelValidationFailureParallel-8 10000000 234 ns/op 304 B/op 8 allocs/op |
|
||||||
BenchmarkStructSimpleCustomTypeSuccess-8 5000000 385 ns/op 32 B/op 2 allocs/op |
|
||||||
BenchmarkStructSimpleCustomTypeSuccessParallel-8 10000000 161 ns/op 32 B/op 2 allocs/op |
|
||||||
BenchmarkStructSimpleCustomTypeFailure-8 2000000 640 ns/op 424 B/op 9 allocs/op |
|
||||||
BenchmarkStructSimpleCustomTypeFailureParallel-8 5000000 318 ns/op 440 B/op 10 allocs/op |
|
||||||
BenchmarkStructFilteredSuccess-8 2000000 597 ns/op 288 B/op 9 allocs/op |
|
||||||
BenchmarkStructFilteredSuccessParallel-8 10000000 266 ns/op 288 B/op 9 allocs/op |
|
||||||
BenchmarkStructFilteredFailure-8 3000000 454 ns/op 256 B/op 7 allocs/op |
|
||||||
BenchmarkStructFilteredFailureParallel-8 10000000 214 ns/op 256 B/op 7 allocs/op |
|
||||||
BenchmarkStructPartialSuccess-8 3000000 502 ns/op 256 B/op 6 allocs/op |
|
||||||
BenchmarkStructPartialSuccessParallel-8 10000000 225 ns/op 256 B/op 6 allocs/op |
|
||||||
BenchmarkStructPartialFailure-8 2000000 702 ns/op 480 B/op 11 allocs/op |
|
||||||
BenchmarkStructPartialFailureParallel-8 5000000 329 ns/op 480 B/op 11 allocs/op |
|
||||||
BenchmarkStructExceptSuccess-8 2000000 793 ns/op 496 B/op 12 allocs/op |
|
||||||
BenchmarkStructExceptSuccessParallel-8 10000000 193 ns/op 240 B/op 5 allocs/op |
|
||||||
BenchmarkStructExceptFailure-8 2000000 639 ns/op 464 B/op 10 allocs/op |
|
||||||
BenchmarkStructExceptFailureParallel-8 5000000 300 ns/op 464 B/op 10 allocs/op |
|
||||||
BenchmarkStructSimpleCrossFieldSuccess-8 3000000 417 ns/op 72 B/op 3 allocs/op |
|
||||||
BenchmarkStructSimpleCrossFieldSuccessParallel-8 10000000 163 ns/op 72 B/op 3 allocs/op |
|
||||||
BenchmarkStructSimpleCrossFieldFailure-8 2000000 645 ns/op 304 B/op 8 allocs/op |
|
||||||
BenchmarkStructSimpleCrossFieldFailureParallel-8 5000000 285 ns/op 304 B/op 8 allocs/op |
|
||||||
BenchmarkStructSimpleCrossStructCrossFieldSuccess-8 3000000 588 ns/op 80 B/op 4 allocs/op |
|
||||||
BenchmarkStructSimpleCrossStructCrossFieldSuccessParallel-8 10000000 221 ns/op 80 B/op 4 allocs/op |
|
||||||
BenchmarkStructSimpleCrossStructCrossFieldFailure-8 2000000 868 ns/op 320 B/op 9 allocs/op |
|
||||||
BenchmarkStructSimpleCrossStructCrossFieldFailureParallel-8 5000000 337 ns/op 320 B/op 9 allocs/op |
|
||||||
BenchmarkStructSimpleSuccess-8 5000000 260 ns/op 0 B/op 0 allocs/op |
|
||||||
BenchmarkStructSimpleSuccessParallel-8 20000000 90.6 ns/op 0 B/op 0 allocs/op |
|
||||||
BenchmarkStructSimpleFailure-8 2000000 619 ns/op 424 B/op 9 allocs/op |
|
||||||
BenchmarkStructSimpleFailureParallel-8 5000000 296 ns/op 424 B/op 9 allocs/op |
|
||||||
BenchmarkStructComplexSuccess-8 1000000 1454 ns/op 128 B/op 8 allocs/op |
|
||||||
BenchmarkStructComplexSuccessParallel-8 3000000 579 ns/op 128 B/op 8 allocs/op |
|
||||||
BenchmarkStructComplexFailure-8 300000 4140 ns/op 3041 B/op 53 allocs/op |
|
||||||
BenchmarkStructComplexFailureParallel-8 1000000 2127 ns/op 3041 B/op 53 allocs/op |
|
||||||
BenchmarkOneof-8 10000000 140 ns/op 0 B/op 0 allocs/op |
|
||||||
BenchmarkOneofParallel-8 20000000 70.1 ns/op 0 B/op 0 allocs/op |
|
||||||
``` |
|
||||||
|
|
||||||
Complementary Software |
|
||||||
---------------------- |
|
||||||
|
|
||||||
Here is a list of software that complements using this library either pre or post validation. |
|
||||||
|
|
||||||
* [form](https://github.com/go-playground/form) - Decodes url.Values into Go value(s) and Encodes Go value(s) into url.Values. Dual Array and Full map support. |
|
||||||
* [mold](https://github.com/go-playground/mold) - A general library to help modify or set data within data structures and other objects |
|
||||||
|
|
||||||
How to Contribute |
|
||||||
------ |
|
||||||
|
|
||||||
Make a pull request... |
|
||||||
|
|
||||||
License |
License |
||||||
------- |
======= |
||||||
Distributed under MIT License, please see license file within the code for more details. |
Distributed under MIT License, please see license file in code for more details. |
||||||
|
|
||||||
Maintainers |
|
||||||
----------- |
|
||||||
This project has grown large enough that more than one person is required to properly support the community. |
|
||||||
If you are interested in becoming a maintainer please reach out to me https://github.com/deankarn |
|
@ -1,39 +0,0 @@ |
|||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"fmt" |
|
||||||
|
|
||||||
"github.com/go-playground/validator/v10" |
|
||||||
) |
|
||||||
|
|
||||||
// MyStruct ..
|
|
||||||
type MyStruct struct { |
|
||||||
String string `validate:"is-awesome"` |
|
||||||
} |
|
||||||
|
|
||||||
// use a single instance of Validate, it caches struct info
|
|
||||||
var validate *validator.Validate |
|
||||||
|
|
||||||
func main() { |
|
||||||
|
|
||||||
validate = validator.New() |
|
||||||
validate.RegisterValidation("is-awesome", ValidateMyVal) |
|
||||||
|
|
||||||
s := MyStruct{String: "awesome"} |
|
||||||
|
|
||||||
err := validate.Struct(s) |
|
||||||
if err != nil { |
|
||||||
fmt.Printf("Err(s):\n%+v\n", err) |
|
||||||
} |
|
||||||
|
|
||||||
s.String = "not awesome" |
|
||||||
err = validate.Struct(s) |
|
||||||
if err != nil { |
|
||||||
fmt.Printf("Err(s):\n%+v\n", err) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// ValidateMyVal implements validator.Func
|
|
||||||
func ValidateMyVal(fl validator.FieldLevel) bool { |
|
||||||
return fl.Field().String() == "awesome" |
|
||||||
} |
|
@ -1,51 +0,0 @@ |
|||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"database/sql" |
|
||||||
"database/sql/driver" |
|
||||||
"fmt" |
|
||||||
"reflect" |
|
||||||
|
|
||||||
"github.com/go-playground/validator/v10" |
|
||||||
) |
|
||||||
|
|
||||||
// DbBackedUser User struct
|
|
||||||
type DbBackedUser struct { |
|
||||||
Name sql.NullString `validate:"required"` |
|
||||||
Age sql.NullInt64 `validate:"required"` |
|
||||||
} |
|
||||||
|
|
||||||
// use a single instance of Validate, it caches struct info
|
|
||||||
var validate *validator.Validate |
|
||||||
|
|
||||||
func main() { |
|
||||||
|
|
||||||
validate = validator.New() |
|
||||||
|
|
||||||
// register all sql.Null* types to use the ValidateValuer CustomTypeFunc
|
|
||||||
validate.RegisterCustomTypeFunc(ValidateValuer, sql.NullString{}, sql.NullInt64{}, sql.NullBool{}, sql.NullFloat64{}) |
|
||||||
|
|
||||||
// build object for validation
|
|
||||||
x := DbBackedUser{Name: sql.NullString{String: "", Valid: true}, Age: sql.NullInt64{Int64: 0, Valid: false}} |
|
||||||
|
|
||||||
err := validate.Struct(x) |
|
||||||
|
|
||||||
if err != nil { |
|
||||||
fmt.Printf("Err(s):\n%+v\n", err) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// ValidateValuer implements validator.CustomTypeFunc
|
|
||||||
func ValidateValuer(field reflect.Value) interface{} { |
|
||||||
|
|
||||||
if valuer, ok := field.Interface().(driver.Valuer); ok { |
|
||||||
|
|
||||||
val, err := valuer.Value() |
|
||||||
if err == nil { |
|
||||||
return val |
|
||||||
} |
|
||||||
// handle the error how you want
|
|
||||||
} |
|
||||||
|
|
||||||
return nil |
|
||||||
} |
|
@ -1,39 +0,0 @@ |
|||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"fmt" |
|
||||||
|
|
||||||
"github.com/go-playground/validator/v10" |
|
||||||
) |
|
||||||
|
|
||||||
// Test ...
|
|
||||||
type Test struct { |
|
||||||
Array []string `validate:"required,gt=0,dive,required"` |
|
||||||
Map map[string]string `validate:"required,gt=0,dive,keys,keymax,endkeys,required,max=1000"` |
|
||||||
} |
|
||||||
|
|
||||||
// use a single instance of Validate, it caches struct info
|
|
||||||
var validate *validator.Validate |
|
||||||
|
|
||||||
func main() { |
|
||||||
|
|
||||||
validate = validator.New() |
|
||||||
|
|
||||||
// registering alias so we can see the differences between
|
|
||||||
// map key, value validation errors
|
|
||||||
validate.RegisterAlias("keymax", "max=10") |
|
||||||
|
|
||||||
var test Test |
|
||||||
|
|
||||||
val(test) |
|
||||||
|
|
||||||
test.Array = []string{""} |
|
||||||
test.Map = map[string]string{"test > than 10": ""} |
|
||||||
val(test) |
|
||||||
} |
|
||||||
|
|
||||||
func val(test Test) { |
|
||||||
fmt.Println("testing") |
|
||||||
err := validate.Struct(test) |
|
||||||
fmt.Println(err) |
|
||||||
} |
|
@ -1,10 +0,0 @@ |
|||||||
package main |
|
||||||
|
|
||||||
import "github.com/gin-gonic/gin/binding" |
|
||||||
|
|
||||||
func main() { |
|
||||||
|
|
||||||
binding.Validator = new(defaultValidator) |
|
||||||
|
|
||||||
// regular gin logic
|
|
||||||
} |
|
@ -1,55 +0,0 @@ |
|||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"reflect" |
|
||||||
"sync" |
|
||||||
|
|
||||||
"github.com/gin-gonic/gin/binding" |
|
||||||
"github.com/go-playground/validator/v10" |
|
||||||
) |
|
||||||
|
|
||||||
type defaultValidator struct { |
|
||||||
once sync.Once |
|
||||||
validate *validator.Validate |
|
||||||
} |
|
||||||
|
|
||||||
var _ binding.StructValidator = &defaultValidator{} |
|
||||||
|
|
||||||
func (v *defaultValidator) ValidateStruct(obj interface{}) error { |
|
||||||
|
|
||||||
if kindOfData(obj) == reflect.Struct { |
|
||||||
|
|
||||||
v.lazyinit() |
|
||||||
|
|
||||||
if err := v.validate.Struct(obj); err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
func (v *defaultValidator) Engine() interface{} { |
|
||||||
v.lazyinit() |
|
||||||
return v.validate |
|
||||||
} |
|
||||||
|
|
||||||
func (v *defaultValidator) lazyinit() { |
|
||||||
v.once.Do(func() { |
|
||||||
v.validate = validator.New() |
|
||||||
v.validate.SetTagName("binding") |
|
||||||
|
|
||||||
// add any custom validations etc. here
|
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
func kindOfData(data interface{}) reflect.Kind { |
|
||||||
|
|
||||||
value := reflect.ValueOf(data) |
|
||||||
valueType := value.Kind() |
|
||||||
|
|
||||||
if valueType == reflect.Ptr { |
|
||||||
valueType = value.Elem().Kind() |
|
||||||
} |
|
||||||
return valueType |
|
||||||
} |
|
@ -1,87 +0,0 @@ |
|||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"fmt" |
|
||||||
"github.com/go-playground/validator/v10" |
|
||||||
) |
|
||||||
|
|
||||||
var validate *validator.Validate |
|
||||||
|
|
||||||
func main() { |
|
||||||
validate = validator.New() |
|
||||||
|
|
||||||
validateMap() |
|
||||||
validateNestedMap() |
|
||||||
} |
|
||||||
|
|
||||||
func validateMap() { |
|
||||||
user := map[string]interface{}{"name": "Arshiya Kiani", "email": "zytel3301@gmail.com"} |
|
||||||
|
|
||||||
// Every rule will be applied to the item of the data that the offset of rule is pointing to.
|
|
||||||
// So if you have a field "email": "omitempty,required,email", the validator will apply these
|
|
||||||
// rules to offset of email in user data
|
|
||||||
rules := map[string]interface{}{"name": "required,min=8,max=32", "email": "omitempty,required,email"} |
|
||||||
|
|
||||||
// ValidateMap will return map[string]error.
|
|
||||||
// The offset of every item in errs is the name of invalid field and the value
|
|
||||||
// is the message of error. If there was no error, ValidateMap method will
|
|
||||||
// return an EMPTY map of errors, not nil. If you want to check that
|
|
||||||
// if there was an error or not, you must check the length of the return value
|
|
||||||
errs := validate.ValidateMap(user, rules) |
|
||||||
|
|
||||||
if len(errs) > 0 { |
|
||||||
fmt.Println(errs) |
|
||||||
// The user is invalid
|
|
||||||
} |
|
||||||
|
|
||||||
// The user is valid
|
|
||||||
} |
|
||||||
|
|
||||||
func validateNestedMap() { |
|
||||||
|
|
||||||
data := map[string]interface{}{ |
|
||||||
"name": "Arshiya Kiani", |
|
||||||
"email": "zytel3301@gmail.com", |
|
||||||
"details": map[string]interface{}{ |
|
||||||
"family_members": map[string]interface{}{ |
|
||||||
"father_name": "Micheal", |
|
||||||
"mother_name": "Hannah", |
|
||||||
}, |
|
||||||
"salary": "1000", |
|
||||||
"phones": []map[string]interface{}{ |
|
||||||
{ |
|
||||||
"number": "11-111-1111", |
|
||||||
"remark": "home", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"number": "22-222-2222", |
|
||||||
"remark": "work", |
|
||||||
}, |
|
||||||
}, |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
// Rules must be set as the structure as the data itself. If you want to dive into the
|
|
||||||
// map, just declare its rules as a map
|
|
||||||
rules := map[string]interface{}{ |
|
||||||
"name": "min=4,max=32", |
|
||||||
"email": "required,email", |
|
||||||
"details": map[string]interface{}{ |
|
||||||
"family_members": map[string]interface{}{ |
|
||||||
"father_name": "required,min=4,max=32", |
|
||||||
"mother_name": "required,min=4,max=32", |
|
||||||
}, |
|
||||||
"salary": "number", |
|
||||||
"phones": map[string]interface{}{ |
|
||||||
"number": "required,min=4,max=32", |
|
||||||
"remark": "required,min=1,max=32", |
|
||||||
}, |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
if len(validate.ValidateMap(data, rules)) == 0 { |
|
||||||
// Data is valid
|
|
||||||
} |
|
||||||
|
|
||||||
// Data is invalid
|
|
||||||
} |
|
@ -1,101 +0,0 @@ |
|||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"fmt" |
|
||||||
|
|
||||||
"github.com/go-playground/validator/v10" |
|
||||||
) |
|
||||||
|
|
||||||
// User contains user information
|
|
||||||
type User struct { |
|
||||||
FirstName string `validate:"required"` |
|
||||||
LastName string `validate:"required"` |
|
||||||
Age uint8 `validate:"gte=0,lte=130"` |
|
||||||
Email string `validate:"required,email"` |
|
||||||
FavouriteColor string `validate:"iscolor"` // alias for 'hexcolor|rgb|rgba|hsl|hsla'
|
|
||||||
Addresses []*Address `validate:"required,dive,required"` // a person can have a home and cottage...
|
|
||||||
} |
|
||||||
|
|
||||||
// Address houses a users address information
|
|
||||||
type Address struct { |
|
||||||
Street string `validate:"required"` |
|
||||||
City string `validate:"required"` |
|
||||||
Planet string `validate:"required"` |
|
||||||
Phone string `validate:"required"` |
|
||||||
} |
|
||||||
|
|
||||||
// use a single instance of Validate, it caches struct info
|
|
||||||
var validate *validator.Validate |
|
||||||
|
|
||||||
func main() { |
|
||||||
|
|
||||||
validate = validator.New() |
|
||||||
|
|
||||||
validateStruct() |
|
||||||
validateVariable() |
|
||||||
} |
|
||||||
|
|
||||||
func validateStruct() { |
|
||||||
|
|
||||||
address := &Address{ |
|
||||||
Street: "Eavesdown Docks", |
|
||||||
Planet: "Persphone", |
|
||||||
Phone: "none", |
|
||||||
} |
|
||||||
|
|
||||||
user := &User{ |
|
||||||
FirstName: "Badger", |
|
||||||
LastName: "Smith", |
|
||||||
Age: 135, |
|
||||||
Email: "Badger.Smith@gmail.com", |
|
||||||
FavouriteColor: "#000-", |
|
||||||
Addresses: []*Address{address}, |
|
||||||
} |
|
||||||
|
|
||||||
// returns nil or ValidationErrors ( []FieldError )
|
|
||||||
err := validate.Struct(user) |
|
||||||
if err != nil { |
|
||||||
|
|
||||||
// this check is only needed when your code could produce
|
|
||||||
// an invalid value for validation such as interface with nil
|
|
||||||
// value most including myself do not usually have code like this.
|
|
||||||
if _, ok := err.(*validator.InvalidValidationError); ok { |
|
||||||
fmt.Println(err) |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
for _, err := range err.(validator.ValidationErrors) { |
|
||||||
|
|
||||||
fmt.Println(err.Namespace()) |
|
||||||
fmt.Println(err.Field()) |
|
||||||
fmt.Println(err.StructNamespace()) |
|
||||||
fmt.Println(err.StructField()) |
|
||||||
fmt.Println(err.Tag()) |
|
||||||
fmt.Println(err.ActualTag()) |
|
||||||
fmt.Println(err.Kind()) |
|
||||||
fmt.Println(err.Type()) |
|
||||||
fmt.Println(err.Value()) |
|
||||||
fmt.Println(err.Param()) |
|
||||||
fmt.Println() |
|
||||||
} |
|
||||||
|
|
||||||
// from here you can create your own error messages in whatever language you wish
|
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
// save user to database
|
|
||||||
} |
|
||||||
|
|
||||||
func validateVariable() { |
|
||||||
|
|
||||||
myEmail := "joeybloggs.gmail.com" |
|
||||||
|
|
||||||
errs := validate.Var(myEmail, "required,email") |
|
||||||
|
|
||||||
if errs != nil { |
|
||||||
fmt.Println(errs) // output: Key: "" Error:Field validation for "" failed on the "email" tag
|
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
// email ok, move on
|
|
||||||
} |
|
@ -1,172 +0,0 @@ |
|||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"encoding/json" |
|
||||||
"fmt" |
|
||||||
"reflect" |
|
||||||
"strings" |
|
||||||
|
|
||||||
"github.com/go-playground/validator/v10" |
|
||||||
) |
|
||||||
|
|
||||||
type validationError struct { |
|
||||||
Namespace string `json:"namespace"` // can differ when a custom TagNameFunc is registered or
|
|
||||||
Field string `json:"field"` // by passing alt name to ReportError like below
|
|
||||||
StructNamespace string `json:"structNamespace"` |
|
||||||
StructField string `json:"structField"` |
|
||||||
Tag string `json:"tag"` |
|
||||||
ActualTag string `json:"actualTag"` |
|
||||||
Kind string `json:"kind"` |
|
||||||
Type string `json:"type"` |
|
||||||
Value string `json:"value"` |
|
||||||
Param string `json:"param"` |
|
||||||
Message string `json:"message"` |
|
||||||
} |
|
||||||
|
|
||||||
type Gender uint |
|
||||||
|
|
||||||
const ( |
|
||||||
Male Gender = iota + 1 |
|
||||||
Female |
|
||||||
Intersex |
|
||||||
) |
|
||||||
|
|
||||||
func (gender Gender) String() string { |
|
||||||
terms := []string{"Male", "Female", "Intersex"} |
|
||||||
if gender < Male || gender > Intersex { |
|
||||||
return "unknown" |
|
||||||
} |
|
||||||
return terms[gender] |
|
||||||
} |
|
||||||
|
|
||||||
// User contains user information
|
|
||||||
type User struct { |
|
||||||
FirstName string `json:"fname"` |
|
||||||
LastName string `json:"lname"` |
|
||||||
Age uint8 `validate:"gte=0,lte=130"` |
|
||||||
Email string `json:"e-mail" validate:"required,email"` |
|
||||||
FavouriteColor string `validate:"hexcolor|rgb|rgba"` |
|
||||||
Addresses []*Address `validate:"required,dive,required"` // a person can have a home and cottage...
|
|
||||||
Gender Gender `json:"gender" validate:"required,gender_custom_validation"` |
|
||||||
} |
|
||||||
|
|
||||||
// Address houses a users address information
|
|
||||||
type Address struct { |
|
||||||
Street string `validate:"required"` |
|
||||||
City string `validate:"required"` |
|
||||||
Planet string `validate:"required"` |
|
||||||
Phone string `validate:"required"` |
|
||||||
} |
|
||||||
|
|
||||||
// use a single instance of Validate, it caches struct info
|
|
||||||
var validate *validator.Validate |
|
||||||
|
|
||||||
func main() { |
|
||||||
|
|
||||||
validate = validator.New() |
|
||||||
|
|
||||||
// register function to get tag name from json tags.
|
|
||||||
validate.RegisterTagNameFunc(func(fld reflect.StructField) string { |
|
||||||
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] |
|
||||||
if name == "-" { |
|
||||||
return "" |
|
||||||
} |
|
||||||
return name |
|
||||||
}) |
|
||||||
|
|
||||||
// register validation for 'User'
|
|
||||||
// NOTE: only have to register a non-pointer type for 'User', validator
|
|
||||||
// internally dereferences during it's type checks.
|
|
||||||
validate.RegisterStructValidation(UserStructLevelValidation, User{}) |
|
||||||
|
|
||||||
// register a custom validation for user genre on a line
|
|
||||||
// validates that an enum is within the interval
|
|
||||||
err := validate.RegisterValidation("gender_custom_validation", func(fl validator.FieldLevel) bool { |
|
||||||
value := fl.Field().Interface().(Gender) |
|
||||||
return value.String() != "unknown" |
|
||||||
}) |
|
||||||
if err != nil { |
|
||||||
fmt.Println(err) |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
// build 'User' info, normally posted data etc...
|
|
||||||
address := &Address{ |
|
||||||
Street: "Eavesdown Docks", |
|
||||||
Planet: "Persphone", |
|
||||||
Phone: "none", |
|
||||||
City: "Unknown", |
|
||||||
} |
|
||||||
|
|
||||||
user := &User{ |
|
||||||
FirstName: "", |
|
||||||
LastName: "", |
|
||||||
Age: 45, |
|
||||||
Email: "Badger.Smith@gmail", |
|
||||||
FavouriteColor: "#000", |
|
||||||
Addresses: []*Address{address}, |
|
||||||
} |
|
||||||
|
|
||||||
// returns InvalidValidationError for bad validation input, nil or ValidationErrors ( []FieldError )
|
|
||||||
err = validate.Struct(user) |
|
||||||
if err != nil { |
|
||||||
|
|
||||||
// this check is only needed when your code could produce
|
|
||||||
// an invalid value for validation such as interface with nil
|
|
||||||
// value most including myself do not usually have code like this.
|
|
||||||
if _, ok := err.(*validator.InvalidValidationError); ok { |
|
||||||
fmt.Println(err) |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
for _, err := range err.(validator.ValidationErrors) { |
|
||||||
e := validationError{ |
|
||||||
Namespace: err.Namespace(), |
|
||||||
Field: err.Field(), |
|
||||||
StructNamespace: err.StructNamespace(), |
|
||||||
StructField: err.StructField(), |
|
||||||
Tag: err.Tag(), |
|
||||||
ActualTag: err.ActualTag(), |
|
||||||
Kind: fmt.Sprintf("%v", err.Kind()), |
|
||||||
Type: fmt.Sprintf("%v", err.Type()), |
|
||||||
Value: fmt.Sprintf("%v", err.Value()), |
|
||||||
Param: err.Param(), |
|
||||||
Message: err.Error(), |
|
||||||
} |
|
||||||
|
|
||||||
indent, err := json.MarshalIndent(e, "", " ") |
|
||||||
if err != nil { |
|
||||||
fmt.Println(err) |
|
||||||
panic(err) |
|
||||||
} |
|
||||||
|
|
||||||
fmt.Println(string(indent)) |
|
||||||
} |
|
||||||
|
|
||||||
// from here you can create your own error messages in whatever language you wish
|
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
// save user to database
|
|
||||||
} |
|
||||||
|
|
||||||
// UserStructLevelValidation contains custom struct level validations that don't always
|
|
||||||
// make sense at the field validation level. For Example this function validates that either
|
|
||||||
// FirstName or LastName exist; could have done that with a custom field validation but then
|
|
||||||
// would have had to add it to both fields duplicating the logic + overhead, this way it's
|
|
||||||
// only validated once.
|
|
||||||
//
|
|
||||||
// NOTE: you may ask why wouldn't I just do this outside of validator, because doing this way
|
|
||||||
// hooks right into validator and you can combine with validation tags and still have a
|
|
||||||
// common error output format.
|
|
||||||
func UserStructLevelValidation(sl validator.StructLevel) { |
|
||||||
|
|
||||||
user := sl.Current().Interface().(User) |
|
||||||
|
|
||||||
if len(user.FirstName) == 0 && len(user.LastName) == 0 { |
|
||||||
sl.ReportError(user.FirstName, "fname", "FirstName", "fnameorlname", "") |
|
||||||
sl.ReportError(user.LastName, "lname", "LastName", "fnameorlname", "") |
|
||||||
} |
|
||||||
|
|
||||||
// plus can do more, even with different tag than "fnameorlname"
|
|
||||||
} |
|
@ -1,92 +0,0 @@ |
|||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"fmt" |
|
||||||
"github.com/go-playground/validator/v10" |
|
||||||
) |
|
||||||
|
|
||||||
type Data struct { |
|
||||||
Name string |
|
||||||
Email string |
|
||||||
Details *Details |
|
||||||
} |
|
||||||
|
|
||||||
type Details struct { |
|
||||||
FamilyMembers *FamilyMembers |
|
||||||
Salary string |
|
||||||
} |
|
||||||
|
|
||||||
type FamilyMembers struct { |
|
||||||
FatherName string |
|
||||||
MotherName string |
|
||||||
} |
|
||||||
|
|
||||||
type Data2 struct { |
|
||||||
Name string |
|
||||||
Age uint32 |
|
||||||
} |
|
||||||
|
|
||||||
var validate = validator.New() |
|
||||||
|
|
||||||
func main() { |
|
||||||
validateStruct() |
|
||||||
// output
|
|
||||||
// Key: 'Data2.Name' Error:Field validation for 'Name' failed on the 'min' tag
|
|
||||||
// Key: 'Data2.Age' Error:Field validation for 'Age' failed on the 'max' tag
|
|
||||||
|
|
||||||
validateStructNested() |
|
||||||
// output
|
|
||||||
// Key: 'Data.Name' Error:Field validation for 'Name' failed on the 'max' tag
|
|
||||||
// Key: 'Data.Details.FamilyMembers' Error:Field validation for 'FamilyMembers' failed on the 'required' tag
|
|
||||||
} |
|
||||||
|
|
||||||
func validateStruct() { |
|
||||||
data := Data2{ |
|
||||||
Name: "leo", |
|
||||||
Age: 1000, |
|
||||||
} |
|
||||||
|
|
||||||
rules := map[string]string{ |
|
||||||
"Name": "min=4,max=6", |
|
||||||
"Age": "min=4,max=6", |
|
||||||
} |
|
||||||
|
|
||||||
validate.RegisterStructValidationMapRules(rules, Data2{}) |
|
||||||
|
|
||||||
err := validate.Struct(data) |
|
||||||
fmt.Println(err) |
|
||||||
fmt.Println() |
|
||||||
} |
|
||||||
|
|
||||||
func validateStructNested() { |
|
||||||
data := Data{ |
|
||||||
Name: "11sdfddd111", |
|
||||||
Email: "zytel3301@mail.com", |
|
||||||
Details: &Details{ |
|
||||||
Salary: "1000", |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
rules1 := map[string]string{ |
|
||||||
"Name": "min=4,max=6", |
|
||||||
"Email": "required,email", |
|
||||||
"Details": "required", |
|
||||||
} |
|
||||||
|
|
||||||
rules2 := map[string]string{ |
|
||||||
"Salary": "number", |
|
||||||
"FamilyMembers": "required", |
|
||||||
} |
|
||||||
|
|
||||||
rules3 := map[string]string{ |
|
||||||
"FatherName": "required,min=4,max=32", |
|
||||||
"MotherName": "required,min=4,max=32", |
|
||||||
} |
|
||||||
|
|
||||||
validate.RegisterStructValidationMapRules(rules1, Data{}) |
|
||||||
validate.RegisterStructValidationMapRules(rules2, Details{}) |
|
||||||
validate.RegisterStructValidationMapRules(rules3, FamilyMembers{}) |
|
||||||
err := validate.Struct(data) |
|
||||||
|
|
||||||
fmt.Println(err) |
|
||||||
} |
|
@ -1,129 +0,0 @@ |
|||||||
package main |
|
||||||
|
|
||||||
import ( |
|
||||||
"fmt" |
|
||||||
|
|
||||||
"github.com/go-playground/locales/en" |
|
||||||
ut "github.com/go-playground/universal-translator" |
|
||||||
"github.com/go-playground/validator/v10" |
|
||||||
en_translations "github.com/go-playground/validator/v10/translations/en" |
|
||||||
) |
|
||||||
|
|
||||||
// User contains user information
|
|
||||||
type User struct { |
|
||||||
FirstName string `validate:"required"` |
|
||||||
LastName string `validate:"required"` |
|
||||||
Age uint8 `validate:"gte=0,lte=130"` |
|
||||||
Email string `validate:"required,email"` |
|
||||||
FavouriteColor string `validate:"iscolor"` // alias for 'hexcolor|rgb|rgba|hsl|hsla'
|
|
||||||
Addresses []*Address `validate:"required,dive,required"` // a person can have a home and cottage...
|
|
||||||
} |
|
||||||
|
|
||||||
// Address houses a users address information
|
|
||||||
type Address struct { |
|
||||||
Street string `validate:"required"` |
|
||||||
City string `validate:"required"` |
|
||||||
Planet string `validate:"required"` |
|
||||||
Phone string `validate:"required"` |
|
||||||
} |
|
||||||
|
|
||||||
// use a single instance , it caches struct info
|
|
||||||
var ( |
|
||||||
uni *ut.UniversalTranslator |
|
||||||
validate *validator.Validate |
|
||||||
) |
|
||||||
|
|
||||||
func main() { |
|
||||||
|
|
||||||
// NOTE: ommitting allot of error checking for brevity
|
|
||||||
|
|
||||||
en := en.New() |
|
||||||
uni = ut.New(en, en) |
|
||||||
|
|
||||||
// this is usually know or extracted from http 'Accept-Language' header
|
|
||||||
// also see uni.FindTranslator(...)
|
|
||||||
trans, _ := uni.GetTranslator("en") |
|
||||||
|
|
||||||
validate = validator.New() |
|
||||||
en_translations.RegisterDefaultTranslations(validate, trans) |
|
||||||
|
|
||||||
translateAll(trans) |
|
||||||
translateIndividual(trans) |
|
||||||
translateOverride(trans) // yep you can specify your own in whatever locale you want!
|
|
||||||
} |
|
||||||
|
|
||||||
func translateAll(trans ut.Translator) { |
|
||||||
|
|
||||||
type User struct { |
|
||||||
Username string `validate:"required"` |
|
||||||
Tagline string `validate:"required,lt=10"` |
|
||||||
Tagline2 string `validate:"required,gt=1"` |
|
||||||
} |
|
||||||
|
|
||||||
user := User{ |
|
||||||
Username: "Joeybloggs", |
|
||||||
Tagline: "This tagline is way too long.", |
|
||||||
Tagline2: "1", |
|
||||||
} |
|
||||||
|
|
||||||
err := validate.Struct(user) |
|
||||||
if err != nil { |
|
||||||
|
|
||||||
// translate all error at once
|
|
||||||
errs := err.(validator.ValidationErrors) |
|
||||||
|
|
||||||
// returns a map with key = namespace & value = translated error
|
|
||||||
// NOTICE: 2 errors are returned and you'll see something surprising
|
|
||||||
// translations are i18n aware!!!!
|
|
||||||
// eg. '10 characters' vs '1 character'
|
|
||||||
fmt.Println(errs.Translate(trans)) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func translateIndividual(trans ut.Translator) { |
|
||||||
|
|
||||||
type User struct { |
|
||||||
Username string `validate:"required"` |
|
||||||
} |
|
||||||
|
|
||||||
var user User |
|
||||||
|
|
||||||
err := validate.Struct(user) |
|
||||||
if err != nil { |
|
||||||
|
|
||||||
errs := err.(validator.ValidationErrors) |
|
||||||
|
|
||||||
for _, e := range errs { |
|
||||||
// can translate each error one at a time.
|
|
||||||
fmt.Println(e.Translate(trans)) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func translateOverride(trans ut.Translator) { |
|
||||||
|
|
||||||
validate.RegisterTranslation("required", trans, func(ut ut.Translator) error { |
|
||||||
return ut.Add("required", "{0} must have a value!", true) // see universal-translator for details
|
|
||||||
}, func(ut ut.Translator, fe validator.FieldError) string { |
|
||||||
t, _ := ut.T("required", fe.Field()) |
|
||||||
|
|
||||||
return t |
|
||||||
}) |
|
||||||
|
|
||||||
type User struct { |
|
||||||
Username string `validate:"required"` |
|
||||||
} |
|
||||||
|
|
||||||
var user User |
|
||||||
|
|
||||||
err := validate.Struct(user) |
|
||||||
if err != nil { |
|
||||||
|
|
||||||
errs := err.(validator.ValidationErrors) |
|
||||||
|
|
||||||
for _, e := range errs { |
|
||||||
// can translate each error one at a time.
|
|
||||||
fmt.Println(e.Translate(trans)) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,327 +0,0 @@ |
|||||||
package validator |
|
||||||
|
|
||||||
import ( |
|
||||||
"fmt" |
|
||||||
"reflect" |
|
||||||
"strings" |
|
||||||
"sync" |
|
||||||
"sync/atomic" |
|
||||||
) |
|
||||||
|
|
||||||
type tagType uint8 |
|
||||||
|
|
||||||
const ( |
|
||||||
typeDefault tagType = iota |
|
||||||
typeOmitEmpty |
|
||||||
typeIsDefault |
|
||||||
typeNoStructLevel |
|
||||||
typeStructOnly |
|
||||||
typeDive |
|
||||||
typeOr |
|
||||||
typeKeys |
|
||||||
typeEndKeys |
|
||||||
) |
|
||||||
|
|
||||||
const ( |
|
||||||
invalidValidation = "Invalid validation tag on field '%s'" |
|
||||||
undefinedValidation = "Undefined validation function '%s' on field '%s'" |
|
||||||
keysTagNotDefined = "'" + endKeysTag + "' tag encountered without a corresponding '" + keysTag + "' tag" |
|
||||||
) |
|
||||||
|
|
||||||
type structCache struct { |
|
||||||
lock sync.Mutex |
|
||||||
m atomic.Value // map[reflect.Type]*cStruct
|
|
||||||
} |
|
||||||
|
|
||||||
func (sc *structCache) Get(key reflect.Type) (c *cStruct, found bool) { |
|
||||||
c, found = sc.m.Load().(map[reflect.Type]*cStruct)[key] |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
func (sc *structCache) Set(key reflect.Type, value *cStruct) { |
|
||||||
m := sc.m.Load().(map[reflect.Type]*cStruct) |
|
||||||
nm := make(map[reflect.Type]*cStruct, len(m)+1) |
|
||||||
for k, v := range m { |
|
||||||
nm[k] = v |
|
||||||
} |
|
||||||
nm[key] = value |
|
||||||
sc.m.Store(nm) |
|
||||||
} |
|
||||||
|
|
||||||
type tagCache struct { |
|
||||||
lock sync.Mutex |
|
||||||
m atomic.Value // map[string]*cTag
|
|
||||||
} |
|
||||||
|
|
||||||
func (tc *tagCache) Get(key string) (c *cTag, found bool) { |
|
||||||
c, found = tc.m.Load().(map[string]*cTag)[key] |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
func (tc *tagCache) Set(key string, value *cTag) { |
|
||||||
m := tc.m.Load().(map[string]*cTag) |
|
||||||
nm := make(map[string]*cTag, len(m)+1) |
|
||||||
for k, v := range m { |
|
||||||
nm[k] = v |
|
||||||
} |
|
||||||
nm[key] = value |
|
||||||
tc.m.Store(nm) |
|
||||||
} |
|
||||||
|
|
||||||
type cStruct struct { |
|
||||||
name string |
|
||||||
fields []*cField |
|
||||||
fn StructLevelFuncCtx |
|
||||||
} |
|
||||||
|
|
||||||
type cField struct { |
|
||||||
idx int |
|
||||||
name string |
|
||||||
altName string |
|
||||||
namesEqual bool |
|
||||||
cTags *cTag |
|
||||||
} |
|
||||||
|
|
||||||
type cTag struct { |
|
||||||
tag string |
|
||||||
aliasTag string |
|
||||||
actualAliasTag string |
|
||||||
param string |
|
||||||
keys *cTag // only populated when using tag's 'keys' and 'endkeys' for map key validation
|
|
||||||
next *cTag |
|
||||||
fn FuncCtx |
|
||||||
typeof tagType |
|
||||||
hasTag bool |
|
||||||
hasAlias bool |
|
||||||
hasParam bool // true if parameter used eg. eq= where the equal sign has been set
|
|
||||||
isBlockEnd bool // indicates the current tag represents the last validation in the block
|
|
||||||
runValidationWhenNil bool |
|
||||||
} |
|
||||||
|
|
||||||
func (v *Validate) extractStructCache(current reflect.Value, sName string) *cStruct { |
|
||||||
v.structCache.lock.Lock() |
|
||||||
defer v.structCache.lock.Unlock() // leave as defer! because if inner panics, it will never get unlocked otherwise!
|
|
||||||
|
|
||||||
typ := current.Type() |
|
||||||
|
|
||||||
// could have been multiple trying to access, but once first is done this ensures struct
|
|
||||||
// isn't parsed again.
|
|
||||||
cs, ok := v.structCache.Get(typ) |
|
||||||
if ok { |
|
||||||
return cs |
|
||||||
} |
|
||||||
|
|
||||||
cs = &cStruct{name: sName, fields: make([]*cField, 0), fn: v.structLevelFuncs[typ]} |
|
||||||
|
|
||||||
numFields := current.NumField() |
|
||||||
rules := v.rules[typ] |
|
||||||
|
|
||||||
var ctag *cTag |
|
||||||
var fld reflect.StructField |
|
||||||
var tag string |
|
||||||
var customName string |
|
||||||
|
|
||||||
for i := 0; i < numFields; i++ { |
|
||||||
|
|
||||||
fld = typ.Field(i) |
|
||||||
|
|
||||||
if !fld.Anonymous && len(fld.PkgPath) > 0 { |
|
||||||
continue |
|
||||||
} |
|
||||||
|
|
||||||
if rtag, ok := rules[fld.Name]; ok { |
|
||||||
tag = rtag |
|
||||||
} else { |
|
||||||
tag = fld.Tag.Get(v.tagName) |
|
||||||
} |
|
||||||
|
|
||||||
if tag == skipValidationTag { |
|
||||||
continue |
|
||||||
} |
|
||||||
|
|
||||||
customName = fld.Name |
|
||||||
|
|
||||||
if v.hasTagNameFunc { |
|
||||||
name := v.tagNameFunc(fld) |
|
||||||
if len(name) > 0 { |
|
||||||
customName = name |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// NOTE: cannot use shared tag cache, because tags may be equal, but things like alias may be different
|
|
||||||
// and so only struct level caching can be used instead of combined with Field tag caching
|
|
||||||
|
|
||||||
if len(tag) > 0 { |
|
||||||
ctag, _ = v.parseFieldTagsRecursive(tag, fld.Name, "", false) |
|
||||||
} else { |
|
||||||
// even if field doesn't have validations need cTag for traversing to potential inner/nested
|
|
||||||
// elements of the field.
|
|
||||||
ctag = new(cTag) |
|
||||||
} |
|
||||||
|
|
||||||
cs.fields = append(cs.fields, &cField{ |
|
||||||
idx: i, |
|
||||||
name: fld.Name, |
|
||||||
altName: customName, |
|
||||||
cTags: ctag, |
|
||||||
namesEqual: fld.Name == customName, |
|
||||||
}) |
|
||||||
} |
|
||||||
v.structCache.Set(typ, cs) |
|
||||||
return cs |
|
||||||
} |
|
||||||
|
|
||||||
func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias string, hasAlias bool) (firstCtag *cTag, current *cTag) { |
|
||||||
var t string |
|
||||||
noAlias := len(alias) == 0 |
|
||||||
tags := strings.Split(tag, tagSeparator) |
|
||||||
|
|
||||||
for i := 0; i < len(tags); i++ { |
|
||||||
t = tags[i] |
|
||||||
if noAlias { |
|
||||||
alias = t |
|
||||||
} |
|
||||||
|
|
||||||
// check map for alias and process new tags, otherwise process as usual
|
|
||||||
if tagsVal, found := v.aliases[t]; found { |
|
||||||
if i == 0 { |
|
||||||
firstCtag, current = v.parseFieldTagsRecursive(tagsVal, fieldName, t, true) |
|
||||||
} else { |
|
||||||
next, curr := v.parseFieldTagsRecursive(tagsVal, fieldName, t, true) |
|
||||||
current.next, current = next, curr |
|
||||||
|
|
||||||
} |
|
||||||
continue |
|
||||||
} |
|
||||||
|
|
||||||
var prevTag tagType |
|
||||||
|
|
||||||
if i == 0 { |
|
||||||
current = &cTag{aliasTag: alias, hasAlias: hasAlias, hasTag: true, typeof: typeDefault} |
|
||||||
firstCtag = current |
|
||||||
} else { |
|
||||||
prevTag = current.typeof |
|
||||||
current.next = &cTag{aliasTag: alias, hasAlias: hasAlias, hasTag: true} |
|
||||||
current = current.next |
|
||||||
} |
|
||||||
|
|
||||||
switch t { |
|
||||||
case diveTag: |
|
||||||
current.typeof = typeDive |
|
||||||
continue |
|
||||||
|
|
||||||
case keysTag: |
|
||||||
current.typeof = typeKeys |
|
||||||
|
|
||||||
if i == 0 || prevTag != typeDive { |
|
||||||
panic(fmt.Sprintf("'%s' tag must be immediately preceded by the '%s' tag", keysTag, diveTag)) |
|
||||||
} |
|
||||||
|
|
||||||
current.typeof = typeKeys |
|
||||||
|
|
||||||
// need to pass along only keys tag
|
|
||||||
// need to increment i to skip over the keys tags
|
|
||||||
b := make([]byte, 0, 64) |
|
||||||
|
|
||||||
i++ |
|
||||||
|
|
||||||
for ; i < len(tags); i++ { |
|
||||||
|
|
||||||
b = append(b, tags[i]...) |
|
||||||
b = append(b, ',') |
|
||||||
|
|
||||||
if tags[i] == endKeysTag { |
|
||||||
break |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
current.keys, _ = v.parseFieldTagsRecursive(string(b[:len(b)-1]), fieldName, "", false) |
|
||||||
continue |
|
||||||
|
|
||||||
case endKeysTag: |
|
||||||
current.typeof = typeEndKeys |
|
||||||
|
|
||||||
// if there are more in tags then there was no keysTag defined
|
|
||||||
// and an error should be thrown
|
|
||||||
if i != len(tags)-1 { |
|
||||||
panic(keysTagNotDefined) |
|
||||||
} |
|
||||||
return |
|
||||||
|
|
||||||
case omitempty: |
|
||||||
current.typeof = typeOmitEmpty |
|
||||||
continue |
|
||||||
|
|
||||||
case structOnlyTag: |
|
||||||
current.typeof = typeStructOnly |
|
||||||
continue |
|
||||||
|
|
||||||
case noStructLevelTag: |
|
||||||
current.typeof = typeNoStructLevel |
|
||||||
continue |
|
||||||
|
|
||||||
default: |
|
||||||
if t == isdefault { |
|
||||||
current.typeof = typeIsDefault |
|
||||||
} |
|
||||||
// if a pipe character is needed within the param you must use the utf8Pipe representation "0x7C"
|
|
||||||
orVals := strings.Split(t, orSeparator) |
|
||||||
|
|
||||||
for j := 0; j < len(orVals); j++ { |
|
||||||
vals := strings.SplitN(orVals[j], tagKeySeparator, 2) |
|
||||||
if noAlias { |
|
||||||
alias = vals[0] |
|
||||||
current.aliasTag = alias |
|
||||||
} else { |
|
||||||
current.actualAliasTag = t |
|
||||||
} |
|
||||||
|
|
||||||
if j > 0 { |
|
||||||
current.next = &cTag{aliasTag: alias, actualAliasTag: current.actualAliasTag, hasAlias: hasAlias, hasTag: true} |
|
||||||
current = current.next |
|
||||||
} |
|
||||||
current.hasParam = len(vals) > 1 |
|
||||||
|
|
||||||
current.tag = vals[0] |
|
||||||
if len(current.tag) == 0 { |
|
||||||
panic(strings.TrimSpace(fmt.Sprintf(invalidValidation, fieldName))) |
|
||||||
} |
|
||||||
|
|
||||||
if wrapper, ok := v.validations[current.tag]; ok { |
|
||||||
current.fn = wrapper.fn |
|
||||||
current.runValidationWhenNil = wrapper.runValidatinOnNil |
|
||||||
} else { |
|
||||||
panic(strings.TrimSpace(fmt.Sprintf(undefinedValidation, current.tag, fieldName))) |
|
||||||
} |
|
||||||
|
|
||||||
if len(orVals) > 1 { |
|
||||||
current.typeof = typeOr |
|
||||||
} |
|
||||||
|
|
||||||
if len(vals) > 1 { |
|
||||||
current.param = strings.Replace(strings.Replace(vals[1], utf8HexComma, ",", -1), utf8Pipe, "|", -1) |
|
||||||
} |
|
||||||
} |
|
||||||
current.isBlockEnd = true |
|
||||||
} |
|
||||||
} |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
func (v *Validate) fetchCacheTag(tag string) *cTag { |
|
||||||
// find cached tag
|
|
||||||
ctag, found := v.tagCache.Get(tag) |
|
||||||
if !found { |
|
||||||
v.tagCache.lock.Lock() |
|
||||||
defer v.tagCache.lock.Unlock() |
|
||||||
|
|
||||||
// could have been multiple trying to access, but once first is done this ensures tag
|
|
||||||
// isn't parsed again.
|
|
||||||
ctag, found = v.tagCache.Get(tag) |
|
||||||
if !found { |
|
||||||
ctag, _ = v.parseFieldTagsRecursive(tag, "", "", false) |
|
||||||
v.tagCache.Set(tag, ctag) |
|
||||||
} |
|
||||||
} |
|
||||||
return ctag |
|
||||||
} |
|
File diff suppressed because it is too large
Load Diff
@ -1,79 +0,0 @@ |
|||||||
package validator |
|
||||||
|
|
||||||
var iso4217 = map[string]bool{ |
|
||||||
"AFN": true, "EUR": true, "ALL": true, "DZD": true, "USD": true, |
|
||||||
"AOA": true, "XCD": true, "ARS": true, "AMD": true, "AWG": true, |
|
||||||
"AUD": true, "AZN": true, "BSD": true, "BHD": true, "BDT": true, |
|
||||||
"BBD": true, "BYN": true, "BZD": true, "XOF": true, "BMD": true, |
|
||||||
"INR": true, "BTN": true, "BOB": true, "BOV": true, "BAM": true, |
|
||||||
"BWP": true, "NOK": true, "BRL": true, "BND": true, "BGN": true, |
|
||||||
"BIF": true, "CVE": true, "KHR": true, "XAF": true, "CAD": true, |
|
||||||
"KYD": true, "CLP": true, "CLF": true, "CNY": true, "COP": true, |
|
||||||
"COU": true, "KMF": true, "CDF": true, "NZD": true, "CRC": true, |
|
||||||
"HRK": true, "CUP": true, "CUC": true, "ANG": true, "CZK": true, |
|
||||||
"DKK": true, "DJF": true, "DOP": true, "EGP": true, "SVC": true, |
|
||||||
"ERN": true, "SZL": true, "ETB": true, "FKP": true, "FJD": true, |
|
||||||
"XPF": true, "GMD": true, "GEL": true, "GHS": true, "GIP": true, |
|
||||||
"GTQ": true, "GBP": true, "GNF": true, "GYD": true, "HTG": true, |
|
||||||
"HNL": true, "HKD": true, "HUF": true, "ISK": true, "IDR": true, |
|
||||||
"XDR": true, "IRR": true, "IQD": true, "ILS": true, "JMD": true, |
|
||||||
"JPY": true, "JOD": true, "KZT": true, "KES": true, "KPW": true, |
|
||||||
"KRW": true, "KWD": true, "KGS": true, "LAK": true, "LBP": true, |
|
||||||
"LSL": true, "ZAR": true, "LRD": true, "LYD": true, "CHF": true, |
|
||||||
"MOP": true, "MKD": true, "MGA": true, "MWK": true, "MYR": true, |
|
||||||
"MVR": true, "MRU": true, "MUR": true, "XUA": true, "MXN": true, |
|
||||||
"MXV": true, "MDL": true, "MNT": true, "MAD": true, "MZN": true, |
|
||||||
"MMK": true, "NAD": true, "NPR": true, "NIO": true, "NGN": true, |
|
||||||
"OMR": true, "PKR": true, "PAB": true, "PGK": true, "PYG": true, |
|
||||||
"PEN": true, "PHP": true, "PLN": true, "QAR": true, "RON": true, |
|
||||||
"RUB": true, "RWF": true, "SHP": true, "WST": true, "STN": true, |
|
||||||
"SAR": true, "RSD": true, "SCR": true, "SLL": true, "SGD": true, |
|
||||||
"XSU": true, "SBD": true, "SOS": true, "SSP": true, "LKR": true, |
|
||||||
"SDG": true, "SRD": true, "SEK": true, "CHE": true, "CHW": true, |
|
||||||
"SYP": true, "TWD": true, "TJS": true, "TZS": true, "THB": true, |
|
||||||
"TOP": true, "TTD": true, "TND": true, "TRY": true, "TMT": true, |
|
||||||
"UGX": true, "UAH": true, "AED": true, "USN": true, "UYU": true, |
|
||||||
"UYI": true, "UYW": true, "UZS": true, "VUV": true, "VES": true, |
|
||||||
"VND": true, "YER": true, "ZMW": true, "ZWL": true, "XBA": true, |
|
||||||
"XBB": true, "XBC": true, "XBD": true, "XTS": true, "XXX": true, |
|
||||||
"XAU": true, "XPD": true, "XPT": true, "XAG": true, |
|
||||||
} |
|
||||||
|
|
||||||
var iso4217_numeric = map[int]bool{ |
|
||||||
8: true, 12: true, 32: true, 36: true, 44: true, |
|
||||||
48: true, 50: true, 51: true, 52: true, 60: true, |
|
||||||
64: true, 68: true, 72: true, 84: true, 90: true, |
|
||||||
96: true, 104: true, 108: true, 116: true, 124: true, |
|
||||||
132: true, 136: true, 144: true, 152: true, 156: true, |
|
||||||
170: true, 174: true, 188: true, 191: true, 192: true, |
|
||||||
203: true, 208: true, 214: true, 222: true, 230: true, |
|
||||||
232: true, 238: true, 242: true, 262: true, 270: true, |
|
||||||
292: true, 320: true, 324: true, 328: true, 332: true, |
|
||||||
340: true, 344: true, 348: true, 352: true, 356: true, |
|
||||||
360: true, 364: true, 368: true, 376: true, 388: true, |
|
||||||
392: true, 398: true, 400: true, 404: true, 408: true, |
|
||||||
410: true, 414: true, 417: true, 418: true, 422: true, |
|
||||||
426: true, 430: true, 434: true, 446: true, 454: true, |
|
||||||
458: true, 462: true, 480: true, 484: true, 496: true, |
|
||||||
498: true, 504: true, 512: true, 516: true, 524: true, |
|
||||||
532: true, 533: true, 548: true, 554: true, 558: true, |
|
||||||
566: true, 578: true, 586: true, 590: true, 598: true, |
|
||||||
600: true, 604: true, 608: true, 634: true, 643: true, |
|
||||||
646: true, 654: true, 682: true, 690: true, 694: true, |
|
||||||
702: true, 704: true, 706: true, 710: true, 728: true, |
|
||||||
748: true, 752: true, 756: true, 760: true, 764: true, |
|
||||||
776: true, 780: true, 784: true, 788: true, 800: true, |
|
||||||
807: true, 818: true, 826: true, 834: true, 840: true, |
|
||||||
858: true, 860: true, 882: true, 886: true, 901: true, |
|
||||||
927: true, 928: true, 929: true, 930: true, 931: true, |
|
||||||
932: true, 933: true, 934: true, 936: true, 938: true, |
|
||||||
940: true, 941: true, 943: true, 944: true, 946: true, |
|
||||||
947: true, 948: true, 949: true, 950: true, 951: true, |
|
||||||
952: true, 953: true, 955: true, 956: true, 957: true, |
|
||||||
958: true, 959: true, 960: true, 961: true, 962: true, |
|
||||||
963: true, 964: true, 965: true, 967: true, 968: true, |
|
||||||
969: true, 970: true, 971: true, 972: true, 973: true, |
|
||||||
975: true, 976: true, 977: true, 978: true, 979: true, |
|
||||||
980: true, 981: true, 984: true, 985: true, 986: true, |
|
||||||
990: true, 994: true, 997: true, 999: true, |
|
||||||
} |
|
@ -1,272 +0,0 @@ |
|||||||
package validator |
|
||||||
|
|
||||||
import ( |
|
||||||
"bytes" |
|
||||||
"fmt" |
|
||||||
"reflect" |
|
||||||
"strings" |
|
||||||
|
|
||||||
ut "github.com/go-playground/universal-translator" |
|
||||||
) |
|
||||||
|
|
||||||
const ( |
|
||||||
fieldErrMsg = "Key: '%s' Error:Field validation for '%s' failed on the '%s' tag" |
|
||||||
) |
|
||||||
|
|
||||||
// ValidationErrorsTranslations is the translation return type
|
|
||||||
type ValidationErrorsTranslations map[string]string |
|
||||||
|
|
||||||
// InvalidValidationError describes an invalid argument passed to
|
|
||||||
// `Struct`, `StructExcept`, StructPartial` or `Field`
|
|
||||||
type InvalidValidationError struct { |
|
||||||
Type reflect.Type |
|
||||||
} |
|
||||||
|
|
||||||
// Error returns InvalidValidationError message
|
|
||||||
func (e *InvalidValidationError) Error() string { |
|
||||||
|
|
||||||
if e.Type == nil { |
|
||||||
return "validator: (nil)" |
|
||||||
} |
|
||||||
|
|
||||||
return "validator: (nil " + e.Type.String() + ")" |
|
||||||
} |
|
||||||
|
|
||||||
// ValidationErrors is an array of FieldError's
|
|
||||||
// for use in custom error messages post validation.
|
|
||||||
type ValidationErrors []FieldError |
|
||||||
|
|
||||||
// Error is intended for use in development + debugging and not intended to be a production error message.
|
|
||||||
// It allows ValidationErrors to subscribe to the Error interface.
|
|
||||||
// All information to create an error message specific to your application is contained within
|
|
||||||
// the FieldError found within the ValidationErrors array
|
|
||||||
func (ve ValidationErrors) Error() string { |
|
||||||
|
|
||||||
buff := bytes.NewBufferString("") |
|
||||||
|
|
||||||
for i := 0; i < len(ve); i++ { |
|
||||||
|
|
||||||
buff.WriteString(ve[i].Error()) |
|
||||||
buff.WriteString("\n") |
|
||||||
} |
|
||||||
|
|
||||||
return strings.TrimSpace(buff.String()) |
|
||||||
} |
|
||||||
|
|
||||||
// Translate translates all of the ValidationErrors
|
|
||||||
func (ve ValidationErrors) Translate(ut ut.Translator) ValidationErrorsTranslations { |
|
||||||
|
|
||||||
trans := make(ValidationErrorsTranslations) |
|
||||||
|
|
||||||
var fe *fieldError |
|
||||||
|
|
||||||
for i := 0; i < len(ve); i++ { |
|
||||||
fe = ve[i].(*fieldError) |
|
||||||
|
|
||||||
// // in case an Anonymous struct was used, ensure that the key
|
|
||||||
// // would be 'Username' instead of ".Username"
|
|
||||||
// if len(fe.ns) > 0 && fe.ns[:1] == "." {
|
|
||||||
// trans[fe.ns[1:]] = fe.Translate(ut)
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
|
|
||||||
trans[fe.ns] = fe.Translate(ut) |
|
||||||
} |
|
||||||
|
|
||||||
return trans |
|
||||||
} |
|
||||||
|
|
||||||
// FieldError contains all functions to get error details
|
|
||||||
type FieldError interface { |
|
||||||
|
|
||||||
// Tag returns the validation tag that failed. if the
|
|
||||||
// validation was an alias, this will return the
|
|
||||||
// alias name and not the underlying tag that failed.
|
|
||||||
//
|
|
||||||
// eg. alias "iscolor": "hexcolor|rgb|rgba|hsl|hsla"
|
|
||||||
// will return "iscolor"
|
|
||||||
Tag() string |
|
||||||
|
|
||||||
// ActualTag returns the validation tag that failed, even if an
|
|
||||||
// alias the actual tag within the alias will be returned.
|
|
||||||
// If an 'or' validation fails the entire or will be returned.
|
|
||||||
//
|
|
||||||
// eg. alias "iscolor": "hexcolor|rgb|rgba|hsl|hsla"
|
|
||||||
// will return "hexcolor|rgb|rgba|hsl|hsla"
|
|
||||||
ActualTag() string |
|
||||||
|
|
||||||
// Namespace returns the namespace for the field error, with the tag
|
|
||||||
// name taking precedence over the field's actual name.
|
|
||||||
//
|
|
||||||
// eg. JSON name "User.fname"
|
|
||||||
//
|
|
||||||
// See StructNamespace() for a version that returns actual names.
|
|
||||||
//
|
|
||||||
// NOTE: this field can be blank when validating a single primitive field
|
|
||||||
// using validate.Field(...) as there is no way to extract it's name
|
|
||||||
Namespace() string |
|
||||||
|
|
||||||
// StructNamespace returns the namespace for the field error, with the field's
|
|
||||||
// actual name.
|
|
||||||
//
|
|
||||||
// eq. "User.FirstName" see Namespace for comparison
|
|
||||||
//
|
|
||||||
// NOTE: this field can be blank when validating a single primitive field
|
|
||||||
// using validate.Field(...) as there is no way to extract its name
|
|
||||||
StructNamespace() string |
|
||||||
|
|
||||||
// Field returns the fields name with the tag name taking precedence over the
|
|
||||||
// field's actual name.
|
|
||||||
//
|
|
||||||
// eq. JSON name "fname"
|
|
||||||
// see StructField for comparison
|
|
||||||
Field() string |
|
||||||
|
|
||||||
// StructField returns the field's actual name from the struct, when able to determine.
|
|
||||||
//
|
|
||||||
// eq. "FirstName"
|
|
||||||
// see Field for comparison
|
|
||||||
StructField() string |
|
||||||
|
|
||||||
// Value returns the actual field's value in case needed for creating the error
|
|
||||||
// message
|
|
||||||
Value() interface{} |
|
||||||
|
|
||||||
// Param returns the param value, in string form for comparison; this will also
|
|
||||||
// help with generating an error message
|
|
||||||
Param() string |
|
||||||
|
|
||||||
// Kind returns the Field's reflect Kind
|
|
||||||
//
|
|
||||||
// eg. time.Time's kind is a struct
|
|
||||||
Kind() reflect.Kind |
|
||||||
|
|
||||||
// Type returns the Field's reflect Type
|
|
||||||
//
|
|
||||||
// eg. time.Time's type is time.Time
|
|
||||||
Type() reflect.Type |
|
||||||
|
|
||||||
// Translate returns the FieldError's translated error
|
|
||||||
// from the provided 'ut.Translator' and registered 'TranslationFunc'
|
|
||||||
//
|
|
||||||
// NOTE: if no registered translator can be found it returns the same as
|
|
||||||
// calling fe.Error()
|
|
||||||
Translate(ut ut.Translator) string |
|
||||||
|
|
||||||
// Error returns the FieldError's message
|
|
||||||
Error() string |
|
||||||
} |
|
||||||
|
|
||||||
// compile time interface checks
|
|
||||||
var _ FieldError = new(fieldError) |
|
||||||
var _ error = new(fieldError) |
|
||||||
|
|
||||||
// fieldError contains a single field's validation error along
|
|
||||||
// with other properties that may be needed for error message creation
|
|
||||||
// it complies with the FieldError interface
|
|
||||||
type fieldError struct { |
|
||||||
v *Validate |
|
||||||
tag string |
|
||||||
actualTag string |
|
||||||
ns string |
|
||||||
structNs string |
|
||||||
fieldLen uint8 |
|
||||||
structfieldLen uint8 |
|
||||||
value interface{} |
|
||||||
param string |
|
||||||
kind reflect.Kind |
|
||||||
typ reflect.Type |
|
||||||
} |
|
||||||
|
|
||||||
// Tag returns the validation tag that failed.
|
|
||||||
func (fe *fieldError) Tag() string { |
|
||||||
return fe.tag |
|
||||||
} |
|
||||||
|
|
||||||
// ActualTag returns the validation tag that failed, even if an
|
|
||||||
// alias the actual tag within the alias will be returned.
|
|
||||||
func (fe *fieldError) ActualTag() string { |
|
||||||
return fe.actualTag |
|
||||||
} |
|
||||||
|
|
||||||
// Namespace returns the namespace for the field error, with the tag
|
|
||||||
// name taking precedence over the field's actual name.
|
|
||||||
func (fe *fieldError) Namespace() string { |
|
||||||
return fe.ns |
|
||||||
} |
|
||||||
|
|
||||||
// StructNamespace returns the namespace for the field error, with the field's
|
|
||||||
// actual name.
|
|
||||||
func (fe *fieldError) StructNamespace() string { |
|
||||||
return fe.structNs |
|
||||||
} |
|
||||||
|
|
||||||
// Field returns the field's name with the tag name taking precedence over the
|
|
||||||
// field's actual name.
|
|
||||||
func (fe *fieldError) Field() string { |
|
||||||
|
|
||||||
return fe.ns[len(fe.ns)-int(fe.fieldLen):] |
|
||||||
// // return fe.field
|
|
||||||
// fld := fe.ns[len(fe.ns)-int(fe.fieldLen):]
|
|
||||||
|
|
||||||
// log.Println("FLD:", fld)
|
|
||||||
|
|
||||||
// if len(fld) > 0 && fld[:1] == "." {
|
|
||||||
// return fld[1:]
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return fld
|
|
||||||
} |
|
||||||
|
|
||||||
// StructField returns the field's actual name from the struct, when able to determine.
|
|
||||||
func (fe *fieldError) StructField() string { |
|
||||||
// return fe.structField
|
|
||||||
return fe.structNs[len(fe.structNs)-int(fe.structfieldLen):] |
|
||||||
} |
|
||||||
|
|
||||||
// Value returns the actual field's value in case needed for creating the error
|
|
||||||
// message
|
|
||||||
func (fe *fieldError) Value() interface{} { |
|
||||||
return fe.value |
|
||||||
} |
|
||||||
|
|
||||||
// Param returns the param value, in string form for comparison; this will
|
|
||||||
// also help with generating an error message
|
|
||||||
func (fe *fieldError) Param() string { |
|
||||||
return fe.param |
|
||||||
} |
|
||||||
|
|
||||||
// Kind returns the Field's reflect Kind
|
|
||||||
func (fe *fieldError) Kind() reflect.Kind { |
|
||||||
return fe.kind |
|
||||||
} |
|
||||||
|
|
||||||
// Type returns the Field's reflect Type
|
|
||||||
func (fe *fieldError) Type() reflect.Type { |
|
||||||
return fe.typ |
|
||||||
} |
|
||||||
|
|
||||||
// Error returns the fieldError's error message
|
|
||||||
func (fe *fieldError) Error() string { |
|
||||||
return fmt.Sprintf(fieldErrMsg, fe.ns, fe.Field(), fe.tag) |
|
||||||
} |
|
||||||
|
|
||||||
// Translate returns the FieldError's translated error
|
|
||||||
// from the provided 'ut.Translator' and registered 'TranslationFunc'
|
|
||||||
//
|
|
||||||
// NOTE: if no registered translation can be found, it returns the original
|
|
||||||
// untranslated error message.
|
|
||||||
func (fe *fieldError) Translate(ut ut.Translator) string { |
|
||||||
|
|
||||||
m, ok := fe.v.transTagFunc[ut] |
|
||||||
if !ok { |
|
||||||
return fe.Error() |
|
||||||
} |
|
||||||
|
|
||||||
fn, ok := m[fe.tag] |
|
||||||
if !ok { |
|
||||||
return fe.Error() |
|
||||||
} |
|
||||||
|
|
||||||
return fn(ut, fe) |
|
||||||
} |
|
@ -1,120 +0,0 @@ |
|||||||
package validator |
|
||||||
|
|
||||||
import "reflect" |
|
||||||
|
|
||||||
// FieldLevel contains all the information and helper functions
|
|
||||||
// to validate a field
|
|
||||||
type FieldLevel interface { |
|
||||||
|
|
||||||
// Top returns the top level struct, if any
|
|
||||||
Top() reflect.Value |
|
||||||
|
|
||||||
// Parent returns the current fields parent struct, if any or
|
|
||||||
// the comparison value if called 'VarWithValue'
|
|
||||||
Parent() reflect.Value |
|
||||||
|
|
||||||
// Field returns current field for validation
|
|
||||||
Field() reflect.Value |
|
||||||
|
|
||||||
// FieldName returns the field's name with the tag
|
|
||||||
// name taking precedence over the fields actual name.
|
|
||||||
FieldName() string |
|
||||||
|
|
||||||
// StructFieldName returns the struct field's name
|
|
||||||
StructFieldName() string |
|
||||||
|
|
||||||
// Param returns param for validation against current field
|
|
||||||
Param() string |
|
||||||
|
|
||||||
// GetTag returns the current validations tag name
|
|
||||||
GetTag() string |
|
||||||
|
|
||||||
// ExtractType gets the actual underlying type of field value.
|
|
||||||
// It will dive into pointers, customTypes and return you the
|
|
||||||
// underlying value and it's kind.
|
|
||||||
ExtractType(field reflect.Value) (value reflect.Value, kind reflect.Kind, nullable bool) |
|
||||||
|
|
||||||
// GetStructFieldOK traverses the parent struct to retrieve a specific field denoted by the provided namespace
|
|
||||||
// in the param and returns the field, field kind and whether is was successful in retrieving
|
|
||||||
// the field at all.
|
|
||||||
//
|
|
||||||
// NOTE: when not successful ok will be false, this can happen when a nested struct is nil and so the field
|
|
||||||
// could not be retrieved because it didn't exist.
|
|
||||||
//
|
|
||||||
// Deprecated: Use GetStructFieldOK2() instead which also return if the value is nullable.
|
|
||||||
GetStructFieldOK() (reflect.Value, reflect.Kind, bool) |
|
||||||
|
|
||||||
// GetStructFieldOKAdvanced is the same as GetStructFieldOK except that it accepts the parent struct to start looking for
|
|
||||||
// the field and namespace allowing more extensibility for validators.
|
|
||||||
//
|
|
||||||
// Deprecated: Use GetStructFieldOKAdvanced2() instead which also return if the value is nullable.
|
|
||||||
GetStructFieldOKAdvanced(val reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool) |
|
||||||
|
|
||||||
// GetStructFieldOK2 traverses the parent struct to retrieve a specific field denoted by the provided namespace
|
|
||||||
// in the param and returns the field, field kind, if it's a nullable type and whether is was successful in retrieving
|
|
||||||
// the field at all.
|
|
||||||
//
|
|
||||||
// NOTE: when not successful ok will be false, this can happen when a nested struct is nil and so the field
|
|
||||||
// could not be retrieved because it didn't exist.
|
|
||||||
GetStructFieldOK2() (reflect.Value, reflect.Kind, bool, bool) |
|
||||||
|
|
||||||
// GetStructFieldOKAdvanced2 is the same as GetStructFieldOK except that it accepts the parent struct to start looking for
|
|
||||||
// the field and namespace allowing more extensibility for validators.
|
|
||||||
GetStructFieldOKAdvanced2(val reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool, bool) |
|
||||||
} |
|
||||||
|
|
||||||
var _ FieldLevel = new(validate) |
|
||||||
|
|
||||||
// Field returns current field for validation
|
|
||||||
func (v *validate) Field() reflect.Value { |
|
||||||
return v.flField |
|
||||||
} |
|
||||||
|
|
||||||
// FieldName returns the field's name with the tag
|
|
||||||
// name taking precedence over the fields actual name.
|
|
||||||
func (v *validate) FieldName() string { |
|
||||||
return v.cf.altName |
|
||||||
} |
|
||||||
|
|
||||||
// GetTag returns the current validations tag name
|
|
||||||
func (v *validate) GetTag() string { |
|
||||||
return v.ct.tag |
|
||||||
} |
|
||||||
|
|
||||||
// StructFieldName returns the struct field's name
|
|
||||||
func (v *validate) StructFieldName() string { |
|
||||||
return v.cf.name |
|
||||||
} |
|
||||||
|
|
||||||
// Param returns param for validation against current field
|
|
||||||
func (v *validate) Param() string { |
|
||||||
return v.ct.param |
|
||||||
} |
|
||||||
|
|
||||||
// GetStructFieldOK returns Param returns param for validation against current field
|
|
||||||
//
|
|
||||||
// Deprecated: Use GetStructFieldOK2() instead which also return if the value is nullable.
|
|
||||||
func (v *validate) GetStructFieldOK() (reflect.Value, reflect.Kind, bool) { |
|
||||||
current, kind, _, found := v.getStructFieldOKInternal(v.slflParent, v.ct.param) |
|
||||||
return current, kind, found |
|
||||||
} |
|
||||||
|
|
||||||
// GetStructFieldOKAdvanced is the same as GetStructFieldOK except that it accepts the parent struct to start looking for
|
|
||||||
// the field and namespace allowing more extensibility for validators.
|
|
||||||
//
|
|
||||||
// Deprecated: Use GetStructFieldOKAdvanced2() instead which also return if the value is nullable.
|
|
||||||
func (v *validate) GetStructFieldOKAdvanced(val reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool) { |
|
||||||
current, kind, _, found := v.GetStructFieldOKAdvanced2(val, namespace) |
|
||||||
return current, kind, found |
|
||||||
} |
|
||||||
|
|
||||||
// GetStructFieldOK2 returns Param returns param for validation against current field
|
|
||||||
func (v *validate) GetStructFieldOK2() (reflect.Value, reflect.Kind, bool, bool) { |
|
||||||
return v.getStructFieldOKInternal(v.slflParent, v.ct.param) |
|
||||||
} |
|
||||||
|
|
||||||
// GetStructFieldOKAdvanced2 is the same as GetStructFieldOK except that it accepts the parent struct to start looking for
|
|
||||||
// the field and namespace allowing more extensibility for validators.
|
|
||||||
func (v *validate) GetStructFieldOKAdvanced2(val reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool, bool) { |
|
||||||
return v.getStructFieldOKInternal(val, namespace) |
|
||||||
} |
|
@ -1,14 +0,0 @@ |
|||||||
module github.com/go-playground/validator/v10 |
|
||||||
|
|
||||||
go 1.18 |
|
||||||
|
|
||||||
require ( |
|
||||||
github.com/go-playground/assert/v2 v2.2.0 |
|
||||||
github.com/go-playground/locales v0.14.1 |
|
||||||
github.com/go-playground/universal-translator v0.18.1 |
|
||||||
github.com/leodido/go-urn v1.2.2 |
|
||||||
golang.org/x/crypto v0.7.0 |
|
||||||
golang.org/x/text v0.8.0 |
|
||||||
) |
|
||||||
|
|
||||||
require golang.org/x/sys v0.6.0 // indirect |
|
@ -1,31 +0,0 @@ |
|||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= |
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= |
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= |
|
||||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= |
|
||||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= |
|
||||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= |
|
||||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= |
|
||||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= |
|
||||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= |
|
||||||
github.com/leodido/go-urn v1.2.2 h1:7z68G0FCGvDk646jz1AelTYNYWrTNm0bEcFAo147wt4= |
|
||||||
github.com/leodido/go-urn v1.2.2/go.mod h1:kUaIbLZWttglzwNuG0pgsh5vuV6u2YcGBYz1hIPjtOQ= |
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= |
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= |
|
||||||
github.com/rwtodd/Go.Sed v0.0.0-20210816025313-55464686f9ef/go.mod h1:8AEUvGVi2uQ5b24BIhcr0GCcpd/RNAFWaN2CJFrWIIQ= |
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= |
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= |
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= |
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= |
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= |
|
||||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= |
|
||||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= |
|
||||||
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= |
|
||||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= |
|
||||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= |
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
|
||||||
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= |
|
||||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= |
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= |
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= |
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
|
@ -1,25 +0,0 @@ |
|||||||
package validators |
|
||||||
|
|
||||||
import ( |
|
||||||
"reflect" |
|
||||||
"strings" |
|
||||||
|
|
||||||
"github.com/go-playground/validator/v10" |
|
||||||
) |
|
||||||
|
|
||||||
// NotBlank is the validation function for validating if the current field
|
|
||||||
// has a value or length greater than zero, or is not a space only string.
|
|
||||||
func NotBlank(fl validator.FieldLevel) bool { |
|
||||||
field := fl.Field() |
|
||||||
|
|
||||||
switch field.Kind() { |
|
||||||
case reflect.String: |
|
||||||
return len(strings.Trim(strings.TrimSpace(field.String()), "\x1c\x1d\x1e\x1f")) > 0 |
|
||||||
case reflect.Chan, reflect.Map, reflect.Slice, reflect.Array: |
|
||||||
return field.Len() > 0 |
|
||||||
case reflect.Ptr, reflect.Interface, reflect.Func: |
|
||||||
return !field.IsNil() |
|
||||||
default: |
|
||||||
return field.IsValid() && field.Interface() != reflect.Zero(field.Type()).Interface() |
|
||||||
} |
|
||||||
} |
|
@ -1,65 +0,0 @@ |
|||||||
package validators |
|
||||||
|
|
||||||
import ( |
|
||||||
"testing" |
|
||||||
|
|
||||||
"github.com/go-playground/assert/v2" |
|
||||||
"github.com/go-playground/validator/v10" |
|
||||||
) |
|
||||||
|
|
||||||
type test struct { |
|
||||||
String string `validate:"notblank"` |
|
||||||
Array []int `validate:"notblank"` |
|
||||||
Pointer *int `validate:"notblank"` |
|
||||||
Number int `validate:"notblank"` |
|
||||||
Interface interface{} `validate:"notblank"` |
|
||||||
Func func() `validate:"notblank"` |
|
||||||
} |
|
||||||
|
|
||||||
func TestNotBlank(t *testing.T) { |
|
||||||
v := validator.New() |
|
||||||
err := v.RegisterValidation("notblank", NotBlank) |
|
||||||
assert.Equal(t, nil, err) |
|
||||||
|
|
||||||
// Errors
|
|
||||||
var x *int |
|
||||||
invalid := test{ |
|
||||||
String: " \x1c\x1d\x1e\x1f\r\n", |
|
||||||
Array: []int{}, |
|
||||||
Pointer: x, |
|
||||||
Number: 0, |
|
||||||
Interface: nil, |
|
||||||
Func: nil, |
|
||||||
} |
|
||||||
fieldsWithError := []string{ |
|
||||||
"String", |
|
||||||
"Array", |
|
||||||
"Pointer", |
|
||||||
"Number", |
|
||||||
"Interface", |
|
||||||
"Func", |
|
||||||
} |
|
||||||
|
|
||||||
errors := v.Struct(invalid).(validator.ValidationErrors) |
|
||||||
var fields []string |
|
||||||
for _, err := range errors { |
|
||||||
fields = append(fields, err.Field()) |
|
||||||
} |
|
||||||
|
|
||||||
assert.Equal(t, fieldsWithError, fields) |
|
||||||
|
|
||||||
// No errors
|
|
||||||
y := 1 |
|
||||||
x = &y |
|
||||||
valid := test{ |
|
||||||
String: "str", |
|
||||||
Array: []int{1}, |
|
||||||
Pointer: x, |
|
||||||
Number: 1, |
|
||||||
Interface: "value", |
|
||||||
Func: func() {}, |
|
||||||
} |
|
||||||
|
|
||||||
err = v.Struct(valid) |
|
||||||
assert.Equal(t, nil, err) |
|
||||||
} |
|
@ -1,173 +0,0 @@ |
|||||||
package validator |
|
||||||
|
|
||||||
import "regexp" |
|
||||||
|
|
||||||
var postCodePatternDict = map[string]string{ |
|
||||||
"GB": `^GIR[ ]?0AA|((AB|AL|B|BA|BB|BD|BH|BL|BN|BR|BS|BT|CA|CB|CF|CH|CM|CO|CR|CT|CV|CW|DA|DD|DE|DG|DH|DL|DN|DT|DY|E|EC|EH|EN|EX|FK|FY|G|GL|GY|GU|HA|HD|HG|HP|HR|HS|HU|HX|IG|IM|IP|IV|JE|KA|KT|KW|KY|L|LA|LD|LE|LL|LN|LS|LU|M|ME|MK|ML|N|NE|NG|NN|NP|NR|NW|OL|OX|PA|PE|PH|PL|PO|PR|RG|RH|RM|S|SA|SE|SG|SK|SL|SM|SN|SO|SP|SR|SS|ST|SW|SY|TA|TD|TF|TN|TQ|TR|TS|TW|UB|W|WA|WC|WD|WF|WN|WR|WS|WV|YO|ZE)(\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}))|BFPO[ ]?\d{1,4}$`, |
|
||||||
"JE": `^JE\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}$`, |
|
||||||
"GG": `^GY\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}$`, |
|
||||||
"IM": `^IM\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}$`, |
|
||||||
"US": `^\d{5}([ \-]\d{4})?$`, |
|
||||||
"CA": `^[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJ-NPRSTV-Z][ ]?\d[ABCEGHJ-NPRSTV-Z]\d$`, |
|
||||||
"DE": `^\d{5}$`, |
|
||||||
"JP": `^\d{3}-\d{4}$`, |
|
||||||
"FR": `^\d{2}[ ]?\d{3}$`, |
|
||||||
"AU": `^\d{4}$`, |
|
||||||
"IT": `^\d{5}$`, |
|
||||||
"CH": `^\d{4}$`, |
|
||||||
"AT": `^\d{4}$`, |
|
||||||
"ES": `^\d{5}$`, |
|
||||||
"NL": `^\d{4}[ ]?[A-Z]{2}$`, |
|
||||||
"BE": `^\d{4}$`, |
|
||||||
"DK": `^\d{4}$`, |
|
||||||
"SE": `^\d{3}[ ]?\d{2}$`, |
|
||||||
"NO": `^\d{4}$`, |
|
||||||
"BR": `^\d{5}[\-]?\d{3}$`, |
|
||||||
"PT": `^\d{4}([\-]\d{3})?$`, |
|
||||||
"FI": `^\d{5}$`, |
|
||||||
"AX": `^22\d{3}$`, |
|
||||||
"KR": `^\d{3}[\-]\d{3}$`, |
|
||||||
"CN": `^\d{6}$`, |
|
||||||
"TW": `^\d{3}(\d{2})?$`, |
|
||||||
"SG": `^\d{6}$`, |
|
||||||
"DZ": `^\d{5}$`, |
|
||||||
"AD": `^AD\d{3}$`, |
|
||||||
"AR": `^([A-HJ-NP-Z])?\d{4}([A-Z]{3})?$`, |
|
||||||
"AM": `^(37)?\d{4}$`, |
|
||||||
"AZ": `^\d{4}$`, |
|
||||||
"BH": `^((1[0-2]|[2-9])\d{2})?$`, |
|
||||||
"BD": `^\d{4}$`, |
|
||||||
"BB": `^(BB\d{5})?$`, |
|
||||||
"BY": `^\d{6}$`, |
|
||||||
"BM": `^[A-Z]{2}[ ]?[A-Z0-9]{2}$`, |
|
||||||
"BA": `^\d{5}$`, |
|
||||||
"IO": `^BBND 1ZZ$`, |
|
||||||
"BN": `^[A-Z]{2}[ ]?\d{4}$`, |
|
||||||
"BG": `^\d{4}$`, |
|
||||||
"KH": `^\d{5}$`, |
|
||||||
"CV": `^\d{4}$`, |
|
||||||
"CL": `^\d{7}$`, |
|
||||||
"CR": `^\d{4,5}|\d{3}-\d{4}$`, |
|
||||||
"HR": `^\d{5}$`, |
|
||||||
"CY": `^\d{4}$`, |
|
||||||
"CZ": `^\d{3}[ ]?\d{2}$`, |
|
||||||
"DO": `^\d{5}$`, |
|
||||||
"EC": `^([A-Z]\d{4}[A-Z]|(?:[A-Z]{2})?\d{6})?$`, |
|
||||||
"EG": `^\d{5}$`, |
|
||||||
"EE": `^\d{5}$`, |
|
||||||
"FO": `^\d{3}$`, |
|
||||||
"GE": `^\d{4}$`, |
|
||||||
"GR": `^\d{3}[ ]?\d{2}$`, |
|
||||||
"GL": `^39\d{2}$`, |
|
||||||
"GT": `^\d{5}$`, |
|
||||||
"HT": `^\d{4}$`, |
|
||||||
"HN": `^(?:\d{5})?$`, |
|
||||||
"HU": `^\d{4}$`, |
|
||||||
"IS": `^\d{3}$`, |
|
||||||
"IN": `^\d{6}$`, |
|
||||||
"ID": `^\d{5}$`, |
|
||||||
"IL": `^\d{5}$`, |
|
||||||
"JO": `^\d{5}$`, |
|
||||||
"KZ": `^\d{6}$`, |
|
||||||
"KE": `^\d{5}$`, |
|
||||||
"KW": `^\d{5}$`, |
|
||||||
"LA": `^\d{5}$`, |
|
||||||
"LV": `^\d{4}$`, |
|
||||||
"LB": `^(\d{4}([ ]?\d{4})?)?$`, |
|
||||||
"LI": `^(948[5-9])|(949[0-7])$`, |
|
||||||
"LT": `^\d{5}$`, |
|
||||||
"LU": `^\d{4}$`, |
|
||||||
"MK": `^\d{4}$`, |
|
||||||
"MY": `^\d{5}$`, |
|
||||||
"MV": `^\d{5}$`, |
|
||||||
"MT": `^[A-Z]{3}[ ]?\d{2,4}$`, |
|
||||||
"MU": `^(\d{3}[A-Z]{2}\d{3})?$`, |
|
||||||
"MX": `^\d{5}$`, |
|
||||||
"MD": `^\d{4}$`, |
|
||||||
"MC": `^980\d{2}$`, |
|
||||||
"MA": `^\d{5}$`, |
|
||||||
"NP": `^\d{5}$`, |
|
||||||
"NZ": `^\d{4}$`, |
|
||||||
"NI": `^((\d{4}-)?\d{3}-\d{3}(-\d{1})?)?$`, |
|
||||||
"NG": `^(\d{6})?$`, |
|
||||||
"OM": `^(PC )?\d{3}$`, |
|
||||||
"PK": `^\d{5}$`, |
|
||||||
"PY": `^\d{4}$`, |
|
||||||
"PH": `^\d{4}$`, |
|
||||||
"PL": `^\d{2}-\d{3}$`, |
|
||||||
"PR": `^00[679]\d{2}([ \-]\d{4})?$`, |
|
||||||
"RO": `^\d{6}$`, |
|
||||||
"RU": `^\d{6}$`, |
|
||||||
"SM": `^4789\d$`, |
|
||||||
"SA": `^\d{5}$`, |
|
||||||
"SN": `^\d{5}$`, |
|
||||||
"SK": `^\d{3}[ ]?\d{2}$`, |
|
||||||
"SI": `^\d{4}$`, |
|
||||||
"ZA": `^\d{4}$`, |
|
||||||
"LK": `^\d{5}$`, |
|
||||||
"TJ": `^\d{6}$`, |
|
||||||
"TH": `^\d{5}$`, |
|
||||||
"TN": `^\d{4}$`, |
|
||||||
"TR": `^\d{5}$`, |
|
||||||
"TM": `^\d{6}$`, |
|
||||||
"UA": `^\d{5}$`, |
|
||||||
"UY": `^\d{5}$`, |
|
||||||
"UZ": `^\d{6}$`, |
|
||||||
"VA": `^00120$`, |
|
||||||
"VE": `^\d{4}$`, |
|
||||||
"ZM": `^\d{5}$`, |
|
||||||
"AS": `^96799$`, |
|
||||||
"CC": `^6799$`, |
|
||||||
"CK": `^\d{4}$`, |
|
||||||
"RS": `^\d{6}$`, |
|
||||||
"ME": `^8\d{4}$`, |
|
||||||
"CS": `^\d{5}$`, |
|
||||||
"YU": `^\d{5}$`, |
|
||||||
"CX": `^6798$`, |
|
||||||
"ET": `^\d{4}$`, |
|
||||||
"FK": `^FIQQ 1ZZ$`, |
|
||||||
"NF": `^2899$`, |
|
||||||
"FM": `^(9694[1-4])([ \-]\d{4})?$`, |
|
||||||
"GF": `^9[78]3\d{2}$`, |
|
||||||
"GN": `^\d{3}$`, |
|
||||||
"GP": `^9[78][01]\d{2}$`, |
|
||||||
"GS": `^SIQQ 1ZZ$`, |
|
||||||
"GU": `^969[123]\d([ \-]\d{4})?$`, |
|
||||||
"GW": `^\d{4}$`, |
|
||||||
"HM": `^\d{4}$`, |
|
||||||
"IQ": `^\d{5}$`, |
|
||||||
"KG": `^\d{6}$`, |
|
||||||
"LR": `^\d{4}$`, |
|
||||||
"LS": `^\d{3}$`, |
|
||||||
"MG": `^\d{3}$`, |
|
||||||
"MH": `^969[67]\d([ \-]\d{4})?$`, |
|
||||||
"MN": `^\d{6}$`, |
|
||||||
"MP": `^9695[012]([ \-]\d{4})?$`, |
|
||||||
"MQ": `^9[78]2\d{2}$`, |
|
||||||
"NC": `^988\d{2}$`, |
|
||||||
"NE": `^\d{4}$`, |
|
||||||
"VI": `^008(([0-4]\d)|(5[01]))([ \-]\d{4})?$`, |
|
||||||
"VN": `^[0-9]{1,6}$`, |
|
||||||
"PF": `^987\d{2}$`, |
|
||||||
"PG": `^\d{3}$`, |
|
||||||
"PM": `^9[78]5\d{2}$`, |
|
||||||
"PN": `^PCRN 1ZZ$`, |
|
||||||
"PW": `^96940$`, |
|
||||||
"RE": `^9[78]4\d{2}$`, |
|
||||||
"SH": `^(ASCN|STHL) 1ZZ$`, |
|
||||||
"SJ": `^\d{4}$`, |
|
||||||
"SO": `^\d{5}$`, |
|
||||||
"SZ": `^[HLMS]\d{3}$`, |
|
||||||
"TC": `^TKCA 1ZZ$`, |
|
||||||
"WF": `^986\d{2}$`, |
|
||||||
"XK": `^\d{5}$`, |
|
||||||
"YT": `^976\d{2}$`, |
|
||||||
} |
|
||||||
|
|
||||||
var postCodeRegexDict = map[string]*regexp.Regexp{} |
|
||||||
|
|
||||||
func init() { |
|
||||||
for countryCode, pattern := range postCodePatternDict { |
|
||||||
postCodeRegexDict[countryCode] = regexp.MustCompile(pattern) |
|
||||||
} |
|
||||||
} |
|
@ -1,175 +0,0 @@ |
|||||||
package validator |
|
||||||
|
|
||||||
import ( |
|
||||||
"context" |
|
||||||
"reflect" |
|
||||||
) |
|
||||||
|
|
||||||
// StructLevelFunc accepts all values needed for struct level validation
|
|
||||||
type StructLevelFunc func(sl StructLevel) |
|
||||||
|
|
||||||
// StructLevelFuncCtx accepts all values needed for struct level validation
|
|
||||||
// but also allows passing of contextual validation information via context.Context.
|
|
||||||
type StructLevelFuncCtx func(ctx context.Context, sl StructLevel) |
|
||||||
|
|
||||||
// wrapStructLevelFunc wraps normal StructLevelFunc makes it compatible with StructLevelFuncCtx
|
|
||||||
func wrapStructLevelFunc(fn StructLevelFunc) StructLevelFuncCtx { |
|
||||||
return func(ctx context.Context, sl StructLevel) { |
|
||||||
fn(sl) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// StructLevel contains all the information and helper functions
|
|
||||||
// to validate a struct
|
|
||||||
type StructLevel interface { |
|
||||||
|
|
||||||
// Validator returns the main validation object, in case one wants to call validations internally.
|
|
||||||
// this is so you don't have to use anonymous functions to get access to the validate
|
|
||||||
// instance.
|
|
||||||
Validator() *Validate |
|
||||||
|
|
||||||
// Top returns the top level struct, if any
|
|
||||||
Top() reflect.Value |
|
||||||
|
|
||||||
// Parent returns the current fields parent struct, if any
|
|
||||||
Parent() reflect.Value |
|
||||||
|
|
||||||
// Current returns the current struct.
|
|
||||||
Current() reflect.Value |
|
||||||
|
|
||||||
// ExtractType gets the actual underlying type of field value.
|
|
||||||
// It will dive into pointers, customTypes and return you the
|
|
||||||
// underlying value and its kind.
|
|
||||||
ExtractType(field reflect.Value) (value reflect.Value, kind reflect.Kind, nullable bool) |
|
||||||
|
|
||||||
// ReportError reports an error just by passing the field and tag information
|
|
||||||
//
|
|
||||||
// NOTES:
|
|
||||||
//
|
|
||||||
// fieldName and altName get appended to the existing namespace that
|
|
||||||
// validator is on. e.g. pass 'FirstName' or 'Names[0]' depending
|
|
||||||
// on the nesting
|
|
||||||
//
|
|
||||||
// tag can be an existing validation tag or just something you make up
|
|
||||||
// and process on the flip side it's up to you.
|
|
||||||
ReportError(field interface{}, fieldName, structFieldName string, tag, param string) |
|
||||||
|
|
||||||
// ReportValidationErrors reports an error just by passing ValidationErrors
|
|
||||||
//
|
|
||||||
// NOTES:
|
|
||||||
//
|
|
||||||
// relativeNamespace and relativeActualNamespace get appended to the
|
|
||||||
// existing namespace that validator is on.
|
|
||||||
// e.g. pass 'User.FirstName' or 'Users[0].FirstName' depending
|
|
||||||
// on the nesting. most of the time they will be blank, unless you validate
|
|
||||||
// at a level lower the the current field depth
|
|
||||||
ReportValidationErrors(relativeNamespace, relativeActualNamespace string, errs ValidationErrors) |
|
||||||
} |
|
||||||
|
|
||||||
var _ StructLevel = new(validate) |
|
||||||
|
|
||||||
// Top returns the top level struct
|
|
||||||
//
|
|
||||||
// NOTE: this can be the same as the current struct being validated
|
|
||||||
// if not is a nested struct.
|
|
||||||
//
|
|
||||||
// this is only called when within Struct and Field Level validation and
|
|
||||||
// should not be relied upon for an acurate value otherwise.
|
|
||||||
func (v *validate) Top() reflect.Value { |
|
||||||
return v.top |
|
||||||
} |
|
||||||
|
|
||||||
// Parent returns the current structs parent
|
|
||||||
//
|
|
||||||
// NOTE: this can be the same as the current struct being validated
|
|
||||||
// if not is a nested struct.
|
|
||||||
//
|
|
||||||
// this is only called when within Struct and Field Level validation and
|
|
||||||
// should not be relied upon for an acurate value otherwise.
|
|
||||||
func (v *validate) Parent() reflect.Value { |
|
||||||
return v.slflParent |
|
||||||
} |
|
||||||
|
|
||||||
// Current returns the current struct.
|
|
||||||
func (v *validate) Current() reflect.Value { |
|
||||||
return v.slCurrent |
|
||||||
} |
|
||||||
|
|
||||||
// Validator returns the main validation object, in case one want to call validations internally.
|
|
||||||
func (v *validate) Validator() *Validate { |
|
||||||
return v.v |
|
||||||
} |
|
||||||
|
|
||||||
// ExtractType gets the actual underlying type of field value.
|
|
||||||
func (v *validate) ExtractType(field reflect.Value) (reflect.Value, reflect.Kind, bool) { |
|
||||||
return v.extractTypeInternal(field, false) |
|
||||||
} |
|
||||||
|
|
||||||
// ReportError reports an error just by passing the field and tag information
|
|
||||||
func (v *validate) ReportError(field interface{}, fieldName, structFieldName, tag, param string) { |
|
||||||
|
|
||||||
fv, kind, _ := v.extractTypeInternal(reflect.ValueOf(field), false) |
|
||||||
|
|
||||||
if len(structFieldName) == 0 { |
|
||||||
structFieldName = fieldName |
|
||||||
} |
|
||||||
|
|
||||||
v.str1 = string(append(v.ns, fieldName...)) |
|
||||||
|
|
||||||
if v.v.hasTagNameFunc || fieldName != structFieldName { |
|
||||||
v.str2 = string(append(v.actualNs, structFieldName...)) |
|
||||||
} else { |
|
||||||
v.str2 = v.str1 |
|
||||||
} |
|
||||||
|
|
||||||
if kind == reflect.Invalid { |
|
||||||
|
|
||||||
v.errs = append(v.errs, |
|
||||||
&fieldError{ |
|
||||||
v: v.v, |
|
||||||
tag: tag, |
|
||||||
actualTag: tag, |
|
||||||
ns: v.str1, |
|
||||||
structNs: v.str2, |
|
||||||
fieldLen: uint8(len(fieldName)), |
|
||||||
structfieldLen: uint8(len(structFieldName)), |
|
||||||
param: param, |
|
||||||
kind: kind, |
|
||||||
}, |
|
||||||
) |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
v.errs = append(v.errs, |
|
||||||
&fieldError{ |
|
||||||
v: v.v, |
|
||||||
tag: tag, |
|
||||||
actualTag: tag, |
|
||||||
ns: v.str1, |
|
||||||
structNs: v.str2, |
|
||||||
fieldLen: uint8(len(fieldName)), |
|
||||||
structfieldLen: uint8(len(structFieldName)), |
|
||||||
value: fv.Interface(), |
|
||||||
param: param, |
|
||||||
kind: kind, |
|
||||||
typ: fv.Type(), |
|
||||||
}, |
|
||||||
) |
|
||||||
} |
|
||||||
|
|
||||||
// ReportValidationErrors reports ValidationErrors obtained from running validations within the Struct Level validation.
|
|
||||||
//
|
|
||||||
// NOTE: this function prepends the current namespace to the relative ones.
|
|
||||||
func (v *validate) ReportValidationErrors(relativeNamespace, relativeStructNamespace string, errs ValidationErrors) { |
|
||||||
|
|
||||||
var err *fieldError |
|
||||||
|
|
||||||
for i := 0; i < len(errs); i++ { |
|
||||||
|
|
||||||
err = errs[i].(*fieldError) |
|
||||||
err.ns = string(append(append(v.ns, relativeNamespace...), err.ns...)) |
|
||||||
err.structNs = string(append(append(v.actualNs, relativeStructNamespace...), err.structNs...)) |
|
||||||
|
|
||||||
v.errs = append(v.errs, err) |
|
||||||
} |
|
||||||
} |
|
@ -1 +0,0 @@ |
|||||||
package testdata |
|
@ -1,11 +0,0 @@ |
|||||||
package validator |
|
||||||
|
|
||||||
import ut "github.com/go-playground/universal-translator" |
|
||||||
|
|
||||||
// TranslationFunc is the function type used to register or override
|
|
||||||
// custom translations
|
|
||||||
type TranslationFunc func(ut ut.Translator, fe FieldError) string |
|
||||||
|
|
||||||
// RegisterTranslationsFunc allows for registering of translations
|
|
||||||
// for a 'ut.Translator' for use within the 'TranslationFunc'
|
|
||||||
type RegisterTranslationsFunc func(ut ut.Translator) error |
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,720 +0,0 @@ |
|||||||
package en |
|
||||||
|
|
||||||
import ( |
|
||||||
"testing" |
|
||||||
"time" |
|
||||||
|
|
||||||
. "github.com/go-playground/assert/v2" |
|
||||||
english "github.com/go-playground/locales/en" |
|
||||||
ut "github.com/go-playground/universal-translator" |
|
||||||
"github.com/go-playground/validator/v10" |
|
||||||
) |
|
||||||
|
|
||||||
func TestTranslations(t *testing.T) { |
|
||||||
eng := english.New() |
|
||||||
uni := ut.New(eng, eng) |
|
||||||
trans, _ := uni.GetTranslator("en") |
|
||||||
|
|
||||||
validate := validator.New() |
|
||||||
|
|
||||||
err := RegisterDefaultTranslations(validate, trans) |
|
||||||
Equal(t, err, nil) |
|
||||||
|
|
||||||
type Inner struct { |
|
||||||
EqCSFieldString string |
|
||||||
NeCSFieldString string |
|
||||||
GtCSFieldString string |
|
||||||
GteCSFieldString string |
|
||||||
LtCSFieldString string |
|
||||||
LteCSFieldString string |
|
||||||
RequiredIf string |
|
||||||
} |
|
||||||
|
|
||||||
type Test struct { |
|
||||||
Inner Inner |
|
||||||
RequiredString string `validate:"required"` |
|
||||||
RequiredNumber int `validate:"required"` |
|
||||||
RequiredMultiple []string `validate:"required"` |
|
||||||
RequiredIf string `validate:"required_if=Inner.RequiredIf abcd"` |
|
||||||
LenString string `validate:"len=1"` |
|
||||||
LenNumber float64 `validate:"len=1113.00"` |
|
||||||
LenMultiple []string `validate:"len=7"` |
|
||||||
MinString string `validate:"min=1"` |
|
||||||
MinNumber float64 `validate:"min=1113.00"` |
|
||||||
MinMultiple []string `validate:"min=7"` |
|
||||||
MaxString string `validate:"max=3"` |
|
||||||
MaxNumber float64 `validate:"max=1113.00"` |
|
||||||
MaxMultiple []string `validate:"max=7"` |
|
||||||
EqString string `validate:"eq=3"` |
|
||||||
EqNumber float64 `validate:"eq=2.33"` |
|
||||||
EqMultiple []string `validate:"eq=7"` |
|
||||||
NeString string `validate:"ne="` |
|
||||||
NeNumber float64 `validate:"ne=0.00"` |
|
||||||
NeMultiple []string `validate:"ne=0"` |
|
||||||
LtString string `validate:"lt=3"` |
|
||||||
LtNumber float64 `validate:"lt=5.56"` |
|
||||||
LtMultiple []string `validate:"lt=2"` |
|
||||||
LtTime time.Time `validate:"lt"` |
|
||||||
LteString string `validate:"lte=3"` |
|
||||||
LteNumber float64 `validate:"lte=5.56"` |
|
||||||
LteMultiple []string `validate:"lte=2"` |
|
||||||
LteTime time.Time `validate:"lte"` |
|
||||||
GtString string `validate:"gt=3"` |
|
||||||
GtNumber float64 `validate:"gt=5.56"` |
|
||||||
GtMultiple []string `validate:"gt=2"` |
|
||||||
GtTime time.Time `validate:"gt"` |
|
||||||
GteString string `validate:"gte=3"` |
|
||||||
GteNumber float64 `validate:"gte=5.56"` |
|
||||||
GteMultiple []string `validate:"gte=2"` |
|
||||||
GteTime time.Time `validate:"gte"` |
|
||||||
EqFieldString string `validate:"eqfield=MaxString"` |
|
||||||
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"` |
|
||||||
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"` |
|
||||||
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"` |
|
||||||
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"` |
|
||||||
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"` |
|
||||||
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"` |
|
||||||
NeFieldString string `validate:"nefield=EqFieldString"` |
|
||||||
GtFieldString string `validate:"gtfield=MaxString"` |
|
||||||
GteFieldString string `validate:"gtefield=MaxString"` |
|
||||||
LtFieldString string `validate:"ltfield=MaxString"` |
|
||||||
LteFieldString string `validate:"ltefield=MaxString"` |
|
||||||
AlphaString string `validate:"alpha"` |
|
||||||
AlphanumString string `validate:"alphanum"` |
|
||||||
NumericString string `validate:"numeric"` |
|
||||||
NumberString string `validate:"number"` |
|
||||||
HexadecimalString string `validate:"hexadecimal"` |
|
||||||
HexColorString string `validate:"hexcolor"` |
|
||||||
RGBColorString string `validate:"rgb"` |
|
||||||
RGBAColorString string `validate:"rgba"` |
|
||||||
HSLColorString string `validate:"hsl"` |
|
||||||
HSLAColorString string `validate:"hsla"` |
|
||||||
Email string `validate:"email"` |
|
||||||
URL string `validate:"url"` |
|
||||||
URI string `validate:"uri"` |
|
||||||
Base64 string `validate:"base64"` |
|
||||||
Contains string `validate:"contains=purpose"` |
|
||||||
ContainsAny string `validate:"containsany=!@#$"` |
|
||||||
Excludes string `validate:"excludes=text"` |
|
||||||
ExcludesAll string `validate:"excludesall=!@#$"` |
|
||||||
ExcludesRune string `validate:"excludesrune=☻"` |
|
||||||
ISBN string `validate:"isbn"` |
|
||||||
ISBN10 string `validate:"isbn10"` |
|
||||||
ISBN13 string `validate:"isbn13"` |
|
||||||
UUID string `validate:"uuid"` |
|
||||||
UUID3 string `validate:"uuid3"` |
|
||||||
UUID4 string `validate:"uuid4"` |
|
||||||
UUID5 string `validate:"uuid5"` |
|
||||||
ULID string `validate:"ulid"` |
|
||||||
ASCII string `validate:"ascii"` |
|
||||||
PrintableASCII string `validate:"printascii"` |
|
||||||
MultiByte string `validate:"multibyte"` |
|
||||||
DataURI string `validate:"datauri"` |
|
||||||
Latitude string `validate:"latitude"` |
|
||||||
Longitude string `validate:"longitude"` |
|
||||||
SSN string `validate:"ssn"` |
|
||||||
IP string `validate:"ip"` |
|
||||||
IPv4 string `validate:"ipv4"` |
|
||||||
IPv6 string `validate:"ipv6"` |
|
||||||
CIDR string `validate:"cidr"` |
|
||||||
CIDRv4 string `validate:"cidrv4"` |
|
||||||
CIDRv6 string `validate:"cidrv6"` |
|
||||||
TCPAddr string `validate:"tcp_addr"` |
|
||||||
TCPAddrv4 string `validate:"tcp4_addr"` |
|
||||||
TCPAddrv6 string `validate:"tcp6_addr"` |
|
||||||
UDPAddr string `validate:"udp_addr"` |
|
||||||
UDPAddrv4 string `validate:"udp4_addr"` |
|
||||||
UDPAddrv6 string `validate:"udp6_addr"` |
|
||||||
IPAddr string `validate:"ip_addr"` |
|
||||||
IPAddrv4 string `validate:"ip4_addr"` |
|
||||||
IPAddrv6 string `validate:"ip6_addr"` |
|
||||||
UinxAddr string `validate:"unix_addr"` // can't fail from within Go's net package currently, but maybe in the future
|
|
||||||
MAC string `validate:"mac"` |
|
||||||
FQDN string `validate:"fqdn"` |
|
||||||
IsColor string `validate:"iscolor"` |
|
||||||
StrPtrMinLen *string `validate:"min=10"` |
|
||||||
StrPtrMaxLen *string `validate:"max=1"` |
|
||||||
StrPtrLen *string `validate:"len=2"` |
|
||||||
StrPtrLt *string `validate:"lt=1"` |
|
||||||
StrPtrLte *string `validate:"lte=1"` |
|
||||||
StrPtrGt *string `validate:"gt=10"` |
|
||||||
StrPtrGte *string `validate:"gte=10"` |
|
||||||
OneOfString string `validate:"oneof=red green"` |
|
||||||
OneOfInt int `validate:"oneof=5 63"` |
|
||||||
UniqueSlice []string `validate:"unique"` |
|
||||||
UniqueArray [3]string `validate:"unique"` |
|
||||||
UniqueMap map[string]string `validate:"unique"` |
|
||||||
JSONString string `validate:"json"` |
|
||||||
JWTString string `validate:"jwt"` |
|
||||||
LowercaseString string `validate:"lowercase"` |
|
||||||
UppercaseString string `validate:"uppercase"` |
|
||||||
Datetime string `validate:"datetime=2006-01-02"` |
|
||||||
PostCode string `validate:"postcode_iso3166_alpha2=SG"` |
|
||||||
PostCodeCountry string |
|
||||||
PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"` |
|
||||||
BooleanString string `validate:"boolean"` |
|
||||||
CveString string `validate:"cve"` |
|
||||||
} |
|
||||||
|
|
||||||
var test Test |
|
||||||
|
|
||||||
test.Inner.EqCSFieldString = "1234" |
|
||||||
test.Inner.GtCSFieldString = "1234" |
|
||||||
test.Inner.GteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.MaxString = "1234" |
|
||||||
test.MaxNumber = 2000 |
|
||||||
test.MaxMultiple = make([]string, 9) |
|
||||||
|
|
||||||
test.LtString = "1234" |
|
||||||
test.LtNumber = 6 |
|
||||||
test.LtMultiple = make([]string, 3) |
|
||||||
test.LtTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LteString = "1234" |
|
||||||
test.LteNumber = 6 |
|
||||||
test.LteMultiple = make([]string, 3) |
|
||||||
test.LteTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LtFieldString = "12345" |
|
||||||
test.LteFieldString = "12345" |
|
||||||
|
|
||||||
test.LtCSFieldString = "1234" |
|
||||||
test.LteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.AlphaString = "abc3" |
|
||||||
test.AlphanumString = "abc3!" |
|
||||||
test.NumericString = "12E.00" |
|
||||||
test.NumberString = "12E" |
|
||||||
|
|
||||||
test.Excludes = "this is some test text" |
|
||||||
test.ExcludesAll = "This is Great!" |
|
||||||
test.ExcludesRune = "Love it ☻" |
|
||||||
|
|
||||||
test.ASCII = "カタカナ" |
|
||||||
test.PrintableASCII = "カタカナ" |
|
||||||
|
|
||||||
test.MultiByte = "1234feerf" |
|
||||||
|
|
||||||
test.LowercaseString = "ABCDEFG" |
|
||||||
test.UppercaseString = "abcdefg" |
|
||||||
|
|
||||||
s := "toolong" |
|
||||||
test.StrPtrMaxLen = &s |
|
||||||
test.StrPtrLen = &s |
|
||||||
|
|
||||||
test.UniqueSlice = []string{"1234", "1234"} |
|
||||||
test.UniqueMap = map[string]string{"key1": "1234", "key2": "1234"} |
|
||||||
test.Datetime = "2008-Feb-01" |
|
||||||
test.BooleanString = "A" |
|
||||||
test.CveString = "A" |
|
||||||
|
|
||||||
test.Inner.RequiredIf = "abcd" |
|
||||||
|
|
||||||
err = validate.Struct(test) |
|
||||||
NotEqual(t, err, nil) |
|
||||||
|
|
||||||
errs, ok := err.(validator.ValidationErrors) |
|
||||||
Equal(t, ok, true) |
|
||||||
|
|
||||||
tests := []struct { |
|
||||||
ns string |
|
||||||
expected string |
|
||||||
}{ |
|
||||||
{ |
|
||||||
ns: "Test.IsColor", |
|
||||||
expected: "IsColor must be a valid color", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MAC", |
|
||||||
expected: "MAC must contain a valid MAC address", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.FQDN", |
|
||||||
expected: "FQDN must be a valid FQDN", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddr", |
|
||||||
expected: "IPAddr must be a resolvable IP address", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv4", |
|
||||||
expected: "IPAddrv4 must be a resolvable IPv4 address", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv6", |
|
||||||
expected: "IPAddrv6 must be a resolvable IPv6 address", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddr", |
|
||||||
expected: "UDPAddr must be a valid UDP address", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv4", |
|
||||||
expected: "UDPAddrv4 must be a valid IPv4 UDP address", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv6", |
|
||||||
expected: "UDPAddrv6 must be a valid IPv6 UDP address", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddr", |
|
||||||
expected: "TCPAddr must be a valid TCP address", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv4", |
|
||||||
expected: "TCPAddrv4 must be a valid IPv4 TCP address", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv6", |
|
||||||
expected: "TCPAddrv6 must be a valid IPv6 TCP address", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDR", |
|
||||||
expected: "CIDR must contain a valid CIDR notation", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv4", |
|
||||||
expected: "CIDRv4 must contain a valid CIDR notation for an IPv4 address", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv6", |
|
||||||
expected: "CIDRv6 must contain a valid CIDR notation for an IPv6 address", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.SSN", |
|
||||||
expected: "SSN must be a valid SSN number", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IP", |
|
||||||
expected: "IP must be a valid IP address", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv4", |
|
||||||
expected: "IPv4 must be a valid IPv4 address", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv6", |
|
||||||
expected: "IPv6 must be a valid IPv6 address", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.DataURI", |
|
||||||
expected: "DataURI must contain a valid Data URI", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Latitude", |
|
||||||
expected: "Latitude must contain valid latitude coordinates", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Longitude", |
|
||||||
expected: "Longitude must contain a valid longitude coordinates", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MultiByte", |
|
||||||
expected: "MultiByte must contain multibyte characters", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ASCII", |
|
||||||
expected: "ASCII must contain only ascii characters", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.PrintableASCII", |
|
||||||
expected: "PrintableASCII must contain only printable ascii characters", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID", |
|
||||||
expected: "UUID must be a valid UUID", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID3", |
|
||||||
expected: "UUID3 must be a valid version 3 UUID", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID4", |
|
||||||
expected: "UUID4 must be a valid version 4 UUID", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID5", |
|
||||||
expected: "UUID5 must be a valid version 5 UUID", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ULID", |
|
||||||
expected: "ULID must be a valid ULID", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN", |
|
||||||
expected: "ISBN must be a valid ISBN number", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN10", |
|
||||||
expected: "ISBN10 must be a valid ISBN-10 number", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN13", |
|
||||||
expected: "ISBN13 must be a valid ISBN-13 number", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Excludes", |
|
||||||
expected: "Excludes cannot contain the text 'text'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesAll", |
|
||||||
expected: "ExcludesAll cannot contain any of the following characters '!@#$'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesRune", |
|
||||||
expected: "ExcludesRune cannot contain the following '☻'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ContainsAny", |
|
||||||
expected: "ContainsAny must contain at least one of the following characters '!@#$'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Contains", |
|
||||||
expected: "Contains must contain the text 'purpose'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Base64", |
|
||||||
expected: "Base64 must be a valid Base64 string", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Email", |
|
||||||
expected: "Email must be a valid email address", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URL", |
|
||||||
expected: "URL must be a valid URL", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URI", |
|
||||||
expected: "URI must be a valid URI", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBColorString", |
|
||||||
expected: "RGBColorString must be a valid RGB color", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBAColorString", |
|
||||||
expected: "RGBAColorString must be a valid RGBA color", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLColorString", |
|
||||||
expected: "HSLColorString must be a valid HSL color", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLAColorString", |
|
||||||
expected: "HSLAColorString must be a valid HSLA color", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexadecimalString", |
|
||||||
expected: "HexadecimalString must be a valid hexadecimal", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexColorString", |
|
||||||
expected: "HexColorString must be a valid HEX color", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumberString", |
|
||||||
expected: "NumberString must be a valid number", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumericString", |
|
||||||
expected: "NumericString must be a valid numeric value", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphanumString", |
|
||||||
expected: "AlphanumString can only contain alphanumeric characters", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphaString", |
|
||||||
expected: "AlphaString can only contain alphabetic characters", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtFieldString", |
|
||||||
expected: "LtFieldString must be less than MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteFieldString", |
|
||||||
expected: "LteFieldString must be less than or equal to MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtFieldString", |
|
||||||
expected: "GtFieldString must be greater than MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteFieldString", |
|
||||||
expected: "GteFieldString must be greater than or equal to MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeFieldString", |
|
||||||
expected: "NeFieldString cannot be equal to EqFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtCSFieldString", |
|
||||||
expected: "LtCSFieldString must be less than Inner.LtCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteCSFieldString", |
|
||||||
expected: "LteCSFieldString must be less than or equal to Inner.LteCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtCSFieldString", |
|
||||||
expected: "GtCSFieldString must be greater than Inner.GtCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteCSFieldString", |
|
||||||
expected: "GteCSFieldString must be greater than or equal to Inner.GteCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeCSFieldString", |
|
||||||
expected: "NeCSFieldString cannot be equal to Inner.NeCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqCSFieldString", |
|
||||||
expected: "EqCSFieldString must be equal to Inner.EqCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqFieldString", |
|
||||||
expected: "EqFieldString must be equal to MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteString", |
|
||||||
expected: "GteString must be at least 3 characters in length", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteNumber", |
|
||||||
expected: "GteNumber must be 5.56 or greater", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteMultiple", |
|
||||||
expected: "GteMultiple must contain at least 2 items", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteTime", |
|
||||||
expected: "GteTime must be greater than or equal to the current Date & Time", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtString", |
|
||||||
expected: "GtString must be greater than 3 characters in length", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtNumber", |
|
||||||
expected: "GtNumber must be greater than 5.56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtMultiple", |
|
||||||
expected: "GtMultiple must contain more than 2 items", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtTime", |
|
||||||
expected: "GtTime must be greater than the current Date & Time", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteString", |
|
||||||
expected: "LteString must be at maximum 3 characters in length", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteNumber", |
|
||||||
expected: "LteNumber must be 5.56 or less", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteMultiple", |
|
||||||
expected: "LteMultiple must contain at maximum 2 items", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteTime", |
|
||||||
expected: "LteTime must be less than or equal to the current Date & Time", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtString", |
|
||||||
expected: "LtString must be less than 3 characters in length", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtNumber", |
|
||||||
expected: "LtNumber must be less than 5.56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtMultiple", |
|
||||||
expected: "LtMultiple must contain less than 2 items", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtTime", |
|
||||||
expected: "LtTime must be less than the current Date & Time", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeString", |
|
||||||
expected: "NeString should not be equal to ", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeNumber", |
|
||||||
expected: "NeNumber should not be equal to 0.00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeMultiple", |
|
||||||
expected: "NeMultiple should not be equal to 0", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqString", |
|
||||||
expected: "EqString is not equal to 3", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqNumber", |
|
||||||
expected: "EqNumber is not equal to 2.33", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqMultiple", |
|
||||||
expected: "EqMultiple is not equal to 7", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxString", |
|
||||||
expected: "MaxString must be a maximum of 3 characters in length", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxNumber", |
|
||||||
expected: "MaxNumber must be 1,113.00 or less", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxMultiple", |
|
||||||
expected: "MaxMultiple must contain at maximum 7 items", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinString", |
|
||||||
expected: "MinString must be at least 1 character in length", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinNumber", |
|
||||||
expected: "MinNumber must be 1,113.00 or greater", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinMultiple", |
|
||||||
expected: "MinMultiple must contain at least 7 items", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenString", |
|
||||||
expected: "LenString must be 1 character in length", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenNumber", |
|
||||||
expected: "LenNumber must be equal to 1,113.00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenMultiple", |
|
||||||
expected: "LenMultiple must contain 7 items", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredString", |
|
||||||
expected: "RequiredString is a required field", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredIf", |
|
||||||
expected: "RequiredIf is a required field", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredNumber", |
|
||||||
expected: "RequiredNumber is a required field", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredMultiple", |
|
||||||
expected: "RequiredMultiple is a required field", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMinLen", |
|
||||||
expected: "StrPtrMinLen must be at least 10 characters in length", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMaxLen", |
|
||||||
expected: "StrPtrMaxLen must be a maximum of 1 character in length", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLen", |
|
||||||
expected: "StrPtrLen must be 2 characters in length", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLt", |
|
||||||
expected: "StrPtrLt must be less than 1 character in length", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLte", |
|
||||||
expected: "StrPtrLte must be at maximum 1 character in length", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGt", |
|
||||||
expected: "StrPtrGt must be greater than 10 characters in length", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGte", |
|
||||||
expected: "StrPtrGte must be at least 10 characters in length", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfString", |
|
||||||
expected: "OneOfString must be one of [red green]", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfInt", |
|
||||||
expected: "OneOfInt must be one of [5 63]", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UniqueSlice", |
|
||||||
expected: "UniqueSlice must contain unique values", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UniqueArray", |
|
||||||
expected: "UniqueArray must contain unique values", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UniqueMap", |
|
||||||
expected: "UniqueMap must contain unique values", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.JSONString", |
|
||||||
expected: "JSONString must be a valid json string", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.JWTString", |
|
||||||
expected: "JWTString must be a valid jwt string", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LowercaseString", |
|
||||||
expected: "LowercaseString must be a lowercase string", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UppercaseString", |
|
||||||
expected: "UppercaseString must be an uppercase string", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Datetime", |
|
||||||
expected: "Datetime does not match the 2006-01-02 format", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.PostCode", |
|
||||||
expected: "PostCode does not match postcode format of SG country", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.PostCodeByField", |
|
||||||
expected: "PostCodeByField does not match postcode format of country in PostCodeCountry field", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.BooleanString", |
|
||||||
expected: "BooleanString must be a valid boolean value", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CveString", |
|
||||||
expected: "CveString must be a valid cve identifier", |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
for _, tt := range tests { |
|
||||||
|
|
||||||
var fe validator.FieldError |
|
||||||
|
|
||||||
for _, e := range errs { |
|
||||||
if tt.ns == e.Namespace() { |
|
||||||
fe = e |
|
||||||
break |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
NotEqual(t, fe, nil) |
|
||||||
Equal(t, tt.expected, fe.Translate(trans)) |
|
||||||
} |
|
||||||
} |
|
File diff suppressed because it is too large
Load Diff
@ -1,658 +0,0 @@ |
|||||||
package es |
|
||||||
|
|
||||||
import ( |
|
||||||
"testing" |
|
||||||
"time" |
|
||||||
|
|
||||||
. "github.com/go-playground/assert/v2" |
|
||||||
spanish "github.com/go-playground/locales/es" |
|
||||||
ut "github.com/go-playground/universal-translator" |
|
||||||
"github.com/go-playground/validator/v10" |
|
||||||
) |
|
||||||
|
|
||||||
func TestTranslations(t *testing.T) { |
|
||||||
|
|
||||||
spa := spanish.New() |
|
||||||
uni := ut.New(spa, spa) |
|
||||||
trans, _ := uni.GetTranslator("es") |
|
||||||
|
|
||||||
validate := validator.New() |
|
||||||
|
|
||||||
err := RegisterDefaultTranslations(validate, trans) |
|
||||||
Equal(t, err, nil) |
|
||||||
|
|
||||||
type Inner struct { |
|
||||||
EqCSFieldString string |
|
||||||
NeCSFieldString string |
|
||||||
GtCSFieldString string |
|
||||||
GteCSFieldString string |
|
||||||
LtCSFieldString string |
|
||||||
LteCSFieldString string |
|
||||||
} |
|
||||||
|
|
||||||
type Test struct { |
|
||||||
Inner Inner |
|
||||||
RequiredString string `validate:"required"` |
|
||||||
RequiredNumber int `validate:"required"` |
|
||||||
RequiredMultiple []string `validate:"required"` |
|
||||||
RequiredIf string `validate:"required_if=Inner.RequiredIf abcd"` |
|
||||||
LenString string `validate:"len=1"` |
|
||||||
LenNumber float64 `validate:"len=1113.00"` |
|
||||||
LenMultiple []string `validate:"len=7"` |
|
||||||
MinString string `validate:"min=1"` |
|
||||||
MinNumber float64 `validate:"min=1113.00"` |
|
||||||
MinMultiple []string `validate:"min=7"` |
|
||||||
MaxString string `validate:"max=3"` |
|
||||||
MaxNumber float64 `validate:"max=1113.00"` |
|
||||||
MaxMultiple []string `validate:"max=7"` |
|
||||||
EqString string `validate:"eq=3"` |
|
||||||
EqNumber float64 `validate:"eq=2.33"` |
|
||||||
EqMultiple []string `validate:"eq=7"` |
|
||||||
NeString string `validate:"ne="` |
|
||||||
NeNumber float64 `validate:"ne=0.00"` |
|
||||||
NeMultiple []string `validate:"ne=0"` |
|
||||||
LtString string `validate:"lt=3"` |
|
||||||
LtNumber float64 `validate:"lt=5.56"` |
|
||||||
LtMultiple []string `validate:"lt=2"` |
|
||||||
LtTime time.Time `validate:"lt"` |
|
||||||
LteString string `validate:"lte=3"` |
|
||||||
LteNumber float64 `validate:"lte=5.56"` |
|
||||||
LteMultiple []string `validate:"lte=2"` |
|
||||||
LteTime time.Time `validate:"lte"` |
|
||||||
GtString string `validate:"gt=3"` |
|
||||||
GtNumber float64 `validate:"gt=5.56"` |
|
||||||
GtMultiple []string `validate:"gt=2"` |
|
||||||
GtTime time.Time `validate:"gt"` |
|
||||||
GteString string `validate:"gte=3"` |
|
||||||
GteNumber float64 `validate:"gte=5.56"` |
|
||||||
GteMultiple []string `validate:"gte=2"` |
|
||||||
GteTime time.Time `validate:"gte"` |
|
||||||
EqFieldString string `validate:"eqfield=MaxString"` |
|
||||||
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"` |
|
||||||
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"` |
|
||||||
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"` |
|
||||||
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"` |
|
||||||
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"` |
|
||||||
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"` |
|
||||||
NeFieldString string `validate:"nefield=EqFieldString"` |
|
||||||
GtFieldString string `validate:"gtfield=MaxString"` |
|
||||||
GteFieldString string `validate:"gtefield=MaxString"` |
|
||||||
LtFieldString string `validate:"ltfield=MaxString"` |
|
||||||
LteFieldString string `validate:"ltefield=MaxString"` |
|
||||||
AlphaString string `validate:"alpha"` |
|
||||||
AlphanumString string `validate:"alphanum"` |
|
||||||
NumericString string `validate:"numeric"` |
|
||||||
NumberString string `validate:"number"` |
|
||||||
HexadecimalString string `validate:"hexadecimal"` |
|
||||||
HexColorString string `validate:"hexcolor"` |
|
||||||
RGBColorString string `validate:"rgb"` |
|
||||||
RGBAColorString string `validate:"rgba"` |
|
||||||
HSLColorString string `validate:"hsl"` |
|
||||||
HSLAColorString string `validate:"hsla"` |
|
||||||
Email string `validate:"email"` |
|
||||||
URL string `validate:"url"` |
|
||||||
URI string `validate:"uri"` |
|
||||||
Base64 string `validate:"base64"` |
|
||||||
Contains string `validate:"contains=purpose"` |
|
||||||
ContainsAny string `validate:"containsany=!@#$"` |
|
||||||
Excludes string `validate:"excludes=text"` |
|
||||||
ExcludesAll string `validate:"excludesall=!@#$"` |
|
||||||
ExcludesRune string `validate:"excludesrune=☻"` |
|
||||||
ISBN string `validate:"isbn"` |
|
||||||
ISBN10 string `validate:"isbn10"` |
|
||||||
ISBN13 string `validate:"isbn13"` |
|
||||||
UUID string `validate:"uuid"` |
|
||||||
UUID3 string `validate:"uuid3"` |
|
||||||
UUID4 string `validate:"uuid4"` |
|
||||||
UUID5 string `validate:"uuid5"` |
|
||||||
ULID string `validate:"ulid"` |
|
||||||
ASCII string `validate:"ascii"` |
|
||||||
PrintableASCII string `validate:"printascii"` |
|
||||||
MultiByte string `validate:"multibyte"` |
|
||||||
DataURI string `validate:"datauri"` |
|
||||||
Latitude string `validate:"latitude"` |
|
||||||
Longitude string `validate:"longitude"` |
|
||||||
SSN string `validate:"ssn"` |
|
||||||
IP string `validate:"ip"` |
|
||||||
IPv4 string `validate:"ipv4"` |
|
||||||
IPv6 string `validate:"ipv6"` |
|
||||||
CIDR string `validate:"cidr"` |
|
||||||
CIDRv4 string `validate:"cidrv4"` |
|
||||||
CIDRv6 string `validate:"cidrv6"` |
|
||||||
TCPAddr string `validate:"tcp_addr"` |
|
||||||
TCPAddrv4 string `validate:"tcp4_addr"` |
|
||||||
TCPAddrv6 string `validate:"tcp6_addr"` |
|
||||||
UDPAddr string `validate:"udp_addr"` |
|
||||||
UDPAddrv4 string `validate:"udp4_addr"` |
|
||||||
UDPAddrv6 string `validate:"udp6_addr"` |
|
||||||
IPAddr string `validate:"ip_addr"` |
|
||||||
IPAddrv4 string `validate:"ip4_addr"` |
|
||||||
IPAddrv6 string `validate:"ip6_addr"` |
|
||||||
UinxAddr string `validate:"unix_addr"` // can't fail from within Go's net package currently, but maybe in the future
|
|
||||||
MAC string `validate:"mac"` |
|
||||||
IsColor string `validate:"iscolor"` |
|
||||||
StrPtrMinLen *string `validate:"min=10"` |
|
||||||
StrPtrMaxLen *string `validate:"max=1"` |
|
||||||
StrPtrLen *string `validate:"len=2"` |
|
||||||
StrPtrLt *string `validate:"lt=1"` |
|
||||||
StrPtrLte *string `validate:"lte=1"` |
|
||||||
StrPtrGt *string `validate:"gt=10"` |
|
||||||
StrPtrGte *string `validate:"gte=10"` |
|
||||||
OneOfString string `validate:"oneof=red green"` |
|
||||||
OneOfInt int `validate:"oneof=5 63"` |
|
||||||
UniqueSlice []string `validate:"unique"` |
|
||||||
UniqueArray [3]string `validate:"unique"` |
|
||||||
UniqueMap map[string]string `validate:"unique"` |
|
||||||
} |
|
||||||
|
|
||||||
var test Test |
|
||||||
|
|
||||||
test.Inner.EqCSFieldString = "1234" |
|
||||||
test.Inner.GtCSFieldString = "1234" |
|
||||||
test.Inner.GteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.MaxString = "1234" |
|
||||||
test.MaxNumber = 2000 |
|
||||||
test.MaxMultiple = make([]string, 9) |
|
||||||
|
|
||||||
test.LtString = "1234" |
|
||||||
test.LtNumber = 6 |
|
||||||
test.LtMultiple = make([]string, 3) |
|
||||||
test.LtTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LteString = "1234" |
|
||||||
test.LteNumber = 6 |
|
||||||
test.LteMultiple = make([]string, 3) |
|
||||||
test.LteTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LtFieldString = "12345" |
|
||||||
test.LteFieldString = "12345" |
|
||||||
|
|
||||||
test.LtCSFieldString = "1234" |
|
||||||
test.LteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.AlphaString = "abc3" |
|
||||||
test.AlphanumString = "abc3!" |
|
||||||
test.NumericString = "12E.00" |
|
||||||
test.NumberString = "12E" |
|
||||||
|
|
||||||
test.Excludes = "this is some test text" |
|
||||||
test.ExcludesAll = "This is Great!" |
|
||||||
test.ExcludesRune = "Love it ☻" |
|
||||||
|
|
||||||
test.ASCII = "カタカナ" |
|
||||||
test.PrintableASCII = "カタカナ" |
|
||||||
|
|
||||||
test.MultiByte = "1234feerf" |
|
||||||
|
|
||||||
s := "toolong" |
|
||||||
test.StrPtrMaxLen = &s |
|
||||||
test.StrPtrLen = &s |
|
||||||
|
|
||||||
test.UniqueSlice = []string{"1234", "1234"} |
|
||||||
test.UniqueMap = map[string]string{"key1": "1234", "key2": "1234"} |
|
||||||
|
|
||||||
err = validate.Struct(test) |
|
||||||
NotEqual(t, err, nil) |
|
||||||
|
|
||||||
errs, ok := err.(validator.ValidationErrors) |
|
||||||
Equal(t, ok, true) |
|
||||||
|
|
||||||
tests := []struct { |
|
||||||
ns string |
|
||||||
expected string |
|
||||||
}{ |
|
||||||
{ |
|
||||||
ns: "Test.IsColor", |
|
||||||
expected: "IsColor debe ser un color válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MAC", |
|
||||||
expected: "MAC debe contener una dirección MAC válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddr", |
|
||||||
expected: "IPAddr debe ser una dirección IP resoluble", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv4", |
|
||||||
expected: "IPAddrv4 debe ser una dirección IPv4 resoluble", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv6", |
|
||||||
expected: "IPAddrv6 debe ser una dirección IPv6 resoluble", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddr", |
|
||||||
expected: "UDPAddr debe ser una dirección UDP válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv4", |
|
||||||
expected: "UDPAddrv4 debe ser una dirección IPv4 UDP válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv6", |
|
||||||
expected: "UDPAddrv6 debe ser una dirección IPv6 UDP válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddr", |
|
||||||
expected: "TCPAddr debe ser una dirección TCP válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv4", |
|
||||||
expected: "TCPAddrv4 debe ser una dirección IPv4 TCP válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv6", |
|
||||||
expected: "TCPAddrv6 debe ser una dirección IPv6 TCP válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDR", |
|
||||||
expected: "CIDR debe contener una anotación válida del CIDR", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv4", |
|
||||||
expected: "CIDRv4 debe contener una notación CIDR válida para una dirección IPv4", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv6", |
|
||||||
expected: "CIDRv6 debe contener una notación CIDR válida para una dirección IPv6", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.SSN", |
|
||||||
expected: "SSN debe ser un número válido de SSN", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IP", |
|
||||||
expected: "IP debe ser una dirección IP válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv4", |
|
||||||
expected: "IPv4 debe ser una dirección IPv4 válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv6", |
|
||||||
expected: "IPv6 debe ser una dirección IPv6 válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.DataURI", |
|
||||||
expected: "DataURI debe contener un URI de datos válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Latitude", |
|
||||||
expected: "Latitude debe contener coordenadas de latitud válidas", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Longitude", |
|
||||||
expected: "Longitude debe contener unas coordenadas de longitud válidas", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MultiByte", |
|
||||||
expected: "MultiByte debe contener caracteres multibyte", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ASCII", |
|
||||||
expected: "ASCII debe contener sólo caracteres ascii", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.PrintableASCII", |
|
||||||
expected: "PrintableASCII debe contener sólo caracteres ASCII imprimibles", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID", |
|
||||||
expected: "UUID debe ser un UUID válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID3", |
|
||||||
expected: "UUID3 debe ser una versión válida 3 UUID", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID4", |
|
||||||
expected: "UUID4 debe ser una versión válida 4 UUID", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID5", |
|
||||||
expected: "UUID5 debe ser una versión válida 5 UUID", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ULID", |
|
||||||
expected: "ULID debe ser un ULID válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN", |
|
||||||
expected: "ISBN debe ser un número ISBN válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN10", |
|
||||||
expected: "ISBN10 debe ser un número ISBN-10 válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN13", |
|
||||||
expected: "ISBN13 debe ser un número ISBN-13 válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Excludes", |
|
||||||
expected: "Excludes no puede contener el texto 'text'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesAll", |
|
||||||
expected: "ExcludesAll no puede contener ninguno de los siguientes caracteres '!@#$'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesRune", |
|
||||||
expected: "ExcludesRune no puede contener lo siguiente '☻'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ContainsAny", |
|
||||||
expected: "ContainsAny debe contener al menos uno de los siguientes caracteres '!@#$'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Contains", |
|
||||||
expected: "Contains debe contener el texto 'purpose'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Base64", |
|
||||||
expected: "Base64 debe ser una cadena de Base64 válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Email", |
|
||||||
expected: "Email debe ser una dirección de correo electrónico válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URL", |
|
||||||
expected: "URL debe ser un URL válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URI", |
|
||||||
expected: "URI debe ser una URI válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBColorString", |
|
||||||
expected: "RGBColorString debe ser un color RGB válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBAColorString", |
|
||||||
expected: "RGBAColorString debe ser un color RGBA válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLColorString", |
|
||||||
expected: "HSLColorString debe ser un color HSL válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLAColorString", |
|
||||||
expected: "HSLAColorString debe ser un color HSL válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexadecimalString", |
|
||||||
expected: "HexadecimalString debe ser un hexadecimal válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexColorString", |
|
||||||
expected: "HexColorString debe ser un color HEX válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumberString", |
|
||||||
expected: "NumberString debe ser un número válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumericString", |
|
||||||
expected: "NumericString debe ser un valor numérico válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphanumString", |
|
||||||
expected: "AlphanumString sólo puede contener caracteres alfanuméricos", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphaString", |
|
||||||
expected: "AlphaString sólo puede contener caracteres alfabéticos", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtFieldString", |
|
||||||
expected: "LtFieldString debe ser menor que MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteFieldString", |
|
||||||
expected: "LteFieldString debe ser menor o igual a MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtFieldString", |
|
||||||
expected: "GtFieldString debe ser mayor que MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteFieldString", |
|
||||||
expected: "GteFieldString debe ser mayor o igual a MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeFieldString", |
|
||||||
expected: "NeFieldString no puede ser igual a EqFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtCSFieldString", |
|
||||||
expected: "LtCSFieldString debe ser menor que Inner.LtCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteCSFieldString", |
|
||||||
expected: "LteCSFieldString debe ser menor o igual a Inner.LteCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtCSFieldString", |
|
||||||
expected: "GtCSFieldString debe ser mayor que Inner.GtCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteCSFieldString", |
|
||||||
expected: "GteCSFieldString debe ser mayor o igual a Inner.GteCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeCSFieldString", |
|
||||||
expected: "NeCSFieldString no puede ser igual a Inner.NeCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqCSFieldString", |
|
||||||
expected: "EqCSFieldString debe ser igual a Inner.EqCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqFieldString", |
|
||||||
expected: "EqFieldString debe ser igual a MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteString", |
|
||||||
expected: "GteString debe tener al menos 3 caracteres de longitud", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteNumber", |
|
||||||
expected: "GteNumber debe ser 5,56 o mayor", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteMultiple", |
|
||||||
expected: "GteMultiple debe contener al menos 2 elementos", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteTime", |
|
||||||
expected: "GteTime debe ser después o durante la fecha y hora actuales", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtString", |
|
||||||
expected: "GtString debe ser mayor que 3 caracteres en longitud", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtNumber", |
|
||||||
expected: "GtNumber debe ser mayor que 5,56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtMultiple", |
|
||||||
expected: "GtMultiple debe contener más de 2 elementos", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtTime", |
|
||||||
expected: "GtTime debe ser después de la fecha y hora actual", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteString", |
|
||||||
expected: "LteString debe tener un máximo de 3 caracteres de longitud", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteNumber", |
|
||||||
expected: "LteNumber debe ser 5,56 o menos", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteMultiple", |
|
||||||
expected: "LteMultiple debe contener como máximo 2 elementos", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteTime", |
|
||||||
expected: "LteTime debe ser antes o durante la fecha y hora actual", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtString", |
|
||||||
expected: "LtString debe tener menos de 3 caracteres de longitud", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtNumber", |
|
||||||
expected: "LtNumber debe ser menos de 5,56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtMultiple", |
|
||||||
expected: "LtMultiple debe contener menos de 2 elementos", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtTime", |
|
||||||
expected: "LtTime debe ser antes de la fecha y hora actual", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeString", |
|
||||||
expected: "NeString no debería ser igual a ", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeNumber", |
|
||||||
expected: "NeNumber no debería ser igual a 0.00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeMultiple", |
|
||||||
expected: "NeMultiple no debería ser igual a 0", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqString", |
|
||||||
expected: "EqString no es igual a 3", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqNumber", |
|
||||||
expected: "EqNumber no es igual a 2.33", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqMultiple", |
|
||||||
expected: "EqMultiple no es igual a 7", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxString", |
|
||||||
expected: "MaxString debe tener un máximo de 3 caracteres de longitud", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxNumber", |
|
||||||
expected: "MaxNumber debe ser 1.113,00 o menos", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxMultiple", |
|
||||||
expected: "MaxMultiple debe contener como máximo 7 elementos", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinString", |
|
||||||
expected: "MinString debe tener al menos 1 carácter de longitud", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinNumber", |
|
||||||
expected: "MinNumber debe ser 1.113,00 o más", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinMultiple", |
|
||||||
expected: "MinMultiple debe contener al menos 7 elementos", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenString", |
|
||||||
expected: "LenString debe tener 1 carácter de longitud", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenNumber", |
|
||||||
expected: "LenNumber debe ser igual a 1.113,00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenMultiple", |
|
||||||
expected: "LenMultiple debe contener 7 elementos", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredString", |
|
||||||
expected: "RequiredString es un campo requerido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredNumber", |
|
||||||
expected: "RequiredNumber es un campo requerido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredMultiple", |
|
||||||
expected: "RequiredMultiple es un campo requerido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMinLen", |
|
||||||
expected: "StrPtrMinLen debe tener al menos 10 caracteres de longitud", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMaxLen", |
|
||||||
expected: "StrPtrMaxLen debe tener un máximo de 1 carácter de longitud", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLen", |
|
||||||
expected: "StrPtrLen debe tener 2 caracteres de longitud", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLt", |
|
||||||
expected: "StrPtrLt debe tener menos de 1 carácter de longitud", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLte", |
|
||||||
expected: "StrPtrLte debe tener un máximo de 1 carácter de longitud", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGt", |
|
||||||
expected: "StrPtrGt debe ser mayor que 10 caracteres en longitud", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGte", |
|
||||||
expected: "StrPtrGte debe tener al menos 10 caracteres de longitud", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfString", |
|
||||||
expected: "OneOfString debe ser uno de [red green]", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfInt", |
|
||||||
expected: "OneOfInt debe ser uno de [5 63]", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UniqueSlice", |
|
||||||
expected: "UniqueSlice debe contener valores únicos", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UniqueArray", |
|
||||||
expected: "UniqueArray debe contener valores únicos", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UniqueMap", |
|
||||||
expected: "UniqueMap debe contener valores únicos", |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
for _, tt := range tests { |
|
||||||
|
|
||||||
var fe validator.FieldError |
|
||||||
|
|
||||||
for _, e := range errs { |
|
||||||
if tt.ns == e.Namespace() { |
|
||||||
fe = e |
|
||||||
break |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
NotEqual(t, fe, nil) |
|
||||||
Equal(t, tt.expected, fe.Translate(trans)) |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,639 +0,0 @@ |
|||||||
package id |
|
||||||
|
|
||||||
import ( |
|
||||||
"testing" |
|
||||||
"time" |
|
||||||
|
|
||||||
. "github.com/go-playground/assert/v2" |
|
||||||
indonesia "github.com/go-playground/locales/id" |
|
||||||
ut "github.com/go-playground/universal-translator" |
|
||||||
"github.com/go-playground/validator/v10" |
|
||||||
) |
|
||||||
|
|
||||||
func TestTranslations(t *testing.T) { |
|
||||||
|
|
||||||
idn := indonesia.New() |
|
||||||
uni := ut.New(idn, idn) |
|
||||||
trans, _ := uni.GetTranslator("id") |
|
||||||
|
|
||||||
validate := validator.New() |
|
||||||
|
|
||||||
err := RegisterDefaultTranslations(validate, trans) |
|
||||||
Equal(t, err, nil) |
|
||||||
|
|
||||||
type Inner struct { |
|
||||||
EqCSFieldString string |
|
||||||
NeCSFieldString string |
|
||||||
GtCSFieldString string |
|
||||||
GteCSFieldString string |
|
||||||
LtCSFieldString string |
|
||||||
LteCSFieldString string |
|
||||||
} |
|
||||||
|
|
||||||
type Test struct { |
|
||||||
Inner Inner |
|
||||||
RequiredString string `validate:"required"` |
|
||||||
RequiredNumber int `validate:"required"` |
|
||||||
RequiredMultiple []string `validate:"required"` |
|
||||||
LenString string `validate:"len=1"` |
|
||||||
LenNumber float64 `validate:"len=1113.00"` |
|
||||||
LenMultiple []string `validate:"len=7"` |
|
||||||
MinString string `validate:"min=1"` |
|
||||||
MinNumber float64 `validate:"min=1113.00"` |
|
||||||
MinMultiple []string `validate:"min=7"` |
|
||||||
MaxString string `validate:"max=3"` |
|
||||||
MaxNumber float64 `validate:"max=1113.00"` |
|
||||||
MaxMultiple []string `validate:"max=7"` |
|
||||||
EqString string `validate:"eq=3"` |
|
||||||
EqNumber float64 `validate:"eq=2.33"` |
|
||||||
EqMultiple []string `validate:"eq=7"` |
|
||||||
NeString string `validate:"ne="` |
|
||||||
NeNumber float64 `validate:"ne=0.00"` |
|
||||||
NeMultiple []string `validate:"ne=0"` |
|
||||||
LtString string `validate:"lt=3"` |
|
||||||
LtNumber float64 `validate:"lt=5.56"` |
|
||||||
LtMultiple []string `validate:"lt=2"` |
|
||||||
LtTime time.Time `validate:"lt"` |
|
||||||
LteString string `validate:"lte=3"` |
|
||||||
LteNumber float64 `validate:"lte=5.56"` |
|
||||||
LteMultiple []string `validate:"lte=2"` |
|
||||||
LteTime time.Time `validate:"lte"` |
|
||||||
GtString string `validate:"gt=3"` |
|
||||||
GtNumber float64 `validate:"gt=5.56"` |
|
||||||
GtMultiple []string `validate:"gt=2"` |
|
||||||
GtTime time.Time `validate:"gt"` |
|
||||||
GteString string `validate:"gte=3"` |
|
||||||
GteNumber float64 `validate:"gte=5.56"` |
|
||||||
GteMultiple []string `validate:"gte=2"` |
|
||||||
GteTime time.Time `validate:"gte"` |
|
||||||
EqFieldString string `validate:"eqfield=MaxString"` |
|
||||||
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"` |
|
||||||
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"` |
|
||||||
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"` |
|
||||||
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"` |
|
||||||
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"` |
|
||||||
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"` |
|
||||||
NeFieldString string `validate:"nefield=EqFieldString"` |
|
||||||
GtFieldString string `validate:"gtfield=MaxString"` |
|
||||||
GteFieldString string `validate:"gtefield=MaxString"` |
|
||||||
LtFieldString string `validate:"ltfield=MaxString"` |
|
||||||
LteFieldString string `validate:"ltefield=MaxString"` |
|
||||||
AlphaString string `validate:"alpha"` |
|
||||||
AlphanumString string `validate:"alphanum"` |
|
||||||
NumericString string `validate:"numeric"` |
|
||||||
NumberString string `validate:"number"` |
|
||||||
HexadecimalString string `validate:"hexadecimal"` |
|
||||||
HexColorString string `validate:"hexcolor"` |
|
||||||
RGBColorString string `validate:"rgb"` |
|
||||||
RGBAColorString string `validate:"rgba"` |
|
||||||
HSLColorString string `validate:"hsl"` |
|
||||||
HSLAColorString string `validate:"hsla"` |
|
||||||
Email string `validate:"email"` |
|
||||||
URL string `validate:"url"` |
|
||||||
URI string `validate:"uri"` |
|
||||||
Base64 string `validate:"base64"` |
|
||||||
Contains string `validate:"contains=tujuan"` |
|
||||||
ContainsAny string `validate:"containsany=!@#$"` |
|
||||||
Excludes string `validate:"excludes=text"` |
|
||||||
ExcludesAll string `validate:"excludesall=!@#$"` |
|
||||||
ExcludesRune string `validate:"excludesrune=☻"` |
|
||||||
ISBN string `validate:"isbn"` |
|
||||||
ISBN10 string `validate:"isbn10"` |
|
||||||
ISBN13 string `validate:"isbn13"` |
|
||||||
UUID string `validate:"uuid"` |
|
||||||
UUID3 string `validate:"uuid3"` |
|
||||||
UUID4 string `validate:"uuid4"` |
|
||||||
UUID5 string `validate:"uuid5"` |
|
||||||
ULID string `validate:"ulid"` |
|
||||||
ASCII string `validate:"ascii"` |
|
||||||
PrintableASCII string `validate:"printascii"` |
|
||||||
MultiByte string `validate:"multibyte"` |
|
||||||
DataURI string `validate:"datauri"` |
|
||||||
Latitude string `validate:"latitude"` |
|
||||||
Longitude string `validate:"longitude"` |
|
||||||
SSN string `validate:"ssn"` |
|
||||||
IP string `validate:"ip"` |
|
||||||
IPv4 string `validate:"ipv4"` |
|
||||||
IPv6 string `validate:"ipv6"` |
|
||||||
CIDR string `validate:"cidr"` |
|
||||||
CIDRv4 string `validate:"cidrv4"` |
|
||||||
CIDRv6 string `validate:"cidrv6"` |
|
||||||
TCPAddr string `validate:"tcp_addr"` |
|
||||||
TCPAddrv4 string `validate:"tcp4_addr"` |
|
||||||
TCPAddrv6 string `validate:"tcp6_addr"` |
|
||||||
UDPAddr string `validate:"udp_addr"` |
|
||||||
UDPAddrv4 string `validate:"udp4_addr"` |
|
||||||
UDPAddrv6 string `validate:"udp6_addr"` |
|
||||||
IPAddr string `validate:"ip_addr"` |
|
||||||
IPAddrv4 string `validate:"ip4_addr"` |
|
||||||
IPAddrv6 string `validate:"ip6_addr"` |
|
||||||
UinxAddr string `validate:"unix_addr"` // can't fail from within Go's net package currently, but maybe in the future
|
|
||||||
MAC string `validate:"mac"` |
|
||||||
IsColor string `validate:"iscolor"` |
|
||||||
StrPtrMinLen *string `validate:"min=10"` |
|
||||||
StrPtrMaxLen *string `validate:"max=1"` |
|
||||||
StrPtrLen *string `validate:"len=2"` |
|
||||||
StrPtrLt *string `validate:"lt=1"` |
|
||||||
StrPtrLte *string `validate:"lte=1"` |
|
||||||
StrPtrGt *string `validate:"gt=10"` |
|
||||||
StrPtrGte *string `validate:"gte=10"` |
|
||||||
OneOfString string `validate:"oneof=merah hijau"` |
|
||||||
OneOfInt int `validate:"oneof=5 63"` |
|
||||||
} |
|
||||||
|
|
||||||
var test Test |
|
||||||
|
|
||||||
test.Inner.EqCSFieldString = "1234" |
|
||||||
test.Inner.GtCSFieldString = "1234" |
|
||||||
test.Inner.GteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.MaxString = "1234" |
|
||||||
test.MaxNumber = 2000 |
|
||||||
test.MaxMultiple = make([]string, 9) |
|
||||||
|
|
||||||
test.LtString = "1234" |
|
||||||
test.LtNumber = 6 |
|
||||||
test.LtMultiple = make([]string, 3) |
|
||||||
test.LtTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LteString = "1234" |
|
||||||
test.LteNumber = 6 |
|
||||||
test.LteMultiple = make([]string, 3) |
|
||||||
test.LteTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LtFieldString = "12345" |
|
||||||
test.LteFieldString = "12345" |
|
||||||
|
|
||||||
test.LtCSFieldString = "1234" |
|
||||||
test.LteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.AlphaString = "abc3" |
|
||||||
test.AlphanumString = "abc3!" |
|
||||||
test.NumericString = "12E.00" |
|
||||||
test.NumberString = "12E" |
|
||||||
|
|
||||||
test.Excludes = "this is some test text" |
|
||||||
test.ExcludesAll = "This is Great!" |
|
||||||
test.ExcludesRune = "Love it ☻" |
|
||||||
|
|
||||||
test.ASCII = "カタカナ" |
|
||||||
test.PrintableASCII = "カタカナ" |
|
||||||
|
|
||||||
test.MultiByte = "1234feerf" |
|
||||||
|
|
||||||
s := "toolong" |
|
||||||
test.StrPtrMaxLen = &s |
|
||||||
test.StrPtrLen = &s |
|
||||||
|
|
||||||
err = validate.Struct(test) |
|
||||||
NotEqual(t, err, nil) |
|
||||||
|
|
||||||
errs, ok := err.(validator.ValidationErrors) |
|
||||||
Equal(t, ok, true) |
|
||||||
|
|
||||||
tests := []struct { |
|
||||||
ns string |
|
||||||
expected string |
|
||||||
}{ |
|
||||||
{ |
|
||||||
ns: "Test.IsColor", |
|
||||||
expected: "IsColor harus berupa warna yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MAC", |
|
||||||
expected: "MAC harus berisi alamat MAC yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddr", |
|
||||||
expected: "IPAddr harus berupa alamat IP yang dapat dipecahkan", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv4", |
|
||||||
expected: "IPAddrv4 harus berupa alamat IPv4 yang dapat diatasi", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv6", |
|
||||||
expected: "IPAddrv6 harus berupa alamat IPv6 yang dapat diatasi", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddr", |
|
||||||
expected: "UDPAddr harus berupa alamat UDP yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv4", |
|
||||||
expected: "UDPAddrv4 harus berupa alamat IPv4 UDP yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv6", |
|
||||||
expected: "UDPAddrv6 harus berupa alamat IPv6 UDP yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddr", |
|
||||||
expected: "TCPAddr harus berupa alamat TCP yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv4", |
|
||||||
expected: "TCPAddrv4 harus berupa alamat TCP IPv4 yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv6", |
|
||||||
expected: "TCPAddrv6 harus berupa alamat TCP IPv6 yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDR", |
|
||||||
expected: "CIDR harus berisi notasi CIDR yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv4", |
|
||||||
expected: "CIDRv4 harus berisi notasi CIDR yang valid untuk alamat IPv4", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv6", |
|
||||||
expected: "CIDRv6 harus berisi notasi CIDR yang valid untuk alamat IPv6", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.SSN", |
|
||||||
expected: "SSN harus berupa nomor SSN yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IP", |
|
||||||
expected: "IP harus berupa alamat IP yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv4", |
|
||||||
expected: "IPv4 harus berupa alamat IPv4 yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv6", |
|
||||||
expected: "IPv6 harus berupa alamat IPv6 yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.DataURI", |
|
||||||
expected: "DataURI harus berisi URI Data yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Latitude", |
|
||||||
expected: "Latitude harus berisi koordinat lintang yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Longitude", |
|
||||||
expected: "Longitude harus berisi koordinat bujur yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MultiByte", |
|
||||||
expected: "MultiByte harus berisi karakter multibyte", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ASCII", |
|
||||||
expected: "ASCII hanya boleh berisi karakter ascii", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.PrintableASCII", |
|
||||||
expected: "PrintableASCII hanya boleh berisi karakter ascii yang dapat dicetak", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID", |
|
||||||
expected: "UUID harus berupa UUID yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID3", |
|
||||||
expected: "UUID3 harus berupa UUID versi 3 yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID4", |
|
||||||
expected: "UUID4 harus berupa UUID versi 4 yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID5", |
|
||||||
expected: "UUID5 harus berupa UUID versi 5 yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ULID", |
|
||||||
expected: "ULID harus berupa ULID yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN", |
|
||||||
expected: "ISBN harus berupa nomor ISBN yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN10", |
|
||||||
expected: "ISBN10 harus berupa nomor ISBN-10 yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN13", |
|
||||||
expected: "ISBN13 harus berupa nomor ISBN-13 yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Excludes", |
|
||||||
expected: "Excludes tidak boleh berisi teks 'text'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesAll", |
|
||||||
expected: "ExcludesAll tidak boleh berisi salah satu karakter berikut '!@#$'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesRune", |
|
||||||
expected: "ExcludesRune tidak boleh berisi '☻'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ContainsAny", |
|
||||||
expected: "ContainsAny harus berisi setidaknya salah satu karakter berikut '!@#$'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Contains", |
|
||||||
expected: "Contains harus berisi teks 'tujuan'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Base64", |
|
||||||
expected: "Base64 harus berupa string Base64 yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Email", |
|
||||||
expected: "Email harus berupa alamat email yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URL", |
|
||||||
expected: "URL harus berupa URL yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URI", |
|
||||||
expected: "URI harus berupa URI yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBColorString", |
|
||||||
expected: "RGBColorString harus berupa warna RGB yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBAColorString", |
|
||||||
expected: "RGBAColorString harus berupa warna RGBA yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLColorString", |
|
||||||
expected: "HSLColorString harus berupa warna HSL yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLAColorString", |
|
||||||
expected: "HSLAColorString harus berupa warna HSLA yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexadecimalString", |
|
||||||
expected: "HexadecimalString harus berupa heksadesimal yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexColorString", |
|
||||||
expected: "HexColorString harus berupa warna HEX yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumberString", |
|
||||||
expected: "NumberString harus berupa angka yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumericString", |
|
||||||
expected: "NumericString harus berupa nilai numerik yang valid", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphanumString", |
|
||||||
expected: "AlphanumString hanya dapat berisi karakter alfanumerik", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphaString", |
|
||||||
expected: "AlphaString hanya dapat berisi karakter abjad", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtFieldString", |
|
||||||
expected: "LtFieldString harus kurang dari MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteFieldString", |
|
||||||
expected: "LteFieldString harus kurang dari atau sama dengan MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtFieldString", |
|
||||||
expected: "GtFieldString harus lebih besar dari MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteFieldString", |
|
||||||
expected: "GteFieldString harus lebih besar dari atau sama dengan MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeFieldString", |
|
||||||
expected: "NeFieldString tidak sama dengan EqFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtCSFieldString", |
|
||||||
expected: "LtCSFieldString harus kurang dari Inner.LtCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteCSFieldString", |
|
||||||
expected: "LteCSFieldString harus kurang dari atau sama dengan Inner.LteCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtCSFieldString", |
|
||||||
expected: "GtCSFieldString harus lebih besar dari Inner.GtCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteCSFieldString", |
|
||||||
expected: "GteCSFieldString harus lebih besar dari atau sama dengan Inner.GteCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeCSFieldString", |
|
||||||
expected: "NeCSFieldString tidak sama dengan Inner.NeCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqCSFieldString", |
|
||||||
expected: "EqCSFieldString harus sama dengan Inner.EqCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqFieldString", |
|
||||||
expected: "EqFieldString harus sama dengan MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteString", |
|
||||||
expected: "panjang minimal GteString adalah 3 karakter", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteNumber", |
|
||||||
expected: "GteNumber harus 5,56 atau lebih besar", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteMultiple", |
|
||||||
expected: "GteMultiple harus berisi setidaknya 2 item", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteTime", |
|
||||||
expected: "GteTime harus lebih besar dari atau sama dengan tanggal & waktu saat ini", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtString", |
|
||||||
expected: "panjang GtString harus lebih dari 3 karakter", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtNumber", |
|
||||||
expected: "GtNumber harus lebih besar dari 5,56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtMultiple", |
|
||||||
expected: "GtMultiple harus berisi lebih dari 2 item", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtTime", |
|
||||||
expected: "GtTime harus lebih besar dari tanggal & waktu saat ini", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteString", |
|
||||||
expected: "panjang maksimal LteString adalah 3 karakter", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteNumber", |
|
||||||
expected: "LteNumber harus 5,56 atau kurang", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteMultiple", |
|
||||||
expected: "LteMultiple harus berisi maksimal 2 item", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteTime", |
|
||||||
expected: "LteTime harus kurang dari atau sama dengan tanggal & waktu saat ini", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtString", |
|
||||||
expected: "panjang LtString harus kurang dari 3 karakter", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtNumber", |
|
||||||
expected: "LtNumber harus kurang dari 5,56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtMultiple", |
|
||||||
expected: "LtMultiple harus berisi kurang dari 2 item", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtTime", |
|
||||||
expected: "LtTime harus kurang dari tanggal & waktu saat ini", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeString", |
|
||||||
expected: "NeString tidak sama dengan ", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeNumber", |
|
||||||
expected: "NeNumber tidak sama dengan 0.00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeMultiple", |
|
||||||
expected: "NeMultiple tidak sama dengan 0", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqString", |
|
||||||
expected: "EqString tidak sama dengan 3", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqNumber", |
|
||||||
expected: "EqNumber tidak sama dengan 2.33", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqMultiple", |
|
||||||
expected: "EqMultiple tidak sama dengan 7", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxString", |
|
||||||
expected: "panjang maksimal MaxString adalah 3 karakter", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxNumber", |
|
||||||
expected: "MaxNumber harus 1.113,00 atau kurang", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxMultiple", |
|
||||||
expected: "MaxMultiple harus berisi maksimal 7 item", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinString", |
|
||||||
expected: "panjang minimal MinString adalah 1 karakter", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinNumber", |
|
||||||
expected: "MinNumber harus 1.113,00 atau lebih besar", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinMultiple", |
|
||||||
expected: "panjang minimal MinMultiple adalah 7 item", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenString", |
|
||||||
expected: "panjang LenString harus 1 karakter", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenNumber", |
|
||||||
expected: "LenNumber harus sama dengan 1.113,00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenMultiple", |
|
||||||
expected: "LenMultiple harus berisi 7 item", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredString", |
|
||||||
expected: "RequiredString wajib diisi", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredNumber", |
|
||||||
expected: "RequiredNumber wajib diisi", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredMultiple", |
|
||||||
expected: "RequiredMultiple wajib diisi", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMinLen", |
|
||||||
expected: "panjang minimal StrPtrMinLen adalah 10 karakter", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMaxLen", |
|
||||||
expected: "panjang maksimal StrPtrMaxLen adalah 1 karakter", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLen", |
|
||||||
expected: "panjang StrPtrLen harus 2 karakter", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLt", |
|
||||||
expected: "panjang StrPtrLt harus kurang dari 1 karakter", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLte", |
|
||||||
expected: "panjang maksimal StrPtrLte adalah 1 karakter", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGt", |
|
||||||
expected: "panjang StrPtrGt harus lebih dari 10 karakter", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGte", |
|
||||||
expected: "panjang minimal StrPtrGte adalah 10 karakter", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfString", |
|
||||||
expected: "OneOfString harus berupa salah satu dari [merah hijau]", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfInt", |
|
||||||
expected: "OneOfInt harus berupa salah satu dari [5 63]", |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
for _, tt := range tests { |
|
||||||
|
|
||||||
var fe validator.FieldError |
|
||||||
|
|
||||||
for _, e := range errs { |
|
||||||
if tt.ns == e.Namespace() { |
|
||||||
fe = e |
|
||||||
break |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
NotEqual(t, fe, nil) |
|
||||||
Equal(t, tt.expected, fe.Translate(trans)) |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
File diff suppressed because it is too large
Load Diff
@ -1,725 +0,0 @@ |
|||||||
package it |
|
||||||
|
|
||||||
import ( |
|
||||||
"testing" |
|
||||||
"time" |
|
||||||
|
|
||||||
. "github.com/go-playground/assert/v2" |
|
||||||
italian "github.com/go-playground/locales/it" |
|
||||||
ut "github.com/go-playground/universal-translator" |
|
||||||
"github.com/go-playground/validator/v10" |
|
||||||
) |
|
||||||
|
|
||||||
func TestTranslations(t *testing.T) { |
|
||||||
ita := italian.New() |
|
||||||
uni := ut.New(ita, ita) |
|
||||||
trans, _ := uni.GetTranslator("it") |
|
||||||
|
|
||||||
validate := validator.New() |
|
||||||
|
|
||||||
err := RegisterDefaultTranslations(validate, trans) |
|
||||||
Equal(t, err, nil) |
|
||||||
|
|
||||||
type Inner struct { |
|
||||||
EqCSFieldString string |
|
||||||
NeCSFieldString string |
|
||||||
GtCSFieldString string |
|
||||||
GteCSFieldString string |
|
||||||
LtCSFieldString string |
|
||||||
LteCSFieldString string |
|
||||||
} |
|
||||||
|
|
||||||
type Test struct { |
|
||||||
Inner Inner |
|
||||||
RequiredString string `validate:"required"` |
|
||||||
RequiredNumber int `validate:"required"` |
|
||||||
RequiredMultiple []string `validate:"required"` |
|
||||||
LenString string `validate:"len=1"` |
|
||||||
LenNumber float64 `validate:"len=1113.00"` |
|
||||||
LenMultiple []string `validate:"len=7"` |
|
||||||
MinString string `validate:"min=1"` |
|
||||||
MinNumber float64 `validate:"min=1113.00"` |
|
||||||
MinMultiple []string `validate:"min=7"` |
|
||||||
MaxString string `validate:"max=3"` |
|
||||||
MaxNumber float64 `validate:"max=1113.00"` |
|
||||||
MaxMultiple []string `validate:"max=7"` |
|
||||||
EqString string `validate:"eq=3"` |
|
||||||
EqNumber float64 `validate:"eq=2.33"` |
|
||||||
EqMultiple []string `validate:"eq=7"` |
|
||||||
NeString string `validate:"ne="` |
|
||||||
NeNumber float64 `validate:"ne=0.00"` |
|
||||||
NeMultiple []string `validate:"ne=0"` |
|
||||||
LtString string `validate:"lt=3"` |
|
||||||
LtNumber float64 `validate:"lt=5.56"` |
|
||||||
LtMultiple []string `validate:"lt=2"` |
|
||||||
LtTime time.Time `validate:"lt"` |
|
||||||
LteString string `validate:"lte=3"` |
|
||||||
LteNumber float64 `validate:"lte=5.56"` |
|
||||||
LteMultiple []string `validate:"lte=2"` |
|
||||||
LteTime time.Time `validate:"lte"` |
|
||||||
GtString string `validate:"gt=3"` |
|
||||||
GtNumber float64 `validate:"gt=5.56"` |
|
||||||
GtMultiple []string `validate:"gt=2"` |
|
||||||
GtTime time.Time `validate:"gt"` |
|
||||||
GteString string `validate:"gte=3"` |
|
||||||
GteNumber float64 `validate:"gte=5.56"` |
|
||||||
GteMultiple []string `validate:"gte=2"` |
|
||||||
GteTime time.Time `validate:"gte"` |
|
||||||
EqFieldString string `validate:"eqfield=MaxString"` |
|
||||||
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"` |
|
||||||
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"` |
|
||||||
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"` |
|
||||||
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"` |
|
||||||
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"` |
|
||||||
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"` |
|
||||||
NeFieldString string `validate:"nefield=EqFieldString"` |
|
||||||
GtFieldString string `validate:"gtfield=MaxString"` |
|
||||||
GteFieldString string `validate:"gtefield=MaxString"` |
|
||||||
LtFieldString string `validate:"ltfield=MaxString"` |
|
||||||
LteFieldString string `validate:"ltefield=MaxString"` |
|
||||||
AlphaString string `validate:"alpha"` |
|
||||||
AlphanumString string `validate:"alphanum"` |
|
||||||
NumericString string `validate:"numeric"` |
|
||||||
NumberString string `validate:"number"` |
|
||||||
HexadecimalString string `validate:"hexadecimal"` |
|
||||||
HexColorString string `validate:"hexcolor"` |
|
||||||
RGBColorString string `validate:"rgb"` |
|
||||||
RGBAColorString string `validate:"rgba"` |
|
||||||
HSLColorString string `validate:"hsl"` |
|
||||||
HSLAColorString string `validate:"hsla"` |
|
||||||
Email string `validate:"email"` |
|
||||||
URL string `validate:"url"` |
|
||||||
URI string `validate:"uri"` |
|
||||||
Base64 string `validate:"base64"` |
|
||||||
Contains string `validate:"contains=purpose"` |
|
||||||
ContainsAny string `validate:"containsany=!@#$"` |
|
||||||
Excludes string `validate:"excludes=text"` |
|
||||||
ExcludesAll string `validate:"excludesall=!@#$"` |
|
||||||
ExcludesRune string `validate:"excludesrune=☻"` |
|
||||||
ISBN string `validate:"isbn"` |
|
||||||
ISBN10 string `validate:"isbn10"` |
|
||||||
ISBN13 string `validate:"isbn13"` |
|
||||||
UUID string `validate:"uuid"` |
|
||||||
UUID3 string `validate:"uuid3"` |
|
||||||
UUID4 string `validate:"uuid4"` |
|
||||||
UUID5 string `validate:"uuid5"` |
|
||||||
ULID string `validate:"ulid"` |
|
||||||
ASCII string `validate:"ascii"` |
|
||||||
PrintableASCII string `validate:"printascii"` |
|
||||||
MultiByte string `validate:"multibyte"` |
|
||||||
DataURI string `validate:"datauri"` |
|
||||||
Latitude string `validate:"latitude"` |
|
||||||
Longitude string `validate:"longitude"` |
|
||||||
SSN string `validate:"ssn"` |
|
||||||
IP string `validate:"ip"` |
|
||||||
IPv4 string `validate:"ipv4"` |
|
||||||
IPv6 string `validate:"ipv6"` |
|
||||||
CIDR string `validate:"cidr"` |
|
||||||
CIDRv4 string `validate:"cidrv4"` |
|
||||||
CIDRv6 string `validate:"cidrv6"` |
|
||||||
TCPAddr string `validate:"tcp_addr"` |
|
||||||
TCPAddrv4 string `validate:"tcp4_addr"` |
|
||||||
TCPAddrv6 string `validate:"tcp6_addr"` |
|
||||||
UDPAddr string `validate:"udp_addr"` |
|
||||||
UDPAddrv4 string `validate:"udp4_addr"` |
|
||||||
UDPAddrv6 string `validate:"udp6_addr"` |
|
||||||
IPAddr string `validate:"ip_addr"` |
|
||||||
IPAddrv4 string `validate:"ip4_addr"` |
|
||||||
IPAddrv6 string `validate:"ip6_addr"` |
|
||||||
UinxAddr string `validate:"unix_addr"` // can't fail from within Go's net package currently, but maybe in the future
|
|
||||||
MAC string `validate:"mac"` |
|
||||||
IsColor string `validate:"iscolor"` |
|
||||||
StrPtrMinLen *string `validate:"min=10"` |
|
||||||
StrPtrMaxLen *string `validate:"max=1"` |
|
||||||
StrPtrLen *string `validate:"len=2"` |
|
||||||
StrPtrLt *string `validate:"lt=1"` |
|
||||||
StrPtrLte *string `validate:"lte=1"` |
|
||||||
StrPtrGt *string `validate:"gt=10"` |
|
||||||
StrPtrGte *string `validate:"gte=10"` |
|
||||||
OneOfString string `validate:"oneof=red green"` |
|
||||||
OneOfInt int `validate:"oneof=5 63"` |
|
||||||
UniqueSlice []string `validate:"unique"` |
|
||||||
UniqueArray [3]string `validate:"unique"` |
|
||||||
UniqueMap map[string]string `validate:"unique"` |
|
||||||
BooleanString string `validate:"boolean"` |
|
||||||
JSONString string `validate:"json"` |
|
||||||
JWTString string `validate:"jwt"` |
|
||||||
LowercaseString string `validate:"lowercase"` |
|
||||||
UppercaseString string `validate:"uppercase"` |
|
||||||
StartsWithString string `validate:"startswith=foo"` |
|
||||||
StartsNotWithString string `validate:"startsnotwith=foo"` |
|
||||||
EndsWithString string `validate:"endswith=foo"` |
|
||||||
EndsNotWithString string `validate:"endsnotwith=foo"` |
|
||||||
Datetime string `validate:"datetime=2006-01-02"` |
|
||||||
PostCode string `validate:"postcode_iso3166_alpha2=SG"` |
|
||||||
PostCodeCountry string |
|
||||||
PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"` |
|
||||||
} |
|
||||||
|
|
||||||
var test Test |
|
||||||
|
|
||||||
test.Inner.EqCSFieldString = "1234" |
|
||||||
test.Inner.GtCSFieldString = "1234" |
|
||||||
test.Inner.GteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.MaxString = "1234" |
|
||||||
test.MaxNumber = 2000 |
|
||||||
test.MaxMultiple = make([]string, 9) |
|
||||||
|
|
||||||
test.LtString = "1234" |
|
||||||
test.LtNumber = 6 |
|
||||||
test.LtMultiple = make([]string, 3) |
|
||||||
test.LtTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LteString = "1234" |
|
||||||
test.LteNumber = 6 |
|
||||||
test.LteMultiple = make([]string, 3) |
|
||||||
test.LteTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LtFieldString = "12345" |
|
||||||
test.LteFieldString = "12345" |
|
||||||
|
|
||||||
test.LtCSFieldString = "1234" |
|
||||||
test.LteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.AlphaString = "abc3" |
|
||||||
test.AlphanumString = "abc3!" |
|
||||||
test.NumericString = "12E.00" |
|
||||||
test.NumberString = "12E" |
|
||||||
|
|
||||||
test.Excludes = "this is some test text" |
|
||||||
test.ExcludesAll = "This is Great!" |
|
||||||
test.ExcludesRune = "Love it ☻" |
|
||||||
|
|
||||||
test.ASCII = "カタカナ" |
|
||||||
test.PrintableASCII = "カタカナ" |
|
||||||
|
|
||||||
test.MultiByte = "1234feerf" |
|
||||||
|
|
||||||
test.LowercaseString = "ABCDEFG" |
|
||||||
test.UppercaseString = "abcdefg" |
|
||||||
|
|
||||||
test.StartsWithString = "hello" |
|
||||||
test.StartsNotWithString = "foo-hello" |
|
||||||
test.EndsWithString = "hello" |
|
||||||
test.EndsNotWithString = "hello-foo" |
|
||||||
|
|
||||||
s := "toolong" |
|
||||||
test.StrPtrMaxLen = &s |
|
||||||
test.StrPtrLen = &s |
|
||||||
|
|
||||||
test.UniqueSlice = []string{"1234", "1234"} |
|
||||||
test.UniqueMap = map[string]string{"key1": "1234", "key2": "1234"} |
|
||||||
test.Datetime = "2008-Feb-01" |
|
||||||
|
|
||||||
err = validate.Struct(test) |
|
||||||
NotEqual(t, err, nil) |
|
||||||
|
|
||||||
errs, ok := err.(validator.ValidationErrors) |
|
||||||
Equal(t, ok, true) |
|
||||||
|
|
||||||
tests := []struct { |
|
||||||
ns string |
|
||||||
expected string |
|
||||||
}{ |
|
||||||
{ |
|
||||||
ns: "Test.IsColor", |
|
||||||
expected: "IsColor deve essere un colore valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MAC", |
|
||||||
expected: "MAC deve contenere un indirizzo MAC valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddr", |
|
||||||
expected: "IPAddr deve essere un indirizzo IP risolvibile", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv4", |
|
||||||
expected: "IPAddrv4 deve essere un indirizzo IPv4 risolvibile", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv6", |
|
||||||
expected: "IPAddrv6 deve essere un indirizzo IPv6 risolvibile", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddr", |
|
||||||
expected: "UDPAddr deve essere un indirizzo UDP valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv4", |
|
||||||
expected: "UDPAddrv4 deve essere un indirizzo IPv4 UDP valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv6", |
|
||||||
expected: "UDPAddrv6 deve essere un indirizzo IPv6 UDP valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddr", |
|
||||||
expected: "TCPAddr deve essere un indirizzo TCP valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv4", |
|
||||||
expected: "TCPAddrv4 deve essere un indirizzo IPv4 TCP valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv6", |
|
||||||
expected: "TCPAddrv6 deve essere un indirizzo IPv6 TCP valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDR", |
|
||||||
expected: "CIDR deve contenere una notazione CIDR valida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv4", |
|
||||||
expected: "CIDRv4 deve contenere una notazione CIDR per un indirizzo IPv4 valida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv6", |
|
||||||
expected: "CIDRv6 deve contenere una notazione CIDR per un indirizzo IPv6 valida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.SSN", |
|
||||||
expected: "SSN deve essere un numero SSN valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IP", |
|
||||||
expected: "IP deve essere un indirizzo IP valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv4", |
|
||||||
expected: "IPv4 deve essere un indirizzo IPv4 valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv6", |
|
||||||
expected: "IPv6 deve essere un indirizzo IPv6 valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.DataURI", |
|
||||||
expected: "DataURI deve contenere un Data URI valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Latitude", |
|
||||||
expected: "Latitude deve contenere una latitudine valida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Longitude", |
|
||||||
expected: "Longitude deve contenere una longitudine valida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MultiByte", |
|
||||||
expected: "MultiByte deve contenere caratteri multibyte", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ASCII", |
|
||||||
expected: "ASCII deve contenere solo caratteri ascii", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.PrintableASCII", |
|
||||||
expected: "PrintableASCII deve contenere solo caratteri ascii stampabili", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID", |
|
||||||
expected: "UUID deve essere un UUID valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID3", |
|
||||||
expected: "UUID3 deve essere un UUID versione 3 valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID4", |
|
||||||
expected: "UUID4 deve essere un UUID versione 4 valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID5", |
|
||||||
expected: "UUID5 deve essere un UUID versione 5 valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ULID", |
|
||||||
expected: "ULID deve essere un ULID valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN", |
|
||||||
expected: "ISBN deve essere un numero ISBN valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN10", |
|
||||||
expected: "ISBN10 deve essere un numero ISBN-10 valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN13", |
|
||||||
expected: "ISBN13 deve essere un numero ISBN-13 valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Excludes", |
|
||||||
expected: "Excludes non deve contenere il testo 'text'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesAll", |
|
||||||
expected: "ExcludesAll non deve contenere alcuno dei seguenti caratteri '!@#$'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesRune", |
|
||||||
expected: "ExcludesRune non deve contenere '☻'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ContainsAny", |
|
||||||
expected: "ContainsAny deve contenere almeno uno dei seguenti caratteri '!@#$'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Contains", |
|
||||||
expected: "Contains deve contenere il testo 'purpose'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Base64", |
|
||||||
expected: "Base64 deve essere una stringa Base64 valida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Email", |
|
||||||
expected: "Email deve essere un indirizzo email valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URL", |
|
||||||
expected: "URL deve essere un URL valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URI", |
|
||||||
expected: "URI deve essere un URI valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBColorString", |
|
||||||
expected: "RGBColorString deve essere un colore RGB valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBAColorString", |
|
||||||
expected: "RGBAColorString deve essere un colore RGBA valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLColorString", |
|
||||||
expected: "HSLColorString deve essere un colore HSL valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLAColorString", |
|
||||||
expected: "HSLAColorString deve essere un colore HSLA valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexadecimalString", |
|
||||||
expected: "HexadecimalString deve essere un esadecimale valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexColorString", |
|
||||||
expected: "HexColorString deve essere un colore HEX valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumberString", |
|
||||||
expected: "NumberString deve essere un numero valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumericString", |
|
||||||
expected: "NumericString deve essere un valore numerico valido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphanumString", |
|
||||||
expected: "AlphanumString può contenere solo caratteri alfanumerici", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphaString", |
|
||||||
expected: "AlphaString può contenere solo caratteri alfabetici", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtFieldString", |
|
||||||
expected: "LtFieldString deve essere minore di MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteFieldString", |
|
||||||
expected: "LteFieldString deve essere minore o uguale a MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtFieldString", |
|
||||||
expected: "GtFieldString deve essere maggiore di MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteFieldString", |
|
||||||
expected: "GteFieldString deve essere maggiore o uguale a MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeFieldString", |
|
||||||
expected: "NeFieldString deve essere diverso da EqFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtCSFieldString", |
|
||||||
expected: "LtCSFieldString deve essere minore di Inner.LtCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteCSFieldString", |
|
||||||
expected: "LteCSFieldString deve essere minore o uguale a Inner.LteCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtCSFieldString", |
|
||||||
expected: "GtCSFieldString deve essere maggiore di Inner.GtCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteCSFieldString", |
|
||||||
expected: "GteCSFieldString deve essere maggiore o uguale a Inner.GteCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeCSFieldString", |
|
||||||
expected: "NeCSFieldString deve essere diverso da Inner.NeCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqCSFieldString", |
|
||||||
expected: "EqCSFieldString deve essere uguale a Inner.EqCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqFieldString", |
|
||||||
expected: "EqFieldString deve essere uguale a MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteString", |
|
||||||
expected: "GteString deve essere lungo almeno 3 caratteri", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteNumber", |
|
||||||
expected: "GteNumber deve essere maggiore o uguale a 5,56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteMultiple", |
|
||||||
expected: "GteMultiple deve contenere almeno 2 elementi", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteTime", |
|
||||||
expected: "GteTime deve essere uguale o successivo alla Data/Ora corrente", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtString", |
|
||||||
expected: "GtString deve essere lungo più di 3 caratteri", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtNumber", |
|
||||||
expected: "GtNumber deve essere maggiore di 5,56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtMultiple", |
|
||||||
expected: "GtMultiple deve contenere più di 2 elementi", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtTime", |
|
||||||
expected: "GtTime deve essere successivo alla Data/Ora corrente", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteString", |
|
||||||
expected: "LteString deve essere lungo al massimo 3 caratteri", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteNumber", |
|
||||||
expected: "LteNumber deve essere minore o uguale a 5,56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteMultiple", |
|
||||||
expected: "LteMultiple deve contenere al massimo 2 elementi", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteTime", |
|
||||||
expected: "LteTime deve essere uguale o precedente alla Data/Ora corrente", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtString", |
|
||||||
expected: "LtString deve essere lungo meno di 3 caratteri", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtNumber", |
|
||||||
expected: "LtNumber deve essere minore di 5,56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtMultiple", |
|
||||||
expected: "LtMultiple deve contenere meno di 2 elementi", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtTime", |
|
||||||
expected: "LtTime deve essere precedente alla Data/Ora corrente", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeString", |
|
||||||
expected: "NeString deve essere diverso da ", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeNumber", |
|
||||||
expected: "NeNumber deve essere diverso da 0.00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeMultiple", |
|
||||||
expected: "NeMultiple deve essere diverso da 0", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqString", |
|
||||||
expected: "EqString non è uguale a 3", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqNumber", |
|
||||||
expected: "EqNumber non è uguale a 2.33", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqMultiple", |
|
||||||
expected: "EqMultiple non è uguale a 7", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxString", |
|
||||||
expected: "MaxString deve essere lungo al massimo 3 caratteri", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxNumber", |
|
||||||
expected: "MaxNumber deve essere minore o uguale a 1.113,00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxMultiple", |
|
||||||
expected: "MaxMultiple deve contenere al massimo 7 elementi", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinString", |
|
||||||
expected: "MinString deve essere lungo almeno 1 carattere", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinNumber", |
|
||||||
expected: "MinNumber deve essere maggiore o uguale a 1.113,00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinMultiple", |
|
||||||
expected: "MinMultiple deve contenere almeno 7 elementi", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenString", |
|
||||||
expected: "LenString deve essere lungo 1 carattere", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenNumber", |
|
||||||
expected: "LenNumber deve essere uguale a 1.113,00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenMultiple", |
|
||||||
expected: "LenMultiple deve contenere 7 elementi", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredString", |
|
||||||
expected: "RequiredString è un campo obbligatorio", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredNumber", |
|
||||||
expected: "RequiredNumber è un campo obbligatorio", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredMultiple", |
|
||||||
expected: "RequiredMultiple è un campo obbligatorio", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMinLen", |
|
||||||
expected: "StrPtrMinLen deve essere lungo almeno 10 caratteri", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMaxLen", |
|
||||||
expected: "StrPtrMaxLen deve essere lungo al massimo 1 carattere", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLen", |
|
||||||
expected: "StrPtrLen deve essere lungo 2 caratteri", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLt", |
|
||||||
expected: "StrPtrLt deve essere lungo meno di 1 carattere", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLte", |
|
||||||
expected: "StrPtrLte deve essere lungo al massimo 1 carattere", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGt", |
|
||||||
expected: "StrPtrGt deve essere lungo più di 10 caratteri", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGte", |
|
||||||
expected: "StrPtrGte deve essere lungo almeno 10 caratteri", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfString", |
|
||||||
expected: "OneOfString deve essere uno di [red green]", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfInt", |
|
||||||
expected: "OneOfInt deve essere uno di [5 63]", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UniqueSlice", |
|
||||||
expected: "UniqueSlice deve contenere valori unici", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UniqueArray", |
|
||||||
expected: "UniqueArray deve contenere valori unici", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UniqueMap", |
|
||||||
expected: "UniqueMap deve contenere valori unici", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.BooleanString", |
|
||||||
expected: "BooleanString deve rappresentare un valore booleano", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.JSONString", |
|
||||||
expected: "JSONString deve essere una stringa json valida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.JWTString", |
|
||||||
expected: "JWTString deve essere una stringa jwt valida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LowercaseString", |
|
||||||
expected: "LowercaseString deve essere una stringa minuscola", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UppercaseString", |
|
||||||
expected: "UppercaseString deve essere una stringa maiuscola", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StartsWithString", |
|
||||||
expected: "StartsWithString deve iniziare con foo", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StartsNotWithString", |
|
||||||
expected: "StartsNotWithString non deve iniziare con foo", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EndsWithString", |
|
||||||
expected: "EndsWithString deve terminare con foo", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EndsNotWithString", |
|
||||||
expected: "EndsNotWithString non deve terminare con foo", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Datetime", |
|
||||||
expected: "Datetime non corrisponde al formato 2006-01-02", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.PostCode", |
|
||||||
expected: "PostCode non corrisponde al formato del codice postale dello stato SG", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.PostCodeByField", |
|
||||||
expected: "PostCodeByField non corrisponde al formato del codice postale dello stato nel campo PostCodeCountry", |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
for _, tt := range tests { |
|
||||||
|
|
||||||
var fe validator.FieldError |
|
||||||
|
|
||||||
for _, e := range errs { |
|
||||||
if tt.ns == e.Namespace() { |
|
||||||
fe = e |
|
||||||
break |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
NotEqual(t, fe, nil) |
|
||||||
Equal(t, tt.expected, fe.Translate(trans)) |
|
||||||
} |
|
||||||
} |
|
File diff suppressed because it is too large
Load Diff
@ -1,710 +0,0 @@ |
|||||||
package ja |
|
||||||
|
|
||||||
import ( |
|
||||||
"testing" |
|
||||||
"time" |
|
||||||
|
|
||||||
. "github.com/go-playground/assert/v2" |
|
||||||
ja_locale "github.com/go-playground/locales/ja" |
|
||||||
ut "github.com/go-playground/universal-translator" |
|
||||||
"github.com/go-playground/validator/v10" |
|
||||||
) |
|
||||||
|
|
||||||
func TestTranslations(t *testing.T) { |
|
||||||
japanese := ja_locale.New() |
|
||||||
uni := ut.New(japanese, japanese) |
|
||||||
trans, _ := uni.GetTranslator("ja") |
|
||||||
|
|
||||||
validate := validator.New() |
|
||||||
|
|
||||||
err := RegisterDefaultTranslations(validate, trans) |
|
||||||
Equal(t, err, nil) |
|
||||||
|
|
||||||
type Inner struct { |
|
||||||
EqCSFieldString string |
|
||||||
NeCSFieldString string |
|
||||||
GtCSFieldString string |
|
||||||
GteCSFieldString string |
|
||||||
LtCSFieldString string |
|
||||||
LteCSFieldString string |
|
||||||
RequiredIf string |
|
||||||
} |
|
||||||
|
|
||||||
type Test struct { |
|
||||||
Inner Inner |
|
||||||
RequiredString string `validate:"required"` |
|
||||||
RequiredNumber int `validate:"required"` |
|
||||||
RequiredMultiple []string `validate:"required"` |
|
||||||
RequiredIf string `validate:"required_if=Inner.RequiredIf abcd"` |
|
||||||
LenString string `validate:"len=1"` |
|
||||||
LenNumber float64 `validate:"len=1113.00"` |
|
||||||
LenMultiple []string `validate:"len=7"` |
|
||||||
MinString string `validate:"min=1"` |
|
||||||
MinNumber float64 `validate:"min=1113.00"` |
|
||||||
MinMultiple []string `validate:"min=7"` |
|
||||||
MaxString string `validate:"max=3"` |
|
||||||
MaxNumber float64 `validate:"max=1113.00"` |
|
||||||
MaxMultiple []string `validate:"max=7"` |
|
||||||
EqString string `validate:"eq=3"` |
|
||||||
EqNumber float64 `validate:"eq=2.33"` |
|
||||||
EqMultiple []string `validate:"eq=7"` |
|
||||||
NeString string `validate:"ne="` |
|
||||||
NeNumber float64 `validate:"ne=0.00"` |
|
||||||
NeMultiple []string `validate:"ne=0"` |
|
||||||
LtString string `validate:"lt=3"` |
|
||||||
LtNumber float64 `validate:"lt=5.56"` |
|
||||||
LtMultiple []string `validate:"lt=2"` |
|
||||||
LtTime time.Time `validate:"lt"` |
|
||||||
LteString string `validate:"lte=3"` |
|
||||||
LteNumber float64 `validate:"lte=5.56"` |
|
||||||
LteMultiple []string `validate:"lte=2"` |
|
||||||
LteTime time.Time `validate:"lte"` |
|
||||||
GtString string `validate:"gt=3"` |
|
||||||
GtNumber float64 `validate:"gt=5.56"` |
|
||||||
GtMultiple []string `validate:"gt=2"` |
|
||||||
GtTime time.Time `validate:"gt"` |
|
||||||
GteString string `validate:"gte=3"` |
|
||||||
GteNumber float64 `validate:"gte=5.56"` |
|
||||||
GteMultiple []string `validate:"gte=2"` |
|
||||||
GteTime time.Time `validate:"gte"` |
|
||||||
EqFieldString string `validate:"eqfield=MaxString"` |
|
||||||
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"` |
|
||||||
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"` |
|
||||||
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"` |
|
||||||
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"` |
|
||||||
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"` |
|
||||||
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"` |
|
||||||
NeFieldString string `validate:"nefield=EqFieldString"` |
|
||||||
GtFieldString string `validate:"gtfield=MaxString"` |
|
||||||
GteFieldString string `validate:"gtefield=MaxString"` |
|
||||||
LtFieldString string `validate:"ltfield=MaxString"` |
|
||||||
LteFieldString string `validate:"ltefield=MaxString"` |
|
||||||
AlphaString string `validate:"alpha"` |
|
||||||
AlphanumString string `validate:"alphanum"` |
|
||||||
NumericString string `validate:"numeric"` |
|
||||||
NumberString string `validate:"number"` |
|
||||||
HexadecimalString string `validate:"hexadecimal"` |
|
||||||
HexColorString string `validate:"hexcolor"` |
|
||||||
RGBColorString string `validate:"rgb"` |
|
||||||
RGBAColorString string `validate:"rgba"` |
|
||||||
HSLColorString string `validate:"hsl"` |
|
||||||
HSLAColorString string `validate:"hsla"` |
|
||||||
Email string `validate:"email"` |
|
||||||
URL string `validate:"url"` |
|
||||||
URI string `validate:"uri"` |
|
||||||
Base64 string `validate:"base64"` |
|
||||||
Contains string `validate:"contains=purpose"` |
|
||||||
ContainsAny string `validate:"containsany=!@#$"` |
|
||||||
Excludes string `validate:"excludes=text"` |
|
||||||
ExcludesAll string `validate:"excludesall=!@#$"` |
|
||||||
ExcludesRune string `validate:"excludesrune=☻"` |
|
||||||
ISBN string `validate:"isbn"` |
|
||||||
ISBN10 string `validate:"isbn10"` |
|
||||||
ISBN13 string `validate:"isbn13"` |
|
||||||
UUID string `validate:"uuid"` |
|
||||||
UUID3 string `validate:"uuid3"` |
|
||||||
UUID4 string `validate:"uuid4"` |
|
||||||
UUID5 string `validate:"uuid5"` |
|
||||||
ULID string `validate:"ulid"` |
|
||||||
ASCII string `validate:"ascii"` |
|
||||||
PrintableASCII string `validate:"printascii"` |
|
||||||
MultiByte string `validate:"multibyte"` |
|
||||||
DataURI string `validate:"datauri"` |
|
||||||
Latitude string `validate:"latitude"` |
|
||||||
Longitude string `validate:"longitude"` |
|
||||||
SSN string `validate:"ssn"` |
|
||||||
IP string `validate:"ip"` |
|
||||||
IPv4 string `validate:"ipv4"` |
|
||||||
IPv6 string `validate:"ipv6"` |
|
||||||
CIDR string `validate:"cidr"` |
|
||||||
CIDRv4 string `validate:"cidrv4"` |
|
||||||
CIDRv6 string `validate:"cidrv6"` |
|
||||||
TCPAddr string `validate:"tcp_addr"` |
|
||||||
TCPAddrv4 string `validate:"tcp4_addr"` |
|
||||||
TCPAddrv6 string `validate:"tcp6_addr"` |
|
||||||
UDPAddr string `validate:"udp_addr"` |
|
||||||
UDPAddrv4 string `validate:"udp4_addr"` |
|
||||||
UDPAddrv6 string `validate:"udp6_addr"` |
|
||||||
IPAddr string `validate:"ip_addr"` |
|
||||||
IPAddrv4 string `validate:"ip4_addr"` |
|
||||||
IPAddrv6 string `validate:"ip6_addr"` |
|
||||||
UinxAddr string `validate:"unix_addr"` // can't fail from within Go's net package currently, but maybe in the future
|
|
||||||
MAC string `validate:"mac"` |
|
||||||
IsColor string `validate:"iscolor"` |
|
||||||
StrPtrMinLen *string `validate:"min=10"` |
|
||||||
StrPtrMaxLen *string `validate:"max=1"` |
|
||||||
StrPtrLen *string `validate:"len=2"` |
|
||||||
StrPtrLt *string `validate:"lt=1"` |
|
||||||
StrPtrLte *string `validate:"lte=1"` |
|
||||||
StrPtrGt *string `validate:"gt=10"` |
|
||||||
StrPtrGte *string `validate:"gte=10"` |
|
||||||
OneOfString string `validate:"oneof=red green"` |
|
||||||
OneOfInt int `validate:"oneof=5 63"` |
|
||||||
UniqueSlice []string `validate:"unique"` |
|
||||||
UniqueArray [3]string `validate:"unique"` |
|
||||||
UniqueMap map[string]string `validate:"unique"` |
|
||||||
JSONString string `validate:"json"` |
|
||||||
JWTString string `validate:"jwt"` |
|
||||||
LowercaseString string `validate:"lowercase"` |
|
||||||
UppercaseString string `validate:"uppercase"` |
|
||||||
Datetime string `validate:"datetime=2006-01-02"` |
|
||||||
PostCode string `validate:"postcode_iso3166_alpha2=SG"` |
|
||||||
PostCodeCountry string |
|
||||||
PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"` |
|
||||||
BooleanString string `validate:"boolean"` |
|
||||||
} |
|
||||||
|
|
||||||
var test Test |
|
||||||
|
|
||||||
test.Inner.EqCSFieldString = "1234" |
|
||||||
test.Inner.GtCSFieldString = "1234" |
|
||||||
test.Inner.GteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.MaxString = "1234" |
|
||||||
test.MaxNumber = 2000 |
|
||||||
test.MaxMultiple = make([]string, 9) |
|
||||||
|
|
||||||
test.LtString = "1234" |
|
||||||
test.LtNumber = 6 |
|
||||||
test.LtMultiple = make([]string, 3) |
|
||||||
test.LtTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LteString = "1234" |
|
||||||
test.LteNumber = 6 |
|
||||||
test.LteMultiple = make([]string, 3) |
|
||||||
test.LteTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LtFieldString = "12345" |
|
||||||
test.LteFieldString = "12345" |
|
||||||
|
|
||||||
test.LtCSFieldString = "1234" |
|
||||||
test.LteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.AlphaString = "abc3" |
|
||||||
test.AlphanumString = "abc3!" |
|
||||||
test.NumericString = "12E.00" |
|
||||||
test.NumberString = "12E" |
|
||||||
|
|
||||||
test.Excludes = "this is some test text" |
|
||||||
test.ExcludesAll = "This is Great!" |
|
||||||
test.ExcludesRune = "Love it ☻" |
|
||||||
|
|
||||||
test.ASCII = "カタカナ" |
|
||||||
test.PrintableASCII = "カタカナ" |
|
||||||
|
|
||||||
test.MultiByte = "1234feerf" |
|
||||||
|
|
||||||
test.LowercaseString = "ABCDEFG" |
|
||||||
test.UppercaseString = "abcdefg" |
|
||||||
|
|
||||||
s := "toolong" |
|
||||||
test.StrPtrMaxLen = &s |
|
||||||
test.StrPtrLen = &s |
|
||||||
|
|
||||||
test.UniqueSlice = []string{"1234", "1234"} |
|
||||||
test.UniqueMap = map[string]string{"key1": "1234", "key2": "1234"} |
|
||||||
test.Datetime = "2008-Feb-01" |
|
||||||
test.BooleanString = "A" |
|
||||||
|
|
||||||
test.Inner.RequiredIf = "abcd" |
|
||||||
|
|
||||||
err = validate.Struct(test) |
|
||||||
NotEqual(t, err, nil) |
|
||||||
|
|
||||||
errs, ok := err.(validator.ValidationErrors) |
|
||||||
Equal(t, ok, true) |
|
||||||
|
|
||||||
tests := []struct { |
|
||||||
ns string |
|
||||||
expected string |
|
||||||
}{ |
|
||||||
{ |
|
||||||
ns: "Test.IsColor", |
|
||||||
expected: "IsColorは正しい色でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MAC", |
|
||||||
expected: "MACは正しいMACアドレスを含まなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddr", |
|
||||||
expected: "IPAddrは解決可能なIPアドレスでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv4", |
|
||||||
expected: "IPAddrv4は解決可能なIPv4アドレスでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv6", |
|
||||||
expected: "IPAddrv6は解決可能なIPv6アドレスでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddr", |
|
||||||
expected: "UDPAddrは正しいUDPアドレスでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv4", |
|
||||||
expected: "UDPAddrv4は正しいIPv4のUDPアドレスでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv6", |
|
||||||
expected: "UDPAddrv6は正しいIPv6のUDPアドレスでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddr", |
|
||||||
expected: "TCPAddrは正しいTCPアドレスでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv4", |
|
||||||
expected: "TCPAddrv4は正しいIPv4のTCPアドレスでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv6", |
|
||||||
expected: "TCPAddrv6は正しいIPv6のTCPアドレスでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDR", |
|
||||||
expected: "CIDRは正しいCIDR表記を含まなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv4", |
|
||||||
expected: "CIDRv4はIPv4アドレスの正しいCIDR表記を含まなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv6", |
|
||||||
expected: "CIDRv6はIPv6アドレスの正しいCIDR表記を含まなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.SSN", |
|
||||||
expected: "SSNは正しい社会保障番号でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IP", |
|
||||||
expected: "IPは正しいIPアドレスでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv4", |
|
||||||
expected: "IPv4は正しいIPv4アドレスでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv6", |
|
||||||
expected: "IPv6は正しいIPv6アドレスでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.DataURI", |
|
||||||
expected: "DataURIは正しいデータURIを含まなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Latitude", |
|
||||||
expected: "Latitudeは正しい緯度の座標を含まなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Longitude", |
|
||||||
expected: "Longitudeは正しい経度の座標を含まなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MultiByte", |
|
||||||
expected: "MultiByteはマルチバイト文字を含まなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ASCII", |
|
||||||
expected: "ASCIIはASCII文字のみを含まなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.PrintableASCII", |
|
||||||
expected: "PrintableASCIIは印刷可能なASCII文字のみを含まなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID", |
|
||||||
expected: "UUIDは正しいUUIDでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID3", |
|
||||||
expected: "UUID3はバージョンが3の正しいUUIDでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID4", |
|
||||||
expected: "UUID4はバージョンが4の正しいUUIDでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID5", |
|
||||||
expected: "UUID5はバージョンが5の正しいUUIDでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ULID", |
|
||||||
expected: "ULIDは正しいULIDでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN", |
|
||||||
expected: "ISBNは正しいISBN番号でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN10", |
|
||||||
expected: "ISBN10は正しいISBN-10番号でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN13", |
|
||||||
expected: "ISBN13は正しいISBN-13番号でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Excludes", |
|
||||||
expected: "Excludesには'text'というテキストを含むことはできません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesAll", |
|
||||||
expected: "ExcludesAllには'!@#$'のどれも含めることはできません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesRune", |
|
||||||
expected: "ExcludesRuneには'☻'を含めることはできません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ContainsAny", |
|
||||||
expected: "ContainsAnyは'!@#$'の少なくとも1つを含まなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Contains", |
|
||||||
expected: "Containsは'purpose'を含まなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Base64", |
|
||||||
expected: "Base64は正しいBase64文字列でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Email", |
|
||||||
expected: "Emailは正しいメールアドレスでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URL", |
|
||||||
expected: "URLは正しいURLでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URI", |
|
||||||
expected: "URIは正しいURIでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBColorString", |
|
||||||
expected: "RGBColorStringは正しいRGBカラーコードでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBAColorString", |
|
||||||
expected: "RGBAColorStringは正しいRGBAカラーコードでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLColorString", |
|
||||||
expected: "HSLColorStringは正しいHSLカラーコードでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLAColorString", |
|
||||||
expected: "HSLAColorStringは正しいHSLAカラーコードでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexadecimalString", |
|
||||||
expected: "HexadecimalStringは正しい16進表記でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexColorString", |
|
||||||
expected: "HexColorStringは正しいHEXカラーコードでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumberString", |
|
||||||
expected: "NumberStringは正しい数でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumericString", |
|
||||||
expected: "NumericStringは正しい数字でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphanumString", |
|
||||||
expected: "AlphanumStringはアルファベットと数字のみを含むことができます", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphaString", |
|
||||||
expected: "AlphaStringはアルファベットのみを含むことができます", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtFieldString", |
|
||||||
expected: "LtFieldStringはMaxStringよりも小さくなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteFieldString", |
|
||||||
expected: "LteFieldStringはMaxString以下でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtFieldString", |
|
||||||
expected: "GtFieldStringはMaxStringよりも大きくなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteFieldString", |
|
||||||
expected: "GteFieldStringはMaxString以上でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeFieldString", |
|
||||||
expected: "NeFieldStringはEqFieldStringとは異ならなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtCSFieldString", |
|
||||||
expected: "LtCSFieldStringはInner.LtCSFieldStringよりも小さくなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteCSFieldString", |
|
||||||
expected: "LteCSFieldStringはInner.LteCSFieldString以下でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtCSFieldString", |
|
||||||
expected: "GtCSFieldStringはInner.GtCSFieldStringよりも大きくなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteCSFieldString", |
|
||||||
expected: "GteCSFieldStringはInner.GteCSFieldString以上でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeCSFieldString", |
|
||||||
expected: "NeCSFieldStringはInner.NeCSFieldStringとは異ならなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqCSFieldString", |
|
||||||
expected: "EqCSFieldStringはInner.EqCSFieldStringと等しくなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqFieldString", |
|
||||||
expected: "EqFieldStringはMaxStringと等しくなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteString", |
|
||||||
expected: "GteStringの長さは少なくとも3文字以上はなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteNumber", |
|
||||||
expected: "GteNumberは5.56以上でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteMultiple", |
|
||||||
expected: "GteMultipleは少なくとも2つの項目を含まなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteTime", |
|
||||||
expected: "GteTimeは現時刻以降でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtString", |
|
||||||
expected: "GtStringの長さは3文字よりも多くなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtNumber", |
|
||||||
expected: "GtNumberは5.56よりも大きくなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtMultiple", |
|
||||||
expected: "GtMultipleは2つの項目よりも多い項目を含まなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtTime", |
|
||||||
expected: "GtTimeは現時刻よりも後でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteString", |
|
||||||
expected: "LteStringの長さは最大でも3文字でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteNumber", |
|
||||||
expected: "LteNumberは5.56以下でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteMultiple", |
|
||||||
expected: "LteMultipleは最大でも2つの項目を含まなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteTime", |
|
||||||
expected: "LteTimeは現時刻以前でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtString", |
|
||||||
expected: "LtStringの長さは3文字よりも少なくなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtNumber", |
|
||||||
expected: "LtNumberは5.56よりも小さくなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtMultiple", |
|
||||||
expected: "LtMultipleは2つの項目よりも少ない項目を含まなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtTime", |
|
||||||
expected: "LtTimeは現時刻よりも前でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeString", |
|
||||||
expected: "NeStringはと異ならなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeNumber", |
|
||||||
expected: "NeNumberは0.00と異ならなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeMultiple", |
|
||||||
expected: "NeMultipleの項目の数は0個と異ならなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqString", |
|
||||||
expected: "EqStringは3と等しくありません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqNumber", |
|
||||||
expected: "EqNumberは2.33と等しくありません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqMultiple", |
|
||||||
expected: "EqMultipleは7と等しくありません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxString", |
|
||||||
expected: "MaxStringの長さは最大でも3文字でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxNumber", |
|
||||||
expected: "MaxNumberは1,113.00以下でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxMultiple", |
|
||||||
expected: "MaxMultipleは最大でも7つの項目を含まなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinString", |
|
||||||
expected: "MinStringの長さは少なくとも1文字はなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinNumber", |
|
||||||
expected: "MinNumberは1,113.00以上でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinMultiple", |
|
||||||
expected: "MinMultipleは少なくとも7つの項目を含まなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenString", |
|
||||||
expected: "LenStringの長さは1文字でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenNumber", |
|
||||||
expected: "LenNumberは1,113.00と等しくなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenMultiple", |
|
||||||
expected: "LenMultipleは7つの項目を含まなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredString", |
|
||||||
expected: "RequiredStringは必須フィールドです", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredIf", |
|
||||||
expected: "RequiredIfは必須フィールドです", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredNumber", |
|
||||||
expected: "RequiredNumberは必須フィールドです", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredMultiple", |
|
||||||
expected: "RequiredMultipleは必須フィールドです", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMinLen", |
|
||||||
expected: "StrPtrMinLenの長さは少なくとも10文字はなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMaxLen", |
|
||||||
expected: "StrPtrMaxLenの長さは最大でも1文字でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLen", |
|
||||||
expected: "StrPtrLenの長さは2文字でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLt", |
|
||||||
expected: "StrPtrLtの長さは1文字よりも少なくなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLte", |
|
||||||
expected: "StrPtrLteの長さは最大でも1文字でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGt", |
|
||||||
expected: "StrPtrGtの長さは10文字よりも多くなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGte", |
|
||||||
expected: "StrPtrGteの長さは少なくとも10文字以上はなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfString", |
|
||||||
expected: "OneOfStringは[red green]のうちのいずれかでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfInt", |
|
||||||
expected: "OneOfIntは[5 63]のうちのいずれかでなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UniqueSlice", |
|
||||||
expected: "UniqueSliceは一意な値のみを含まなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UniqueArray", |
|
||||||
expected: "UniqueArrayは一意な値のみを含まなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UniqueMap", |
|
||||||
expected: "UniqueMapは一意な値のみを含まなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.JSONString", |
|
||||||
expected: "JSONStringは正しいJSON文字列でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.JWTString", |
|
||||||
expected: "JWTStringは正しいJWT文字列でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LowercaseString", |
|
||||||
expected: "LowercaseStringは小文字でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UppercaseString", |
|
||||||
expected: "UppercaseStringは大文字でなければなりません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Datetime", |
|
||||||
expected: "Datetimeは2006-01-02の書式と一致しません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.PostCode", |
|
||||||
expected: "PostCodeは国名コードSGの郵便番号形式と一致しません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.PostCodeByField", |
|
||||||
expected: "PostCodeByFieldはPostCodeCountryフィールドで指定された国名コードの郵便番号形式と一致しません", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.BooleanString", |
|
||||||
expected: "BooleanStringは正しいブール値でなければなりません", |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
for _, tt := range tests { |
|
||||||
|
|
||||||
var fe validator.FieldError |
|
||||||
|
|
||||||
for _, e := range errs { |
|
||||||
if tt.ns == e.Namespace() { |
|
||||||
fe = e |
|
||||||
break |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
NotEqual(t, fe, nil) |
|
||||||
Equal(t, tt.expected, fe.Translate(trans)) |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
File diff suppressed because it is too large
Load Diff
@ -1,709 +0,0 @@ |
|||||||
package lv |
|
||||||
|
|
||||||
import ( |
|
||||||
"testing" |
|
||||||
"time" |
|
||||||
|
|
||||||
. "github.com/go-playground/assert/v2" |
|
||||||
english "github.com/go-playground/locales/en" |
|
||||||
ut "github.com/go-playground/universal-translator" |
|
||||||
"github.com/go-playground/validator/v10" |
|
||||||
) |
|
||||||
|
|
||||||
func TestTranslations(t *testing.T) { |
|
||||||
eng := english.New() |
|
||||||
uni := ut.New(eng, eng) |
|
||||||
trans, _ := uni.GetTranslator("en") |
|
||||||
|
|
||||||
validate := validator.New() |
|
||||||
|
|
||||||
err := RegisterDefaultTranslations(validate, trans) |
|
||||||
Equal(t, err, nil) |
|
||||||
|
|
||||||
type Inner struct { |
|
||||||
EqCSFieldString string |
|
||||||
NeCSFieldString string |
|
||||||
GtCSFieldString string |
|
||||||
GteCSFieldString string |
|
||||||
LtCSFieldString string |
|
||||||
LteCSFieldString string |
|
||||||
RequiredIf string |
|
||||||
} |
|
||||||
|
|
||||||
type Test struct { |
|
||||||
Inner Inner |
|
||||||
RequiredString string `validate:"required"` |
|
||||||
RequiredNumber int `validate:"required"` |
|
||||||
RequiredMultiple []string `validate:"required"` |
|
||||||
RequiredIf string `validate:"required_if=Inner.RequiredIf abcd"` |
|
||||||
LenString string `validate:"len=1"` |
|
||||||
LenNumber float64 `validate:"len=1113.00"` |
|
||||||
LenMultiple []string `validate:"len=7"` |
|
||||||
MinString string `validate:"min=1"` |
|
||||||
MinNumber float64 `validate:"min=1113.00"` |
|
||||||
MinMultiple []string `validate:"min=7"` |
|
||||||
MaxString string `validate:"max=3"` |
|
||||||
MaxNumber float64 `validate:"max=1113.00"` |
|
||||||
MaxMultiple []string `validate:"max=7"` |
|
||||||
EqString string `validate:"eq=3"` |
|
||||||
EqNumber float64 `validate:"eq=2.33"` |
|
||||||
EqMultiple []string `validate:"eq=7"` |
|
||||||
NeString string `validate:"ne="` |
|
||||||
NeNumber float64 `validate:"ne=0.00"` |
|
||||||
NeMultiple []string `validate:"ne=0"` |
|
||||||
LtString string `validate:"lt=3"` |
|
||||||
LtNumber float64 `validate:"lt=5.56"` |
|
||||||
LtMultiple []string `validate:"lt=2"` |
|
||||||
LtTime time.Time `validate:"lt"` |
|
||||||
LteString string `validate:"lte=3"` |
|
||||||
LteNumber float64 `validate:"lte=5.56"` |
|
||||||
LteMultiple []string `validate:"lte=2"` |
|
||||||
LteTime time.Time `validate:"lte"` |
|
||||||
GtString string `validate:"gt=3"` |
|
||||||
GtNumber float64 `validate:"gt=5.56"` |
|
||||||
GtMultiple []string `validate:"gt=2"` |
|
||||||
GtTime time.Time `validate:"gt"` |
|
||||||
GteString string `validate:"gte=3"` |
|
||||||
GteNumber float64 `validate:"gte=5.56"` |
|
||||||
GteMultiple []string `validate:"gte=2"` |
|
||||||
GteTime time.Time `validate:"gte"` |
|
||||||
EqFieldString string `validate:"eqfield=MaxString"` |
|
||||||
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"` |
|
||||||
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"` |
|
||||||
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"` |
|
||||||
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"` |
|
||||||
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"` |
|
||||||
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"` |
|
||||||
NeFieldString string `validate:"nefield=EqFieldString"` |
|
||||||
GtFieldString string `validate:"gtfield=MaxString"` |
|
||||||
GteFieldString string `validate:"gtefield=MaxString"` |
|
||||||
LtFieldString string `validate:"ltfield=MaxString"` |
|
||||||
LteFieldString string `validate:"ltefield=MaxString"` |
|
||||||
AlphaString string `validate:"alpha"` |
|
||||||
AlphanumString string `validate:"alphanum"` |
|
||||||
NumericString string `validate:"numeric"` |
|
||||||
NumberString string `validate:"number"` |
|
||||||
HexadecimalString string `validate:"hexadecimal"` |
|
||||||
HexColorString string `validate:"hexcolor"` |
|
||||||
RGBColorString string `validate:"rgb"` |
|
||||||
RGBAColorString string `validate:"rgba"` |
|
||||||
HSLColorString string `validate:"hsl"` |
|
||||||
HSLAColorString string `validate:"hsla"` |
|
||||||
Email string `validate:"email"` |
|
||||||
URL string `validate:"url"` |
|
||||||
URI string `validate:"uri"` |
|
||||||
Base64 string `validate:"base64"` |
|
||||||
Contains string `validate:"contains=purpose"` |
|
||||||
ContainsAny string `validate:"containsany=!@#$"` |
|
||||||
Excludes string `validate:"excludes=text"` |
|
||||||
ExcludesAll string `validate:"excludesall=!@#$"` |
|
||||||
ExcludesRune string `validate:"excludesrune=☻"` |
|
||||||
ISBN string `validate:"isbn"` |
|
||||||
ISBN10 string `validate:"isbn10"` |
|
||||||
ISBN13 string `validate:"isbn13"` |
|
||||||
UUID string `validate:"uuid"` |
|
||||||
UUID3 string `validate:"uuid3"` |
|
||||||
UUID4 string `validate:"uuid4"` |
|
||||||
UUID5 string `validate:"uuid5"` |
|
||||||
ULID string `validate:"ulid"` |
|
||||||
ASCII string `validate:"ascii"` |
|
||||||
PrintableASCII string `validate:"printascii"` |
|
||||||
MultiByte string `validate:"multibyte"` |
|
||||||
DataURI string `validate:"datauri"` |
|
||||||
Latitude string `validate:"latitude"` |
|
||||||
Longitude string `validate:"longitude"` |
|
||||||
SSN string `validate:"ssn"` |
|
||||||
IP string `validate:"ip"` |
|
||||||
IPv4 string `validate:"ipv4"` |
|
||||||
IPv6 string `validate:"ipv6"` |
|
||||||
CIDR string `validate:"cidr"` |
|
||||||
CIDRv4 string `validate:"cidrv4"` |
|
||||||
CIDRv6 string `validate:"cidrv6"` |
|
||||||
TCPAddr string `validate:"tcp_addr"` |
|
||||||
TCPAddrv4 string `validate:"tcp4_addr"` |
|
||||||
TCPAddrv6 string `validate:"tcp6_addr"` |
|
||||||
UDPAddr string `validate:"udp_addr"` |
|
||||||
UDPAddrv4 string `validate:"udp4_addr"` |
|
||||||
UDPAddrv6 string `validate:"udp6_addr"` |
|
||||||
IPAddr string `validate:"ip_addr"` |
|
||||||
IPAddrv4 string `validate:"ip4_addr"` |
|
||||||
IPAddrv6 string `validate:"ip6_addr"` |
|
||||||
UinxAddr string `validate:"unix_addr"` // can't fail from within Go's net package currently, but maybe in the future
|
|
||||||
MAC string `validate:"mac"` |
|
||||||
IsColor string `validate:"iscolor"` |
|
||||||
StrPtrMinLen *string `validate:"min=10"` |
|
||||||
StrPtrMaxLen *string `validate:"max=1"` |
|
||||||
StrPtrLen *string `validate:"len=2"` |
|
||||||
StrPtrLt *string `validate:"lt=1"` |
|
||||||
StrPtrLte *string `validate:"lte=1"` |
|
||||||
StrPtrGt *string `validate:"gt=10"` |
|
||||||
StrPtrGte *string `validate:"gte=10"` |
|
||||||
OneOfString string `validate:"oneof=red green"` |
|
||||||
OneOfInt int `validate:"oneof=5 63"` |
|
||||||
UniqueSlice []string `validate:"unique"` |
|
||||||
UniqueArray [3]string `validate:"unique"` |
|
||||||
UniqueMap map[string]string `validate:"unique"` |
|
||||||
JSONString string `validate:"json"` |
|
||||||
JWTString string `validate:"jwt"` |
|
||||||
LowercaseString string `validate:"lowercase"` |
|
||||||
UppercaseString string `validate:"uppercase"` |
|
||||||
Datetime string `validate:"datetime=2006-01-02"` |
|
||||||
PostCode string `validate:"postcode_iso3166_alpha2=SG"` |
|
||||||
PostCodeCountry string |
|
||||||
PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"` |
|
||||||
BooleanString string `validate:"boolean"` |
|
||||||
} |
|
||||||
|
|
||||||
var test Test |
|
||||||
|
|
||||||
test.Inner.EqCSFieldString = "1234" |
|
||||||
test.Inner.GtCSFieldString = "1234" |
|
||||||
test.Inner.GteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.MaxString = "1234" |
|
||||||
test.MaxNumber = 2000 |
|
||||||
test.MaxMultiple = make([]string, 9) |
|
||||||
|
|
||||||
test.LtString = "1234" |
|
||||||
test.LtNumber = 6 |
|
||||||
test.LtMultiple = make([]string, 3) |
|
||||||
test.LtTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LteString = "1234" |
|
||||||
test.LteNumber = 6 |
|
||||||
test.LteMultiple = make([]string, 3) |
|
||||||
test.LteTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LtFieldString = "12345" |
|
||||||
test.LteFieldString = "12345" |
|
||||||
|
|
||||||
test.LtCSFieldString = "1234" |
|
||||||
test.LteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.AlphaString = "abc3" |
|
||||||
test.AlphanumString = "abc3!" |
|
||||||
test.NumericString = "12E.00" |
|
||||||
test.NumberString = "12E" |
|
||||||
|
|
||||||
test.Excludes = "this is some test text" |
|
||||||
test.ExcludesAll = "This is Great!" |
|
||||||
test.ExcludesRune = "Love it ☻" |
|
||||||
|
|
||||||
test.ASCII = "カタカナ" |
|
||||||
test.PrintableASCII = "カタカナ" |
|
||||||
|
|
||||||
test.MultiByte = "1234feerf" |
|
||||||
|
|
||||||
test.LowercaseString = "ABCDEFG" |
|
||||||
test.UppercaseString = "abcdefg" |
|
||||||
|
|
||||||
s := "toolong" |
|
||||||
test.StrPtrMaxLen = &s |
|
||||||
test.StrPtrLen = &s |
|
||||||
|
|
||||||
test.UniqueSlice = []string{"1234", "1234"} |
|
||||||
test.UniqueMap = map[string]string{"key1": "1234", "key2": "1234"} |
|
||||||
test.Datetime = "2008-Feb-01" |
|
||||||
test.BooleanString = "A" |
|
||||||
|
|
||||||
test.Inner.RequiredIf = "abcd" |
|
||||||
|
|
||||||
err = validate.Struct(test) |
|
||||||
NotEqual(t, err, nil) |
|
||||||
|
|
||||||
errs, ok := err.(validator.ValidationErrors) |
|
||||||
Equal(t, ok, true) |
|
||||||
|
|
||||||
tests := []struct { |
|
||||||
ns string |
|
||||||
expected string |
|
||||||
}{ |
|
||||||
{ |
|
||||||
ns: "Test.IsColor", |
|
||||||
expected: "IsColor jābūt derīgai krāsai", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MAC", |
|
||||||
expected: "MAC jābūt derīgai MAC adresei", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddr", |
|
||||||
expected: "IPAddr jābūt atrisināmai IP adresei", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv4", |
|
||||||
expected: "IPAddrv4 jābūt atrisināmai IPv4 adresei", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv6", |
|
||||||
expected: "IPAddrv6 jābūt atrisināmai IPv6 adresei", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddr", |
|
||||||
expected: "UDPAddr jābūt derīgai UDP adresei", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv4", |
|
||||||
expected: "UDPAddrv4 jābūt derīgai IPv4 UDP adresei", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv6", |
|
||||||
expected: "UDPAddrv6 jābūt derīgai IPv6 UDP adresei", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddr", |
|
||||||
expected: "TCPAddr jābūt derīgai TCP adresei", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv4", |
|
||||||
expected: "TCPAddrv4 jābūt derīgai IPv4 TCP adresei", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv6", |
|
||||||
expected: "TCPAddrv6 jābūt derīgai IPv6 TCP adresei", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDR", |
|
||||||
expected: "CIDR jāsatur derīgu CIDR notāciju", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv4", |
|
||||||
expected: "CIDRv4 jāsatur derīgu CIDR notāciju IPv4 adresei", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv6", |
|
||||||
expected: "CIDRv6 jāsatur derīgu CIDR notāciju IPv6 adresei", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.SSN", |
|
||||||
expected: "SSN jābūt derīgam SSN numuram", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IP", |
|
||||||
expected: "IP jābūt derīgai IP adresei", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv4", |
|
||||||
expected: "IPv4 jābūt derīgai IPv4 adresei", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv6", |
|
||||||
expected: "IPv6 jābūt derīgai IPv6 adresei", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.DataURI", |
|
||||||
expected: "DataURI jāsatur derīgs Data URI", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Latitude", |
|
||||||
expected: "Latitude jāsatur derīgus platuma grādus", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Longitude", |
|
||||||
expected: "Longitude jāsatur derīgus garuma grādus", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MultiByte", |
|
||||||
expected: "MultiByte jāsatur multibyte rakstu zīmes", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ASCII", |
|
||||||
expected: "ASCII jāsatur tikai ascii rakstu zīmes", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.PrintableASCII", |
|
||||||
expected: "PrintableASCII jāsatur tikai drukājamas ascii rakstu zīmes", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID", |
|
||||||
expected: "UUID jābūt derīgam UUID", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID3", |
|
||||||
expected: "UUID3 jābūt derīgam 3. versijas UUID", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID4", |
|
||||||
expected: "UUID4 jābūt derīgam 4. versijas UUID", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID5", |
|
||||||
expected: "UUID5 jābūt derīgam 5. versijas UUID", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ULID", |
|
||||||
expected: "ULID jābūt derīgam ULID", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN", |
|
||||||
expected: "ISBN jābūt derīgam ISBN numuram", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN10", |
|
||||||
expected: "ISBN10 jābūt derīgam ISBN-10 numuram", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN13", |
|
||||||
expected: "ISBN13 jābūt derīgam ISBN-13 numuram", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Excludes", |
|
||||||
expected: "Excludes nedrīkst saturēt tekstu 'text'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesAll", |
|
||||||
expected: "ExcludesAll nedrīkst saturēt nevienu no sekojošām rakstu zīmēm '!@#$'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesRune", |
|
||||||
expected: "ExcludesRune nedrīkst saturēt sekojošo '☻'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ContainsAny", |
|
||||||
expected: "ContainsAny jāsatur minimums 1 no rakstu zīmēm '!@#$'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Contains", |
|
||||||
expected: "Contains jāsatur teksts 'purpose'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Base64", |
|
||||||
expected: "Base64 jābūt derīgai Base64 virknei", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Email", |
|
||||||
expected: "Email jābūt derīgai e-pasta adresei", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URL", |
|
||||||
expected: "URL jābūt derīgam URL", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URI", |
|
||||||
expected: "URI jābūt derīgam URI", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBColorString", |
|
||||||
expected: "RGBColorString jābūt derīgai RGB krāsai", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBAColorString", |
|
||||||
expected: "RGBAColorString jābūt derīgai RGBA krāsai", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLColorString", |
|
||||||
expected: "HSLColorString jābūt derīgai HSL krāsai", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLAColorString", |
|
||||||
expected: "HSLAColorString jābūt derīgai HSLA krāsai", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexadecimalString", |
|
||||||
expected: "HexadecimalString jābūt heksadecimālam skaitlim", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexColorString", |
|
||||||
expected: "HexColorString jābūt derīgai HEX krāsai", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumberString", |
|
||||||
expected: "NumberString jāsatur derīgs skaitlis", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumericString", |
|
||||||
expected: "NumericString jāsatur tikai cipari", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphanumString", |
|
||||||
expected: "AlphanumString jāsatur tikai simboli no alfabēta vai cipari (Alphanumeric)", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphaString", |
|
||||||
expected: "AlphaString jāsatur tikai simboli no alfabēta", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtFieldString", |
|
||||||
expected: "LtFieldString jābūt mazākam par MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteFieldString", |
|
||||||
expected: "LteFieldString jābūt mazākam par MaxString vai vienādam", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtFieldString", |
|
||||||
expected: "GtFieldString jābūt lielākam par MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteFieldString", |
|
||||||
expected: "GteFieldString jābūt lielākam par MaxString vai vienādam", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeFieldString", |
|
||||||
expected: "NeFieldString nedrīkst būt vienāds ar EqFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtCSFieldString", |
|
||||||
expected: "LtCSFieldString jābūt mazākam par Inner.LtCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteCSFieldString", |
|
||||||
expected: "LteCSFieldString jābūt mazākam par Inner.LteCSFieldString vai vienādam", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtCSFieldString", |
|
||||||
expected: "GtCSFieldString jābūt lielākam par Inner.GtCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteCSFieldString", |
|
||||||
expected: "GteCSFieldString jābūt lielākam par Inner.GteCSFieldString vai vienādam", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeCSFieldString", |
|
||||||
expected: "NeCSFieldString nedrīkst būt vienāds ar Inner.NeCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqCSFieldString", |
|
||||||
expected: "EqCSFieldString jābūt vienādam ar Inner.EqCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqFieldString", |
|
||||||
expected: "EqFieldString jābūt vienādam ar MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteString", |
|
||||||
expected: "GteString garumam jābūt minimums 3 rakstu zīmes", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteNumber", |
|
||||||
expected: "GteNumber jābūt 5.56 vai lielākam", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteMultiple", |
|
||||||
expected: "GteMultiple jāsatur minimums 2 elementi", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteTime", |
|
||||||
expected: "GteTime jābūt lielākam par šī brīža Datumu un laiku vai vienādam", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtString", |
|
||||||
expected: "GtString ir jābūt garākam par 3 rakstu zīmēm", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtNumber", |
|
||||||
expected: "GtNumber jābūt lielākam par 5.56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtMultiple", |
|
||||||
expected: "GtMultiple jāsatur vairāk par 2 elementiem", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtTime", |
|
||||||
expected: "GtTime jābūt lielākam par šī brīža Datumu un laiku", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteString", |
|
||||||
expected: "LteString garumam jābūt maksimums 3 rakstu zīmes", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteNumber", |
|
||||||
expected: "LteNumber jābūt 5.56 vai mazākam", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteMultiple", |
|
||||||
expected: "LteMultiple jāsatur maksimums 2 elementi", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteTime", |
|
||||||
expected: "LteTime jābūt mazākam par šī brīža Datumu un laiku vai vienādam", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtString", |
|
||||||
expected: "LtString garumam jābūt mazākam par 3 rakstu zīmēm", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtNumber", |
|
||||||
expected: "LtNumber jābūt mazākam par 5.56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtMultiple", |
|
||||||
expected: "LtMultiple jāsatur mazāk par 2 elementiem", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtTime", |
|
||||||
expected: "LtTime jābūt mazākam par šī brīža Datumu un laiku", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeString", |
|
||||||
expected: "NeString nedrīkst būt vienāds ar ", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeNumber", |
|
||||||
expected: "NeNumber nedrīkst būt vienāds ar 0.00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeMultiple", |
|
||||||
expected: "NeMultiple nedrīkst būt vienāds ar 0", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqString", |
|
||||||
expected: "EqString nav vienāds ar 3", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqNumber", |
|
||||||
expected: "EqNumber nav vienāds ar 2.33", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqMultiple", |
|
||||||
expected: "EqMultiple nav vienāds ar 7", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxString", |
|
||||||
expected: "MaxString vērtība pārsniedz maksimālo garumu 3 rakstu zīmes", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxNumber", |
|
||||||
expected: "MaxNumber vērtībai jābūt 1,113.00 vai mazākai", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxMultiple", |
|
||||||
expected: "MaxMultiple jāsatur maksimums 7 elementi", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinString", |
|
||||||
expected: "MinString garumam jābūt minimums 1 rakstu zīme", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinNumber", |
|
||||||
expected: "MinNumber vērtībai jābūt 1,113.00 vai lielākai", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinMultiple", |
|
||||||
expected: "MinMultiple jāsatur minimums 7 elementi", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenString", |
|
||||||
expected: "LenString garumam jābūt 1 rakstu zīme", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenNumber", |
|
||||||
expected: "LenNumber vērtībai jābūt 1,113.00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenMultiple", |
|
||||||
expected: "LenMultiple vērtībai jāsatur 7 elementi", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredString", |
|
||||||
expected: "RequiredString ir obligāts lauks", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredIf", |
|
||||||
expected: "RequiredIf ir obligāts lauks", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredNumber", |
|
||||||
expected: "RequiredNumber ir obligāts lauks", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredMultiple", |
|
||||||
expected: "RequiredMultiple ir obligāts lauks", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMinLen", |
|
||||||
expected: "StrPtrMinLen garumam jābūt minimums 10 rakstu zīmes", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMaxLen", |
|
||||||
expected: "StrPtrMaxLen vērtība pārsniedz maksimālo garumu 1 rakstu zīme", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLen", |
|
||||||
expected: "StrPtrLen garumam jābūt 2 rakstu zīmes", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLt", |
|
||||||
expected: "StrPtrLt garumam jābūt mazākam par 1 rakstu zīmi", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLte", |
|
||||||
expected: "StrPtrLte garumam jābūt maksimums 1 rakstu zīme", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGt", |
|
||||||
expected: "StrPtrGt ir jābūt garākam par 10 rakstu zīmēm", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGte", |
|
||||||
expected: "StrPtrGte garumam jābūt minimums 10 rakstu zīmes", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfString", |
|
||||||
expected: "OneOfString jābūt vienam no [red green]", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfInt", |
|
||||||
expected: "OneOfInt jābūt vienam no [5 63]", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UniqueSlice", |
|
||||||
expected: "UniqueSlice jāsatur unikālas vērtības", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UniqueArray", |
|
||||||
expected: "UniqueArray jāsatur unikālas vērtības", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UniqueMap", |
|
||||||
expected: "UniqueMap jāsatur unikālas vērtības", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.JSONString", |
|
||||||
expected: "JSONString jābūt derīgai json virknei", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.JWTString", |
|
||||||
expected: "JWTString jābūt derīgai jwt virknei", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LowercaseString", |
|
||||||
expected: "LowercaseString jābūt mazo burtu virknei", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UppercaseString", |
|
||||||
expected: "UppercaseString jābūt lielo burtu virknei", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Datetime", |
|
||||||
expected: "Datetime neatbilst formātam 2006-01-02", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.PostCode", |
|
||||||
expected: "PostCode neatbilst pasta indeksa formātam valstī SG", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.PostCodeByField", |
|
||||||
expected: "PostCodeByField neatbilst pasta indeksa formātam valstī, kura norādīta laukā PostCodeCountry", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.BooleanString", |
|
||||||
expected: "BooleanString jābūt derīgai boolean vērtībai", |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
for _, tt := range tests { |
|
||||||
|
|
||||||
var fe validator.FieldError |
|
||||||
|
|
||||||
for _, e := range errs { |
|
||||||
if tt.ns == e.Namespace() { |
|
||||||
fe = e |
|
||||||
break |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
NotEqual(t, fe, nil) |
|
||||||
Equal(t, tt.expected, fe.Translate(trans)) |
|
||||||
} |
|
||||||
} |
|
File diff suppressed because it is too large
Load Diff
@ -1,639 +0,0 @@ |
|||||||
package nl |
|
||||||
|
|
||||||
import ( |
|
||||||
"testing" |
|
||||||
"time" |
|
||||||
|
|
||||||
. "github.com/go-playground/assert/v2" |
|
||||||
english "github.com/go-playground/locales/en" |
|
||||||
ut "github.com/go-playground/universal-translator" |
|
||||||
"github.com/go-playground/validator/v10" |
|
||||||
) |
|
||||||
|
|
||||||
func TestTranslations(t *testing.T) { |
|
||||||
|
|
||||||
eng := english.New() |
|
||||||
uni := ut.New(eng, eng) |
|
||||||
trans, _ := uni.GetTranslator("en") |
|
||||||
|
|
||||||
validate := validator.New() |
|
||||||
|
|
||||||
err := RegisterDefaultTranslations(validate, trans) |
|
||||||
Equal(t, err, nil) |
|
||||||
|
|
||||||
type Inner struct { |
|
||||||
EqCSFieldString string |
|
||||||
NeCSFieldString string |
|
||||||
GtCSFieldString string |
|
||||||
GteCSFieldString string |
|
||||||
LtCSFieldString string |
|
||||||
LteCSFieldString string |
|
||||||
} |
|
||||||
|
|
||||||
type Test struct { |
|
||||||
Inner Inner |
|
||||||
RequiredString string `validate:"required"` |
|
||||||
RequiredNumber int `validate:"required"` |
|
||||||
RequiredMultiple []string `validate:"required"` |
|
||||||
LenString string `validate:"len=1"` |
|
||||||
LenNumber float64 `validate:"len=1113.00"` |
|
||||||
LenMultiple []string `validate:"len=7"` |
|
||||||
MinString string `validate:"min=1"` |
|
||||||
MinNumber float64 `validate:"min=1113.00"` |
|
||||||
MinMultiple []string `validate:"min=7"` |
|
||||||
MaxString string `validate:"max=3"` |
|
||||||
MaxNumber float64 `validate:"max=1113.00"` |
|
||||||
MaxMultiple []string `validate:"max=7"` |
|
||||||
EqString string `validate:"eq=3"` |
|
||||||
EqNumber float64 `validate:"eq=2.33"` |
|
||||||
EqMultiple []string `validate:"eq=7"` |
|
||||||
NeString string `validate:"ne="` |
|
||||||
NeNumber float64 `validate:"ne=0.00"` |
|
||||||
NeMultiple []string `validate:"ne=0"` |
|
||||||
LtString string `validate:"lt=3"` |
|
||||||
LtNumber float64 `validate:"lt=5.56"` |
|
||||||
LtMultiple []string `validate:"lt=2"` |
|
||||||
LtTime time.Time `validate:"lt"` |
|
||||||
LteString string `validate:"lte=3"` |
|
||||||
LteNumber float64 `validate:"lte=5.56"` |
|
||||||
LteMultiple []string `validate:"lte=2"` |
|
||||||
LteTime time.Time `validate:"lte"` |
|
||||||
GtString string `validate:"gt=3"` |
|
||||||
GtNumber float64 `validate:"gt=5.56"` |
|
||||||
GtMultiple []string `validate:"gt=2"` |
|
||||||
GtTime time.Time `validate:"gt"` |
|
||||||
GteString string `validate:"gte=3"` |
|
||||||
GteNumber float64 `validate:"gte=5.56"` |
|
||||||
GteMultiple []string `validate:"gte=2"` |
|
||||||
GteTime time.Time `validate:"gte"` |
|
||||||
EqFieldString string `validate:"eqfield=MaxString"` |
|
||||||
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"` |
|
||||||
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"` |
|
||||||
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"` |
|
||||||
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"` |
|
||||||
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"` |
|
||||||
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"` |
|
||||||
NeFieldString string `validate:"nefield=EqFieldString"` |
|
||||||
GtFieldString string `validate:"gtfield=MaxString"` |
|
||||||
GteFieldString string `validate:"gtefield=MaxString"` |
|
||||||
LtFieldString string `validate:"ltfield=MaxString"` |
|
||||||
LteFieldString string `validate:"ltefield=MaxString"` |
|
||||||
AlphaString string `validate:"alpha"` |
|
||||||
AlphanumString string `validate:"alphanum"` |
|
||||||
NumericString string `validate:"numeric"` |
|
||||||
NumberString string `validate:"number"` |
|
||||||
HexadecimalString string `validate:"hexadecimal"` |
|
||||||
HexColorString string `validate:"hexcolor"` |
|
||||||
RGBColorString string `validate:"rgb"` |
|
||||||
RGBAColorString string `validate:"rgba"` |
|
||||||
HSLColorString string `validate:"hsl"` |
|
||||||
HSLAColorString string `validate:"hsla"` |
|
||||||
Email string `validate:"email"` |
|
||||||
URL string `validate:"url"` |
|
||||||
URI string `validate:"uri"` |
|
||||||
Base64 string `validate:"base64"` |
|
||||||
Contains string `validate:"contains=purpose"` |
|
||||||
ContainsAny string `validate:"containsany=!@#$"` |
|
||||||
Excludes string `validate:"excludes=text"` |
|
||||||
ExcludesAll string `validate:"excludesall=!@#$"` |
|
||||||
ExcludesRune string `validate:"excludesrune=☻"` |
|
||||||
ISBN string `validate:"isbn"` |
|
||||||
ISBN10 string `validate:"isbn10"` |
|
||||||
ISBN13 string `validate:"isbn13"` |
|
||||||
UUID string `validate:"uuid"` |
|
||||||
UUID3 string `validate:"uuid3"` |
|
||||||
UUID4 string `validate:"uuid4"` |
|
||||||
UUID5 string `validate:"uuid5"` |
|
||||||
ULID string `validate:"ulid"` |
|
||||||
ASCII string `validate:"ascii"` |
|
||||||
PrintableASCII string `validate:"printascii"` |
|
||||||
MultiByte string `validate:"multibyte"` |
|
||||||
DataURI string `validate:"datauri"` |
|
||||||
Latitude string `validate:"latitude"` |
|
||||||
Longitude string `validate:"longitude"` |
|
||||||
SSN string `validate:"ssn"` |
|
||||||
IP string `validate:"ip"` |
|
||||||
IPv4 string `validate:"ipv4"` |
|
||||||
IPv6 string `validate:"ipv6"` |
|
||||||
CIDR string `validate:"cidr"` |
|
||||||
CIDRv4 string `validate:"cidrv4"` |
|
||||||
CIDRv6 string `validate:"cidrv6"` |
|
||||||
TCPAddr string `validate:"tcp_addr"` |
|
||||||
TCPAddrv4 string `validate:"tcp4_addr"` |
|
||||||
TCPAddrv6 string `validate:"tcp6_addr"` |
|
||||||
UDPAddr string `validate:"udp_addr"` |
|
||||||
UDPAddrv4 string `validate:"udp4_addr"` |
|
||||||
UDPAddrv6 string `validate:"udp6_addr"` |
|
||||||
IPAddr string `validate:"ip_addr"` |
|
||||||
IPAddrv4 string `validate:"ip4_addr"` |
|
||||||
IPAddrv6 string `validate:"ip6_addr"` |
|
||||||
UinxAddr string `validate:"unix_addr"` // can't fail from within Go's net package currently, but maybe in the future
|
|
||||||
MAC string `validate:"mac"` |
|
||||||
IsColor string `validate:"iscolor"` |
|
||||||
StrPtrMinLen *string `validate:"min=10"` |
|
||||||
StrPtrMaxLen *string `validate:"max=1"` |
|
||||||
StrPtrLen *string `validate:"len=2"` |
|
||||||
StrPtrLt *string `validate:"lt=1"` |
|
||||||
StrPtrLte *string `validate:"lte=1"` |
|
||||||
StrPtrGt *string `validate:"gt=10"` |
|
||||||
StrPtrGte *string `validate:"gte=10"` |
|
||||||
OneOfString string `validate:"oneof=red green"` |
|
||||||
OneOfInt int `validate:"oneof=5 63"` |
|
||||||
} |
|
||||||
|
|
||||||
var test Test |
|
||||||
|
|
||||||
test.Inner.EqCSFieldString = "1234" |
|
||||||
test.Inner.GtCSFieldString = "1234" |
|
||||||
test.Inner.GteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.MaxString = "1234" |
|
||||||
test.MaxNumber = 2000 |
|
||||||
test.MaxMultiple = make([]string, 9) |
|
||||||
|
|
||||||
test.LtString = "1234" |
|
||||||
test.LtNumber = 6 |
|
||||||
test.LtMultiple = make([]string, 3) |
|
||||||
test.LtTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LteString = "1234" |
|
||||||
test.LteNumber = 6 |
|
||||||
test.LteMultiple = make([]string, 3) |
|
||||||
test.LteTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LtFieldString = "12345" |
|
||||||
test.LteFieldString = "12345" |
|
||||||
|
|
||||||
test.LtCSFieldString = "1234" |
|
||||||
test.LteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.AlphaString = "abc3" |
|
||||||
test.AlphanumString = "abc3!" |
|
||||||
test.NumericString = "12E.00" |
|
||||||
test.NumberString = "12E" |
|
||||||
|
|
||||||
test.Excludes = "this is some test text" |
|
||||||
test.ExcludesAll = "This is Great!" |
|
||||||
test.ExcludesRune = "Love it ☻" |
|
||||||
|
|
||||||
test.ASCII = "カタカナ" |
|
||||||
test.PrintableASCII = "カタカナ" |
|
||||||
|
|
||||||
test.MultiByte = "1234feerf" |
|
||||||
|
|
||||||
s := "toolong" |
|
||||||
test.StrPtrMaxLen = &s |
|
||||||
test.StrPtrLen = &s |
|
||||||
|
|
||||||
err = validate.Struct(test) |
|
||||||
NotEqual(t, err, nil) |
|
||||||
|
|
||||||
errs, ok := err.(validator.ValidationErrors) |
|
||||||
Equal(t, ok, true) |
|
||||||
|
|
||||||
tests := []struct { |
|
||||||
ns string |
|
||||||
expected string |
|
||||||
}{ |
|
||||||
{ |
|
||||||
ns: "Test.IsColor", |
|
||||||
expected: "IsColor moet een geldige kleur zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MAC", |
|
||||||
expected: "MAC moet een geldig MAC adres bevatten", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddr", |
|
||||||
expected: "IPAddr moet een oplosbaar IP adres zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv4", |
|
||||||
expected: "IPAddrv4 moet een oplosbaar IPv4 adres zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv6", |
|
||||||
expected: "IPAddrv6 moet een oplosbaar IPv6 adres zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddr", |
|
||||||
expected: "UDPAddr moet een geldig UDP adres zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv4", |
|
||||||
expected: "UDPAddrv4 moet een geldig IPv4 UDP adres zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv6", |
|
||||||
expected: "UDPAddrv6 moet een geldig IPv6 UDP adres zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddr", |
|
||||||
expected: "TCPAddr moet een geldig TCP adres zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv4", |
|
||||||
expected: "TCPAddrv4 moet een geldig IPv4 TCP adres zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv6", |
|
||||||
expected: "TCPAddrv6 moet een geldig IPv6 TCP adres zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDR", |
|
||||||
expected: "CIDR moet een geldige CIDR notatie bevatten", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv4", |
|
||||||
expected: "CIDRv4 moet een geldige CIDR notatie voor een IPv4 adres bevatten", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv6", |
|
||||||
expected: "CIDRv6 moet een geldige CIDR notatie voor een IPv6 adres bevatten", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.SSN", |
|
||||||
expected: "SSN moet een geldig SSN nummer zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IP", |
|
||||||
expected: "IP moet een geldig IP adres zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv4", |
|
||||||
expected: "IPv4 moet een geldig IPv4 adres zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv6", |
|
||||||
expected: "IPv6 moet een geldig IPv6 adres zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.DataURI", |
|
||||||
expected: "DataURI moet een geldige Data URI bevatten", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Latitude", |
|
||||||
expected: "Latitude moet geldige breedtegraadcoördinaten bevatten", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Longitude", |
|
||||||
expected: "Longitude moet geldige lengtegraadcoördinaten bevatten", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MultiByte", |
|
||||||
expected: "MultiByte moet multibyte karakters bevatten", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ASCII", |
|
||||||
expected: "ASCII mag alleen ascii karakters bevatten", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.PrintableASCII", |
|
||||||
expected: "PrintableASCII mag alleen afdrukbare ascii karakters bevatten", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID", |
|
||||||
expected: "UUID moet een geldige UUID zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID3", |
|
||||||
expected: "UUID3 moet een geldige versie 3 UUID zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID4", |
|
||||||
expected: "UUID4 moet een geldige versie 4 UUID zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID5", |
|
||||||
expected: "UUID5 moet een geldige versie 5 UUID zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ULID", |
|
||||||
expected: "ULID moet een geldige ULID zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN", |
|
||||||
expected: "ISBN moet een geldig ISBN nummer zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN10", |
|
||||||
expected: "ISBN10 moet een geldig ISBN-10 nummer zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN13", |
|
||||||
expected: "ISBN13 moet een geldig ISBN-13 nummer zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Excludes", |
|
||||||
expected: "Excludes mag niet de tekst 'text' bevatten", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesAll", |
|
||||||
expected: "ExcludesAll mag niet een van de volgende karakters bevatten '!@#$'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesRune", |
|
||||||
expected: "ExcludesRune mag niet het volgende bevatten '☻'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ContainsAny", |
|
||||||
expected: "ContainsAny moet tenminste een van de volgende karakters bevatten '!@#$'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Contains", |
|
||||||
expected: "Contains moet de tekst 'purpose' bevatten", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Base64", |
|
||||||
expected: "Base64 moet een geldige Base64 string zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Email", |
|
||||||
expected: "Email moet een geldig email adres zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URL", |
|
||||||
expected: "URL moet een geldige URL zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URI", |
|
||||||
expected: "URI moet een geldige URI zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBColorString", |
|
||||||
expected: "RGBColorString moet een geldige RGB kleur zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBAColorString", |
|
||||||
expected: "RGBAColorString moet een geldige RGBA kleur zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLColorString", |
|
||||||
expected: "HSLColorString moet een geldige HSL kleur zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLAColorString", |
|
||||||
expected: "HSLAColorString moet een geldige HSLA kleur zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexadecimalString", |
|
||||||
expected: "HexadecimalString moet een geldig hexadecimaal getal zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexColorString", |
|
||||||
expected: "HexColorString moet een geldige HEX kleur zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumberString", |
|
||||||
expected: "NumberString moet een geldig getal zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumericString", |
|
||||||
expected: "NumericString moet een geldige numerieke waarde zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphanumString", |
|
||||||
expected: "AlphanumString mag alleen alfanumerieke karakters bevatten", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphaString", |
|
||||||
expected: "AlphaString mag alleen alfabetische karakters bevatten", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtFieldString", |
|
||||||
expected: "LtFieldString moet kleiner zijn dan MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteFieldString", |
|
||||||
expected: "LteFieldString moet kleiner dan of gelijk aan MaxString zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtFieldString", |
|
||||||
expected: "GtFieldString moet groter zijn dan MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteFieldString", |
|
||||||
expected: "GteFieldString moet groter dan of gelijk aan MaxString zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeFieldString", |
|
||||||
expected: "NeFieldString mag niet gelijk zijn aan EqFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtCSFieldString", |
|
||||||
expected: "LtCSFieldString moet kleiner zijn dan Inner.LtCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteCSFieldString", |
|
||||||
expected: "LteCSFieldString moet kleiner dan of gelijk aan Inner.LteCSFieldString zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtCSFieldString", |
|
||||||
expected: "GtCSFieldString moet groter zijn dan Inner.GtCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteCSFieldString", |
|
||||||
expected: "GteCSFieldString moet groter dan of gelijk aan Inner.GteCSFieldString zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeCSFieldString", |
|
||||||
expected: "NeCSFieldString mag niet gelijk zijn aan Inner.NeCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqCSFieldString", |
|
||||||
expected: "EqCSFieldString moet gelijk zijn aan Inner.EqCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqFieldString", |
|
||||||
expected: "EqFieldString moet gelijk zijn aan MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteString", |
|
||||||
expected: "GteString moet tenminste 3 karakters lang zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteNumber", |
|
||||||
expected: "GteNumber moet 5.56 of groter zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteMultiple", |
|
||||||
expected: "GteMultiple moet tenminste 2 items bevatten", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteTime", |
|
||||||
expected: "GteTime moet groter dan of gelijk zijn aan de huidige datum & tijd", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtString", |
|
||||||
expected: "GtString moet langer dan 3 karakters zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtNumber", |
|
||||||
expected: "GtNumber moet groter zijn dan 5.56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtMultiple", |
|
||||||
expected: "GtMultiple moet meer dan 2 items bevatten", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtTime", |
|
||||||
expected: "GtTime moet groter zijn dan de huidige datum & tijd", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteString", |
|
||||||
expected: "LteString mag maximaal 3 karakters lang zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteNumber", |
|
||||||
expected: "LteNumber moet 5.56 of minder zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteMultiple", |
|
||||||
expected: "LteMultiple mag maximaal 2 items bevatten", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteTime", |
|
||||||
expected: "LteTime moet kleiner dan of gelijk aan de huidige datum & tijd zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtString", |
|
||||||
expected: "LtString moet minder dan 3 karakters lang zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtNumber", |
|
||||||
expected: "LtNumber moet kleiner zijn dan 5.56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtMultiple", |
|
||||||
expected: "LtMultiple moet minder dan 2 items bevatten", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtTime", |
|
||||||
expected: "LtTime moet kleiner zijn dan de huidige datum & tijd", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeString", |
|
||||||
expected: "NeString mag niet gelijk zijn aan ", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeNumber", |
|
||||||
expected: "NeNumber mag niet gelijk zijn aan 0.00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeMultiple", |
|
||||||
expected: "NeMultiple mag niet gelijk zijn aan 0", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqString", |
|
||||||
expected: "EqString is niet gelijk aan 3", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqNumber", |
|
||||||
expected: "EqNumber is niet gelijk aan 2.33", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqMultiple", |
|
||||||
expected: "EqMultiple is niet gelijk aan 7", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxString", |
|
||||||
expected: "MaxString mag maximaal 3 karakters lang zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxNumber", |
|
||||||
expected: "MaxNumber moet 1,113.00 of kleiner zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxMultiple", |
|
||||||
expected: "MaxMultiple mag maximaal 7 items bevatten", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinString", |
|
||||||
expected: "MinString moet tenminste 1 karakter lang zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinNumber", |
|
||||||
expected: "MinNumber moet 1,113.00 of groter zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinMultiple", |
|
||||||
expected: "MinMultiple moet tenminste 7 items bevatten", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenString", |
|
||||||
expected: "LenString moet 1 karakter lang zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenNumber", |
|
||||||
expected: "LenNumber moet gelijk zijn aan 1,113.00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenMultiple", |
|
||||||
expected: "LenMultiple moet 7 items bevatten", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredString", |
|
||||||
expected: "RequiredString is een verplicht veld", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredNumber", |
|
||||||
expected: "RequiredNumber is een verplicht veld", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredMultiple", |
|
||||||
expected: "RequiredMultiple is een verplicht veld", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMinLen", |
|
||||||
expected: "StrPtrMinLen moet tenminste 10 karakters lang zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMaxLen", |
|
||||||
expected: "StrPtrMaxLen mag maximaal 1 karakter lang zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLen", |
|
||||||
expected: "StrPtrLen moet 2 karakters lang zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLt", |
|
||||||
expected: "StrPtrLt moet minder dan 1 karakter lang zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLte", |
|
||||||
expected: "StrPtrLte mag maximaal 1 karakter lang zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGt", |
|
||||||
expected: "StrPtrGt moet langer dan 10 karakters zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGte", |
|
||||||
expected: "StrPtrGte moet tenminste 10 karakters lang zijn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfString", |
|
||||||
expected: "OneOfString moet een van de volgende zijn [red green]", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfInt", |
|
||||||
expected: "OneOfInt moet een van de volgende zijn [5 63]", |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
for _, tt := range tests { |
|
||||||
|
|
||||||
var fe validator.FieldError |
|
||||||
|
|
||||||
for _, e := range errs { |
|
||||||
if tt.ns == e.Namespace() { |
|
||||||
fe = e |
|
||||||
break |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
NotEqual(t, fe, nil) |
|
||||||
Equal(t, tt.expected, fe.Translate(trans)) |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
File diff suppressed because it is too large
Load Diff
@ -1,682 +0,0 @@ |
|||||||
package pt |
|
||||||
|
|
||||||
import ( |
|
||||||
"testing" |
|
||||||
"time" |
|
||||||
|
|
||||||
. "github.com/go-playground/assert/v2" |
|
||||||
"github.com/go-playground/locales/pt" |
|
||||||
ut "github.com/go-playground/universal-translator" |
|
||||||
|
|
||||||
"github.com/go-playground/validator/v10" |
|
||||||
) |
|
||||||
|
|
||||||
func TestTranslations(t *testing.T) { |
|
||||||
|
|
||||||
pt := pt.New() |
|
||||||
uni := ut.New(pt, pt) |
|
||||||
trans, _ := uni.GetTranslator("pt") |
|
||||||
|
|
||||||
validate := validator.New() |
|
||||||
|
|
||||||
err := RegisterDefaultTranslations(validate, trans) |
|
||||||
Equal(t, err, nil) |
|
||||||
|
|
||||||
type Inner struct { |
|
||||||
EqCSFieldString string |
|
||||||
NeCSFieldString string |
|
||||||
GtCSFieldString string |
|
||||||
GteCSFieldString string |
|
||||||
LtCSFieldString string |
|
||||||
LteCSFieldString string |
|
||||||
} |
|
||||||
|
|
||||||
type Test struct { |
|
||||||
Inner Inner |
|
||||||
RequiredString string `validate:"required"` |
|
||||||
RequiredNumber int `validate:"required"` |
|
||||||
RequiredMultiple []string `validate:"required"` |
|
||||||
LenString string `validate:"len=1"` |
|
||||||
LenNumber float64 `validate:"len=1113.00"` |
|
||||||
LenMultiple []string `validate:"len=7"` |
|
||||||
MinString string `validate:"min=1"` |
|
||||||
MinNumber float64 `validate:"min=1113.00"` |
|
||||||
MinMultiple []string `validate:"min=7"` |
|
||||||
MaxString string `validate:"max=3"` |
|
||||||
MaxNumber float64 `validate:"max=1113.00"` |
|
||||||
MaxMultiple []string `validate:"max=7"` |
|
||||||
EqString string `validate:"eq=3"` |
|
||||||
EqNumber float64 `validate:"eq=2.33"` |
|
||||||
EqMultiple []string `validate:"eq=7"` |
|
||||||
NeString string `validate:"ne="` |
|
||||||
NeNumber float64 `validate:"ne=0.00"` |
|
||||||
NeMultiple []string `validate:"ne=0"` |
|
||||||
LtString string `validate:"lt=3"` |
|
||||||
LtNumber float64 `validate:"lt=5.56"` |
|
||||||
LtMultiple []string `validate:"lt=2"` |
|
||||||
LtTime time.Time `validate:"lt"` |
|
||||||
LteString string `validate:"lte=3"` |
|
||||||
LteNumber float64 `validate:"lte=5.56"` |
|
||||||
LteMultiple []string `validate:"lte=2"` |
|
||||||
LteTime time.Time `validate:"lte"` |
|
||||||
GtString string `validate:"gt=3"` |
|
||||||
GtNumber float64 `validate:"gt=5.56"` |
|
||||||
GtMultiple []string `validate:"gt=2"` |
|
||||||
GtTime time.Time `validate:"gt"` |
|
||||||
GteString string `validate:"gte=3"` |
|
||||||
GteNumber float64 `validate:"gte=5.56"` |
|
||||||
GteMultiple []string `validate:"gte=2"` |
|
||||||
GteTime time.Time `validate:"gte"` |
|
||||||
EqFieldString string `validate:"eqfield=MaxString"` |
|
||||||
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"` |
|
||||||
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"` |
|
||||||
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"` |
|
||||||
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"` |
|
||||||
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"` |
|
||||||
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"` |
|
||||||
NeFieldString string `validate:"nefield=EqFieldString"` |
|
||||||
GtFieldString string `validate:"gtfield=MaxString"` |
|
||||||
GteFieldString string `validate:"gtefield=MaxString"` |
|
||||||
LtFieldString string `validate:"ltfield=MaxString"` |
|
||||||
LteFieldString string `validate:"ltefield=MaxString"` |
|
||||||
AlphaString string `validate:"alpha"` |
|
||||||
AlphanumString string `validate:"alphanum"` |
|
||||||
NumericString string `validate:"numeric"` |
|
||||||
NumberString string `validate:"number"` |
|
||||||
HexadecimalString string `validate:"hexadecimal"` |
|
||||||
HexColorString string `validate:"hexcolor"` |
|
||||||
RGBColorString string `validate:"rgb"` |
|
||||||
RGBAColorString string `validate:"rgba"` |
|
||||||
HSLColorString string `validate:"hsl"` |
|
||||||
HSLAColorString string `validate:"hsla"` |
|
||||||
Email string `validate:"email"` |
|
||||||
URL string `validate:"url"` |
|
||||||
URI string `validate:"uri"` |
|
||||||
Base64 string `validate:"base64"` |
|
||||||
Contains string `validate:"contains=purpose"` |
|
||||||
ContainsAny string `validate:"containsany=!@#$"` |
|
||||||
Excludes string `validate:"excludes=text"` |
|
||||||
ExcludesAll string `validate:"excludesall=!@#$"` |
|
||||||
ExcludesRune string `validate:"excludesrune=☻"` |
|
||||||
ISBN string `validate:"isbn"` |
|
||||||
ISBN10 string `validate:"isbn10"` |
|
||||||
ISBN13 string `validate:"isbn13"` |
|
||||||
UUID string `validate:"uuid"` |
|
||||||
UUID3 string `validate:"uuid3"` |
|
||||||
UUID4 string `validate:"uuid4"` |
|
||||||
UUID5 string `validate:"uuid5"` |
|
||||||
ULID string `validate:"ulid"` |
|
||||||
ASCII string `validate:"ascii"` |
|
||||||
PrintableASCII string `validate:"printascii"` |
|
||||||
MultiByte string `validate:"multibyte"` |
|
||||||
DataURI string `validate:"datauri"` |
|
||||||
Latitude string `validate:"latitude"` |
|
||||||
Longitude string `validate:"longitude"` |
|
||||||
SSN string `validate:"ssn"` |
|
||||||
IP string `validate:"ip"` |
|
||||||
IPv4 string `validate:"ipv4"` |
|
||||||
IPv6 string `validate:"ipv6"` |
|
||||||
CIDR string `validate:"cidr"` |
|
||||||
CIDRv4 string `validate:"cidrv4"` |
|
||||||
CIDRv6 string `validate:"cidrv6"` |
|
||||||
TCPAddr string `validate:"tcp_addr"` |
|
||||||
TCPAddrv4 string `validate:"tcp4_addr"` |
|
||||||
TCPAddrv6 string `validate:"tcp6_addr"` |
|
||||||
UDPAddr string `validate:"udp_addr"` |
|
||||||
UDPAddrv4 string `validate:"udp4_addr"` |
|
||||||
UDPAddrv6 string `validate:"udp6_addr"` |
|
||||||
IPAddr string `validate:"ip_addr"` |
|
||||||
IPAddrv4 string `validate:"ip4_addr"` |
|
||||||
IPAddrv6 string `validate:"ip6_addr"` |
|
||||||
UinxAddr string `validate:"unix_addr"` // can't fail from within Go's net package currently, but maybe in the future
|
|
||||||
MAC string `validate:"mac"` |
|
||||||
IsColor string `validate:"iscolor"` |
|
||||||
StrPtrMinLen *string `validate:"min=10"` |
|
||||||
StrPtrMaxLen *string `validate:"max=1"` |
|
||||||
StrPtrLen *string `validate:"len=2"` |
|
||||||
StrPtrLt *string `validate:"lt=1"` |
|
||||||
StrPtrLte *string `validate:"lte=1"` |
|
||||||
StrPtrGt *string `validate:"gt=10"` |
|
||||||
StrPtrGte *string `validate:"gte=10"` |
|
||||||
OneOfString string `validate:"oneof=red green"` |
|
||||||
OneOfInt int `validate:"oneof=5 63"` |
|
||||||
UniqueSlice []string `validate:"unique"` |
|
||||||
UniqueArray [3]string `validate:"unique"` |
|
||||||
UniqueMap map[string]string `validate:"unique"` |
|
||||||
JSONString string `validate:"json"` |
|
||||||
LowercaseString string `validate:"lowercase"` |
|
||||||
UppercaseString string `validate:"uppercase"` |
|
||||||
Datetime string `validate:"datetime=2006-01-02"` |
|
||||||
} |
|
||||||
|
|
||||||
var test Test |
|
||||||
|
|
||||||
test.Inner.EqCSFieldString = "1234" |
|
||||||
test.Inner.GtCSFieldString = "1234" |
|
||||||
test.Inner.GteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.MaxString = "1234" |
|
||||||
test.MaxNumber = 2000 |
|
||||||
test.MaxMultiple = make([]string, 9) |
|
||||||
|
|
||||||
test.LtString = "1234" |
|
||||||
test.LtNumber = 6 |
|
||||||
test.LtMultiple = make([]string, 3) |
|
||||||
test.LtTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LteString = "1234" |
|
||||||
test.LteNumber = 6 |
|
||||||
test.LteMultiple = make([]string, 3) |
|
||||||
test.LteTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LtFieldString = "12345" |
|
||||||
test.LteFieldString = "12345" |
|
||||||
|
|
||||||
test.LtCSFieldString = "1234" |
|
||||||
test.LteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.AlphaString = "abc3" |
|
||||||
test.AlphanumString = "abc3!" |
|
||||||
test.NumericString = "12E.00" |
|
||||||
test.NumberString = "12E" |
|
||||||
|
|
||||||
test.Excludes = "this is some test text" |
|
||||||
test.ExcludesAll = "This is Great!" |
|
||||||
test.ExcludesRune = "Love it ☻" |
|
||||||
|
|
||||||
test.ASCII = "カタカナ" |
|
||||||
test.PrintableASCII = "カタカナ" |
|
||||||
|
|
||||||
test.MultiByte = "1234feerf" |
|
||||||
|
|
||||||
test.LowercaseString = "ABCDEFG" |
|
||||||
test.UppercaseString = "abcdefg" |
|
||||||
|
|
||||||
s := "toolong" |
|
||||||
test.StrPtrMaxLen = &s |
|
||||||
test.StrPtrLen = &s |
|
||||||
|
|
||||||
test.UniqueSlice = []string{"1234", "1234"} |
|
||||||
test.UniqueMap = map[string]string{"key1": "1234", "key2": "1234"} |
|
||||||
test.Datetime = "2008-Feb-01" |
|
||||||
|
|
||||||
err = validate.Struct(test) |
|
||||||
NotEqual(t, err, nil) |
|
||||||
|
|
||||||
errs, ok := err.(validator.ValidationErrors) |
|
||||||
Equal(t, ok, true) |
|
||||||
|
|
||||||
tests := []struct { |
|
||||||
ns string |
|
||||||
expected string |
|
||||||
}{ |
|
||||||
{ |
|
||||||
ns: "Test.IsColor", |
|
||||||
expected: "IsColor deve ser uma cor válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MAC", |
|
||||||
expected: "MAC deve conter um endereço MAC válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddr", |
|
||||||
expected: "IPAddr deve ser um endereço IP resolvível", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv4", |
|
||||||
expected: "IPAddrv4 deve ser um endereço IPv4 resolvível", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv6", |
|
||||||
expected: "IPAddrv6 deve ser um endereço IPv6 resolvível", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddr", |
|
||||||
expected: "UDPAddr deve ser um endereço UDP válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv4", |
|
||||||
expected: "UDPAddrv4 deve ser um endereço UDP IPv4 válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv6", |
|
||||||
expected: "UDPAddrv6 deve ser um endereço UDP IPv6 válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddr", |
|
||||||
expected: "TCPAddr deve ser um endereço TCP válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv4", |
|
||||||
expected: "TCPAddrv4 deve ser um endereço TCP IPv4 válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv6", |
|
||||||
expected: "TCPAddrv6 deve ser um endereço TCP IPv6 válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDR", |
|
||||||
expected: "CIDR não respeita a notação CIDR", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv4", |
|
||||||
expected: "CIDRv4 não respeita a notação CIDR para um endereço IPv4", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv6", |
|
||||||
expected: "CIDRv6 não respeita a notação CIDR para um endereço IPv6", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.SSN", |
|
||||||
expected: "SSN deve ser um número SSN válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IP", |
|
||||||
expected: "IP deve ser um endereço IP válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv4", |
|
||||||
expected: "IPv4 deve ser um endereço IPv4 válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv6", |
|
||||||
expected: "IPv6 deve ser um endereço IPv6 válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.DataURI", |
|
||||||
expected: "DataURI deve conter um Data URI válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Latitude", |
|
||||||
expected: "Latitude deve conter uma coordenada de latitude válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Longitude", |
|
||||||
expected: "Longitude deve conter uma coordenada de longitude válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MultiByte", |
|
||||||
expected: "MultiByte deve conter caracteres multibyte", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ASCII", |
|
||||||
expected: "ASCII deve conter apenas caracteres ascii", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.PrintableASCII", |
|
||||||
expected: "PrintableASCII deve conter apenas caracteres ascii imprimíveis", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID", |
|
||||||
expected: "UUID deve ser um UUID válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID3", |
|
||||||
expected: "UUID3 deve ser um UUID versão 3 válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID4", |
|
||||||
expected: "UUID4 deve ser um UUID versão 4 válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID5", |
|
||||||
expected: "UUID5 deve ser um UUID versão 5 válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ULID", |
|
||||||
expected: "ULID deve ser um ULID válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN", |
|
||||||
expected: "ISBN deve ser um número de ISBN válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN10", |
|
||||||
expected: "ISBN10 deve ser um número ISBN-10 válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN13", |
|
||||||
expected: "ISBN13 deve ser um número ISBN-13 válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Excludes", |
|
||||||
expected: "Excludes não deve conter o texto 'text'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesAll", |
|
||||||
expected: "ExcludesAll não deve conter os seguintes caracteres '!@#$'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesRune", |
|
||||||
expected: "ExcludesRune não pode conter o seguinte '☻'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ContainsAny", |
|
||||||
expected: "ContainsAny deve conter pelo menos um dos seguintes caracteres '!@#$'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Contains", |
|
||||||
expected: "Contains deve conter o texto 'purpose'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Base64", |
|
||||||
expected: "Base64 deve ser uma string Base64 válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Email", |
|
||||||
expected: "Email deve ser um endereço de e-mail válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URL", |
|
||||||
expected: "URL deve ser um URL válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URI", |
|
||||||
expected: "URI deve ser um URI válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBColorString", |
|
||||||
expected: "RGBColorString deve ser uma cor RGB válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBAColorString", |
|
||||||
expected: "RGBAColorString deve ser uma cor RGBA válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLColorString", |
|
||||||
expected: "HSLColorString deve ser uma cor HSL válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLAColorString", |
|
||||||
expected: "HSLAColorString deve ser uma cor HSLA válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexadecimalString", |
|
||||||
expected: "HexadecimalString deve ser um hexadecimal válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexColorString", |
|
||||||
expected: "HexColorString deve ser uma cor HEX válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumberString", |
|
||||||
expected: "NumberString deve ser um número válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumericString", |
|
||||||
expected: "NumericString deve ser um valor numérico válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphanumString", |
|
||||||
expected: "AlphanumString deve conter apenas caracteres alfanuméricos", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphaString", |
|
||||||
expected: "AlphaString deve conter apenas caracteres alfabéticos", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtFieldString", |
|
||||||
expected: "LtFieldString deve ser menor que MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteFieldString", |
|
||||||
expected: "LteFieldString deve ser menor ou igual que MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtFieldString", |
|
||||||
expected: "GtFieldString deve ser maior que MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteFieldString", |
|
||||||
expected: "GteFieldString deve ser maior ou igual que MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeFieldString", |
|
||||||
expected: "NeFieldString não deve ser igual a EqFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtCSFieldString", |
|
||||||
expected: "LtCSFieldString deve ser menor que Inner.LtCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteCSFieldString", |
|
||||||
expected: "LteCSFieldString deve ser menor ou igual que Inner.LteCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtCSFieldString", |
|
||||||
expected: "GtCSFieldString deve ser maior que Inner.GtCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteCSFieldString", |
|
||||||
expected: "GteCSFieldString deve ser maior ou igual que Inner.GteCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeCSFieldString", |
|
||||||
expected: "NeCSFieldString não deve ser igual a Inner.NeCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqCSFieldString", |
|
||||||
expected: "EqCSFieldString deve ser igual a Inner.EqCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqFieldString", |
|
||||||
expected: "EqFieldString deve ser igual a MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteString", |
|
||||||
expected: "GteString deve ter pelo menos 3 caracteres", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteNumber", |
|
||||||
expected: "GteNumber deve ser maior ou igual a 5,56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteMultiple", |
|
||||||
expected: "GteMultiple deve conter pelo menos 2 items", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteTime", |
|
||||||
expected: "GteTime deve ser posterior ou igual à data/hora atual", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtString", |
|
||||||
expected: "GtString deve conter mais de 3 caracteres", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtNumber", |
|
||||||
expected: "GtNumber deve ser maior que 5,56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtMultiple", |
|
||||||
expected: "GtMultiple deve conter mais de 2 items", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtTime", |
|
||||||
expected: "GtTime deve ser posterior à data/hora atual", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteString", |
|
||||||
expected: "LteString deve ter no máximo 3 caracteres", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteNumber", |
|
||||||
expected: "LteNumber deve ser menor ou igual a 5,56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteMultiple", |
|
||||||
expected: "LteMultiple deve conter no máximo 2 items", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteTime", |
|
||||||
expected: "LteTime deve ser anterior ou igual à data/hora atual", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtString", |
|
||||||
expected: "LtString deve ter menos de 3 caracteres", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtNumber", |
|
||||||
expected: "LtNumber deve ser menor que 5,56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtMultiple", |
|
||||||
expected: "LtMultiple deve conter menos de 2 items", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtTime", |
|
||||||
expected: "LtTime deve ser anterior à data / hora atual", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeString", |
|
||||||
expected: "NeString não deve ser igual a ", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeNumber", |
|
||||||
expected: "NeNumber não deve ser igual a 0.00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeMultiple", |
|
||||||
expected: "NeMultiple não deve ser igual a 0", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqString", |
|
||||||
expected: "EqString não é igual a 3", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqNumber", |
|
||||||
expected: "EqNumber não é igual a 2.33", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqMultiple", |
|
||||||
expected: "EqMultiple não é igual a 7", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxString", |
|
||||||
expected: "MaxString deve ter no máximo 3 caracteres", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxNumber", |
|
||||||
expected: "MaxNumber deve ser 1.113,00 ou menos", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxMultiple", |
|
||||||
expected: "MaxMultiple deve conter no máximo 7 items", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinString", |
|
||||||
expected: "MinString deve ter pelo menos 1 caractere", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinNumber", |
|
||||||
expected: "MinNumber deve ser 1.113,00 ou superior", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinMultiple", |
|
||||||
expected: "MinMultiple deve conter pelo menos 7 items", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenString", |
|
||||||
expected: "LenString deve ter 1 caractere", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenNumber", |
|
||||||
expected: "LenNumber deve ser igual a 1.113,00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenMultiple", |
|
||||||
expected: "LenMultiple deve conter 7 items", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredString", |
|
||||||
expected: "RequiredString é obrigatório", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredNumber", |
|
||||||
expected: "RequiredNumber é obrigatório", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredMultiple", |
|
||||||
expected: "RequiredMultiple é obrigatório", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMinLen", |
|
||||||
expected: "StrPtrMinLen deve ter pelo menos 10 caracteres", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMaxLen", |
|
||||||
expected: "StrPtrMaxLen deve ter no máximo 1 caractere", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLen", |
|
||||||
expected: "StrPtrLen deve ter 2 caracteres", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLt", |
|
||||||
expected: "StrPtrLt deve ter menos de 1 caractere", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLte", |
|
||||||
expected: "StrPtrLte deve ter no máximo 1 caractere", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGt", |
|
||||||
expected: "StrPtrGt deve conter mais de 10 caracteres", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGte", |
|
||||||
expected: "StrPtrGte deve ter pelo menos 10 caracteres", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfString", |
|
||||||
expected: "OneOfString deve ser um de [red green]", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfInt", |
|
||||||
expected: "OneOfInt deve ser um de [5 63]", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UniqueSlice", |
|
||||||
expected: "UniqueSlice deve conter valores únicos", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UniqueArray", |
|
||||||
expected: "UniqueArray deve conter valores únicos", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UniqueMap", |
|
||||||
expected: "UniqueMap deve conter valores únicos", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.JSONString", |
|
||||||
expected: "JSONString deve ser uma string json válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LowercaseString", |
|
||||||
expected: "LowercaseString deve estar em minuscúlas", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UppercaseString", |
|
||||||
expected: "UppercaseString deve estar em maiúsculas", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Datetime", |
|
||||||
expected: "Datetime não está no formato 2006-01-02", |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
for _, tt := range tests { |
|
||||||
|
|
||||||
var fe validator.FieldError |
|
||||||
|
|
||||||
for _, e := range errs { |
|
||||||
if tt.ns == e.Namespace() { |
|
||||||
fe = e |
|
||||||
break |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
NotEqual(t, fe, nil) |
|
||||||
Equal(t, tt.expected, fe.Translate(trans)) |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
File diff suppressed because it is too large
Load Diff
@ -1,651 +0,0 @@ |
|||||||
package pt_BR |
|
||||||
|
|
||||||
import ( |
|
||||||
"testing" |
|
||||||
"time" |
|
||||||
|
|
||||||
. "github.com/go-playground/assert/v2" |
|
||||||
brazilian_portuguese "github.com/go-playground/locales/pt_BR" |
|
||||||
ut "github.com/go-playground/universal-translator" |
|
||||||
"github.com/go-playground/validator/v10" |
|
||||||
) |
|
||||||
|
|
||||||
func TestTranslations(t *testing.T) { |
|
||||||
|
|
||||||
ptbr := brazilian_portuguese.New() |
|
||||||
uni := ut.New(ptbr, ptbr) |
|
||||||
trans, _ := uni.GetTranslator("pt_BR") |
|
||||||
|
|
||||||
validate := validator.New() |
|
||||||
|
|
||||||
err := RegisterDefaultTranslations(validate, trans) |
|
||||||
Equal(t, err, nil) |
|
||||||
|
|
||||||
type Inner struct { |
|
||||||
EqCSFieldString string |
|
||||||
NeCSFieldString string |
|
||||||
GtCSFieldString string |
|
||||||
GteCSFieldString string |
|
||||||
LtCSFieldString string |
|
||||||
LteCSFieldString string |
|
||||||
} |
|
||||||
|
|
||||||
type Test struct { |
|
||||||
Inner Inner |
|
||||||
RequiredString string `validate:"required"` |
|
||||||
RequiredNumber int `validate:"required"` |
|
||||||
RequiredMultiple []string `validate:"required"` |
|
||||||
LenString string `validate:"len=1"` |
|
||||||
LenNumber float64 `validate:"len=1113.00"` |
|
||||||
LenMultiple []string `validate:"len=7"` |
|
||||||
MinString string `validate:"min=1"` |
|
||||||
MinNumber float64 `validate:"min=1113.00"` |
|
||||||
MinMultiple []string `validate:"min=7"` |
|
||||||
MaxString string `validate:"max=3"` |
|
||||||
MaxNumber float64 `validate:"max=1113.00"` |
|
||||||
MaxMultiple []string `validate:"max=7"` |
|
||||||
EqString string `validate:"eq=3"` |
|
||||||
EqNumber float64 `validate:"eq=2.33"` |
|
||||||
EqMultiple []string `validate:"eq=7"` |
|
||||||
NeString string `validate:"ne="` |
|
||||||
NeNumber float64 `validate:"ne=0.00"` |
|
||||||
NeMultiple []string `validate:"ne=0"` |
|
||||||
LtString string `validate:"lt=3"` |
|
||||||
LtNumber float64 `validate:"lt=5.56"` |
|
||||||
LtMultiple []string `validate:"lt=2"` |
|
||||||
LtTime time.Time `validate:"lt"` |
|
||||||
LteString string `validate:"lte=3"` |
|
||||||
LteNumber float64 `validate:"lte=5.56"` |
|
||||||
LteMultiple []string `validate:"lte=2"` |
|
||||||
LteTime time.Time `validate:"lte"` |
|
||||||
GtString string `validate:"gt=3"` |
|
||||||
GtNumber float64 `validate:"gt=5.56"` |
|
||||||
GtMultiple []string `validate:"gt=2"` |
|
||||||
GtTime time.Time `validate:"gt"` |
|
||||||
GteString string `validate:"gte=3"` |
|
||||||
GteNumber float64 `validate:"gte=5.56"` |
|
||||||
GteMultiple []string `validate:"gte=2"` |
|
||||||
GteTime time.Time `validate:"gte"` |
|
||||||
EqFieldString string `validate:"eqfield=MaxString"` |
|
||||||
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"` |
|
||||||
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"` |
|
||||||
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"` |
|
||||||
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"` |
|
||||||
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"` |
|
||||||
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"` |
|
||||||
NeFieldString string `validate:"nefield=EqFieldString"` |
|
||||||
GtFieldString string `validate:"gtfield=MaxString"` |
|
||||||
GteFieldString string `validate:"gtefield=MaxString"` |
|
||||||
LtFieldString string `validate:"ltfield=MaxString"` |
|
||||||
LteFieldString string `validate:"ltefield=MaxString"` |
|
||||||
AlphaString string `validate:"alpha"` |
|
||||||
AlphanumString string `validate:"alphanum"` |
|
||||||
NumericString string `validate:"numeric"` |
|
||||||
NumberString string `validate:"number"` |
|
||||||
HexadecimalString string `validate:"hexadecimal"` |
|
||||||
HexColorString string `validate:"hexcolor"` |
|
||||||
RGBColorString string `validate:"rgb"` |
|
||||||
RGBAColorString string `validate:"rgba"` |
|
||||||
HSLColorString string `validate:"hsl"` |
|
||||||
HSLAColorString string `validate:"hsla"` |
|
||||||
Email string `validate:"email"` |
|
||||||
URL string `validate:"url"` |
|
||||||
URI string `validate:"uri"` |
|
||||||
Base64 string `validate:"base64"` |
|
||||||
Contains string `validate:"contains=purpose"` |
|
||||||
ContainsAny string `validate:"containsany=!@#$"` |
|
||||||
Excludes string `validate:"excludes=text"` |
|
||||||
ExcludesAll string `validate:"excludesall=!@#$"` |
|
||||||
ExcludesRune string `validate:"excludesrune=☻"` |
|
||||||
ISBN string `validate:"isbn"` |
|
||||||
ISBN10 string `validate:"isbn10"` |
|
||||||
ISBN13 string `validate:"isbn13"` |
|
||||||
UUID string `validate:"uuid"` |
|
||||||
UUID3 string `validate:"uuid3"` |
|
||||||
UUID4 string `validate:"uuid4"` |
|
||||||
UUID5 string `validate:"uuid5"` |
|
||||||
ULID string `validate:"ulid"` |
|
||||||
ASCII string `validate:"ascii"` |
|
||||||
PrintableASCII string `validate:"printascii"` |
|
||||||
MultiByte string `validate:"multibyte"` |
|
||||||
DataURI string `validate:"datauri"` |
|
||||||
Latitude string `validate:"latitude"` |
|
||||||
Longitude string `validate:"longitude"` |
|
||||||
SSN string `validate:"ssn"` |
|
||||||
IP string `validate:"ip"` |
|
||||||
IPv4 string `validate:"ipv4"` |
|
||||||
IPv6 string `validate:"ipv6"` |
|
||||||
CIDR string `validate:"cidr"` |
|
||||||
CIDRv4 string `validate:"cidrv4"` |
|
||||||
CIDRv6 string `validate:"cidrv6"` |
|
||||||
TCPAddr string `validate:"tcp_addr"` |
|
||||||
TCPAddrv4 string `validate:"tcp4_addr"` |
|
||||||
TCPAddrv6 string `validate:"tcp6_addr"` |
|
||||||
UDPAddr string `validate:"udp_addr"` |
|
||||||
UDPAddrv4 string `validate:"udp4_addr"` |
|
||||||
UDPAddrv6 string `validate:"udp6_addr"` |
|
||||||
IPAddr string `validate:"ip_addr"` |
|
||||||
IPAddrv4 string `validate:"ip4_addr"` |
|
||||||
IPAddrv6 string `validate:"ip6_addr"` |
|
||||||
UinxAddr string `validate:"unix_addr"` // can't fail from within Go's net package currently, but maybe in the future
|
|
||||||
MAC string `validate:"mac"` |
|
||||||
IsColor string `validate:"iscolor"` |
|
||||||
StrPtrMinLen *string `validate:"min=10"` |
|
||||||
StrPtrMaxLen *string `validate:"max=1"` |
|
||||||
StrPtrLen *string `validate:"len=2"` |
|
||||||
StrPtrLt *string `validate:"lt=1"` |
|
||||||
StrPtrLte *string `validate:"lte=1"` |
|
||||||
StrPtrGt *string `validate:"gt=10"` |
|
||||||
StrPtrGte *string `validate:"gte=10"` |
|
||||||
OneOfString string `validate:"oneof=red green"` |
|
||||||
OneOfInt int `validate:"oneof=5 63"` |
|
||||||
BooleanString string `validate:"boolean"` |
|
||||||
CveString string `validate:"cve"` |
|
||||||
} |
|
||||||
|
|
||||||
var test Test |
|
||||||
|
|
||||||
test.Inner.EqCSFieldString = "1234" |
|
||||||
test.Inner.GtCSFieldString = "1234" |
|
||||||
test.Inner.GteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.MaxString = "1234" |
|
||||||
test.MaxNumber = 2000 |
|
||||||
test.MaxMultiple = make([]string, 9) |
|
||||||
|
|
||||||
test.LtString = "1234" |
|
||||||
test.LtNumber = 6 |
|
||||||
test.LtMultiple = make([]string, 3) |
|
||||||
test.LtTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LteString = "1234" |
|
||||||
test.LteNumber = 6 |
|
||||||
test.LteMultiple = make([]string, 3) |
|
||||||
test.LteTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LtFieldString = "12345" |
|
||||||
test.LteFieldString = "12345" |
|
||||||
|
|
||||||
test.LtCSFieldString = "1234" |
|
||||||
test.LteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.AlphaString = "abc3" |
|
||||||
test.AlphanumString = "abc3!" |
|
||||||
test.NumericString = "12E.00" |
|
||||||
test.NumberString = "12E" |
|
||||||
test.BooleanString = "A" |
|
||||||
test.CveString = "A" |
|
||||||
|
|
||||||
test.Excludes = "este é um texto de teste" |
|
||||||
test.ExcludesAll = "Isso é Ótimo!" |
|
||||||
test.ExcludesRune = "Amo isso ☻" |
|
||||||
|
|
||||||
test.ASCII = "カタカナ" |
|
||||||
test.PrintableASCII = "カタカナ" |
|
||||||
|
|
||||||
test.MultiByte = "1234feerf" |
|
||||||
|
|
||||||
s := "toolong" |
|
||||||
test.StrPtrMaxLen = &s |
|
||||||
test.StrPtrLen = &s |
|
||||||
|
|
||||||
err = validate.Struct(test) |
|
||||||
NotEqual(t, err, nil) |
|
||||||
|
|
||||||
errs, ok := err.(validator.ValidationErrors) |
|
||||||
Equal(t, ok, true) |
|
||||||
|
|
||||||
tests := []struct { |
|
||||||
ns string |
|
||||||
expected string |
|
||||||
}{ |
|
||||||
{ |
|
||||||
ns: "Test.IsColor", |
|
||||||
expected: "IsColor deve ser uma cor válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MAC", |
|
||||||
expected: "MAC deve conter um endereço MAC válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddr", |
|
||||||
expected: "IPAddr deve ser um endereço IP resolvível", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv4", |
|
||||||
expected: "IPAddrv4 deve ser um endereço IPv4 resolvível", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv6", |
|
||||||
expected: "IPAddrv6 deve ser um endereço IPv6 resolvível", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddr", |
|
||||||
expected: "UDPAddr deve ser um endereço UDP válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv4", |
|
||||||
expected: "UDPAddrv4 deve ser um endereço IPv4 UDP válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv6", |
|
||||||
expected: "UDPAddrv6 deve ser um endereço IPv6 UDP válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddr", |
|
||||||
expected: "TCPAddr deve ser um endereço TCP válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv4", |
|
||||||
expected: "TCPAddrv4 deve ser um endereço IPv4 TCP válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv6", |
|
||||||
expected: "TCPAddrv6 deve ser um endereço IPv6 TCP válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDR", |
|
||||||
expected: "CIDR deve conter uma notação CIDR válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv4", |
|
||||||
expected: "CIDRv4 deve conter uma notação CIDR válida para um endereço IPv4", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv6", |
|
||||||
expected: "CIDRv6 deve conter uma notação CIDR válida para um endereço IPv6", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.SSN", |
|
||||||
expected: "SSN deve ser um número SSN válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IP", |
|
||||||
expected: "IP deve ser um endereço de IP válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv4", |
|
||||||
expected: "IPv4 deve ser um endereço IPv4 válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv6", |
|
||||||
expected: "IPv6 deve ser um endereço IPv6 válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.DataURI", |
|
||||||
expected: "DataURI deve conter um URI data válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Latitude", |
|
||||||
expected: "Latitude deve conter uma coordenada de latitude válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Longitude", |
|
||||||
expected: "Longitude deve conter uma coordenada de longitude válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MultiByte", |
|
||||||
expected: "MultiByte deve conter caracteres multibyte", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ASCII", |
|
||||||
expected: "ASCII deve conter apenas caracteres ascii", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.PrintableASCII", |
|
||||||
expected: "PrintableASCII deve conter apenas caracteres ascii imprimíveis", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID", |
|
||||||
expected: "UUID deve ser um UUID válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID3", |
|
||||||
expected: "UUID3 deve ser um UUID versão 3 válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID4", |
|
||||||
expected: "UUID4 deve ser um UUID versão 4 válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID5", |
|
||||||
expected: "UUID5 deve ser um UUID versão 5 válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ULID", |
|
||||||
expected: "ULID deve ser uma ULID válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN", |
|
||||||
expected: "ISBN deve ser um número ISBN válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN10", |
|
||||||
expected: "ISBN10 deve ser um número ISBN-10 válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN13", |
|
||||||
expected: "ISBN13 deve ser um número ISBN-13 válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Excludes", |
|
||||||
expected: "Excludes não deve conter o texto 'text'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesAll", |
|
||||||
expected: "ExcludesAll não deve conter nenhum dos caracteres '!@#$'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesRune", |
|
||||||
expected: "ExcludesRune não deve conter '☻'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ContainsAny", |
|
||||||
expected: "ContainsAny deve conter pelo menos um dos caracteres '!@#$'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Contains", |
|
||||||
expected: "Contains deve conter o texto 'purpose'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Base64", |
|
||||||
expected: "Base64 deve ser uma string Base64 válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Email", |
|
||||||
expected: "Email deve ser um endereço de e-mail válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URL", |
|
||||||
expected: "URL deve ser uma URL válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URI", |
|
||||||
expected: "URI deve ser uma URI válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBColorString", |
|
||||||
expected: "RGBColorString deve ser uma cor RGB válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBAColorString", |
|
||||||
expected: "RGBAColorString deve ser uma cor RGBA válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLColorString", |
|
||||||
expected: "HSLColorString deve ser uma cor HSL válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLAColorString", |
|
||||||
expected: "HSLAColorString deve ser uma cor HSLA válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexadecimalString", |
|
||||||
expected: "HexadecimalString deve ser um hexadecimal válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexColorString", |
|
||||||
expected: "HexColorString deve ser uma cor HEX válida", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumberString", |
|
||||||
expected: "NumberString deve ser um número válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumericString", |
|
||||||
expected: "NumericString deve ser um valor numérico válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphanumString", |
|
||||||
expected: "AlphanumString deve conter caracteres alfanuméricos", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphaString", |
|
||||||
expected: "AlphaString deve conter caracteres alfabéticos", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtFieldString", |
|
||||||
expected: "LtFieldString deve ser menor que MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteFieldString", |
|
||||||
expected: "LteFieldString deve ser menor ou igual a MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtFieldString", |
|
||||||
expected: "GtFieldString deve ser maior do que MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteFieldString", |
|
||||||
expected: "GteFieldString deve ser maior ou igual a MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeFieldString", |
|
||||||
expected: "NeFieldString não deve ser igual a EqFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtCSFieldString", |
|
||||||
expected: "LtCSFieldString deve ser menor que Inner.LtCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteCSFieldString", |
|
||||||
expected: "LteCSFieldString deve ser menor ou igual a Inner.LteCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtCSFieldString", |
|
||||||
expected: "GtCSFieldString deve ser maior do que Inner.GtCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteCSFieldString", |
|
||||||
expected: "GteCSFieldString deve ser maior ou igual a Inner.GteCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeCSFieldString", |
|
||||||
expected: "NeCSFieldString não deve ser igual a Inner.NeCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqCSFieldString", |
|
||||||
expected: "EqCSFieldString deve ser igual a Inner.EqCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqFieldString", |
|
||||||
expected: "EqFieldString deve ser igual a MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteString", |
|
||||||
expected: "GteString deve ter pelo menos 3 caracteres", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteNumber", |
|
||||||
expected: "GteNumber deve ser 5,56 ou superior", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteMultiple", |
|
||||||
expected: "GteMultiple deve conter pelo menos 2 itens", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteTime", |
|
||||||
expected: "GteTime deve ser maior ou igual à Data e Hora atual", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtString", |
|
||||||
expected: "GtString deve ter mais de 3 caracteres", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtNumber", |
|
||||||
expected: "GtNumber deve ser maior do que 5,56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtMultiple", |
|
||||||
expected: "GtMultiple deve conter mais de 2 itens", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtTime", |
|
||||||
expected: "GtTime deve ser maior que a Data e Hora atual", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteString", |
|
||||||
expected: "LteString deve ter no máximo 3 caracteres", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteNumber", |
|
||||||
expected: "LteNumber deve ser 5,56 ou menor", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteMultiple", |
|
||||||
expected: "LteMultiple deve conter no máximo 2 itens", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteTime", |
|
||||||
expected: "LteTime deve ser menor ou igual à Data e Hora atual", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtString", |
|
||||||
expected: "LtString deve ter menos de 3 caracteres", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtNumber", |
|
||||||
expected: "LtNumber deve ser menor que 5,56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtMultiple", |
|
||||||
expected: "LtMultiple deve conter menos de 2 itens", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtTime", |
|
||||||
expected: "LtTime deve ser inferior à Data e Hora atual", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeString", |
|
||||||
expected: "NeString não deve ser igual a ", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeNumber", |
|
||||||
expected: "NeNumber não deve ser igual a 0.00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeMultiple", |
|
||||||
expected: "NeMultiple não deve ser igual a 0", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqString", |
|
||||||
expected: "EqString não é igual a 3", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqNumber", |
|
||||||
expected: "EqNumber não é igual a 2.33", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqMultiple", |
|
||||||
expected: "EqMultiple não é igual a 7", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxString", |
|
||||||
expected: "MaxString deve ter no máximo 3 caracteres", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxNumber", |
|
||||||
expected: "MaxNumber deve ser 1.113,00 ou menor", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxMultiple", |
|
||||||
expected: "MaxMultiple deve conter no máximo 7 itens", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinString", |
|
||||||
expected: "MinString deve ter pelo menos 1 caractere", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinNumber", |
|
||||||
expected: "MinNumber deve ser 1.113,00 ou superior", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinMultiple", |
|
||||||
expected: "MinMultiple deve conter pelo menos 7 itens", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenString", |
|
||||||
expected: "LenString deve ter 1 caractere", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenNumber", |
|
||||||
expected: "LenNumber deve ser igual a 1.113,00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenMultiple", |
|
||||||
expected: "LenMultiple deve conter 7 itens", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredString", |
|
||||||
expected: "RequiredString é um campo obrigatório", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredNumber", |
|
||||||
expected: "RequiredNumber é um campo obrigatório", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredMultiple", |
|
||||||
expected: "RequiredMultiple é um campo obrigatório", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMinLen", |
|
||||||
expected: "StrPtrMinLen deve ter pelo menos 10 caracteres", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMaxLen", |
|
||||||
expected: "StrPtrMaxLen deve ter no máximo 1 caractere", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLen", |
|
||||||
expected: "StrPtrLen deve ter 2 caracteres", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLt", |
|
||||||
expected: "StrPtrLt deve ter menos de 1 caractere", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLte", |
|
||||||
expected: "StrPtrLte deve ter no máximo 1 caractere", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGt", |
|
||||||
expected: "StrPtrGt deve ter mais de 10 caracteres", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGte", |
|
||||||
expected: "StrPtrGte deve ter pelo menos 10 caracteres", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfString", |
|
||||||
expected: "OneOfString deve ser um de [red green]", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfInt", |
|
||||||
expected: "OneOfInt deve ser um de [5 63]", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.BooleanString", |
|
||||||
expected: "BooleanString deve ser um valor booleano válido", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CveString", |
|
||||||
expected: "CveString deve ser um identificador cve válido", |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
for _, tt := range tests { |
|
||||||
|
|
||||||
var fe validator.FieldError |
|
||||||
|
|
||||||
for _, e := range errs { |
|
||||||
if tt.ns == e.Namespace() { |
|
||||||
fe = e |
|
||||||
break |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
NotEqual(t, fe, nil) |
|
||||||
Equal(t, tt.expected, fe.Translate(trans)) |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,657 +0,0 @@ |
|||||||
package tr |
|
||||||
|
|
||||||
import ( |
|
||||||
"testing" |
|
||||||
"time" |
|
||||||
|
|
||||||
. "github.com/go-playground/assert/v2" |
|
||||||
turkish "github.com/go-playground/locales/tr" |
|
||||||
ut "github.com/go-playground/universal-translator" |
|
||||||
"github.com/go-playground/validator/v10" |
|
||||||
) |
|
||||||
|
|
||||||
func TestTranslations(t *testing.T) { |
|
||||||
|
|
||||||
tr := turkish.New() |
|
||||||
uni := ut.New(tr, tr) |
|
||||||
trans, _ := uni.GetTranslator("tr") |
|
||||||
|
|
||||||
validate := validator.New() |
|
||||||
|
|
||||||
err := RegisterDefaultTranslations(validate, trans) |
|
||||||
Equal(t, err, nil) |
|
||||||
|
|
||||||
type Inner struct { |
|
||||||
EqCSFieldString string |
|
||||||
NeCSFieldString string |
|
||||||
GtCSFieldString string |
|
||||||
GteCSFieldString string |
|
||||||
LtCSFieldString string |
|
||||||
LteCSFieldString string |
|
||||||
} |
|
||||||
|
|
||||||
type Test struct { |
|
||||||
Inner Inner |
|
||||||
RequiredString string `validate:"required"` |
|
||||||
RequiredNumber int `validate:"required"` |
|
||||||
RequiredMultiple []string `validate:"required"` |
|
||||||
LenString string `validate:"len=1"` |
|
||||||
LenNumber float64 `validate:"len=1113.00"` |
|
||||||
LenMultiple []string `validate:"len=7"` |
|
||||||
MinString string `validate:"min=1"` |
|
||||||
MinNumber float64 `validate:"min=1113.00"` |
|
||||||
MinMultiple []string `validate:"min=7"` |
|
||||||
MaxString string `validate:"max=3"` |
|
||||||
MaxNumber float64 `validate:"max=1113.00"` |
|
||||||
MaxMultiple []string `validate:"max=7"` |
|
||||||
EqString string `validate:"eq=3"` |
|
||||||
EqNumber float64 `validate:"eq=2.33"` |
|
||||||
EqMultiple []string `validate:"eq=7"` |
|
||||||
NeString string `validate:"ne="` |
|
||||||
NeNumber float64 `validate:"ne=0.00"` |
|
||||||
NeMultiple []string `validate:"ne=0"` |
|
||||||
LtString string `validate:"lt=3"` |
|
||||||
LtNumber float64 `validate:"lt=5.56"` |
|
||||||
LtMultiple []string `validate:"lt=2"` |
|
||||||
LtTime time.Time `validate:"lt"` |
|
||||||
LteString string `validate:"lte=3"` |
|
||||||
LteNumber float64 `validate:"lte=5.56"` |
|
||||||
LteMultiple []string `validate:"lte=2"` |
|
||||||
LteTime time.Time `validate:"lte"` |
|
||||||
GtString string `validate:"gt=3"` |
|
||||||
GtNumber float64 `validate:"gt=5.56"` |
|
||||||
GtMultiple []string `validate:"gt=2"` |
|
||||||
GtTime time.Time `validate:"gt"` |
|
||||||
GteString string `validate:"gte=3"` |
|
||||||
GteNumber float64 `validate:"gte=5.56"` |
|
||||||
GteMultiple []string `validate:"gte=2"` |
|
||||||
GteTime time.Time `validate:"gte"` |
|
||||||
EqFieldString string `validate:"eqfield=MaxString"` |
|
||||||
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"` |
|
||||||
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"` |
|
||||||
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"` |
|
||||||
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"` |
|
||||||
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"` |
|
||||||
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"` |
|
||||||
NeFieldString string `validate:"nefield=EqFieldString"` |
|
||||||
GtFieldString string `validate:"gtfield=MaxString"` |
|
||||||
GteFieldString string `validate:"gtefield=MaxString"` |
|
||||||
LtFieldString string `validate:"ltfield=MaxString"` |
|
||||||
LteFieldString string `validate:"ltefield=MaxString"` |
|
||||||
AlphaString string `validate:"alpha"` |
|
||||||
AlphanumString string `validate:"alphanum"` |
|
||||||
NumericString string `validate:"numeric"` |
|
||||||
NumberString string `validate:"number"` |
|
||||||
HexadecimalString string `validate:"hexadecimal"` |
|
||||||
HexColorString string `validate:"hexcolor"` |
|
||||||
RGBColorString string `validate:"rgb"` |
|
||||||
RGBAColorString string `validate:"rgba"` |
|
||||||
HSLColorString string `validate:"hsl"` |
|
||||||
HSLAColorString string `validate:"hsla"` |
|
||||||
Email string `validate:"email"` |
|
||||||
URL string `validate:"url"` |
|
||||||
URI string `validate:"uri"` |
|
||||||
Base64 string `validate:"base64"` |
|
||||||
Contains string `validate:"contains=purpose"` |
|
||||||
ContainsAny string `validate:"containsany=!@#$"` |
|
||||||
Excludes string `validate:"excludes=text"` |
|
||||||
ExcludesAll string `validate:"excludesall=!@#$"` |
|
||||||
ExcludesRune string `validate:"excludesrune=☻"` |
|
||||||
ISBN string `validate:"isbn"` |
|
||||||
ISBN10 string `validate:"isbn10"` |
|
||||||
ISBN13 string `validate:"isbn13"` |
|
||||||
UUID string `validate:"uuid"` |
|
||||||
UUID3 string `validate:"uuid3"` |
|
||||||
UUID4 string `validate:"uuid4"` |
|
||||||
UUID5 string `validate:"uuid5"` |
|
||||||
ULID string `validate:"ulid"` |
|
||||||
ASCII string `validate:"ascii"` |
|
||||||
PrintableASCII string `validate:"printascii"` |
|
||||||
MultiByte string `validate:"multibyte"` |
|
||||||
DataURI string `validate:"datauri"` |
|
||||||
Latitude string `validate:"latitude"` |
|
||||||
Longitude string `validate:"longitude"` |
|
||||||
SSN string `validate:"ssn"` |
|
||||||
IP string `validate:"ip"` |
|
||||||
IPv4 string `validate:"ipv4"` |
|
||||||
IPv6 string `validate:"ipv6"` |
|
||||||
CIDR string `validate:"cidr"` |
|
||||||
CIDRv4 string `validate:"cidrv4"` |
|
||||||
CIDRv6 string `validate:"cidrv6"` |
|
||||||
TCPAddr string `validate:"tcp_addr"` |
|
||||||
TCPAddrv4 string `validate:"tcp4_addr"` |
|
||||||
TCPAddrv6 string `validate:"tcp6_addr"` |
|
||||||
UDPAddr string `validate:"udp_addr"` |
|
||||||
UDPAddrv4 string `validate:"udp4_addr"` |
|
||||||
UDPAddrv6 string `validate:"udp6_addr"` |
|
||||||
IPAddr string `validate:"ip_addr"` |
|
||||||
IPAddrv4 string `validate:"ip4_addr"` |
|
||||||
IPAddrv6 string `validate:"ip6_addr"` |
|
||||||
UinxAddr string `validate:"unix_addr"` // can't fail from within Go's net package currently, but maybe in the future
|
|
||||||
MAC string `validate:"mac"` |
|
||||||
IsColor string `validate:"iscolor"` |
|
||||||
StrPtrMinLen *string `validate:"min=10"` |
|
||||||
StrPtrMaxLen *string `validate:"max=1"` |
|
||||||
StrPtrLen *string `validate:"len=2"` |
|
||||||
StrPtrLt *string `validate:"lt=1"` |
|
||||||
StrPtrLte *string `validate:"lte=1"` |
|
||||||
StrPtrGt *string `validate:"gt=10"` |
|
||||||
StrPtrGte *string `validate:"gte=10"` |
|
||||||
OneOfString string `validate:"oneof=red green"` |
|
||||||
OneOfInt int `validate:"oneof=5 63"` |
|
||||||
UniqueSlice []string `validate:"unique"` |
|
||||||
UniqueArray [3]string `validate:"unique"` |
|
||||||
UniqueMap map[string]string `validate:"unique"` |
|
||||||
} |
|
||||||
|
|
||||||
var test Test |
|
||||||
|
|
||||||
test.Inner.EqCSFieldString = "1234" |
|
||||||
test.Inner.GtCSFieldString = "1234" |
|
||||||
test.Inner.GteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.MaxString = "1234" |
|
||||||
test.MaxNumber = 2000 |
|
||||||
test.MaxMultiple = make([]string, 9) |
|
||||||
|
|
||||||
test.LtString = "1234" |
|
||||||
test.LtNumber = 6 |
|
||||||
test.LtMultiple = make([]string, 3) |
|
||||||
test.LtTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LteString = "1234" |
|
||||||
test.LteNumber = 6 |
|
||||||
test.LteMultiple = make([]string, 3) |
|
||||||
test.LteTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LtFieldString = "12345" |
|
||||||
test.LteFieldString = "12345" |
|
||||||
|
|
||||||
test.LtCSFieldString = "1234" |
|
||||||
test.LteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.AlphaString = "abc3" |
|
||||||
test.AlphanumString = "abc3!" |
|
||||||
test.NumericString = "12E.00" |
|
||||||
test.NumberString = "12E" |
|
||||||
|
|
||||||
test.Excludes = "this is some test text" |
|
||||||
test.ExcludesAll = "This is Great!" |
|
||||||
test.ExcludesRune = "Love it ☻" |
|
||||||
|
|
||||||
test.ASCII = "カタカナ" |
|
||||||
test.PrintableASCII = "カタカナ" |
|
||||||
|
|
||||||
test.MultiByte = "1234feerf" |
|
||||||
|
|
||||||
s := "toolong" |
|
||||||
test.StrPtrMaxLen = &s |
|
||||||
test.StrPtrLen = &s |
|
||||||
|
|
||||||
test.UniqueSlice = []string{"1234", "1234"} |
|
||||||
test.UniqueMap = map[string]string{"key1": "1234", "key2": "1234"} |
|
||||||
|
|
||||||
err = validate.Struct(test) |
|
||||||
NotEqual(t, err, nil) |
|
||||||
|
|
||||||
errs, ok := err.(validator.ValidationErrors) |
|
||||||
Equal(t, ok, true) |
|
||||||
|
|
||||||
tests := []struct { |
|
||||||
ns string |
|
||||||
expected string |
|
||||||
}{ |
|
||||||
{ |
|
||||||
ns: "Test.IsColor", |
|
||||||
expected: "IsColor geçerli bir renk olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MAC", |
|
||||||
expected: "MAC geçerli bir MAC adresi içermelidir", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddr", |
|
||||||
expected: "IPAddr çözülebilir bir IP adresi olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv4", |
|
||||||
expected: "IPAddrv4 çözülebilir bir IPv4 adresi olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv6", |
|
||||||
expected: "IPAddrv6 çözülebilir bir IPv6 adresi olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddr", |
|
||||||
expected: "UDPAddr geçerli bir UDP adresi olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv4", |
|
||||||
expected: "UDPAddrv4 geçerli bir IPv4 UDP adresi olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv6", |
|
||||||
expected: "UDPAddrv6 geçerli bir IPv6 UDP adresi olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddr", |
|
||||||
expected: "TCPAddr geçerli bir TCP adresi olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv4", |
|
||||||
expected: "TCPAddrv4 geçerli bir IPv4 TCP adresi olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv6", |
|
||||||
expected: "TCPAddrv6 geçerli bir IPv6 TCP adresi olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDR", |
|
||||||
expected: "CIDR geçerli bir CIDR gösterimi içermelidir", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv4", |
|
||||||
expected: "CIDRv4 bir IPv4 adresi için geçerli bir CIDR gösterimi içermelidir", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv6", |
|
||||||
expected: "CIDRv6 bir IPv6 adresi için geçerli bir CIDR gösterimi içermelidir", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.SSN", |
|
||||||
expected: "SSN geçerli bir SSN numarası olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IP", |
|
||||||
expected: "IP geçerli bir IP adresi olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv4", |
|
||||||
expected: "IPv4 geçerli bir IPv4 adresi olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv6", |
|
||||||
expected: "IPv6 geçerli bir IPv6 adresi olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.DataURI", |
|
||||||
expected: "DataURI geçerli bir Veri URI içermelidir", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Latitude", |
|
||||||
expected: "Latitude geçerli bir enlem koordinatı içermelidir", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Longitude", |
|
||||||
expected: "Longitude geçerli bir boylam koordinatı içermelidir", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MultiByte", |
|
||||||
expected: "MultiByte çok baytlı karakterler içermelidir", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ASCII", |
|
||||||
expected: "ASCII yalnızca ascii karakterler içermelidir", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.PrintableASCII", |
|
||||||
expected: "PrintableASCII yalnızca yazdırılabilir ascii karakterleri içermelidir", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID", |
|
||||||
expected: "UUID geçerli bir UUID olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID3", |
|
||||||
expected: "UUID3 geçerli bir sürüm 3 UUID olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID4", |
|
||||||
expected: "UUID4 geçerli bir sürüm 4 UUID olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID5", |
|
||||||
expected: "UUID5 geçerli bir sürüm 5 UUID olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ULID", |
|
||||||
expected: "ULID geçerli bir ULID olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN", |
|
||||||
expected: "ISBN geçerli bir ISBN numarası olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN10", |
|
||||||
expected: "ISBN10 geçerli bir ISBN-10 numarası olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN13", |
|
||||||
expected: "ISBN13 geçerli bir ISBN-13 numarası olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Excludes", |
|
||||||
expected: "Excludes, 'text' metnini içeremez", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesAll", |
|
||||||
expected: "ExcludesAll, '!@#$' karakterlerinden hiçbirini içeremez", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesRune", |
|
||||||
expected: "ExcludesRune, '☻' ifadesini içeremez", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ContainsAny", |
|
||||||
expected: "ContainsAny, '!@#$' karakterlerinden en az birini içermelidir", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Contains", |
|
||||||
expected: "Contains, 'purpose' metnini içermelidir", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Base64", |
|
||||||
expected: "Base64 geçerli bir Base64 karakter dizesi olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Email", |
|
||||||
expected: "Email geçerli bir e-posta adresi olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URL", |
|
||||||
expected: "URL geçerli bir URL olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URI", |
|
||||||
expected: "URI geçerli bir URI olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBColorString", |
|
||||||
expected: "RGBColorString geçerli bir RGB rengi olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBAColorString", |
|
||||||
expected: "RGBAColorString geçerli bir RGBA rengi olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLColorString", |
|
||||||
expected: "HSLColorString geçerli bir HSL rengi olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLAColorString", |
|
||||||
expected: "HSLAColorString geçerli bir HSLA rengi olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexadecimalString", |
|
||||||
expected: "HexadecimalString geçerli bir onaltılık olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexColorString", |
|
||||||
expected: "HexColorString geçerli bir HEX rengi olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumberString", |
|
||||||
expected: "NumberString geçerli bir sayı olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumericString", |
|
||||||
expected: "NumericString geçerli bir sayısal değer olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphanumString", |
|
||||||
expected: "AlphanumString yalnızca alfanümerik karakterler içerebilir", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphaString", |
|
||||||
expected: "AlphaString yalnızca alfabetik karakterler içerebilir", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtFieldString", |
|
||||||
expected: "LtFieldString, MaxString değerinden küçük olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteFieldString", |
|
||||||
expected: "LteFieldString, MaxString değerinden küçük veya ona eşit olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtFieldString", |
|
||||||
expected: "GtFieldString, MaxString değerinden büyük olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteFieldString", |
|
||||||
expected: "GteFieldString, MaxString değerinden büyük veya ona eşit olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeFieldString", |
|
||||||
expected: "NeFieldString, EqFieldString değerine eşit olmamalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtCSFieldString", |
|
||||||
expected: "LtCSFieldString, Inner.LtCSFieldString değerinden küçük olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteCSFieldString", |
|
||||||
expected: "LteCSFieldString, Inner.LteCSFieldString değerinden küçük veya ona eşit olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtCSFieldString", |
|
||||||
expected: "GtCSFieldString, Inner.GtCSFieldString değerinden büyük olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteCSFieldString", |
|
||||||
expected: "GteCSFieldString, Inner.GteCSFieldString değerinden küçük veya ona eşit olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeCSFieldString", |
|
||||||
expected: "NeCSFieldString, Inner.NeCSFieldString değerine eşit olmamalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqCSFieldString", |
|
||||||
expected: "EqCSFieldString, Inner.EqCSFieldString değerine eşit olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqFieldString", |
|
||||||
expected: "EqFieldString, MaxString değerine eşit olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteString", |
|
||||||
expected: "GteString en az 3 karakter uzunluğunda olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteNumber", |
|
||||||
expected: "GteNumber, 5,56 veya daha büyük olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteMultiple", |
|
||||||
expected: "GteMultiple en az 2 öğe içermelidir", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteTime", |
|
||||||
expected: "GteTime geçerli Tarih ve Saatten büyük veya ona eşit olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtString", |
|
||||||
expected: "GtString, 3 karakter uzunluğundan fazla olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtNumber", |
|
||||||
expected: "GtNumber, 5,56 değerinden büyük olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtMultiple", |
|
||||||
expected: "GtMultiple, 2 öğeden daha fazla içermelidir", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtTime", |
|
||||||
expected: "GtTime geçerli Tarih ve Saatten büyük olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteString", |
|
||||||
expected: "LteString en fazla 3 karakter uzunluğunda olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteNumber", |
|
||||||
expected: "LteNumber, 5,56 veya daha az olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteMultiple", |
|
||||||
expected: "LteMultiple, maksimum 2 öğe içermelidir", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteTime", |
|
||||||
expected: "LteTime geçerli Tarih ve Saate eşit veya daha küçük olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtString", |
|
||||||
expected: "LtString, 3 karakter uzunluğundan daha az olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtNumber", |
|
||||||
expected: "LtNumber, 5,56 değerinden küçük olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtMultiple", |
|
||||||
expected: "LtMultiple, 2 öğeden daha az içermelidir", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtTime", |
|
||||||
expected: "LtTime geçerli Tarih ve Saatten daha az olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeString", |
|
||||||
expected: "NeString, değerine eşit olmamalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeNumber", |
|
||||||
expected: "NeNumber, 0.00 değerine eşit olmamalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeMultiple", |
|
||||||
expected: "NeMultiple, 0 değerine eşit olmamalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqString", |
|
||||||
expected: "EqString, 3 değerine eşit değil", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqNumber", |
|
||||||
expected: "EqNumber, 2.33 değerine eşit değil", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqMultiple", |
|
||||||
expected: "EqMultiple, 7 değerine eşit değil", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxString", |
|
||||||
expected: "MaxString uzunluğu en fazla 3 karakter olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxNumber", |
|
||||||
expected: "MaxNumber, 1.113,00 veya daha az olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxMultiple", |
|
||||||
expected: "MaxMultiple maksimum 7 öğe içermelidir", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinString", |
|
||||||
expected: "MinString en az 1 karakter uzunluğunda olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinNumber", |
|
||||||
expected: "MinNumber, 1.113,00 veya daha büyük olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinMultiple", |
|
||||||
expected: "MinMultiple en az 7 öğe içermelidir", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenString", |
|
||||||
expected: "LenString uzunluğu 1 karakter olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenNumber", |
|
||||||
expected: "LenNumber, 1.113,00 değerine eşit olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenMultiple", |
|
||||||
expected: "LenMultiple, 7 öğe içermelidir", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredString", |
|
||||||
expected: "RequiredString zorunlu bir alandır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredNumber", |
|
||||||
expected: "RequiredNumber zorunlu bir alandır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredMultiple", |
|
||||||
expected: "RequiredMultiple zorunlu bir alandır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMinLen", |
|
||||||
expected: "StrPtrMinLen en az 10 karakter uzunluğunda olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMaxLen", |
|
||||||
expected: "StrPtrMaxLen uzunluğu en fazla 1 karakter olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLen", |
|
||||||
expected: "StrPtrLen uzunluğu 2 karakter olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLt", |
|
||||||
expected: "StrPtrLt, 1 karakter uzunluğundan daha az olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLte", |
|
||||||
expected: "StrPtrLte en fazla 1 karakter uzunluğunda olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGt", |
|
||||||
expected: "StrPtrGt, 10 karakter uzunluğundan fazla olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGte", |
|
||||||
expected: "StrPtrGte en az 10 karakter uzunluğunda olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfString", |
|
||||||
expected: "OneOfString, [red green]'dan biri olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfInt", |
|
||||||
expected: "OneOfInt, [5 63]'dan biri olmalıdır", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UniqueSlice", |
|
||||||
expected: "UniqueSlice benzersiz değerler içermelidir", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UniqueArray", |
|
||||||
expected: "UniqueArray benzersiz değerler içermelidir", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UniqueMap", |
|
||||||
expected: "UniqueMap benzersiz değerler içermelidir", |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
for _, tt := range tests { |
|
||||||
|
|
||||||
var fe validator.FieldError |
|
||||||
|
|
||||||
for _, e := range errs { |
|
||||||
if tt.ns == e.Namespace() { |
|
||||||
fe = e |
|
||||||
break |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
NotEqual(t, fe, nil) |
|
||||||
Equal(t, tt.expected, fe.Translate(trans)) |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
File diff suppressed because it is too large
Load Diff
@ -1,690 +0,0 @@ |
|||||||
package vi |
|
||||||
|
|
||||||
import ( |
|
||||||
"testing" |
|
||||||
"time" |
|
||||||
|
|
||||||
. "github.com/go-playground/assert/v2" |
|
||||||
vietnamese "github.com/go-playground/locales/vi" |
|
||||||
ut "github.com/go-playground/universal-translator" |
|
||||||
"github.com/go-playground/validator/v10" |
|
||||||
) |
|
||||||
|
|
||||||
func TestTranslations(t *testing.T) { |
|
||||||
vie := vietnamese.New() |
|
||||||
uni := ut.New(vie, vie) |
|
||||||
trans, _ := uni.GetTranslator("vi") |
|
||||||
|
|
||||||
validate := validator.New() |
|
||||||
|
|
||||||
err := RegisterDefaultTranslations(validate, trans) |
|
||||||
Equal(t, err, nil) |
|
||||||
|
|
||||||
type Inner struct { |
|
||||||
EqCSFieldString string |
|
||||||
NeCSFieldString string |
|
||||||
GtCSFieldString string |
|
||||||
GteCSFieldString string |
|
||||||
LtCSFieldString string |
|
||||||
LteCSFieldString string |
|
||||||
} |
|
||||||
|
|
||||||
type Test struct { |
|
||||||
Inner Inner |
|
||||||
RequiredString string `validate:"required"` |
|
||||||
RequiredNumber int `validate:"required"` |
|
||||||
RequiredMultiple []string `validate:"required"` |
|
||||||
LenString string `validate:"len=1"` |
|
||||||
LenNumber float64 `validate:"len=1113.00"` |
|
||||||
LenMultiple []string `validate:"len=7"` |
|
||||||
MinString string `validate:"min=1"` |
|
||||||
MinNumber float64 `validate:"min=1113.00"` |
|
||||||
MinMultiple []string `validate:"min=7"` |
|
||||||
MaxString string `validate:"max=3"` |
|
||||||
MaxNumber float64 `validate:"max=1113.00"` |
|
||||||
MaxMultiple []string `validate:"max=7"` |
|
||||||
EqString string `validate:"eq=3"` |
|
||||||
EqNumber float64 `validate:"eq=2.33"` |
|
||||||
EqMultiple []string `validate:"eq=7"` |
|
||||||
NeString string `validate:"ne="` |
|
||||||
NeNumber float64 `validate:"ne=0.00"` |
|
||||||
NeMultiple []string `validate:"ne=0"` |
|
||||||
LtString string `validate:"lt=3"` |
|
||||||
LtNumber float64 `validate:"lt=5.56"` |
|
||||||
LtMultiple []string `validate:"lt=2"` |
|
||||||
LtTime time.Time `validate:"lt"` |
|
||||||
LteString string `validate:"lte=3"` |
|
||||||
LteNumber float64 `validate:"lte=5.56"` |
|
||||||
LteMultiple []string `validate:"lte=2"` |
|
||||||
LteTime time.Time `validate:"lte"` |
|
||||||
GtString string `validate:"gt=3"` |
|
||||||
GtNumber float64 `validate:"gt=5.56"` |
|
||||||
GtMultiple []string `validate:"gt=2"` |
|
||||||
GtTime time.Time `validate:"gt"` |
|
||||||
GteString string `validate:"gte=3"` |
|
||||||
GteNumber float64 `validate:"gte=5.56"` |
|
||||||
GteMultiple []string `validate:"gte=2"` |
|
||||||
GteTime time.Time `validate:"gte"` |
|
||||||
EqFieldString string `validate:"eqfield=MaxString"` |
|
||||||
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"` |
|
||||||
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"` |
|
||||||
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"` |
|
||||||
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"` |
|
||||||
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"` |
|
||||||
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"` |
|
||||||
NeFieldString string `validate:"nefield=EqFieldString"` |
|
||||||
GtFieldString string `validate:"gtfield=MaxString"` |
|
||||||
GteFieldString string `validate:"gtefield=MaxString"` |
|
||||||
LtFieldString string `validate:"ltfield=MaxString"` |
|
||||||
LteFieldString string `validate:"ltefield=MaxString"` |
|
||||||
AlphaString string `validate:"alpha"` |
|
||||||
AlphanumString string `validate:"alphanum"` |
|
||||||
NumericString string `validate:"numeric"` |
|
||||||
NumberString string `validate:"number"` |
|
||||||
HexadecimalString string `validate:"hexadecimal"` |
|
||||||
HexColorString string `validate:"hexcolor"` |
|
||||||
RGBColorString string `validate:"rgb"` |
|
||||||
RGBAColorString string `validate:"rgba"` |
|
||||||
HSLColorString string `validate:"hsl"` |
|
||||||
HSLAColorString string `validate:"hsla"` |
|
||||||
Email string `validate:"email"` |
|
||||||
URL string `validate:"url"` |
|
||||||
URI string `validate:"uri"` |
|
||||||
Base64 string `validate:"base64"` |
|
||||||
Contains string `validate:"contains=purpose"` |
|
||||||
ContainsAny string `validate:"containsany=!@#$"` |
|
||||||
Excludes string `validate:"excludes=text"` |
|
||||||
ExcludesAll string `validate:"excludesall=!@#$"` |
|
||||||
ExcludesRune string `validate:"excludesrune=☻"` |
|
||||||
ISBN string `validate:"isbn"` |
|
||||||
ISBN10 string `validate:"isbn10"` |
|
||||||
ISBN13 string `validate:"isbn13"` |
|
||||||
UUID string `validate:"uuid"` |
|
||||||
UUID3 string `validate:"uuid3"` |
|
||||||
UUID4 string `validate:"uuid4"` |
|
||||||
UUID5 string `validate:"uuid5"` |
|
||||||
ASCII string `validate:"ascii"` |
|
||||||
PrintableASCII string `validate:"printascii"` |
|
||||||
MultiByte string `validate:"multibyte"` |
|
||||||
DataURI string `validate:"datauri"` |
|
||||||
Latitude string `validate:"latitude"` |
|
||||||
Longitude string `validate:"longitude"` |
|
||||||
SSN string `validate:"ssn"` |
|
||||||
IP string `validate:"ip"` |
|
||||||
IPv4 string `validate:"ipv4"` |
|
||||||
IPv6 string `validate:"ipv6"` |
|
||||||
CIDR string `validate:"cidr"` |
|
||||||
CIDRv4 string `validate:"cidrv4"` |
|
||||||
CIDRv6 string `validate:"cidrv6"` |
|
||||||
TCPAddr string `validate:"tcp_addr"` |
|
||||||
TCPAddrv4 string `validate:"tcp4_addr"` |
|
||||||
TCPAddrv6 string `validate:"tcp6_addr"` |
|
||||||
UDPAddr string `validate:"udp_addr"` |
|
||||||
UDPAddrv4 string `validate:"udp4_addr"` |
|
||||||
UDPAddrv6 string `validate:"udp6_addr"` |
|
||||||
IPAddr string `validate:"ip_addr"` |
|
||||||
IPAddrv4 string `validate:"ip4_addr"` |
|
||||||
IPAddrv6 string `validate:"ip6_addr"` |
|
||||||
UinxAddr string `validate:"unix_addr"` // can't fail from within Go's net package currently, but maybe in the future
|
|
||||||
MAC string `validate:"mac"` |
|
||||||
IsColor string `validate:"iscolor"` |
|
||||||
StrPtrMinLen *string `validate:"min=10"` |
|
||||||
StrPtrMaxLen *string `validate:"max=1"` |
|
||||||
StrPtrLen *string `validate:"len=2"` |
|
||||||
StrPtrLt *string `validate:"lt=1"` |
|
||||||
StrPtrLte *string `validate:"lte=1"` |
|
||||||
StrPtrGt *string `validate:"gt=10"` |
|
||||||
StrPtrGte *string `validate:"gte=10"` |
|
||||||
OneOfString string `validate:"oneof=red green"` |
|
||||||
OneOfInt int `validate:"oneof=5 63"` |
|
||||||
UniqueSlice []string `validate:"unique"` |
|
||||||
UniqueArray [3]string `validate:"unique"` |
|
||||||
UniqueMap map[string]string `validate:"unique"` |
|
||||||
JSONString string `validate:"json"` |
|
||||||
JWTString string `validate:"jwt"` |
|
||||||
LowercaseString string `validate:"lowercase"` |
|
||||||
UppercaseString string `validate:"uppercase"` |
|
||||||
Datetime string `validate:"datetime=2006-01-02"` |
|
||||||
PostCode string `validate:"postcode_iso3166_alpha2=SG"` |
|
||||||
PostCodeCountry string |
|
||||||
PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"` |
|
||||||
} |
|
||||||
|
|
||||||
var test Test |
|
||||||
|
|
||||||
test.Inner.EqCSFieldString = "1234" |
|
||||||
test.Inner.GtCSFieldString = "1234" |
|
||||||
test.Inner.GteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.MaxString = "1234" |
|
||||||
test.MaxNumber = 2000 |
|
||||||
test.MaxMultiple = make([]string, 9) |
|
||||||
|
|
||||||
test.LtString = "1234" |
|
||||||
test.LtNumber = 6 |
|
||||||
test.LtMultiple = make([]string, 3) |
|
||||||
test.LtTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LteString = "1234" |
|
||||||
test.LteNumber = 6 |
|
||||||
test.LteMultiple = make([]string, 3) |
|
||||||
test.LteTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LtFieldString = "12345" |
|
||||||
test.LteFieldString = "12345" |
|
||||||
|
|
||||||
test.LtCSFieldString = "1234" |
|
||||||
test.LteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.AlphaString = "abc3" |
|
||||||
test.AlphanumString = "abc3!" |
|
||||||
test.NumericString = "12E.00" |
|
||||||
test.NumberString = "12E" |
|
||||||
|
|
||||||
test.Excludes = "this is some test text" |
|
||||||
test.ExcludesAll = "This is Great!" |
|
||||||
test.ExcludesRune = "Love it ☻" |
|
||||||
|
|
||||||
test.ASCII = "カタカナ" |
|
||||||
test.PrintableASCII = "カタカナ" |
|
||||||
|
|
||||||
test.MultiByte = "1234feerf" |
|
||||||
|
|
||||||
test.LowercaseString = "ABCDEFG" |
|
||||||
test.UppercaseString = "abcdefg" |
|
||||||
|
|
||||||
s := "toolong" |
|
||||||
test.StrPtrMaxLen = &s |
|
||||||
test.StrPtrLen = &s |
|
||||||
|
|
||||||
test.UniqueSlice = []string{"1234", "1234"} |
|
||||||
test.UniqueMap = map[string]string{"key1": "1234", "key2": "1234"} |
|
||||||
test.Datetime = "2008-Feb-01" |
|
||||||
|
|
||||||
err = validate.Struct(test) |
|
||||||
NotEqual(t, err, nil) |
|
||||||
|
|
||||||
errs, ok := err.(validator.ValidationErrors) |
|
||||||
Equal(t, ok, true) |
|
||||||
|
|
||||||
tests := []struct { |
|
||||||
ns string |
|
||||||
expected string |
|
||||||
}{ |
|
||||||
{ |
|
||||||
ns: "Test.IsColor", |
|
||||||
expected: "IsColor phải là màu sắc hợp lệ", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MAC", |
|
||||||
expected: "MAC chỉ được chứa địa chỉ MAC", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddr", |
|
||||||
expected: "IPAddr phải là địa chỉ IP có thể phân giải", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv4", |
|
||||||
expected: "IPAddrv4 phải là địa chỉ IPv4 có thể phân giải", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv6", |
|
||||||
expected: "IPAddrv6 phải là địa chỉ IPv6 có thể phân giải", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddr", |
|
||||||
expected: "UDPAddr phải là địa chỉ UDP", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv4", |
|
||||||
expected: "UDPAddrv4 phải là địa chỉ IPv4 UDP", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv6", |
|
||||||
expected: "UDPAddrv6 phải là địa chỉ IPv6 UDP", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddr", |
|
||||||
expected: "TCPAddr phải là địa chỉ TCP", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv4", |
|
||||||
expected: "TCPAddrv4 phải là địa chỉ IPv4 TCP", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv6", |
|
||||||
expected: "TCPAddrv6 phải là địa chỉ IPv6 TCP", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDR", |
|
||||||
expected: "CIDR chỉ được chứa CIDR notation", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv4", |
|
||||||
expected: "CIDRv4 chỉ được chứa CIDR notation của một địa chỉ IPv4", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv6", |
|
||||||
expected: "CIDRv6 chỉ được chứa CIDR notation của một địa chỉ IPv6", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.SSN", |
|
||||||
expected: "SSN phải là SSN number", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IP", |
|
||||||
expected: "IP phải là địa chỉ IP", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv4", |
|
||||||
expected: "IPv4 phải là địa chỉ IPv4", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv6", |
|
||||||
expected: "IPv6 phải là địa chỉ IPv6", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.DataURI", |
|
||||||
expected: "DataURI chỉ được chứa Data URI", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Latitude", |
|
||||||
expected: "Latitude chỉ được chứa latitude (vỹ độ)", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Longitude", |
|
||||||
expected: "Longitude chỉ được chứa longitude (kinh độ)", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MultiByte", |
|
||||||
expected: "MultiByte chỉ được chứa ký tự multibyte", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ASCII", |
|
||||||
expected: "ASCII chỉ được chứa ký tự ASCII", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.PrintableASCII", |
|
||||||
expected: "PrintableASCII chỉ được chứa ký tự ASCII có thể in ấn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID", |
|
||||||
expected: "UUID phải là giá trị UUID", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID3", |
|
||||||
expected: "UUID3 phải là giá trị UUID phiên bản 3", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID4", |
|
||||||
expected: "UUID4 phải là giá trị UUID phiên bản 4", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID5", |
|
||||||
expected: "UUID5 phải là giá trị UUID phiên bản 5", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN", |
|
||||||
expected: "ISBN phải là số ISBN", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN10", |
|
||||||
expected: "ISBN10 phải là số ISBN-10", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN13", |
|
||||||
expected: "ISBN13 phải là số ISBN-13", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Excludes", |
|
||||||
expected: "Excludes không được chứa chuỗi 'text'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesAll", |
|
||||||
expected: "ExcludesAll không được chứa bất kỳ ký tự nào trong nhóm ký tự '!@#$'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesRune", |
|
||||||
expected: "ExcludesRune không được chứa '☻'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ContainsAny", |
|
||||||
expected: "ContainsAny phải chứa ít nhất 1 trong cách ký tự sau '!@#$'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Contains", |
|
||||||
expected: "Contains phải chứa chuỗi 'purpose'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Base64", |
|
||||||
expected: "Base64 phải là giá trị chuỗi Base64", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Email", |
|
||||||
expected: "Email phải là giá trị email address", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URL", |
|
||||||
expected: "URL phải là giá trị URL", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URI", |
|
||||||
expected: "URI phải là giá trị URI", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBColorString", |
|
||||||
expected: "RGBColorString phải là giá trị RGB color", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBAColorString", |
|
||||||
expected: "RGBAColorString phải là giá trị RGBA color", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLColorString", |
|
||||||
expected: "HSLColorString phải là giá trị HSL color", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLAColorString", |
|
||||||
expected: "HSLAColorString phải là giá trị HSLA color", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexadecimalString", |
|
||||||
expected: "HexadecimalString phải là giá trị hexadecimal", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexColorString", |
|
||||||
expected: "HexColorString phải là giá trị HEX color", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumberString", |
|
||||||
expected: "NumberString chỉ được chứa giá trị số", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumericString", |
|
||||||
expected: "NumericString chỉ được chứa giá trị số hoặc số dưới dạng chữ", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphanumString", |
|
||||||
expected: "AlphanumString chỉ được chứa ký tự dạng alphanumeric", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphaString", |
|
||||||
expected: "AlphaString chỉ được chứa ký tự dạng alphabetic", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtFieldString", |
|
||||||
expected: "LtFieldString chỉ được nhỏ hơn MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteFieldString", |
|
||||||
expected: "LteFieldString chỉ được nhỏ hơn hoặc bằng MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtFieldString", |
|
||||||
expected: "GtFieldString phải lớn hơn MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteFieldString", |
|
||||||
expected: "GteFieldString phải lớn hơn hoặc bằng MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeFieldString", |
|
||||||
expected: "NeFieldString không được phép bằng EqFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtCSFieldString", |
|
||||||
expected: "LtCSFieldString chỉ được nhỏ hơn Inner.LtCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteCSFieldString", |
|
||||||
expected: "LteCSFieldString chỉ được nhỏ hơn hoặc bằng Inner.LteCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtCSFieldString", |
|
||||||
expected: "GtCSFieldString phải lớn hơn Inner.GtCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteCSFieldString", |
|
||||||
expected: "GteCSFieldString phải lớn hơn hoặc bằng Inner.GteCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeCSFieldString", |
|
||||||
expected: "NeCSFieldString không được phép bằng Inner.NeCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqCSFieldString", |
|
||||||
expected: "EqCSFieldString phải bằng Inner.EqCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqFieldString", |
|
||||||
expected: "EqFieldString phải bằng MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteString", |
|
||||||
expected: "GteString phải có độ dài ít nhất 3 ký tự", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteNumber", |
|
||||||
expected: "GteNumber phải là 5,56 hoặc lớn hơn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteMultiple", |
|
||||||
expected: "GteMultiple phải chứa ít nhất 2 phần tử", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteTime", |
|
||||||
expected: "GteTime phải lớn hơn hoặc bằng Ngày & Giờ hiện tại", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtString", |
|
||||||
expected: "GtString phải có độ dài lớn hơn 3 ký tự", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtNumber", |
|
||||||
expected: "GtNumber phải lớn hơn 5,56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtMultiple", |
|
||||||
expected: "GtMultiple phải chứa nhiều hơn 2 phần tử", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtTime", |
|
||||||
expected: "GtTime phải lớn hơn Ngày & Giờ hiện tại", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteString", |
|
||||||
expected: "LteString chỉ được có độ dài tối đa là 3 ký tự", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteNumber", |
|
||||||
expected: "LteNumber phải là 5,56 hoặc nhỏ hơn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteMultiple", |
|
||||||
expected: "LteMultiple chỉ được chứa nhiều nhất 2 phần tử", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteTime", |
|
||||||
expected: "LteTime chỉ được nhỏ hơn hoặc bằng Ngày & Giờ hiện tại", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtString", |
|
||||||
expected: "LtString phải có độ dài nhỏ hơn 3 ký tự", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtNumber", |
|
||||||
expected: "LtNumber phải nhỏ hơn 5,56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtMultiple", |
|
||||||
expected: "LtMultiple chỉ được chứa ít hơn 2 phần tử", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtTime", |
|
||||||
expected: "LtTime phải nhỏ hơn Ngày & Giờ hiện tại", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeString", |
|
||||||
expected: "NeString không được bằng ", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeNumber", |
|
||||||
expected: "NeNumber không được bằng 0.00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeMultiple", |
|
||||||
expected: "NeMultiple không được bằng 0", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqString", |
|
||||||
expected: "EqString không bằng 3", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqNumber", |
|
||||||
expected: "EqNumber không bằng 2.33", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqMultiple", |
|
||||||
expected: "EqMultiple không bằng 7", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxString", |
|
||||||
expected: "MaxString chỉ được chứa tối đa 3 ký tự", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxNumber", |
|
||||||
expected: "MaxNumber phải là 1.113,00 hoặc nhỏ hơn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxMultiple", |
|
||||||
expected: "MaxMultiple chỉ được chứa tối đa 7 phần tử", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinString", |
|
||||||
expected: "MinString phải chứa ít nhất 1 ký tự", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinNumber", |
|
||||||
expected: "MinNumber phải bằng 1.113,00 hoặc lớn hơn", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinMultiple", |
|
||||||
expected: "MinMultiple phải chứa ít nhất 7 phần tử", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenString", |
|
||||||
expected: "LenString phải có độ dài là 1 ký tự", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenNumber", |
|
||||||
expected: "LenNumber phải bằng 1.113,00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenMultiple", |
|
||||||
expected: "LenMultiple phải chứa 7 phần tử", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredString", |
|
||||||
expected: "RequiredString không được bỏ trống", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredNumber", |
|
||||||
expected: "RequiredNumber không được bỏ trống", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredMultiple", |
|
||||||
expected: "RequiredMultiple không được bỏ trống", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMinLen", |
|
||||||
expected: "StrPtrMinLen phải chứa ít nhất 10 ký tự", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMaxLen", |
|
||||||
expected: "StrPtrMaxLen chỉ được chứa tối đa 1 ký tự", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLen", |
|
||||||
expected: "StrPtrLen phải có độ dài là 2 ký tự", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLt", |
|
||||||
expected: "StrPtrLt phải có độ dài nhỏ hơn 1 ký tự", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLte", |
|
||||||
expected: "StrPtrLte chỉ được có độ dài tối đa là 1 ký tự", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGt", |
|
||||||
expected: "StrPtrGt phải có độ dài lớn hơn 10 ký tự", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGte", |
|
||||||
expected: "StrPtrGte phải có độ dài ít nhất 10 ký tự", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfString", |
|
||||||
expected: "OneOfString phải là trong những giá trị [red green]", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfInt", |
|
||||||
expected: "OneOfInt phải là trong những giá trị [5 63]", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UniqueSlice", |
|
||||||
expected: "UniqueSlice chỉ được chứa những giá trị không trùng lặp", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UniqueArray", |
|
||||||
expected: "UniqueArray chỉ được chứa những giá trị không trùng lặp", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UniqueMap", |
|
||||||
expected: "UniqueMap chỉ được chứa những giá trị không trùng lặp", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.JSONString", |
|
||||||
expected: "JSONString phải là một chuỗi json hợp lệ", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.JWTString", |
|
||||||
expected: "JWTString phải là một chuỗi jwt hợp lệ", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LowercaseString", |
|
||||||
expected: "LowercaseString phải được viết thường", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UppercaseString", |
|
||||||
expected: "UppercaseString phải được viết hoa", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Datetime", |
|
||||||
expected: "Datetime không trùng định dạng ngày tháng 2006-01-02", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.PostCode", |
|
||||||
expected: "PostCode sai định dạng postcode của quốc gia SG", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.PostCodeByField", |
|
||||||
expected: "PostCodeByField sai định dạng postcode của quốc gia tương ứng thuộc trường PostCodeCountry", |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
for _, tt := range tests { |
|
||||||
|
|
||||||
var fe validator.FieldError |
|
||||||
|
|
||||||
for _, e := range errs { |
|
||||||
if tt.ns == e.Namespace() { |
|
||||||
fe = e |
|
||||||
break |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
NotEqual(t, fe, nil) |
|
||||||
Equal(t, tt.expected, fe.Translate(trans)) |
|
||||||
} |
|
||||||
} |
|
File diff suppressed because it is too large
Load Diff
@ -1,696 +0,0 @@ |
|||||||
package zh |
|
||||||
|
|
||||||
import ( |
|
||||||
"testing" |
|
||||||
"time" |
|
||||||
|
|
||||||
. "github.com/go-playground/assert/v2" |
|
||||||
zhongwen "github.com/go-playground/locales/zh" |
|
||||||
ut "github.com/go-playground/universal-translator" |
|
||||||
"github.com/go-playground/validator/v10" |
|
||||||
) |
|
||||||
|
|
||||||
func TestTranslations(t *testing.T) { |
|
||||||
|
|
||||||
zh := zhongwen.New() |
|
||||||
uni := ut.New(zh, zh) |
|
||||||
trans, _ := uni.GetTranslator("zh") |
|
||||||
|
|
||||||
validate := validator.New() |
|
||||||
|
|
||||||
err := RegisterDefaultTranslations(validate, trans) |
|
||||||
Equal(t, err, nil) |
|
||||||
|
|
||||||
type Inner struct { |
|
||||||
EqCSFieldString string |
|
||||||
NeCSFieldString string |
|
||||||
GtCSFieldString string |
|
||||||
GteCSFieldString string |
|
||||||
LtCSFieldString string |
|
||||||
LteCSFieldString string |
|
||||||
} |
|
||||||
|
|
||||||
type Test struct { |
|
||||||
Inner Inner |
|
||||||
RequiredString string `validate:"required"` |
|
||||||
RequiredNumber int `validate:"required"` |
|
||||||
RequiredMultiple []string `validate:"required"` |
|
||||||
LenString string `validate:"len=1"` |
|
||||||
LenNumber float64 `validate:"len=1113.00"` |
|
||||||
LenMultiple []string `validate:"len=7"` |
|
||||||
MinString string `validate:"min=1"` |
|
||||||
MinNumber float64 `validate:"min=1113.00"` |
|
||||||
MinMultiple []string `validate:"min=7"` |
|
||||||
MaxString string `validate:"max=3"` |
|
||||||
MaxNumber float64 `validate:"max=1113.00"` |
|
||||||
MaxMultiple []string `validate:"max=7"` |
|
||||||
EqString string `validate:"eq=3"` |
|
||||||
EqNumber float64 `validate:"eq=2.33"` |
|
||||||
EqMultiple []string `validate:"eq=7"` |
|
||||||
NeString string `validate:"ne="` |
|
||||||
NeNumber float64 `validate:"ne=0.00"` |
|
||||||
NeMultiple []string `validate:"ne=0"` |
|
||||||
LtString string `validate:"lt=3"` |
|
||||||
LtNumber float64 `validate:"lt=5.56"` |
|
||||||
LtMultiple []string `validate:"lt=2"` |
|
||||||
LtTime time.Time `validate:"lt"` |
|
||||||
LteString string `validate:"lte=3"` |
|
||||||
LteNumber float64 `validate:"lte=5.56"` |
|
||||||
LteMultiple []string `validate:"lte=2"` |
|
||||||
LteTime time.Time `validate:"lte"` |
|
||||||
GtString string `validate:"gt=3"` |
|
||||||
GtNumber float64 `validate:"gt=5.56"` |
|
||||||
GtMultiple []string `validate:"gt=2"` |
|
||||||
GtTime time.Time `validate:"gt"` |
|
||||||
GteString string `validate:"gte=3"` |
|
||||||
GteNumber float64 `validate:"gte=5.56"` |
|
||||||
GteMultiple []string `validate:"gte=2"` |
|
||||||
GteTime time.Time `validate:"gte"` |
|
||||||
EqFieldString string `validate:"eqfield=MaxString"` |
|
||||||
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"` |
|
||||||
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"` |
|
||||||
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"` |
|
||||||
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"` |
|
||||||
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"` |
|
||||||
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"` |
|
||||||
NeFieldString string `validate:"nefield=EqFieldString"` |
|
||||||
GtFieldString string `validate:"gtfield=MaxString"` |
|
||||||
GteFieldString string `validate:"gtefield=MaxString"` |
|
||||||
LtFieldString string `validate:"ltfield=MaxString"` |
|
||||||
LteFieldString string `validate:"ltefield=MaxString"` |
|
||||||
AlphaString string `validate:"alpha"` |
|
||||||
AlphanumString string `validate:"alphanum"` |
|
||||||
AlphanumUnicodeString string `validate:"alphanumunicode"` |
|
||||||
AlphaUnicodeString string `validate:"alphaunicode"` |
|
||||||
NumericString string `validate:"numeric"` |
|
||||||
NumberString string `validate:"number"` |
|
||||||
HexadecimalString string `validate:"hexadecimal"` |
|
||||||
HexColorString string `validate:"hexcolor"` |
|
||||||
RGBColorString string `validate:"rgb"` |
|
||||||
RGBAColorString string `validate:"rgba"` |
|
||||||
HSLColorString string `validate:"hsl"` |
|
||||||
HSLAColorString string `validate:"hsla"` |
|
||||||
Email string `validate:"email"` |
|
||||||
URL string `validate:"url"` |
|
||||||
URI string `validate:"uri"` |
|
||||||
Base64 string `validate:"base64"` |
|
||||||
Contains string `validate:"contains=purpose"` |
|
||||||
ContainsAny string `validate:"containsany=!@#$"` |
|
||||||
ContainsRune string `validate:"containsrune=☻"` |
|
||||||
Excludes string `validate:"excludes=text"` |
|
||||||
ExcludesAll string `validate:"excludesall=!@#$"` |
|
||||||
ExcludesRune string `validate:"excludesrune=☻"` |
|
||||||
EndsWith string `validate:"endswith=end"` |
|
||||||
StartsWith string `validate:"startswith=start"` |
|
||||||
ISBN string `validate:"isbn"` |
|
||||||
ISBN10 string `validate:"isbn10"` |
|
||||||
ISBN13 string `validate:"isbn13"` |
|
||||||
UUID string `validate:"uuid"` |
|
||||||
UUID3 string `validate:"uuid3"` |
|
||||||
UUID4 string `validate:"uuid4"` |
|
||||||
UUID5 string `validate:"uuid5"` |
|
||||||
ULID string `validate:"ulid"` |
|
||||||
ASCII string `validate:"ascii"` |
|
||||||
PrintableASCII string `validate:"printascii"` |
|
||||||
MultiByte string `validate:"multibyte"` |
|
||||||
DataURI string `validate:"datauri"` |
|
||||||
Latitude string `validate:"latitude"` |
|
||||||
Longitude string `validate:"longitude"` |
|
||||||
SSN string `validate:"ssn"` |
|
||||||
IP string `validate:"ip"` |
|
||||||
IPv4 string `validate:"ipv4"` |
|
||||||
IPv6 string `validate:"ipv6"` |
|
||||||
CIDR string `validate:"cidr"` |
|
||||||
CIDRv4 string `validate:"cidrv4"` |
|
||||||
CIDRv6 string `validate:"cidrv6"` |
|
||||||
TCPAddr string `validate:"tcp_addr"` |
|
||||||
TCPAddrv4 string `validate:"tcp4_addr"` |
|
||||||
TCPAddrv6 string `validate:"tcp6_addr"` |
|
||||||
UDPAddr string `validate:"udp_addr"` |
|
||||||
UDPAddrv4 string `validate:"udp4_addr"` |
|
||||||
UDPAddrv6 string `validate:"udp6_addr"` |
|
||||||
IPAddr string `validate:"ip_addr"` |
|
||||||
IPAddrv4 string `validate:"ip4_addr"` |
|
||||||
IPAddrv6 string `validate:"ip6_addr"` |
|
||||||
UinxAddr string `validate:"unix_addr"` // can't fail from within Go's net package currently, but maybe in the future
|
|
||||||
MAC string `validate:"mac"` |
|
||||||
IsColor string `validate:"iscolor"` |
|
||||||
StrPtrMinLen *string `validate:"min=10"` |
|
||||||
StrPtrMaxLen *string `validate:"max=1"` |
|
||||||
StrPtrLen *string `validate:"len=2"` |
|
||||||
StrPtrLt *string `validate:"lt=1"` |
|
||||||
StrPtrLte *string `validate:"lte=1"` |
|
||||||
StrPtrGt *string `validate:"gt=10"` |
|
||||||
StrPtrGte *string `validate:"gte=10"` |
|
||||||
OneOfString string `validate:"oneof=red green"` |
|
||||||
OneOfInt int `validate:"oneof=5 63"` |
|
||||||
JsonString string `validate:"json"` |
|
||||||
LowercaseString string `validate:"lowercase"` |
|
||||||
UppercaseString string `validate:"uppercase"` |
|
||||||
Datetime string `validate:"datetime=2006-01-02"` |
|
||||||
} |
|
||||||
|
|
||||||
var test Test |
|
||||||
|
|
||||||
test.Inner.EqCSFieldString = "1234" |
|
||||||
test.Inner.GtCSFieldString = "1234" |
|
||||||
test.Inner.GteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.MaxString = "1234" |
|
||||||
test.MaxNumber = 2000 |
|
||||||
test.MaxMultiple = make([]string, 9) |
|
||||||
|
|
||||||
test.LtString = "1234" |
|
||||||
test.LtNumber = 6 |
|
||||||
test.LtMultiple = make([]string, 3) |
|
||||||
test.LtTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LteString = "1234" |
|
||||||
test.LteNumber = 6 |
|
||||||
test.LteMultiple = make([]string, 3) |
|
||||||
test.LteTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LtFieldString = "12345" |
|
||||||
test.LteFieldString = "12345" |
|
||||||
|
|
||||||
test.LtCSFieldString = "1234" |
|
||||||
test.LteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.AlphaString = "abc3" |
|
||||||
test.AlphanumString = "abc3!" |
|
||||||
test.AlphanumUnicodeString = "abc3啊!" |
|
||||||
test.AlphaUnicodeString = "abc3啊" |
|
||||||
test.NumericString = "12E.00" |
|
||||||
test.NumberString = "12E" |
|
||||||
|
|
||||||
test.Excludes = "this is some test text" |
|
||||||
test.ExcludesAll = "This is Great!" |
|
||||||
test.ExcludesRune = "Love it ☻" |
|
||||||
|
|
||||||
test.EndsWith = "this is some test text" |
|
||||||
test.StartsWith = "this is some test text" |
|
||||||
|
|
||||||
test.ASCII = "カタカナ" |
|
||||||
test.PrintableASCII = "カタカナ" |
|
||||||
|
|
||||||
test.MultiByte = "1234feerf" |
|
||||||
|
|
||||||
s := "toolong" |
|
||||||
test.StrPtrMaxLen = &s |
|
||||||
test.StrPtrLen = &s |
|
||||||
|
|
||||||
test.JsonString = "{\"foo\":\"bar\",}" |
|
||||||
|
|
||||||
test.LowercaseString = "ABCDEFG" |
|
||||||
test.UppercaseString = "abcdefg" |
|
||||||
|
|
||||||
test.Datetime = "20060102" |
|
||||||
|
|
||||||
err = validate.Struct(test) |
|
||||||
NotEqual(t, err, nil) |
|
||||||
|
|
||||||
errs, ok := err.(validator.ValidationErrors) |
|
||||||
Equal(t, ok, true) |
|
||||||
|
|
||||||
tests := []struct { |
|
||||||
ns string |
|
||||||
expected string |
|
||||||
}{ |
|
||||||
{ |
|
||||||
ns: "Test.IsColor", |
|
||||||
expected: "IsColor必须是一个有效的颜色", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MAC", |
|
||||||
expected: "MAC必须是一个有效的MAC地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddr", |
|
||||||
expected: "IPAddr必须是一个有效的IP地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv4", |
|
||||||
expected: "IPAddrv4必须是一个有效的IPv4地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv6", |
|
||||||
expected: "IPAddrv6必须是一个有效的IPv6地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddr", |
|
||||||
expected: "UDPAddr必须是一个有效的UDP地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv4", |
|
||||||
expected: "UDPAddrv4必须是一个有效的IPv4 UDP地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv6", |
|
||||||
expected: "UDPAddrv6必须是一个有效的IPv6 UDP地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddr", |
|
||||||
expected: "TCPAddr必须是一个有效的TCP地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv4", |
|
||||||
expected: "TCPAddrv4必须是一个有效的IPv4 TCP地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv6", |
|
||||||
expected: "TCPAddrv6必须是一个有效的IPv6 TCP地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDR", |
|
||||||
expected: "CIDR必须是一个有效的无类别域间路由(CIDR)", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv4", |
|
||||||
expected: "CIDRv4必须是一个包含IPv4地址的有效无类别域间路由(CIDR)", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv6", |
|
||||||
expected: "CIDRv6必须是一个包含IPv6地址的有效无类别域间路由(CIDR)", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.SSN", |
|
||||||
expected: "SSN必须是一个有效的社会安全号码(SSN)", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IP", |
|
||||||
expected: "IP必须是一个有效的IP地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv4", |
|
||||||
expected: "IPv4必须是一个有效的IPv4地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv6", |
|
||||||
expected: "IPv6必须是一个有效的IPv6地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.DataURI", |
|
||||||
expected: "DataURI必须包含有效的数据URI", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Latitude", |
|
||||||
expected: "Latitude必须包含有效的纬度坐标", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Longitude", |
|
||||||
expected: "Longitude必须包含有效的经度坐标", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MultiByte", |
|
||||||
expected: "MultiByte必须包含多字节字符", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ASCII", |
|
||||||
expected: "ASCII必须只包含ascii字符", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.PrintableASCII", |
|
||||||
expected: "PrintableASCII必须只包含可打印的ascii字符", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID", |
|
||||||
expected: "UUID必须是一个有效的UUID", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID3", |
|
||||||
expected: "UUID3必须是一个有效的V3 UUID", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID4", |
|
||||||
expected: "UUID4必须是一个有效的V4 UUID", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID5", |
|
||||||
expected: "UUID5必须是一个有效的V5 UUID", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ULID", |
|
||||||
expected: "ULID必须是一个有效的ULID", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN", |
|
||||||
expected: "ISBN必须是一个有效的ISBN编号", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN10", |
|
||||||
expected: "ISBN10必须是一个有效的ISBN-10编号", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN13", |
|
||||||
expected: "ISBN13必须是一个有效的ISBN-13编号", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EndsWith", |
|
||||||
expected: "EndsWith必须以文本'end'结尾", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StartsWith", |
|
||||||
expected: "StartsWith必须以文本'start'开头", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Excludes", |
|
||||||
expected: "Excludes不能包含文本'text'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesAll", |
|
||||||
expected: "ExcludesAll不能包含以下任何字符'!@#$'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesRune", |
|
||||||
expected: "ExcludesRune不能包含'☻'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ContainsRune", |
|
||||||
expected: "ContainsRune必须包含字符'☻'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ContainsAny", |
|
||||||
expected: "ContainsAny必须包含至少一个以下字符'!@#$'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Contains", |
|
||||||
expected: "Contains必须包含文本'purpose'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Base64", |
|
||||||
expected: "Base64必须是一个有效的Base64字符串", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Email", |
|
||||||
expected: "Email必须是一个有效的邮箱", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URL", |
|
||||||
expected: "URL必须是一个有效的URL", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URI", |
|
||||||
expected: "URI必须是一个有效的URI", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBColorString", |
|
||||||
expected: "RGBColorString必须是一个有效的RGB颜色", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBAColorString", |
|
||||||
expected: "RGBAColorString必须是一个有效的RGBA颜色", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLColorString", |
|
||||||
expected: "HSLColorString必须是一个有效的HSL颜色", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLAColorString", |
|
||||||
expected: "HSLAColorString必须是一个有效的HSLA颜色", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexadecimalString", |
|
||||||
expected: "HexadecimalString必须是一个有效的十六进制", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexColorString", |
|
||||||
expected: "HexColorString必须是一个有效的十六进制颜色", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumberString", |
|
||||||
expected: "NumberString必须是一个有效的数字", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumericString", |
|
||||||
expected: "NumericString必须是一个有效的数值", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphaUnicodeString", |
|
||||||
expected: "AlphaUnicodeString只能包含字母和Unicode字符", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphanumUnicodeString", |
|
||||||
expected: "AlphanumUnicodeString只能包含字母数字和Unicode字符", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphanumString", |
|
||||||
expected: "AlphanumString只能包含字母和数字", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphaString", |
|
||||||
expected: "AlphaString只能包含字母", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtFieldString", |
|
||||||
expected: "LtFieldString必须小于MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteFieldString", |
|
||||||
expected: "LteFieldString必须小于或等于MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtFieldString", |
|
||||||
expected: "GtFieldString必须大于MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteFieldString", |
|
||||||
expected: "GteFieldString必须大于或等于MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeFieldString", |
|
||||||
expected: "NeFieldString不能等于EqFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtCSFieldString", |
|
||||||
expected: "LtCSFieldString必须小于Inner.LtCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteCSFieldString", |
|
||||||
expected: "LteCSFieldString必须小于或等于Inner.LteCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtCSFieldString", |
|
||||||
expected: "GtCSFieldString必须大于Inner.GtCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteCSFieldString", |
|
||||||
expected: "GteCSFieldString必须大于或等于Inner.GteCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeCSFieldString", |
|
||||||
expected: "NeCSFieldString不能等于Inner.NeCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqCSFieldString", |
|
||||||
expected: "EqCSFieldString必须等于Inner.EqCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqFieldString", |
|
||||||
expected: "EqFieldString必须等于MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteString", |
|
||||||
expected: "GteString长度必须至少为3个字符", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteNumber", |
|
||||||
expected: "GteNumber必须大于或等于5.56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteMultiple", |
|
||||||
expected: "GteMultiple必须至少包含2项", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteTime", |
|
||||||
expected: "GteTime必须大于或等于当前日期和时间", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtString", |
|
||||||
expected: "GtString长度必须大于3个字符", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtNumber", |
|
||||||
expected: "GtNumber必须大于5.56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtMultiple", |
|
||||||
expected: "GtMultiple必须大于2项", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtTime", |
|
||||||
expected: "GtTime必须大于当前日期和时间", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteString", |
|
||||||
expected: "LteString长度不能超过3个字符", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteNumber", |
|
||||||
expected: "LteNumber必须小于或等于5.56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteMultiple", |
|
||||||
expected: "LteMultiple最多只能包含2项", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteTime", |
|
||||||
expected: "LteTime必须小于或等于当前日期和时间", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtString", |
|
||||||
expected: "LtString长度必须小于3个字符", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtNumber", |
|
||||||
expected: "LtNumber必须小于5.56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtMultiple", |
|
||||||
expected: "LtMultiple必须包含少于2项", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtTime", |
|
||||||
expected: "LtTime必须小于当前日期和时间", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeString", |
|
||||||
expected: "NeString不能等于", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeNumber", |
|
||||||
expected: "NeNumber不能等于0.00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeMultiple", |
|
||||||
expected: "NeMultiple不能等于0", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqString", |
|
||||||
expected: "EqString不等于3", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqNumber", |
|
||||||
expected: "EqNumber不等于2.33", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqMultiple", |
|
||||||
expected: "EqMultiple不等于7", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxString", |
|
||||||
expected: "MaxString长度不能超过3个字符", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxNumber", |
|
||||||
expected: "MaxNumber必须小于或等于1,113.00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxMultiple", |
|
||||||
expected: "MaxMultiple最多只能包含7项", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinString", |
|
||||||
expected: "MinString长度必须至少为1个字符", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinNumber", |
|
||||||
expected: "MinNumber最小只能为1,113.00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinMultiple", |
|
||||||
expected: "MinMultiple必须至少包含7项", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenString", |
|
||||||
expected: "LenString长度必须是1个字符", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenNumber", |
|
||||||
expected: "LenNumber必须等于1,113.00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenMultiple", |
|
||||||
expected: "LenMultiple必须包含7项", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredString", |
|
||||||
expected: "RequiredString为必填字段", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredNumber", |
|
||||||
expected: "RequiredNumber为必填字段", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredMultiple", |
|
||||||
expected: "RequiredMultiple为必填字段", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMinLen", |
|
||||||
expected: "StrPtrMinLen长度必须至少为10个字符", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMaxLen", |
|
||||||
expected: "StrPtrMaxLen长度不能超过1个字符", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLen", |
|
||||||
expected: "StrPtrLen长度必须是2个字符", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLt", |
|
||||||
expected: "StrPtrLt长度必须小于1个字符", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLte", |
|
||||||
expected: "StrPtrLte长度不能超过1个字符", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGt", |
|
||||||
expected: "StrPtrGt长度必须大于10个字符", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGte", |
|
||||||
expected: "StrPtrGte长度必须至少为10个字符", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfString", |
|
||||||
expected: "OneOfString必须是[red green]中的一个", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfInt", |
|
||||||
expected: "OneOfInt必须是[5 63]中的一个", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.JsonString", |
|
||||||
expected: "JsonString必须是一个JSON字符串", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LowercaseString", |
|
||||||
expected: "LowercaseString必须是小写字母", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UppercaseString", |
|
||||||
expected: "UppercaseString必须是大写字母", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Datetime", |
|
||||||
expected: "Datetime的格式必须是2006-01-02", |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
for _, tt := range tests { |
|
||||||
|
|
||||||
var fe validator.FieldError |
|
||||||
|
|
||||||
for _, e := range errs { |
|
||||||
if tt.ns == e.Namespace() { |
|
||||||
fe = e |
|
||||||
break |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
NotEqual(t, fe, nil) |
|
||||||
Equal(t, tt.expected, fe.Translate(trans)) |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
File diff suppressed because it is too large
Load Diff
@ -1,646 +0,0 @@ |
|||||||
package zh_tw |
|
||||||
|
|
||||||
import ( |
|
||||||
"testing" |
|
||||||
"time" |
|
||||||
|
|
||||||
. "github.com/go-playground/assert/v2" |
|
||||||
zhongwen "github.com/go-playground/locales/zh_Hant_TW" |
|
||||||
ut "github.com/go-playground/universal-translator" |
|
||||||
"github.com/go-playground/validator/v10" |
|
||||||
) |
|
||||||
|
|
||||||
func TestTranslations(t *testing.T) { |
|
||||||
|
|
||||||
zh := zhongwen.New() |
|
||||||
uni := ut.New(zh, zh) |
|
||||||
trans, _ := uni.GetTranslator("zh") |
|
||||||
|
|
||||||
validate := validator.New() |
|
||||||
|
|
||||||
err := RegisterDefaultTranslations(validate, trans) |
|
||||||
Equal(t, err, nil) |
|
||||||
|
|
||||||
type Inner struct { |
|
||||||
EqCSFieldString string |
|
||||||
NeCSFieldString string |
|
||||||
GtCSFieldString string |
|
||||||
GteCSFieldString string |
|
||||||
LtCSFieldString string |
|
||||||
LteCSFieldString string |
|
||||||
} |
|
||||||
|
|
||||||
type Test struct { |
|
||||||
Inner Inner |
|
||||||
RequiredString string `validate:"required"` |
|
||||||
RequiredNumber int `validate:"required"` |
|
||||||
RequiredMultiple []string `validate:"required"` |
|
||||||
LenString string `validate:"len=1"` |
|
||||||
LenNumber float64 `validate:"len=1113.00"` |
|
||||||
LenMultiple []string `validate:"len=7"` |
|
||||||
MinString string `validate:"min=1"` |
|
||||||
MinNumber float64 `validate:"min=1113.00"` |
|
||||||
MinMultiple []string `validate:"min=7"` |
|
||||||
MaxString string `validate:"max=3"` |
|
||||||
MaxNumber float64 `validate:"max=1113.00"` |
|
||||||
MaxMultiple []string `validate:"max=7"` |
|
||||||
EqString string `validate:"eq=3"` |
|
||||||
EqNumber float64 `validate:"eq=2.33"` |
|
||||||
EqMultiple []string `validate:"eq=7"` |
|
||||||
NeString string `validate:"ne="` |
|
||||||
NeNumber float64 `validate:"ne=0.00"` |
|
||||||
NeMultiple []string `validate:"ne=0"` |
|
||||||
LtString string `validate:"lt=3"` |
|
||||||
LtNumber float64 `validate:"lt=5.56"` |
|
||||||
LtMultiple []string `validate:"lt=2"` |
|
||||||
LtTime time.Time `validate:"lt"` |
|
||||||
LteString string `validate:"lte=3"` |
|
||||||
LteNumber float64 `validate:"lte=5.56"` |
|
||||||
LteMultiple []string `validate:"lte=2"` |
|
||||||
LteTime time.Time `validate:"lte"` |
|
||||||
GtString string `validate:"gt=3"` |
|
||||||
GtNumber float64 `validate:"gt=5.56"` |
|
||||||
GtMultiple []string `validate:"gt=2"` |
|
||||||
GtTime time.Time `validate:"gt"` |
|
||||||
GteString string `validate:"gte=3"` |
|
||||||
GteNumber float64 `validate:"gte=5.56"` |
|
||||||
GteMultiple []string `validate:"gte=2"` |
|
||||||
GteTime time.Time `validate:"gte"` |
|
||||||
EqFieldString string `validate:"eqfield=MaxString"` |
|
||||||
EqCSFieldString string `validate:"eqcsfield=Inner.EqCSFieldString"` |
|
||||||
NeCSFieldString string `validate:"necsfield=Inner.NeCSFieldString"` |
|
||||||
GtCSFieldString string `validate:"gtcsfield=Inner.GtCSFieldString"` |
|
||||||
GteCSFieldString string `validate:"gtecsfield=Inner.GteCSFieldString"` |
|
||||||
LtCSFieldString string `validate:"ltcsfield=Inner.LtCSFieldString"` |
|
||||||
LteCSFieldString string `validate:"ltecsfield=Inner.LteCSFieldString"` |
|
||||||
NeFieldString string `validate:"nefield=EqFieldString"` |
|
||||||
GtFieldString string `validate:"gtfield=MaxString"` |
|
||||||
GteFieldString string `validate:"gtefield=MaxString"` |
|
||||||
LtFieldString string `validate:"ltfield=MaxString"` |
|
||||||
LteFieldString string `validate:"ltefield=MaxString"` |
|
||||||
AlphaString string `validate:"alpha"` |
|
||||||
AlphanumString string `validate:"alphanum"` |
|
||||||
NumericString string `validate:"numeric"` |
|
||||||
NumberString string `validate:"number"` |
|
||||||
HexadecimalString string `validate:"hexadecimal"` |
|
||||||
HexColorString string `validate:"hexcolor"` |
|
||||||
RGBColorString string `validate:"rgb"` |
|
||||||
RGBAColorString string `validate:"rgba"` |
|
||||||
HSLColorString string `validate:"hsl"` |
|
||||||
HSLAColorString string `validate:"hsla"` |
|
||||||
Email string `validate:"email"` |
|
||||||
URL string `validate:"url"` |
|
||||||
URI string `validate:"uri"` |
|
||||||
Base64 string `validate:"base64"` |
|
||||||
Contains string `validate:"contains=purpose"` |
|
||||||
ContainsAny string `validate:"containsany=!@#$"` |
|
||||||
Excludes string `validate:"excludes=text"` |
|
||||||
ExcludesAll string `validate:"excludesall=!@#$"` |
|
||||||
ExcludesRune string `validate:"excludesrune=☻"` |
|
||||||
ISBN string `validate:"isbn"` |
|
||||||
ISBN10 string `validate:"isbn10"` |
|
||||||
ISBN13 string `validate:"isbn13"` |
|
||||||
UUID string `validate:"uuid"` |
|
||||||
UUID3 string `validate:"uuid3"` |
|
||||||
UUID4 string `validate:"uuid4"` |
|
||||||
UUID5 string `validate:"uuid5"` |
|
||||||
ULID string `validate:"ulid"` |
|
||||||
ASCII string `validate:"ascii"` |
|
||||||
PrintableASCII string `validate:"printascii"` |
|
||||||
MultiByte string `validate:"multibyte"` |
|
||||||
DataURI string `validate:"datauri"` |
|
||||||
Latitude string `validate:"latitude"` |
|
||||||
Longitude string `validate:"longitude"` |
|
||||||
SSN string `validate:"ssn"` |
|
||||||
IP string `validate:"ip"` |
|
||||||
IPv4 string `validate:"ipv4"` |
|
||||||
IPv6 string `validate:"ipv6"` |
|
||||||
CIDR string `validate:"cidr"` |
|
||||||
CIDRv4 string `validate:"cidrv4"` |
|
||||||
CIDRv6 string `validate:"cidrv6"` |
|
||||||
TCPAddr string `validate:"tcp_addr"` |
|
||||||
TCPAddrv4 string `validate:"tcp4_addr"` |
|
||||||
TCPAddrv6 string `validate:"tcp6_addr"` |
|
||||||
UDPAddr string `validate:"udp_addr"` |
|
||||||
UDPAddrv4 string `validate:"udp4_addr"` |
|
||||||
UDPAddrv6 string `validate:"udp6_addr"` |
|
||||||
IPAddr string `validate:"ip_addr"` |
|
||||||
IPAddrv4 string `validate:"ip4_addr"` |
|
||||||
IPAddrv6 string `validate:"ip6_addr"` |
|
||||||
UinxAddr string `validate:"unix_addr"` // can't fail from within Go's net package currently, but maybe in the future
|
|
||||||
MAC string `validate:"mac"` |
|
||||||
IsColor string `validate:"iscolor"` |
|
||||||
StrPtrMinLen *string `validate:"min=10"` |
|
||||||
StrPtrMaxLen *string `validate:"max=1"` |
|
||||||
StrPtrLen *string `validate:"len=2"` |
|
||||||
StrPtrLt *string `validate:"lt=1"` |
|
||||||
StrPtrLte *string `validate:"lte=1"` |
|
||||||
StrPtrGt *string `validate:"gt=10"` |
|
||||||
StrPtrGte *string `validate:"gte=10"` |
|
||||||
OneOfString string `validate:"oneof=red green"` |
|
||||||
OneOfInt int `validate:"oneof=5 63"` |
|
||||||
Datetime string `validate:"datetime=2006-01-02"` |
|
||||||
} |
|
||||||
|
|
||||||
var test Test |
|
||||||
|
|
||||||
test.Inner.EqCSFieldString = "1234" |
|
||||||
test.Inner.GtCSFieldString = "1234" |
|
||||||
test.Inner.GteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.MaxString = "1234" |
|
||||||
test.MaxNumber = 2000 |
|
||||||
test.MaxMultiple = make([]string, 9) |
|
||||||
|
|
||||||
test.LtString = "1234" |
|
||||||
test.LtNumber = 6 |
|
||||||
test.LtMultiple = make([]string, 3) |
|
||||||
test.LtTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LteString = "1234" |
|
||||||
test.LteNumber = 6 |
|
||||||
test.LteMultiple = make([]string, 3) |
|
||||||
test.LteTime = time.Now().Add(time.Hour * 24) |
|
||||||
|
|
||||||
test.LtFieldString = "12345" |
|
||||||
test.LteFieldString = "12345" |
|
||||||
|
|
||||||
test.LtCSFieldString = "1234" |
|
||||||
test.LteCSFieldString = "1234" |
|
||||||
|
|
||||||
test.AlphaString = "abc3" |
|
||||||
test.AlphanumString = "abc3!" |
|
||||||
test.NumericString = "12E.00" |
|
||||||
test.NumberString = "12E" |
|
||||||
|
|
||||||
test.Excludes = "this is some test text" |
|
||||||
test.ExcludesAll = "This is Great!" |
|
||||||
test.ExcludesRune = "Love it ☻" |
|
||||||
|
|
||||||
test.ASCII = "カタカナ" |
|
||||||
test.PrintableASCII = "カタカナ" |
|
||||||
|
|
||||||
test.MultiByte = "1234feerf" |
|
||||||
|
|
||||||
s := "toolong" |
|
||||||
test.StrPtrMaxLen = &s |
|
||||||
test.StrPtrLen = &s |
|
||||||
|
|
||||||
test.Datetime = "2008-Feb-01" |
|
||||||
|
|
||||||
err = validate.Struct(test) |
|
||||||
NotEqual(t, err, nil) |
|
||||||
|
|
||||||
errs, ok := err.(validator.ValidationErrors) |
|
||||||
Equal(t, ok, true) |
|
||||||
|
|
||||||
tests := []struct { |
|
||||||
ns string |
|
||||||
expected string |
|
||||||
}{ |
|
||||||
{ |
|
||||||
ns: "Test.IsColor", |
|
||||||
expected: "IsColor必須是一個有效的顏色", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MAC", |
|
||||||
expected: "MAC必須是一個有效的MAC地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddr", |
|
||||||
expected: "IPAddr必須是一個有效的IP地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv4", |
|
||||||
expected: "IPAddrv4必須是一個有效的IPv4地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPAddrv6", |
|
||||||
expected: "IPAddrv6必須是一個有效的IPv6地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddr", |
|
||||||
expected: "UDPAddr必須是一個有效的UDP地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv4", |
|
||||||
expected: "UDPAddrv4必須是一個有效的IPv4 UDP地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UDPAddrv6", |
|
||||||
expected: "UDPAddrv6必須是一個有效的IPv6 UDP地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddr", |
|
||||||
expected: "TCPAddr必須是一個有效的TCP地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv4", |
|
||||||
expected: "TCPAddrv4必須是一個有效的IPv4 TCP地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.TCPAddrv6", |
|
||||||
expected: "TCPAddrv6必須是一個有效的IPv6 TCP地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDR", |
|
||||||
expected: "CIDR必須是一個有效的無類別域間路由(CIDR)", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv4", |
|
||||||
expected: "CIDRv4必須是一个包含IPv4地址的有效無類別域間路由(CIDR)", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.CIDRv6", |
|
||||||
expected: "CIDRv6必須是一个包含IPv6地址的有效無類別域間路由(CIDR)", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.SSN", |
|
||||||
expected: "SSN必須是一個有效的社會安全編號(SSN)", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IP", |
|
||||||
expected: "IP必須是一個有效的IP地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv4", |
|
||||||
expected: "IPv4必須是一個有效的IPv4地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.IPv6", |
|
||||||
expected: "IPv6必須是一個有效的IPv6地址", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.DataURI", |
|
||||||
expected: "DataURI必須包含有效的數據URI", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Latitude", |
|
||||||
expected: "Latitude必須包含有效的緯度座標", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Longitude", |
|
||||||
expected: "Longitude必須包含有效的經度座標", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MultiByte", |
|
||||||
expected: "MultiByte必須包含多個字元", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ASCII", |
|
||||||
expected: "ASCII必須只包含ascii字元", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.PrintableASCII", |
|
||||||
expected: "PrintableASCII必須只包含可輸出的ascii字元", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID", |
|
||||||
expected: "UUID必須是一個有效的UUID", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID3", |
|
||||||
expected: "UUID3必須是一個有效的V3 UUID", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID4", |
|
||||||
expected: "UUID4必須是一個有效的V4 UUID", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.UUID5", |
|
||||||
expected: "UUID5必須是一個有效的V5 UUID", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ULID", |
|
||||||
expected: "ULID必須是一個有效的ULID", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN", |
|
||||||
expected: "ISBN必須是一個有效的ISBN編號", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN10", |
|
||||||
expected: "ISBN10必須是一個有效的ISBN-10編號", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ISBN13", |
|
||||||
expected: "ISBN13必須是一個有效的ISBN-13編號", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Excludes", |
|
||||||
expected: "Excludes不能包含文字'text'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesAll", |
|
||||||
expected: "ExcludesAll不能包含以下任何字元'!@#$'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ExcludesRune", |
|
||||||
expected: "ExcludesRune不能包含'☻'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.ContainsAny", |
|
||||||
expected: "ContainsAny必須包含至少一個以下字元'!@#$'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Contains", |
|
||||||
expected: "Contains必須包含文字'purpose'", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Base64", |
|
||||||
expected: "Base64必須是一個有效的Base64字元串", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Email", |
|
||||||
expected: "Email必須是一個有效的信箱", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URL", |
|
||||||
expected: "URL必須是一個有效的URL", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.URI", |
|
||||||
expected: "URI必須是一個有效的URI", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBColorString", |
|
||||||
expected: "RGBColorString必須是一個有效的RGB顏色", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RGBAColorString", |
|
||||||
expected: "RGBAColorString必須是一個有效的RGBA顏色", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLColorString", |
|
||||||
expected: "HSLColorString必須是一個有效的HSL顏色", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HSLAColorString", |
|
||||||
expected: "HSLAColorString必須是一個有效的HSLA顏色", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexadecimalString", |
|
||||||
expected: "HexadecimalString必須是一個有效的十六進制", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.HexColorString", |
|
||||||
expected: "HexColorString必須是一個有效的十六進制顏色", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumberString", |
|
||||||
expected: "NumberString必須是一個有效的數字", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NumericString", |
|
||||||
expected: "NumericString必須是一個有效的數值", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphanumString", |
|
||||||
expected: "AlphanumString只能包含字母和數字", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.AlphaString", |
|
||||||
expected: "AlphaString只能包含字母", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtFieldString", |
|
||||||
expected: "LtFieldString必須小於MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteFieldString", |
|
||||||
expected: "LteFieldString必須小於或等於MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtFieldString", |
|
||||||
expected: "GtFieldString必須大於MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteFieldString", |
|
||||||
expected: "GteFieldString必須大於或等於MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeFieldString", |
|
||||||
expected: "NeFieldString不能等於EqFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtCSFieldString", |
|
||||||
expected: "LtCSFieldString必須小於Inner.LtCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteCSFieldString", |
|
||||||
expected: "LteCSFieldString必須小於或等於Inner.LteCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtCSFieldString", |
|
||||||
expected: "GtCSFieldString必須大於Inner.GtCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteCSFieldString", |
|
||||||
expected: "GteCSFieldString必須大於或等於Inner.GteCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeCSFieldString", |
|
||||||
expected: "NeCSFieldString不能等於Inner.NeCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqCSFieldString", |
|
||||||
expected: "EqCSFieldString必須等於Inner.EqCSFieldString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqFieldString", |
|
||||||
expected: "EqFieldString必須等於MaxString", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteString", |
|
||||||
expected: "GteString長度必須至少為3個字元", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteNumber", |
|
||||||
expected: "GteNumber必須大於或等於5.56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteMultiple", |
|
||||||
expected: "GteMultiple必須至少包含2項", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GteTime", |
|
||||||
expected: "GteTime必須大於或等於目前日期和時間", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtString", |
|
||||||
expected: "GtString長度必須大於3個字元", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtNumber", |
|
||||||
expected: "GtNumber必須大於5.56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtMultiple", |
|
||||||
expected: "GtMultiple必須大於2項", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.GtTime", |
|
||||||
expected: "GtTime必須大於目前日期和時間", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteString", |
|
||||||
expected: "LteString長度不能超過3個字元", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteNumber", |
|
||||||
expected: "LteNumber必須小於或等於5.56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteMultiple", |
|
||||||
expected: "LteMultiple最多只能包含2項", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LteTime", |
|
||||||
expected: "LteTime必須小於或等於目前日期和時間", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtString", |
|
||||||
expected: "LtString長度必須小於3個字元", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtNumber", |
|
||||||
expected: "LtNumber必須小於5.56", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtMultiple", |
|
||||||
expected: "LtMultiple必須包含少於2項", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LtTime", |
|
||||||
expected: "LtTime必須小於目前日期和時間", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeString", |
|
||||||
expected: "NeString不能等於", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeNumber", |
|
||||||
expected: "NeNumber不能等於0.00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.NeMultiple", |
|
||||||
expected: "NeMultiple不能等於0", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqString", |
|
||||||
expected: "EqString不等於3", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqNumber", |
|
||||||
expected: "EqNumber不等於2.33", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.EqMultiple", |
|
||||||
expected: "EqMultiple不等於7", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxString", |
|
||||||
expected: "MaxString長度不能超過3個字元", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxNumber", |
|
||||||
expected: "MaxNumber必須小於或等於1,113.00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MaxMultiple", |
|
||||||
expected: "MaxMultiple最多只能包含7項", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinString", |
|
||||||
expected: "MinString長度必須至少為1個字元", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinNumber", |
|
||||||
expected: "MinNumber最小只能為1,113.00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.MinMultiple", |
|
||||||
expected: "MinMultiple必須至少包含7項", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenString", |
|
||||||
expected: "LenString長度必須為1個字元", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenNumber", |
|
||||||
expected: "LenNumber必須等於1,113.00", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.LenMultiple", |
|
||||||
expected: "LenMultiple必須包含7項", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredString", |
|
||||||
expected: "RequiredString為必填欄位", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredNumber", |
|
||||||
expected: "RequiredNumber為必填欄位", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.RequiredMultiple", |
|
||||||
expected: "RequiredMultiple為必填欄位", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMinLen", |
|
||||||
expected: "StrPtrMinLen長度必須至少為10個字元", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrMaxLen", |
|
||||||
expected: "StrPtrMaxLen長度不能超過1個字元", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLen", |
|
||||||
expected: "StrPtrLen長度必須為2個字元", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLt", |
|
||||||
expected: "StrPtrLt長度必須小於1個字元", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrLte", |
|
||||||
expected: "StrPtrLte長度不能超過1個字元", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGt", |
|
||||||
expected: "StrPtrGt長度必須大於10個字元", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.StrPtrGte", |
|
||||||
expected: "StrPtrGte長度必須至少為10個字元", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfString", |
|
||||||
expected: "OneOfString必須是[red green]中的一個", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.OneOfInt", |
|
||||||
expected: "OneOfInt必須是[5 63]中的一個", |
|
||||||
}, |
|
||||||
{ |
|
||||||
ns: "Test.Datetime", |
|
||||||
expected: "Datetime與2006-01-02格式不匹配", |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
for _, tt := range tests { |
|
||||||
|
|
||||||
var fe validator.FieldError |
|
||||||
|
|
||||||
for _, e := range errs { |
|
||||||
if tt.ns == e.Namespace() { |
|
||||||
fe = e |
|
||||||
break |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
NotEqual(t, fe, nil) |
|
||||||
Equal(t, tt.expected, fe.Translate(trans)) |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,288 +0,0 @@ |
|||||||
package validator |
|
||||||
|
|
||||||
import ( |
|
||||||
"reflect" |
|
||||||
"strconv" |
|
||||||
"strings" |
|
||||||
"time" |
|
||||||
) |
|
||||||
|
|
||||||
// extractTypeInternal gets the actual underlying type of field value.
|
|
||||||
// It will dive into pointers, customTypes and return you the
|
|
||||||
// underlying value and it's kind.
|
|
||||||
func (v *validate) extractTypeInternal(current reflect.Value, nullable bool) (reflect.Value, reflect.Kind, bool) { |
|
||||||
|
|
||||||
BEGIN: |
|
||||||
switch current.Kind() { |
|
||||||
case reflect.Ptr: |
|
||||||
|
|
||||||
nullable = true |
|
||||||
|
|
||||||
if current.IsNil() { |
|
||||||
return current, reflect.Ptr, nullable |
|
||||||
} |
|
||||||
|
|
||||||
current = current.Elem() |
|
||||||
goto BEGIN |
|
||||||
|
|
||||||
case reflect.Interface: |
|
||||||
|
|
||||||
nullable = true |
|
||||||
|
|
||||||
if current.IsNil() { |
|
||||||
return current, reflect.Interface, nullable |
|
||||||
} |
|
||||||
|
|
||||||
current = current.Elem() |
|
||||||
goto BEGIN |
|
||||||
|
|
||||||
case reflect.Invalid: |
|
||||||
return current, reflect.Invalid, nullable |
|
||||||
|
|
||||||
default: |
|
||||||
|
|
||||||
if v.v.hasCustomFuncs { |
|
||||||
|
|
||||||
if fn, ok := v.v.customFuncs[current.Type()]; ok { |
|
||||||
current = reflect.ValueOf(fn(current)) |
|
||||||
goto BEGIN |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return current, current.Kind(), nullable |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// getStructFieldOKInternal traverses a struct to retrieve a specific field denoted by the provided namespace and
|
|
||||||
// returns the field, field kind and whether is was successful in retrieving the field at all.
|
|
||||||
//
|
|
||||||
// NOTE: when not successful ok will be false, this can happen when a nested struct is nil and so the field
|
|
||||||
// could not be retrieved because it didn't exist.
|
|
||||||
func (v *validate) getStructFieldOKInternal(val reflect.Value, namespace string) (current reflect.Value, kind reflect.Kind, nullable bool, found bool) { |
|
||||||
|
|
||||||
BEGIN: |
|
||||||
current, kind, nullable = v.ExtractType(val) |
|
||||||
if kind == reflect.Invalid { |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
if namespace == "" { |
|
||||||
found = true |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
switch kind { |
|
||||||
|
|
||||||
case reflect.Ptr, reflect.Interface: |
|
||||||
return |
|
||||||
|
|
||||||
case reflect.Struct: |
|
||||||
|
|
||||||
typ := current.Type() |
|
||||||
fld := namespace |
|
||||||
var ns string |
|
||||||
|
|
||||||
if !typ.ConvertibleTo(timeType) { |
|
||||||
|
|
||||||
idx := strings.Index(namespace, namespaceSeparator) |
|
||||||
|
|
||||||
if idx != -1 { |
|
||||||
fld = namespace[:idx] |
|
||||||
ns = namespace[idx+1:] |
|
||||||
} else { |
|
||||||
ns = "" |
|
||||||
} |
|
||||||
|
|
||||||
bracketIdx := strings.Index(fld, leftBracket) |
|
||||||
if bracketIdx != -1 { |
|
||||||
fld = fld[:bracketIdx] |
|
||||||
|
|
||||||
ns = namespace[bracketIdx:] |
|
||||||
} |
|
||||||
|
|
||||||
val = current.FieldByName(fld) |
|
||||||
namespace = ns |
|
||||||
goto BEGIN |
|
||||||
} |
|
||||||
|
|
||||||
case reflect.Array, reflect.Slice: |
|
||||||
idx := strings.Index(namespace, leftBracket) |
|
||||||
idx2 := strings.Index(namespace, rightBracket) |
|
||||||
|
|
||||||
arrIdx, _ := strconv.Atoi(namespace[idx+1 : idx2]) |
|
||||||
|
|
||||||
if arrIdx >= current.Len() { |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
startIdx := idx2 + 1 |
|
||||||
|
|
||||||
if startIdx < len(namespace) { |
|
||||||
if namespace[startIdx:startIdx+1] == namespaceSeparator { |
|
||||||
startIdx++ |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
val = current.Index(arrIdx) |
|
||||||
namespace = namespace[startIdx:] |
|
||||||
goto BEGIN |
|
||||||
|
|
||||||
case reflect.Map: |
|
||||||
idx := strings.Index(namespace, leftBracket) + 1 |
|
||||||
idx2 := strings.Index(namespace, rightBracket) |
|
||||||
|
|
||||||
endIdx := idx2 |
|
||||||
|
|
||||||
if endIdx+1 < len(namespace) { |
|
||||||
if namespace[endIdx+1:endIdx+2] == namespaceSeparator { |
|
||||||
endIdx++ |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
key := namespace[idx:idx2] |
|
||||||
|
|
||||||
switch current.Type().Key().Kind() { |
|
||||||
case reflect.Int: |
|
||||||
i, _ := strconv.Atoi(key) |
|
||||||
val = current.MapIndex(reflect.ValueOf(i)) |
|
||||||
namespace = namespace[endIdx+1:] |
|
||||||
|
|
||||||
case reflect.Int8: |
|
||||||
i, _ := strconv.ParseInt(key, 10, 8) |
|
||||||
val = current.MapIndex(reflect.ValueOf(int8(i))) |
|
||||||
namespace = namespace[endIdx+1:] |
|
||||||
|
|
||||||
case reflect.Int16: |
|
||||||
i, _ := strconv.ParseInt(key, 10, 16) |
|
||||||
val = current.MapIndex(reflect.ValueOf(int16(i))) |
|
||||||
namespace = namespace[endIdx+1:] |
|
||||||
|
|
||||||
case reflect.Int32: |
|
||||||
i, _ := strconv.ParseInt(key, 10, 32) |
|
||||||
val = current.MapIndex(reflect.ValueOf(int32(i))) |
|
||||||
namespace = namespace[endIdx+1:] |
|
||||||
|
|
||||||
case reflect.Int64: |
|
||||||
i, _ := strconv.ParseInt(key, 10, 64) |
|
||||||
val = current.MapIndex(reflect.ValueOf(i)) |
|
||||||
namespace = namespace[endIdx+1:] |
|
||||||
|
|
||||||
case reflect.Uint: |
|
||||||
i, _ := strconv.ParseUint(key, 10, 0) |
|
||||||
val = current.MapIndex(reflect.ValueOf(uint(i))) |
|
||||||
namespace = namespace[endIdx+1:] |
|
||||||
|
|
||||||
case reflect.Uint8: |
|
||||||
i, _ := strconv.ParseUint(key, 10, 8) |
|
||||||
val = current.MapIndex(reflect.ValueOf(uint8(i))) |
|
||||||
namespace = namespace[endIdx+1:] |
|
||||||
|
|
||||||
case reflect.Uint16: |
|
||||||
i, _ := strconv.ParseUint(key, 10, 16) |
|
||||||
val = current.MapIndex(reflect.ValueOf(uint16(i))) |
|
||||||
namespace = namespace[endIdx+1:] |
|
||||||
|
|
||||||
case reflect.Uint32: |
|
||||||
i, _ := strconv.ParseUint(key, 10, 32) |
|
||||||
val = current.MapIndex(reflect.ValueOf(uint32(i))) |
|
||||||
namespace = namespace[endIdx+1:] |
|
||||||
|
|
||||||
case reflect.Uint64: |
|
||||||
i, _ := strconv.ParseUint(key, 10, 64) |
|
||||||
val = current.MapIndex(reflect.ValueOf(i)) |
|
||||||
namespace = namespace[endIdx+1:] |
|
||||||
|
|
||||||
case reflect.Float32: |
|
||||||
f, _ := strconv.ParseFloat(key, 32) |
|
||||||
val = current.MapIndex(reflect.ValueOf(float32(f))) |
|
||||||
namespace = namespace[endIdx+1:] |
|
||||||
|
|
||||||
case reflect.Float64: |
|
||||||
f, _ := strconv.ParseFloat(key, 64) |
|
||||||
val = current.MapIndex(reflect.ValueOf(f)) |
|
||||||
namespace = namespace[endIdx+1:] |
|
||||||
|
|
||||||
case reflect.Bool: |
|
||||||
b, _ := strconv.ParseBool(key) |
|
||||||
val = current.MapIndex(reflect.ValueOf(b)) |
|
||||||
namespace = namespace[endIdx+1:] |
|
||||||
|
|
||||||
// reflect.Type = string
|
|
||||||
default: |
|
||||||
val = current.MapIndex(reflect.ValueOf(key)) |
|
||||||
namespace = namespace[endIdx+1:] |
|
||||||
} |
|
||||||
|
|
||||||
goto BEGIN |
|
||||||
} |
|
||||||
|
|
||||||
// if got here there was more namespace, cannot go any deeper
|
|
||||||
panic("Invalid field namespace") |
|
||||||
} |
|
||||||
|
|
||||||
// asInt returns the parameter as a int64
|
|
||||||
// or panics if it can't convert
|
|
||||||
func asInt(param string) int64 { |
|
||||||
i, err := strconv.ParseInt(param, 0, 64) |
|
||||||
panicIf(err) |
|
||||||
|
|
||||||
return i |
|
||||||
} |
|
||||||
|
|
||||||
// asIntFromTimeDuration parses param as time.Duration and returns it as int64
|
|
||||||
// or panics on error.
|
|
||||||
func asIntFromTimeDuration(param string) int64 { |
|
||||||
d, err := time.ParseDuration(param) |
|
||||||
if err != nil { |
|
||||||
// attempt parsing as an an integer assuming nanosecond precision
|
|
||||||
return asInt(param) |
|
||||||
} |
|
||||||
return int64(d) |
|
||||||
} |
|
||||||
|
|
||||||
// asIntFromType calls the proper function to parse param as int64,
|
|
||||||
// given a field's Type t.
|
|
||||||
func asIntFromType(t reflect.Type, param string) int64 { |
|
||||||
switch t { |
|
||||||
case timeDurationType: |
|
||||||
return asIntFromTimeDuration(param) |
|
||||||
default: |
|
||||||
return asInt(param) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// asUint returns the parameter as a uint64
|
|
||||||
// or panics if it can't convert
|
|
||||||
func asUint(param string) uint64 { |
|
||||||
|
|
||||||
i, err := strconv.ParseUint(param, 0, 64) |
|
||||||
panicIf(err) |
|
||||||
|
|
||||||
return i |
|
||||||
} |
|
||||||
|
|
||||||
// asFloat returns the parameter as a float64
|
|
||||||
// or panics if it can't convert
|
|
||||||
func asFloat(param string) float64 { |
|
||||||
|
|
||||||
i, err := strconv.ParseFloat(param, 64) |
|
||||||
panicIf(err) |
|
||||||
|
|
||||||
return i |
|
||||||
} |
|
||||||
|
|
||||||
// asBool returns the parameter as a bool
|
|
||||||
// or panics if it can't convert
|
|
||||||
func asBool(param string) bool { |
|
||||||
|
|
||||||
i, err := strconv.ParseBool(param) |
|
||||||
panicIf(err) |
|
||||||
|
|
||||||
return i |
|
||||||
} |
|
||||||
|
|
||||||
func panicIf(err error) { |
|
||||||
if err != nil { |
|
||||||
panic(err.Error()) |
|
||||||
} |
|
||||||
} |
|
@ -1,485 +1,375 @@ |
|||||||
|
/** |
||||||
|
* Package validator |
||||||
|
* |
||||||
|
* MISC: |
||||||
|
* - anonymous structs - they don't have names so expect the Struct name within StructValidationErrors to be blank |
||||||
|
* |
||||||
|
*/ |
||||||
|
|
||||||
package validator |
package validator |
||||||
|
|
||||||
import ( |
import ( |
||||||
"context" |
"bytes" |
||||||
|
"errors" |
||||||
"fmt" |
"fmt" |
||||||
"reflect" |
"reflect" |
||||||
"strconv" |
"strings" |
||||||
|
"time" |
||||||
|
"unicode" |
||||||
|
) |
||||||
|
|
||||||
|
const ( |
||||||
|
tagSeparator = "," |
||||||
|
orSeparator = "|" |
||||||
|
noValidationTag = "-" |
||||||
|
tagKeySeparator = "=" |
||||||
|
structOnlyTag = "structonly" |
||||||
|
omitempty = "omitempty" |
||||||
|
validationFieldErrMsg = "Field validation for \"%s\" failed on the \"%s\" tag\n" |
||||||
|
validationStructErrMsg = "Struct:%s\n" |
||||||
) |
) |
||||||
|
|
||||||
// per validate construct
|
// FieldValidationError contains a single field's validation error along
|
||||||
type validate struct { |
// with other properties that may be needed for error message creation
|
||||||
v *Validate |
type FieldValidationError struct { |
||||||
top reflect.Value |
Field string |
||||||
ns []byte |
ErrorTag string |
||||||
actualNs []byte |
Kind reflect.Kind |
||||||
errs ValidationErrors |
Type reflect.Type |
||||||
includeExclude map[string]struct{} // reset only if StructPartial or StructExcept are called, no need otherwise
|
Param string |
||||||
ffn FilterFunc |
Value interface{} |
||||||
slflParent reflect.Value // StructLevel & FieldLevel
|
|
||||||
slCurrent reflect.Value // StructLevel & FieldLevel
|
|
||||||
flField reflect.Value // StructLevel & FieldLevel
|
|
||||||
cf *cField // StructLevel & FieldLevel
|
|
||||||
ct *cTag // StructLevel & FieldLevel
|
|
||||||
misc []byte // misc reusable
|
|
||||||
str1 string // misc reusable
|
|
||||||
str2 string // misc reusable
|
|
||||||
fldIsPointer bool // StructLevel & FieldLevel
|
|
||||||
isPartial bool |
|
||||||
hasExcludes bool |
|
||||||
} |
} |
||||||
|
|
||||||
// parent and current will be the same the first run of validateStruct
|
// This is intended for use in development + debugging and not intended to be a production error message.
|
||||||
func (v *validate) validateStruct(ctx context.Context, parent reflect.Value, current reflect.Value, typ reflect.Type, ns []byte, structNs []byte, ct *cTag) { |
// it also allows FieldValidationError to be used as an Error interface
|
||||||
|
func (e *FieldValidationError) Error() string { |
||||||
|
return fmt.Sprintf(validationFieldErrMsg, e.Field, e.ErrorTag) |
||||||
|
} |
||||||
|
|
||||||
cs, ok := v.v.structCache.Get(typ) |
// StructValidationErrors is hierarchical list of field and struct validation errors
|
||||||
if !ok { |
// for a non hierarchical representation please see the Flatten method for StructValidationErrors
|
||||||
cs = v.v.extractStructCache(current, typ.Name()) |
type StructValidationErrors struct { |
||||||
} |
// Name of the Struct
|
||||||
|
Struct string |
||||||
|
// Struct Field Errors
|
||||||
|
Errors map[string]*FieldValidationError |
||||||
|
// Struct Fields of type struct and their errors
|
||||||
|
// key = Field Name of current struct, but internally Struct will be the actual struct name unless anonymous struct, it will be blank
|
||||||
|
StructErrors map[string]*StructValidationErrors |
||||||
|
} |
||||||
|
|
||||||
if len(ns) == 0 && len(cs.name) != 0 { |
// This is intended for use in development + debugging and not intended to be a production error message.
|
||||||
|
// it also allows StructValidationErrors to be used as an Error interface
|
||||||
|
func (e *StructValidationErrors) Error() string { |
||||||
|
buff := bytes.NewBufferString(fmt.Sprintf(validationStructErrMsg, e.Struct)) |
||||||
|
|
||||||
ns = append(ns, cs.name...) |
for _, err := range e.Errors { |
||||||
ns = append(ns, '.') |
buff.WriteString(err.Error()) |
||||||
|
} |
||||||
|
|
||||||
structNs = append(structNs, cs.name...) |
for _, err := range e.StructErrors { |
||||||
structNs = append(structNs, '.') |
buff.WriteString(err.Error()) |
||||||
} |
} |
||||||
|
buff.WriteString("\n\n") |
||||||
|
return buff.String() |
||||||
|
} |
||||||
|
|
||||||
// ct is nil on top level struct, and structs as fields that have no tag info
|
// Flatten flattens the StructValidationErrors hierarchical structure into a flat namespace style field name
|
||||||
// so if nil or if not nil and the structonly tag isn't present
|
// for those that want/need it
|
||||||
if ct == nil || ct.typeof != typeStructOnly { |
func (e *StructValidationErrors) Flatten() map[string]*FieldValidationError { |
||||||
|
|
||||||
var f *cField |
if e == nil { |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
for i := 0; i < len(cs.fields); i++ { |
errs := map[string]*FieldValidationError{} |
||||||
|
|
||||||
f = cs.fields[i] |
for _, f := range e.Errors { |
||||||
|
|
||||||
if v.isPartial { |
errs[f.Field] = f |
||||||
|
} |
||||||
|
|
||||||
if v.ffn != nil { |
for key, val := range e.StructErrors { |
||||||
// used with StructFiltered
|
|
||||||
if v.ffn(append(structNs, f.name...)) { |
|
||||||
continue |
|
||||||
} |
|
||||||
|
|
||||||
} else { |
otherErrs := val.Flatten() |
||||||
// used with StructPartial & StructExcept
|
|
||||||
_, ok = v.includeExclude[string(append(structNs, f.name...))] |
|
||||||
|
|
||||||
if (ok && v.hasExcludes) || (!ok && !v.hasExcludes) { |
for _, f2 := range otherErrs { |
||||||
continue |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
v.traverseField(ctx, current, current.Field(f.idx), ns, structNs, f, f.cTags) |
f2.Field = fmt.Sprintf("%s.%s", key, f2.Field) |
||||||
|
errs[f2.Field] = f2 |
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
// check if any struct level validations, after all field validations already checked.
|
return errs |
||||||
// first iteration will have no info about nostructlevel tag, and is checked prior to
|
} |
||||||
// calling the next iteration of validateStruct called from traverseField.
|
|
||||||
if cs.fn != nil { |
|
||||||
|
|
||||||
v.slflParent = parent |
// ValidationFunc accepts all values needed for file and cross field validation
|
||||||
v.slCurrent = current |
// top = top level struct when validating by struct otherwise nil
|
||||||
v.ns = ns |
// current = current level struct when validating by struct otherwise optional comparison value
|
||||||
v.actualNs = structNs |
// f = field value for validation
|
||||||
|
// param = parameter used in validation i.e. gt=0 param would be 0
|
||||||
|
type ValidationFunc func(top interface{}, current interface{}, f interface{}, param string) bool |
||||||
|
|
||||||
|
// Validator implements the Validator Struct
|
||||||
|
// NOTE: Fields within are not thread safe and that is on purpose
|
||||||
|
// Functions and Tags should all be predifined before use, so subscribe to the philosiphy
|
||||||
|
// or make it thread safe on your end
|
||||||
|
type Validator struct { |
||||||
|
// tagName being used.
|
||||||
|
tagName string |
||||||
|
// validationFuncs is a map of validation functions and the tag keys
|
||||||
|
validationFuncs map[string]ValidationFunc |
||||||
|
} |
||||||
|
|
||||||
cs.fn(ctx, v) |
// NewValidator creates a new Validator instance for use.
|
||||||
|
func NewValidator(tagName string, funcs map[string]ValidationFunc) *Validator { |
||||||
|
return &Validator{ |
||||||
|
tagName: tagName, |
||||||
|
validationFuncs: funcs, |
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
// traverseField validates any field, be it a struct or single field, ensures it's validity and passes it along to be validated via it's tag options
|
// SetTag sets tagName of the Validator to one of your choosing after creation
|
||||||
func (v *validate) traverseField(ctx context.Context, parent reflect.Value, current reflect.Value, ns []byte, structNs []byte, cf *cField, ct *cTag) { |
// perhaps to dodge a tag name conflict in a specific section of code
|
||||||
var typ reflect.Type |
func (v *Validator) SetTag(tagName string) { |
||||||
var kind reflect.Kind |
v.tagName = tagName |
||||||
|
} |
||||||
current, kind, v.fldIsPointer = v.extractTypeInternal(current, false) |
|
||||||
|
|
||||||
switch kind { |
// AddFunction adds a ValidationFunc to a Validator's map of validators denoted by the key
|
||||||
case reflect.Ptr, reflect.Interface, reflect.Invalid: |
// NOTE: if the key already exists, it will get replaced.
|
||||||
|
func (v *Validator) AddFunction(key string, f ValidationFunc) error { |
||||||
|
|
||||||
if ct == nil { |
if len(key) == 0 { |
||||||
return |
return errors.New("Function Key cannot be empty") |
||||||
} |
} |
||||||
|
|
||||||
if ct.typeof == typeOmitEmpty || ct.typeof == typeIsDefault { |
if f == nil { |
||||||
return |
return errors.New("Function cannot be empty") |
||||||
} |
} |
||||||
|
|
||||||
if ct.hasTag { |
v.validationFuncs[key] = f |
||||||
if kind == reflect.Invalid { |
|
||||||
v.str1 = string(append(ns, cf.altName...)) |
|
||||||
if v.v.hasTagNameFunc { |
|
||||||
v.str2 = string(append(structNs, cf.name...)) |
|
||||||
} else { |
|
||||||
v.str2 = v.str1 |
|
||||||
} |
|
||||||
v.errs = append(v.errs, |
|
||||||
&fieldError{ |
|
||||||
v: v.v, |
|
||||||
tag: ct.aliasTag, |
|
||||||
actualTag: ct.tag, |
|
||||||
ns: v.str1, |
|
||||||
structNs: v.str2, |
|
||||||
fieldLen: uint8(len(cf.altName)), |
|
||||||
structfieldLen: uint8(len(cf.name)), |
|
||||||
param: ct.param, |
|
||||||
kind: kind, |
|
||||||
}, |
|
||||||
) |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
v.str1 = string(append(ns, cf.altName...)) |
return nil |
||||||
if v.v.hasTagNameFunc { |
} |
||||||
v.str2 = string(append(structNs, cf.name...)) |
|
||||||
} else { |
|
||||||
v.str2 = v.str1 |
|
||||||
} |
|
||||||
if !ct.runValidationWhenNil { |
|
||||||
v.errs = append(v.errs, |
|
||||||
&fieldError{ |
|
||||||
v: v.v, |
|
||||||
tag: ct.aliasTag, |
|
||||||
actualTag: ct.tag, |
|
||||||
ns: v.str1, |
|
||||||
structNs: v.str2, |
|
||||||
fieldLen: uint8(len(cf.altName)), |
|
||||||
structfieldLen: uint8(len(cf.name)), |
|
||||||
value: current.Interface(), |
|
||||||
param: ct.param, |
|
||||||
kind: kind, |
|
||||||
typ: current.Type(), |
|
||||||
}, |
|
||||||
) |
|
||||||
return |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
case reflect.Struct: |
// ValidateStruct validates a struct, even it's nested structs, and returns a struct containing the errors
|
||||||
|
// NOTE: Nested Arrays, or Maps of structs do not get validated only the Array or Map itself; the reason is that there is no good
|
||||||
typ = current.Type() |
// way to represent or report which struct within the array has the error, besides can validate the struct prior to adding it to
|
||||||
|
// the Array or Map.
|
||||||
if !typ.ConvertibleTo(timeType) { |
func (v *Validator) ValidateStruct(s interface{}) *StructValidationErrors { |
||||||
|
|
||||||
if ct != nil { |
|
||||||
|
|
||||||
if ct.typeof == typeStructOnly { |
|
||||||
goto CONTINUE |
|
||||||
} else if ct.typeof == typeIsDefault { |
|
||||||
// set Field Level fields
|
|
||||||
v.slflParent = parent |
|
||||||
v.flField = current |
|
||||||
v.cf = cf |
|
||||||
v.ct = ct |
|
||||||
|
|
||||||
if !ct.fn(ctx, v) { |
|
||||||
v.str1 = string(append(ns, cf.altName...)) |
|
||||||
|
|
||||||
if v.v.hasTagNameFunc { |
|
||||||
v.str2 = string(append(structNs, cf.name...)) |
|
||||||
} else { |
|
||||||
v.str2 = v.str1 |
|
||||||
} |
|
||||||
|
|
||||||
v.errs = append(v.errs, |
|
||||||
&fieldError{ |
|
||||||
v: v.v, |
|
||||||
tag: ct.aliasTag, |
|
||||||
actualTag: ct.tag, |
|
||||||
ns: v.str1, |
|
||||||
structNs: v.str2, |
|
||||||
fieldLen: uint8(len(cf.altName)), |
|
||||||
structfieldLen: uint8(len(cf.name)), |
|
||||||
value: current.Interface(), |
|
||||||
param: ct.param, |
|
||||||
kind: kind, |
|
||||||
typ: typ, |
|
||||||
}, |
|
||||||
) |
|
||||||
return |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
ct = ct.next |
return v.validateStructRecursive(s, s, s) |
||||||
} |
} |
||||||
|
|
||||||
if ct != nil && ct.typeof == typeNoStructLevel { |
// validateStructRecursive validates a struct recursivly and passes the top level and current struct around for use in validator functions and returns a struct containing the errors
|
||||||
return |
func (v *Validator) validateStructRecursive(top interface{}, current interface{}, s interface{}) *StructValidationErrors { |
||||||
} |
|
||||||
|
|
||||||
CONTINUE: |
structValue := reflect.ValueOf(s) |
||||||
// if len == 0 then validating using 'Var' or 'VarWithValue'
|
structType := reflect.TypeOf(s) |
||||||
// Var - doesn't make much sense to do it that way, should call 'Struct', but no harm...
|
structName := structType.Name() |
||||||
// VarWithField - this allows for validating against each field within the struct against a specific value
|
|
||||||
// pretty handy in certain situations
|
|
||||||
if len(cf.name) > 0 { |
|
||||||
ns = append(append(ns, cf.altName...), '.') |
|
||||||
structNs = append(append(structNs, cf.name...), '.') |
|
||||||
} |
|
||||||
|
|
||||||
v.validateStruct(ctx, parent, current, typ, ns, structNs, ct) |
if structValue.Kind() == reflect.Ptr && !structValue.IsNil() { |
||||||
return |
return v.validateStructRecursive(top, current, structValue.Elem().Interface()) |
||||||
} |
|
||||||
} |
} |
||||||
|
|
||||||
if ct == nil || !ct.hasTag { |
if structValue.Kind() != reflect.Struct && structValue.Kind() != reflect.Interface { |
||||||
return |
panic("interface passed for validation is not a struct") |
||||||
} |
} |
||||||
|
|
||||||
typ = current.Type() |
validationErrors := &StructValidationErrors{ |
||||||
|
Struct: structName, |
||||||
|
Errors: map[string]*FieldValidationError{}, |
||||||
|
StructErrors: map[string]*StructValidationErrors{}, |
||||||
|
} |
||||||
|
|
||||||
OUTER: |
var numFields = structValue.NumField() |
||||||
for { |
|
||||||
if ct == nil { |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
switch ct.typeof { |
for i := 0; i < numFields; i++ { |
||||||
|
|
||||||
case typeOmitEmpty: |
valueField := structValue.Field(i) |
||||||
|
typeField := structType.Field(i) |
||||||
|
|
||||||
// set Field Level fields
|
if valueField.Kind() == reflect.Ptr && !valueField.IsNil() { |
||||||
v.slflParent = parent |
valueField = valueField.Elem() |
||||||
v.flField = current |
} |
||||||
v.cf = cf |
|
||||||
v.ct = ct |
|
||||||
|
|
||||||
if !hasValue(v) { |
tag := typeField.Tag.Get(v.tagName) |
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
ct = ct.next |
if tag == noValidationTag { |
||||||
continue |
continue |
||||||
|
} |
||||||
|
|
||||||
case typeEndKeys: |
// if no validation and not a struct (which may containt fields for validation)
|
||||||
return |
if tag == "" && valueField.Kind() != reflect.Struct && valueField.Kind() != reflect.Interface { |
||||||
|
continue |
||||||
case typeDive: |
} |
||||||
|
|
||||||
ct = ct.next |
switch valueField.Kind() { |
||||||
|
|
||||||
// traverse slice or map here
|
case reflect.Struct, reflect.Interface: |
||||||
// or panic ;)
|
|
||||||
switch kind { |
|
||||||
case reflect.Slice, reflect.Array: |
|
||||||
|
|
||||||
var i64 int64 |
if !unicode.IsUpper(rune(typeField.Name[0])) { |
||||||
reusableCF := &cField{} |
continue |
||||||
|
} |
||||||
|
|
||||||
for i := 0; i < current.Len(); i++ { |
if valueField.Type() == reflect.TypeOf(time.Time{}) { |
||||||
|
|
||||||
i64 = int64(i) |
if fieldError := v.validateFieldByNameAndTagAndValue(top, current, valueField.Interface(), typeField.Name, tag); fieldError != nil { |
||||||
|
validationErrors.Errors[fieldError.Field] = fieldError |
||||||
|
// free up memory reference
|
||||||
|
fieldError = nil |
||||||
|
} |
||||||
|
|
||||||
v.misc = append(v.misc[0:0], cf.name...) |
} else { |
||||||
v.misc = append(v.misc, '[') |
|
||||||
v.misc = strconv.AppendInt(v.misc, i64, 10) |
|
||||||
v.misc = append(v.misc, ']') |
|
||||||
|
|
||||||
reusableCF.name = string(v.misc) |
if strings.Contains(tag, structOnlyTag) { |
||||||
|
continue |
||||||
|
} |
||||||
|
|
||||||
if cf.namesEqual { |
if structErrors := v.validateStructRecursive(top, valueField.Interface(), valueField.Interface()); structErrors != nil { |
||||||
reusableCF.altName = reusableCF.name |
validationErrors.StructErrors[typeField.Name] = structErrors |
||||||
} else { |
// free up memory map no longer needed
|
||||||
|
structErrors = nil |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
v.misc = append(v.misc[0:0], cf.altName...) |
default: |
||||||
v.misc = append(v.misc, '[') |
|
||||||
v.misc = strconv.AppendInt(v.misc, i64, 10) |
|
||||||
v.misc = append(v.misc, ']') |
|
||||||
|
|
||||||
reusableCF.altName = string(v.misc) |
if fieldError := v.validateFieldByNameAndTagAndValue(top, current, valueField.Interface(), typeField.Name, tag); fieldError != nil { |
||||||
} |
validationErrors.Errors[fieldError.Field] = fieldError |
||||||
v.traverseField(ctx, parent, current.Index(i), ns, structNs, reusableCF, ct) |
// free up memory reference
|
||||||
} |
fieldError = nil |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
case reflect.Map: |
if len(validationErrors.Errors) == 0 && len(validationErrors.StructErrors) == 0 { |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
var pv string |
return validationErrors |
||||||
reusableCF := &cField{} |
} |
||||||
|
|
||||||
for _, key := range current.MapKeys() { |
// ValidateFieldByTag allows validation of a single field, still using tag style validation to check multiple errors
|
||||||
|
func (v *Validator) ValidateFieldByTag(f interface{}, tag string) *FieldValidationError { |
||||||
|
|
||||||
pv = fmt.Sprintf("%v", key.Interface()) |
return v.ValidateFieldByTagAndValue(nil, f, tag) |
||||||
|
} |
||||||
|
|
||||||
v.misc = append(v.misc[0:0], cf.name...) |
// ValidateFieldByTagAndValue allows validation of a single field, possibly even against another fields value, still using tag style validation to check multiple errors
|
||||||
v.misc = append(v.misc, '[') |
func (v *Validator) ValidateFieldByTagAndValue(val interface{}, f interface{}, tag string) *FieldValidationError { |
||||||
v.misc = append(v.misc, pv...) |
|
||||||
v.misc = append(v.misc, ']') |
|
||||||
|
|
||||||
reusableCF.name = string(v.misc) |
return v.validateFieldByNameAndTagAndValue(nil, val, f, "", tag) |
||||||
|
} |
||||||
|
|
||||||
if cf.namesEqual { |
func (v *Validator) validateFieldByNameAndTagAndValue(val interface{}, current interface{}, f interface{}, name string, tag string) *FieldValidationError { |
||||||
reusableCF.altName = reusableCF.name |
|
||||||
} else { |
|
||||||
v.misc = append(v.misc[0:0], cf.altName...) |
|
||||||
v.misc = append(v.misc, '[') |
|
||||||
v.misc = append(v.misc, pv...) |
|
||||||
v.misc = append(v.misc, ']') |
|
||||||
|
|
||||||
reusableCF.altName = string(v.misc) |
// This is a double check if coming from ValidateStruct but need to be here in case function is called directly
|
||||||
} |
if tag == noValidationTag { |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
if ct != nil && ct.typeof == typeKeys && ct.keys != nil { |
if strings.Contains(tag, omitempty) && !hasValue(val, current, f, "") { |
||||||
v.traverseField(ctx, parent, key, ns, structNs, reusableCF, ct.keys) |
return nil |
||||||
// can be nil when just keys being validated
|
} |
||||||
if ct.next != nil { |
|
||||||
v.traverseField(ctx, parent, current.MapIndex(key), ns, structNs, reusableCF, ct.next) |
|
||||||
} |
|
||||||
} else { |
|
||||||
v.traverseField(ctx, parent, current.MapIndex(key), ns, structNs, reusableCF, ct) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
default: |
valueField := reflect.ValueOf(f) |
||||||
// throw error, if not a slice or map then should not have gotten here
|
fieldKind := valueField.Kind() |
||||||
// bad dive tag
|
|
||||||
panic("dive error! can't dive on a non slice or map") |
|
||||||
} |
|
||||||
|
|
||||||
return |
if fieldKind == reflect.Ptr && !valueField.IsNil() { |
||||||
|
return v.validateFieldByNameAndTagAndValue(val, current, valueField.Elem().Interface(), name, tag) |
||||||
|
} |
||||||
|
|
||||||
case typeOr: |
fieldType := valueField.Type() |
||||||
|
|
||||||
v.misc = v.misc[0:0] |
switch fieldKind { |
||||||
|
|
||||||
for { |
case reflect.Struct, reflect.Interface, reflect.Invalid: |
||||||
|
|
||||||
// set Field Level fields
|
if fieldType != reflect.TypeOf(time.Time{}) { |
||||||
v.slflParent = parent |
panic("Invalid field passed to ValidateFieldWithTag") |
||||||
v.flField = current |
} |
||||||
v.cf = cf |
} |
||||||
v.ct = ct |
|
||||||
|
|
||||||
if ct.fn(ctx, v) { |
var valErr *FieldValidationError |
||||||
if ct.isBlockEnd { |
var err error |
||||||
ct = ct.next |
valTags := strings.Split(tag, tagSeparator) |
||||||
continue OUTER |
|
||||||
} |
|
||||||
|
|
||||||
// drain rest of the 'or' values, then continue or leave
|
for _, valTag := range valTags { |
||||||
for { |
|
||||||
|
|
||||||
ct = ct.next |
orVals := strings.Split(valTag, orSeparator) |
||||||
|
|
||||||
if ct == nil { |
if len(orVals) > 1 { |
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
if ct.typeof != typeOr { |
errTag := "" |
||||||
continue OUTER |
|
||||||
} |
|
||||||
|
|
||||||
if ct.isBlockEnd { |
for _, val := range orVals { |
||||||
ct = ct.next |
|
||||||
continue OUTER |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
v.misc = append(v.misc, '|') |
valErr, err = v.validateFieldByNameAndSingleTag(val, current, f, name, val) |
||||||
v.misc = append(v.misc, ct.tag...) |
|
||||||
|
|
||||||
if ct.hasParam { |
if err == nil { |
||||||
v.misc = append(v.misc, '=') |
return nil |
||||||
v.misc = append(v.misc, ct.param...) |
|
||||||
} |
} |
||||||
|
|
||||||
if ct.isBlockEnd || ct.next == nil { |
errTag += orSeparator + valErr.ErrorTag |
||||||
// if we get here, no valid 'or' value and no more tags
|
|
||||||
v.str1 = string(append(ns, cf.altName...)) |
|
||||||
|
|
||||||
if v.v.hasTagNameFunc { |
|
||||||
v.str2 = string(append(structNs, cf.name...)) |
|
||||||
} else { |
|
||||||
v.str2 = v.str1 |
|
||||||
} |
|
||||||
|
|
||||||
if ct.hasAlias { |
|
||||||
|
|
||||||
v.errs = append(v.errs, |
|
||||||
&fieldError{ |
|
||||||
v: v.v, |
|
||||||
tag: ct.aliasTag, |
|
||||||
actualTag: ct.actualAliasTag, |
|
||||||
ns: v.str1, |
|
||||||
structNs: v.str2, |
|
||||||
fieldLen: uint8(len(cf.altName)), |
|
||||||
structfieldLen: uint8(len(cf.name)), |
|
||||||
value: current.Interface(), |
|
||||||
param: ct.param, |
|
||||||
kind: kind, |
|
||||||
typ: typ, |
|
||||||
}, |
|
||||||
) |
|
||||||
|
|
||||||
} else { |
|
||||||
|
|
||||||
tVal := string(v.misc)[1:] |
|
||||||
|
|
||||||
v.errs = append(v.errs, |
|
||||||
&fieldError{ |
|
||||||
v: v.v, |
|
||||||
tag: tVal, |
|
||||||
actualTag: tVal, |
|
||||||
ns: v.str1, |
|
||||||
structNs: v.str2, |
|
||||||
fieldLen: uint8(len(cf.altName)), |
|
||||||
structfieldLen: uint8(len(cf.name)), |
|
||||||
value: current.Interface(), |
|
||||||
param: ct.param, |
|
||||||
kind: kind, |
|
||||||
typ: typ, |
|
||||||
}, |
|
||||||
) |
|
||||||
} |
|
||||||
|
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
ct = ct.next |
|
||||||
} |
} |
||||||
|
|
||||||
default: |
errTag = strings.TrimLeft(errTag, orSeparator) |
||||||
|
|
||||||
// set Field Level fields
|
valErr.ErrorTag = errTag |
||||||
v.slflParent = parent |
valErr.Kind = fieldKind |
||||||
v.flField = current |
|
||||||
v.cf = cf |
|
||||||
v.ct = ct |
|
||||||
|
|
||||||
if !ct.fn(ctx, v) { |
return valErr |
||||||
v.str1 = string(append(ns, cf.altName...)) |
} |
||||||
|
|
||||||
if v.v.hasTagNameFunc { |
if valErr, err = v.validateFieldByNameAndSingleTag(val, current, f, name, valTag); err != nil { |
||||||
v.str2 = string(append(structNs, cf.name...)) |
|
||||||
} else { |
|
||||||
v.str2 = v.str1 |
|
||||||
} |
|
||||||
|
|
||||||
v.errs = append(v.errs, |
valErr.Kind = valueField.Kind() |
||||||
&fieldError{ |
valErr.Type = fieldType |
||||||
v: v.v, |
|
||||||
tag: ct.aliasTag, |
return valErr |
||||||
actualTag: ct.tag, |
|
||||||
ns: v.str1, |
|
||||||
structNs: v.str2, |
|
||||||
fieldLen: uint8(len(cf.altName)), |
|
||||||
structfieldLen: uint8(len(cf.name)), |
|
||||||
value: current.Interface(), |
|
||||||
param: ct.param, |
|
||||||
kind: kind, |
|
||||||
typ: typ, |
|
||||||
}, |
|
||||||
) |
|
||||||
|
|
||||||
return |
|
||||||
} |
|
||||||
ct = ct.next |
|
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
func (v *Validator) validateFieldByNameAndSingleTag(val interface{}, current interface{}, f interface{}, name string, valTag string) (*FieldValidationError, error) { |
||||||
|
|
||||||
|
vals := strings.Split(valTag, tagKeySeparator) |
||||||
|
key := strings.Trim(vals[0], " ") |
||||||
|
|
||||||
|
if len(key) == 0 { |
||||||
|
panic(fmt.Sprintf("Invalid validation tag on field %s", name)) |
||||||
|
} |
||||||
|
|
||||||
|
valErr := &FieldValidationError{ |
||||||
|
Field: name, |
||||||
|
ErrorTag: key, |
||||||
|
Value: f, |
||||||
|
Param: "", |
||||||
|
} |
||||||
|
|
||||||
|
// OK to continue because we checked it's existance before getting into this loop
|
||||||
|
if key == omitempty { |
||||||
|
return valErr, nil |
||||||
|
} |
||||||
|
|
||||||
|
valFunc, ok := v.validationFuncs[key] |
||||||
|
if !ok { |
||||||
|
panic(fmt.Sprintf("Undefined validation function on field %s", name)) |
||||||
|
} |
||||||
|
|
||||||
|
param := "" |
||||||
|
if len(vals) > 1 { |
||||||
|
param = strings.Trim(vals[1], " ") |
||||||
|
} |
||||||
|
|
||||||
|
if err := valFunc(val, current, f, param); !err { |
||||||
|
valErr.Param = param |
||||||
|
return valErr, errors.New(key) |
||||||
|
} |
||||||
|
|
||||||
|
return valErr, nil |
||||||
} |
} |
||||||
|
@ -1,700 +0,0 @@ |
|||||||
package validator |
|
||||||
|
|
||||||
import ( |
|
||||||
"context" |
|
||||||
"errors" |
|
||||||
"fmt" |
|
||||||
"reflect" |
|
||||||
"strings" |
|
||||||
"sync" |
|
||||||
"time" |
|
||||||
|
|
||||||
ut "github.com/go-playground/universal-translator" |
|
||||||
) |
|
||||||
|
|
||||||
const ( |
|
||||||
defaultTagName = "validate" |
|
||||||
utf8HexComma = "0x2C" |
|
||||||
utf8Pipe = "0x7C" |
|
||||||
tagSeparator = "," |
|
||||||
orSeparator = "|" |
|
||||||
tagKeySeparator = "=" |
|
||||||
structOnlyTag = "structonly" |
|
||||||
noStructLevelTag = "nostructlevel" |
|
||||||
omitempty = "omitempty" |
|
||||||
isdefault = "isdefault" |
|
||||||
requiredWithoutAllTag = "required_without_all" |
|
||||||
requiredWithoutTag = "required_without" |
|
||||||
requiredWithTag = "required_with" |
|
||||||
requiredWithAllTag = "required_with_all" |
|
||||||
requiredIfTag = "required_if" |
|
||||||
requiredUnlessTag = "required_unless" |
|
||||||
excludedWithoutAllTag = "excluded_without_all" |
|
||||||
excludedWithoutTag = "excluded_without" |
|
||||||
excludedWithTag = "excluded_with" |
|
||||||
excludedWithAllTag = "excluded_with_all" |
|
||||||
excludedIfTag = "excluded_if" |
|
||||||
excludedUnlessTag = "excluded_unless" |
|
||||||
skipValidationTag = "-" |
|
||||||
diveTag = "dive" |
|
||||||
keysTag = "keys" |
|
||||||
endKeysTag = "endkeys" |
|
||||||
requiredTag = "required" |
|
||||||
namespaceSeparator = "." |
|
||||||
leftBracket = "[" |
|
||||||
rightBracket = "]" |
|
||||||
restrictedTagChars = ".[],|=+()`~!@#$%^&*\\\"/?<>{}" |
|
||||||
restrictedAliasErr = "Alias '%s' either contains restricted characters or is the same as a restricted tag needed for normal operation" |
|
||||||
restrictedTagErr = "Tag '%s' either contains restricted characters or is the same as a restricted tag needed for normal operation" |
|
||||||
) |
|
||||||
|
|
||||||
var ( |
|
||||||
timeDurationType = reflect.TypeOf(time.Duration(0)) |
|
||||||
timeType = reflect.TypeOf(time.Time{}) |
|
||||||
|
|
||||||
defaultCField = &cField{namesEqual: true} |
|
||||||
) |
|
||||||
|
|
||||||
// FilterFunc is the type used to filter fields using
|
|
||||||
// StructFiltered(...) function.
|
|
||||||
// returning true results in the field being filtered/skiped from
|
|
||||||
// validation
|
|
||||||
type FilterFunc func(ns []byte) bool |
|
||||||
|
|
||||||
// CustomTypeFunc allows for overriding or adding custom field type handler functions
|
|
||||||
// field = field value of the type to return a value to be validated
|
|
||||||
// example Valuer from sql drive see https://golang.org/src/database/sql/driver/types.go?s=1210:1293#L29
|
|
||||||
type CustomTypeFunc func(field reflect.Value) interface{} |
|
||||||
|
|
||||||
// TagNameFunc allows for adding of a custom tag name parser
|
|
||||||
type TagNameFunc func(field reflect.StructField) string |
|
||||||
|
|
||||||
type internalValidationFuncWrapper struct { |
|
||||||
fn FuncCtx |
|
||||||
runValidatinOnNil bool |
|
||||||
} |
|
||||||
|
|
||||||
// Validate contains the validator settings and cache
|
|
||||||
type Validate struct { |
|
||||||
tagName string |
|
||||||
pool *sync.Pool |
|
||||||
hasCustomFuncs bool |
|
||||||
hasTagNameFunc bool |
|
||||||
tagNameFunc TagNameFunc |
|
||||||
structLevelFuncs map[reflect.Type]StructLevelFuncCtx |
|
||||||
customFuncs map[reflect.Type]CustomTypeFunc |
|
||||||
aliases map[string]string |
|
||||||
validations map[string]internalValidationFuncWrapper |
|
||||||
transTagFunc map[ut.Translator]map[string]TranslationFunc // map[<locale>]map[<tag>]TranslationFunc
|
|
||||||
rules map[reflect.Type]map[string]string |
|
||||||
tagCache *tagCache |
|
||||||
structCache *structCache |
|
||||||
} |
|
||||||
|
|
||||||
// New returns a new instance of 'validate' with sane defaults.
|
|
||||||
// Validate is designed to be thread-safe and used as a singleton instance.
|
|
||||||
// It caches information about your struct and validations,
|
|
||||||
// in essence only parsing your validation tags once per struct type.
|
|
||||||
// Using multiple instances neglects the benefit of caching.
|
|
||||||
func New() *Validate { |
|
||||||
|
|
||||||
tc := new(tagCache) |
|
||||||
tc.m.Store(make(map[string]*cTag)) |
|
||||||
|
|
||||||
sc := new(structCache) |
|
||||||
sc.m.Store(make(map[reflect.Type]*cStruct)) |
|
||||||
|
|
||||||
v := &Validate{ |
|
||||||
tagName: defaultTagName, |
|
||||||
aliases: make(map[string]string, len(bakedInAliases)), |
|
||||||
validations: make(map[string]internalValidationFuncWrapper, len(bakedInValidators)), |
|
||||||
tagCache: tc, |
|
||||||
structCache: sc, |
|
||||||
} |
|
||||||
|
|
||||||
// must copy alias validators for separate validations to be used in each validator instance
|
|
||||||
for k, val := range bakedInAliases { |
|
||||||
v.RegisterAlias(k, val) |
|
||||||
} |
|
||||||
|
|
||||||
// must copy validators for separate validations to be used in each instance
|
|
||||||
for k, val := range bakedInValidators { |
|
||||||
|
|
||||||
switch k { |
|
||||||
// these require that even if the value is nil that the validation should run, omitempty still overrides this behaviour
|
|
||||||
case requiredIfTag, requiredUnlessTag, requiredWithTag, requiredWithAllTag, requiredWithoutTag, requiredWithoutAllTag, |
|
||||||
excludedIfTag, excludedUnlessTag, excludedWithTag, excludedWithAllTag, excludedWithoutTag, excludedWithoutAllTag: |
|
||||||
_ = v.registerValidation(k, wrapFunc(val), true, true) |
|
||||||
default: |
|
||||||
// no need to error check here, baked in will always be valid
|
|
||||||
_ = v.registerValidation(k, wrapFunc(val), true, false) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
v.pool = &sync.Pool{ |
|
||||||
New: func() interface{} { |
|
||||||
return &validate{ |
|
||||||
v: v, |
|
||||||
ns: make([]byte, 0, 64), |
|
||||||
actualNs: make([]byte, 0, 64), |
|
||||||
misc: make([]byte, 32), |
|
||||||
} |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
return v |
|
||||||
} |
|
||||||
|
|
||||||
// SetTagName allows for changing of the default tag name of 'validate'
|
|
||||||
func (v *Validate) SetTagName(name string) { |
|
||||||
v.tagName = name |
|
||||||
} |
|
||||||
|
|
||||||
// ValidateMapCtx validates a map using a map of validation rules and allows passing of contextual
|
|
||||||
// validation validation information via context.Context.
|
|
||||||
func (v Validate) ValidateMapCtx(ctx context.Context, data map[string]interface{}, rules map[string]interface{}) map[string]interface{} { |
|
||||||
errs := make(map[string]interface{}) |
|
||||||
for field, rule := range rules { |
|
||||||
if ruleObj, ok := rule.(map[string]interface{}); ok { |
|
||||||
if dataObj, ok := data[field].(map[string]interface{}); ok { |
|
||||||
err := v.ValidateMapCtx(ctx, dataObj, ruleObj) |
|
||||||
if len(err) > 0 { |
|
||||||
errs[field] = err |
|
||||||
} |
|
||||||
} else if dataObjs, ok := data[field].([]map[string]interface{}); ok { |
|
||||||
for _, obj := range dataObjs { |
|
||||||
err := v.ValidateMapCtx(ctx, obj, ruleObj) |
|
||||||
if len(err) > 0 { |
|
||||||
errs[field] = err |
|
||||||
} |
|
||||||
} |
|
||||||
} else { |
|
||||||
errs[field] = errors.New("The field: '" + field + "' is not a map to dive") |
|
||||||
} |
|
||||||
} else if ruleStr, ok := rule.(string); ok { |
|
||||||
err := v.VarCtx(ctx, data[field], ruleStr) |
|
||||||
if err != nil { |
|
||||||
errs[field] = err |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return errs |
|
||||||
} |
|
||||||
|
|
||||||
// ValidateMap validates map data from a map of tags
|
|
||||||
func (v *Validate) ValidateMap(data map[string]interface{}, rules map[string]interface{}) map[string]interface{} { |
|
||||||
return v.ValidateMapCtx(context.Background(), data, rules) |
|
||||||
} |
|
||||||
|
|
||||||
// RegisterTagNameFunc registers a function to get alternate names for StructFields.
|
|
||||||
//
|
|
||||||
// eg. to use the names which have been specified for JSON representations of structs, rather than normal Go field names:
|
|
||||||
//
|
|
||||||
// validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
|
|
||||||
// name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
|
|
||||||
// // skip if tag key says it should be ignored
|
|
||||||
// if name == "-" {
|
|
||||||
// return ""
|
|
||||||
// }
|
|
||||||
// return name
|
|
||||||
// })
|
|
||||||
func (v *Validate) RegisterTagNameFunc(fn TagNameFunc) { |
|
||||||
v.tagNameFunc = fn |
|
||||||
v.hasTagNameFunc = true |
|
||||||
} |
|
||||||
|
|
||||||
// RegisterValidation adds a validation with the given tag
|
|
||||||
//
|
|
||||||
// NOTES:
|
|
||||||
// - if the key already exists, the previous validation function will be replaced.
|
|
||||||
// - this method is not thread-safe it is intended that these all be registered prior to any validation
|
|
||||||
func (v *Validate) RegisterValidation(tag string, fn Func, callValidationEvenIfNull ...bool) error { |
|
||||||
return v.RegisterValidationCtx(tag, wrapFunc(fn), callValidationEvenIfNull...) |
|
||||||
} |
|
||||||
|
|
||||||
// RegisterValidationCtx does the same as RegisterValidation on accepts a FuncCtx validation
|
|
||||||
// allowing context.Context validation support.
|
|
||||||
func (v *Validate) RegisterValidationCtx(tag string, fn FuncCtx, callValidationEvenIfNull ...bool) error { |
|
||||||
var nilCheckable bool |
|
||||||
if len(callValidationEvenIfNull) > 0 { |
|
||||||
nilCheckable = callValidationEvenIfNull[0] |
|
||||||
} |
|
||||||
return v.registerValidation(tag, fn, false, nilCheckable) |
|
||||||
} |
|
||||||
|
|
||||||
func (v *Validate) registerValidation(tag string, fn FuncCtx, bakedIn bool, nilCheckable bool) error { |
|
||||||
if len(tag) == 0 { |
|
||||||
return errors.New("function Key cannot be empty") |
|
||||||
} |
|
||||||
|
|
||||||
if fn == nil { |
|
||||||
return errors.New("function cannot be empty") |
|
||||||
} |
|
||||||
|
|
||||||
_, ok := restrictedTags[tag] |
|
||||||
if !bakedIn && (ok || strings.ContainsAny(tag, restrictedTagChars)) { |
|
||||||
panic(fmt.Sprintf(restrictedTagErr, tag)) |
|
||||||
} |
|
||||||
v.validations[tag] = internalValidationFuncWrapper{fn: fn, runValidatinOnNil: nilCheckable} |
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
// RegisterAlias registers a mapping of a single validation tag that
|
|
||||||
// defines a common or complex set of validation(s) to simplify adding validation
|
|
||||||
// to structs.
|
|
||||||
//
|
|
||||||
// NOTE: this function is not thread-safe it is intended that these all be registered prior to any validation
|
|
||||||
func (v *Validate) RegisterAlias(alias, tags string) { |
|
||||||
|
|
||||||
_, ok := restrictedTags[alias] |
|
||||||
|
|
||||||
if ok || strings.ContainsAny(alias, restrictedTagChars) { |
|
||||||
panic(fmt.Sprintf(restrictedAliasErr, alias)) |
|
||||||
} |
|
||||||
|
|
||||||
v.aliases[alias] = tags |
|
||||||
} |
|
||||||
|
|
||||||
// RegisterStructValidation registers a StructLevelFunc against a number of types.
|
|
||||||
//
|
|
||||||
// NOTE:
|
|
||||||
// - this method is not thread-safe it is intended that these all be registered prior to any validation
|
|
||||||
func (v *Validate) RegisterStructValidation(fn StructLevelFunc, types ...interface{}) { |
|
||||||
v.RegisterStructValidationCtx(wrapStructLevelFunc(fn), types...) |
|
||||||
} |
|
||||||
|
|
||||||
// RegisterStructValidationCtx registers a StructLevelFuncCtx against a number of types and allows passing
|
|
||||||
// of contextual validation information via context.Context.
|
|
||||||
//
|
|
||||||
// NOTE:
|
|
||||||
// - this method is not thread-safe it is intended that these all be registered prior to any validation
|
|
||||||
func (v *Validate) RegisterStructValidationCtx(fn StructLevelFuncCtx, types ...interface{}) { |
|
||||||
|
|
||||||
if v.structLevelFuncs == nil { |
|
||||||
v.structLevelFuncs = make(map[reflect.Type]StructLevelFuncCtx) |
|
||||||
} |
|
||||||
|
|
||||||
for _, t := range types { |
|
||||||
tv := reflect.ValueOf(t) |
|
||||||
if tv.Kind() == reflect.Ptr { |
|
||||||
t = reflect.Indirect(tv).Interface() |
|
||||||
} |
|
||||||
|
|
||||||
v.structLevelFuncs[reflect.TypeOf(t)] = fn |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// RegisterStructValidationMapRules registers validate map rules.
|
|
||||||
// Be aware that map validation rules supersede those defined on a/the struct if present.
|
|
||||||
//
|
|
||||||
// NOTE: this method is not thread-safe it is intended that these all be registered prior to any validation
|
|
||||||
func (v *Validate) RegisterStructValidationMapRules(rules map[string]string, types ...interface{}) { |
|
||||||
if v.rules == nil { |
|
||||||
v.rules = make(map[reflect.Type]map[string]string) |
|
||||||
} |
|
||||||
|
|
||||||
deepCopyRules := make(map[string]string) |
|
||||||
for i, rule := range rules { |
|
||||||
deepCopyRules[i] = rule |
|
||||||
} |
|
||||||
|
|
||||||
for _, t := range types { |
|
||||||
typ := reflect.TypeOf(t) |
|
||||||
|
|
||||||
if typ.Kind() == reflect.Ptr { |
|
||||||
typ = typ.Elem() |
|
||||||
} |
|
||||||
|
|
||||||
if typ.Kind() != reflect.Struct { |
|
||||||
continue |
|
||||||
} |
|
||||||
v.rules[typ] = deepCopyRules |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// RegisterCustomTypeFunc registers a CustomTypeFunc against a number of types
|
|
||||||
//
|
|
||||||
// NOTE: this method is not thread-safe it is intended that these all be registered prior to any validation
|
|
||||||
func (v *Validate) RegisterCustomTypeFunc(fn CustomTypeFunc, types ...interface{}) { |
|
||||||
|
|
||||||
if v.customFuncs == nil { |
|
||||||
v.customFuncs = make(map[reflect.Type]CustomTypeFunc) |
|
||||||
} |
|
||||||
|
|
||||||
for _, t := range types { |
|
||||||
v.customFuncs[reflect.TypeOf(t)] = fn |
|
||||||
} |
|
||||||
|
|
||||||
v.hasCustomFuncs = true |
|
||||||
} |
|
||||||
|
|
||||||
// RegisterTranslation registers translations against the provided tag.
|
|
||||||
func (v *Validate) RegisterTranslation(tag string, trans ut.Translator, registerFn RegisterTranslationsFunc, translationFn TranslationFunc) (err error) { |
|
||||||
|
|
||||||
if v.transTagFunc == nil { |
|
||||||
v.transTagFunc = make(map[ut.Translator]map[string]TranslationFunc) |
|
||||||
} |
|
||||||
|
|
||||||
if err = registerFn(trans); err != nil { |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
m, ok := v.transTagFunc[trans] |
|
||||||
if !ok { |
|
||||||
m = make(map[string]TranslationFunc) |
|
||||||
v.transTagFunc[trans] = m |
|
||||||
} |
|
||||||
|
|
||||||
m[tag] = translationFn |
|
||||||
|
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
// Struct validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified.
|
|
||||||
//
|
|
||||||
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
|
|
||||||
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
|
|
||||||
func (v *Validate) Struct(s interface{}) error { |
|
||||||
return v.StructCtx(context.Background(), s) |
|
||||||
} |
|
||||||
|
|
||||||
// StructCtx validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified
|
|
||||||
// and also allows passing of context.Context for contextual validation information.
|
|
||||||
//
|
|
||||||
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
|
|
||||||
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
|
|
||||||
func (v *Validate) StructCtx(ctx context.Context, s interface{}) (err error) { |
|
||||||
|
|
||||||
val := reflect.ValueOf(s) |
|
||||||
top := val |
|
||||||
|
|
||||||
if val.Kind() == reflect.Ptr && !val.IsNil() { |
|
||||||
val = val.Elem() |
|
||||||
} |
|
||||||
|
|
||||||
if val.Kind() != reflect.Struct || val.Type().ConvertibleTo(timeType) { |
|
||||||
return &InvalidValidationError{Type: reflect.TypeOf(s)} |
|
||||||
} |
|
||||||
|
|
||||||
// good to validate
|
|
||||||
vd := v.pool.Get().(*validate) |
|
||||||
vd.top = top |
|
||||||
vd.isPartial = false |
|
||||||
// vd.hasExcludes = false // only need to reset in StructPartial and StructExcept
|
|
||||||
|
|
||||||
vd.validateStruct(ctx, top, val, val.Type(), vd.ns[0:0], vd.actualNs[0:0], nil) |
|
||||||
|
|
||||||
if len(vd.errs) > 0 { |
|
||||||
err = vd.errs |
|
||||||
vd.errs = nil |
|
||||||
} |
|
||||||
|
|
||||||
v.pool.Put(vd) |
|
||||||
|
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
// StructFiltered validates a structs exposed fields, that pass the FilterFunc check and automatically validates
|
|
||||||
// nested structs, unless otherwise specified.
|
|
||||||
//
|
|
||||||
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
|
|
||||||
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
|
|
||||||
func (v *Validate) StructFiltered(s interface{}, fn FilterFunc) error { |
|
||||||
return v.StructFilteredCtx(context.Background(), s, fn) |
|
||||||
} |
|
||||||
|
|
||||||
// StructFilteredCtx validates a structs exposed fields, that pass the FilterFunc check and automatically validates
|
|
||||||
// nested structs, unless otherwise specified and also allows passing of contextual validation information via
|
|
||||||
// context.Context
|
|
||||||
//
|
|
||||||
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
|
|
||||||
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
|
|
||||||
func (v *Validate) StructFilteredCtx(ctx context.Context, s interface{}, fn FilterFunc) (err error) { |
|
||||||
val := reflect.ValueOf(s) |
|
||||||
top := val |
|
||||||
|
|
||||||
if val.Kind() == reflect.Ptr && !val.IsNil() { |
|
||||||
val = val.Elem() |
|
||||||
} |
|
||||||
|
|
||||||
if val.Kind() != reflect.Struct || val.Type().ConvertibleTo(timeType) { |
|
||||||
return &InvalidValidationError{Type: reflect.TypeOf(s)} |
|
||||||
} |
|
||||||
|
|
||||||
// good to validate
|
|
||||||
vd := v.pool.Get().(*validate) |
|
||||||
vd.top = top |
|
||||||
vd.isPartial = true |
|
||||||
vd.ffn = fn |
|
||||||
// vd.hasExcludes = false // only need to reset in StructPartial and StructExcept
|
|
||||||
|
|
||||||
vd.validateStruct(ctx, top, val, val.Type(), vd.ns[0:0], vd.actualNs[0:0], nil) |
|
||||||
|
|
||||||
if len(vd.errs) > 0 { |
|
||||||
err = vd.errs |
|
||||||
vd.errs = nil |
|
||||||
} |
|
||||||
|
|
||||||
v.pool.Put(vd) |
|
||||||
|
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
// StructPartial validates the fields passed in only, ignoring all others.
|
|
||||||
// Fields may be provided in a namespaced fashion relative to the struct provided
|
|
||||||
// eg. NestedStruct.Field or NestedArrayField[0].Struct.Name
|
|
||||||
//
|
|
||||||
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
|
|
||||||
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
|
|
||||||
func (v *Validate) StructPartial(s interface{}, fields ...string) error { |
|
||||||
return v.StructPartialCtx(context.Background(), s, fields...) |
|
||||||
} |
|
||||||
|
|
||||||
// StructPartialCtx validates the fields passed in only, ignoring all others and allows passing of contextual
|
|
||||||
// validation validation information via context.Context
|
|
||||||
// Fields may be provided in a namespaced fashion relative to the struct provided
|
|
||||||
// eg. NestedStruct.Field or NestedArrayField[0].Struct.Name
|
|
||||||
//
|
|
||||||
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
|
|
||||||
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
|
|
||||||
func (v *Validate) StructPartialCtx(ctx context.Context, s interface{}, fields ...string) (err error) { |
|
||||||
val := reflect.ValueOf(s) |
|
||||||
top := val |
|
||||||
|
|
||||||
if val.Kind() == reflect.Ptr && !val.IsNil() { |
|
||||||
val = val.Elem() |
|
||||||
} |
|
||||||
|
|
||||||
if val.Kind() != reflect.Struct || val.Type().ConvertibleTo(timeType) { |
|
||||||
return &InvalidValidationError{Type: reflect.TypeOf(s)} |
|
||||||
} |
|
||||||
|
|
||||||
// good to validate
|
|
||||||
vd := v.pool.Get().(*validate) |
|
||||||
vd.top = top |
|
||||||
vd.isPartial = true |
|
||||||
vd.ffn = nil |
|
||||||
vd.hasExcludes = false |
|
||||||
vd.includeExclude = make(map[string]struct{}) |
|
||||||
|
|
||||||
typ := val.Type() |
|
||||||
name := typ.Name() |
|
||||||
|
|
||||||
for _, k := range fields { |
|
||||||
|
|
||||||
flds := strings.Split(k, namespaceSeparator) |
|
||||||
if len(flds) > 0 { |
|
||||||
|
|
||||||
vd.misc = append(vd.misc[0:0], name...) |
|
||||||
// Don't append empty name for unnamed structs
|
|
||||||
if len(vd.misc) != 0 { |
|
||||||
vd.misc = append(vd.misc, '.') |
|
||||||
} |
|
||||||
|
|
||||||
for _, s := range flds { |
|
||||||
|
|
||||||
idx := strings.Index(s, leftBracket) |
|
||||||
|
|
||||||
if idx != -1 { |
|
||||||
for idx != -1 { |
|
||||||
vd.misc = append(vd.misc, s[:idx]...) |
|
||||||
vd.includeExclude[string(vd.misc)] = struct{}{} |
|
||||||
|
|
||||||
idx2 := strings.Index(s, rightBracket) |
|
||||||
idx2++ |
|
||||||
vd.misc = append(vd.misc, s[idx:idx2]...) |
|
||||||
vd.includeExclude[string(vd.misc)] = struct{}{} |
|
||||||
s = s[idx2:] |
|
||||||
idx = strings.Index(s, leftBracket) |
|
||||||
} |
|
||||||
} else { |
|
||||||
|
|
||||||
vd.misc = append(vd.misc, s...) |
|
||||||
vd.includeExclude[string(vd.misc)] = struct{}{} |
|
||||||
} |
|
||||||
|
|
||||||
vd.misc = append(vd.misc, '.') |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
vd.validateStruct(ctx, top, val, typ, vd.ns[0:0], vd.actualNs[0:0], nil) |
|
||||||
|
|
||||||
if len(vd.errs) > 0 { |
|
||||||
err = vd.errs |
|
||||||
vd.errs = nil |
|
||||||
} |
|
||||||
|
|
||||||
v.pool.Put(vd) |
|
||||||
|
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
// StructExcept validates all fields except the ones passed in.
|
|
||||||
// Fields may be provided in a namespaced fashion relative to the struct provided
|
|
||||||
// i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name
|
|
||||||
//
|
|
||||||
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
|
|
||||||
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
|
|
||||||
func (v *Validate) StructExcept(s interface{}, fields ...string) error { |
|
||||||
return v.StructExceptCtx(context.Background(), s, fields...) |
|
||||||
} |
|
||||||
|
|
||||||
// StructExceptCtx validates all fields except the ones passed in and allows passing of contextual
|
|
||||||
// validation validation information via context.Context
|
|
||||||
// Fields may be provided in a namespaced fashion relative to the struct provided
|
|
||||||
// i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name
|
|
||||||
//
|
|
||||||
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
|
|
||||||
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
|
|
||||||
func (v *Validate) StructExceptCtx(ctx context.Context, s interface{}, fields ...string) (err error) { |
|
||||||
val := reflect.ValueOf(s) |
|
||||||
top := val |
|
||||||
|
|
||||||
if val.Kind() == reflect.Ptr && !val.IsNil() { |
|
||||||
val = val.Elem() |
|
||||||
} |
|
||||||
|
|
||||||
if val.Kind() != reflect.Struct || val.Type().ConvertibleTo(timeType) { |
|
||||||
return &InvalidValidationError{Type: reflect.TypeOf(s)} |
|
||||||
} |
|
||||||
|
|
||||||
// good to validate
|
|
||||||
vd := v.pool.Get().(*validate) |
|
||||||
vd.top = top |
|
||||||
vd.isPartial = true |
|
||||||
vd.ffn = nil |
|
||||||
vd.hasExcludes = true |
|
||||||
vd.includeExclude = make(map[string]struct{}) |
|
||||||
|
|
||||||
typ := val.Type() |
|
||||||
name := typ.Name() |
|
||||||
|
|
||||||
for _, key := range fields { |
|
||||||
|
|
||||||
vd.misc = vd.misc[0:0] |
|
||||||
|
|
||||||
if len(name) > 0 { |
|
||||||
vd.misc = append(vd.misc, name...) |
|
||||||
vd.misc = append(vd.misc, '.') |
|
||||||
} |
|
||||||
|
|
||||||
vd.misc = append(vd.misc, key...) |
|
||||||
vd.includeExclude[string(vd.misc)] = struct{}{} |
|
||||||
} |
|
||||||
|
|
||||||
vd.validateStruct(ctx, top, val, typ, vd.ns[0:0], vd.actualNs[0:0], nil) |
|
||||||
|
|
||||||
if len(vd.errs) > 0 { |
|
||||||
err = vd.errs |
|
||||||
vd.errs = nil |
|
||||||
} |
|
||||||
|
|
||||||
v.pool.Put(vd) |
|
||||||
|
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
// Var validates a single variable using tag style validation.
|
|
||||||
// eg.
|
|
||||||
// var i int
|
|
||||||
// validate.Var(i, "gt=1,lt=10")
|
|
||||||
//
|
|
||||||
// WARNING: a struct can be passed for validation eg. time.Time is a struct or
|
|
||||||
// if you have a custom type and have registered a custom type handler, so must
|
|
||||||
// allow it; however unforeseen validations will occur if trying to validate a
|
|
||||||
// struct that is meant to be passed to 'validate.Struct'
|
|
||||||
//
|
|
||||||
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
|
|
||||||
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
|
|
||||||
// validate Array, Slice and maps fields which may contain more than one error
|
|
||||||
func (v *Validate) Var(field interface{}, tag string) error { |
|
||||||
return v.VarCtx(context.Background(), field, tag) |
|
||||||
} |
|
||||||
|
|
||||||
// VarCtx validates a single variable using tag style validation and allows passing of contextual
|
|
||||||
// validation information via context.Context.
|
|
||||||
// eg.
|
|
||||||
// var i int
|
|
||||||
// validate.Var(i, "gt=1,lt=10")
|
|
||||||
//
|
|
||||||
// WARNING: a struct can be passed for validation eg. time.Time is a struct or
|
|
||||||
// if you have a custom type and have registered a custom type handler, so must
|
|
||||||
// allow it; however unforeseen validations will occur if trying to validate a
|
|
||||||
// struct that is meant to be passed to 'validate.Struct'
|
|
||||||
//
|
|
||||||
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
|
|
||||||
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
|
|
||||||
// validate Array, Slice and maps fields which may contain more than one error
|
|
||||||
func (v *Validate) VarCtx(ctx context.Context, field interface{}, tag string) (err error) { |
|
||||||
if len(tag) == 0 || tag == skipValidationTag { |
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
ctag := v.fetchCacheTag(tag) |
|
||||||
|
|
||||||
val := reflect.ValueOf(field) |
|
||||||
vd := v.pool.Get().(*validate) |
|
||||||
vd.top = val |
|
||||||
vd.isPartial = false |
|
||||||
vd.traverseField(ctx, val, val, vd.ns[0:0], vd.actualNs[0:0], defaultCField, ctag) |
|
||||||
|
|
||||||
if len(vd.errs) > 0 { |
|
||||||
err = vd.errs |
|
||||||
vd.errs = nil |
|
||||||
} |
|
||||||
v.pool.Put(vd) |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
// VarWithValue validates a single variable, against another variable/field's value using tag style validation
|
|
||||||
// eg.
|
|
||||||
// s1 := "abcd"
|
|
||||||
// s2 := "abcd"
|
|
||||||
// validate.VarWithValue(s1, s2, "eqcsfield") // returns true
|
|
||||||
//
|
|
||||||
// WARNING: a struct can be passed for validation eg. time.Time is a struct or
|
|
||||||
// if you have a custom type and have registered a custom type handler, so must
|
|
||||||
// allow it; however unforeseen validations will occur if trying to validate a
|
|
||||||
// struct that is meant to be passed to 'validate.Struct'
|
|
||||||
//
|
|
||||||
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
|
|
||||||
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
|
|
||||||
// validate Array, Slice and maps fields which may contain more than one error
|
|
||||||
func (v *Validate) VarWithValue(field interface{}, other interface{}, tag string) error { |
|
||||||
return v.VarWithValueCtx(context.Background(), field, other, tag) |
|
||||||
} |
|
||||||
|
|
||||||
// VarWithValueCtx validates a single variable, against another variable/field's value using tag style validation and
|
|
||||||
// allows passing of contextual validation validation information via context.Context.
|
|
||||||
// eg.
|
|
||||||
// s1 := "abcd"
|
|
||||||
// s2 := "abcd"
|
|
||||||
// validate.VarWithValue(s1, s2, "eqcsfield") // returns true
|
|
||||||
//
|
|
||||||
// WARNING: a struct can be passed for validation eg. time.Time is a struct or
|
|
||||||
// if you have a custom type and have registered a custom type handler, so must
|
|
||||||
// allow it; however unforeseen validations will occur if trying to validate a
|
|
||||||
// struct that is meant to be passed to 'validate.Struct'
|
|
||||||
//
|
|
||||||
// It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise.
|
|
||||||
// You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors.
|
|
||||||
// validate Array, Slice and maps fields which may contain more than one error
|
|
||||||
func (v *Validate) VarWithValueCtx(ctx context.Context, field interface{}, other interface{}, tag string) (err error) { |
|
||||||
if len(tag) == 0 || tag == skipValidationTag { |
|
||||||
return nil |
|
||||||
} |
|
||||||
ctag := v.fetchCacheTag(tag) |
|
||||||
otherVal := reflect.ValueOf(other) |
|
||||||
vd := v.pool.Get().(*validate) |
|
||||||
vd.top = otherVal |
|
||||||
vd.isPartial = false |
|
||||||
vd.traverseField(ctx, otherVal, reflect.ValueOf(field), vd.ns[0:0], vd.actualNs[0:0], defaultCField, ctag) |
|
||||||
|
|
||||||
if len(vd.errs) > 0 { |
|
||||||
err = vd.errs |
|
||||||
vd.errs = nil |
|
||||||
} |
|
||||||
v.pool.Put(vd) |
|
||||||
return |
|
||||||
} |
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue