Add logging for invalid model errors (#126)
Add logging for invalid model errors Co-authored-by: kolaente <k@knt.li> Reviewed-on: https://kolaente.dev/vikunja/api/pulls/126
This commit is contained in:
1
vendor/github.com/cweill/gotests/.gitignore
generated
vendored
Normal file
1
vendor/github.com/cweill/gotests/.gitignore
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
.DS_Store
|
15
vendor/github.com/cweill/gotests/.travis.yml
generated
vendored
Normal file
15
vendor/github.com/cweill/gotests/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
sudo: required
|
||||
language: go
|
||||
go:
|
||||
- 1.9.x
|
||||
- 1.10.x
|
||||
- 1.11.x
|
||||
- 1.12.x
|
||||
before_install:
|
||||
- go get github.com/mattn/goveralls
|
||||
- if ! go get github.com/golang/tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi
|
||||
script:
|
||||
- go test ./...
|
||||
- go test -c -covermode=count -coverpkg=github.com/cweill/gotests,github.com/cweill/gotests/internal/input,github.com/cweill/gotests/internal/render,github.com/cweill/gotests/internal/goparser,github.com/cweill/gotests/internal/output,github.com/cweill/gotests/internal/models
|
||||
- ./gotests.test -test.coverprofile coverage.cov
|
||||
- $HOME/gopath/bin/goveralls -service=travis-ci -coverprofile=coverage.cov
|
24
vendor/github.com/cweill/gotests/CONTRIBUTING.md
generated
vendored
Normal file
24
vendor/github.com/cweill/gotests/CONTRIBUTING.md
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
Want to contribute? Great! First, read this page (including the small print at the end).
|
||||
|
||||
### Before you contribute ###
|
||||
Before we can use your code, you must sign the
|
||||
[Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual?csw=1)
|
||||
(CLA), which you can do online. The CLA is necessary mainly because you own the
|
||||
copyright to your changes, even after your contribution becomes part of our
|
||||
codebase, so we need your permission to use and distribute your code. We also
|
||||
need to be sure of various other things—for instance that you'll tell us if you
|
||||
know that your code infringes on other people's patents. You don't have to sign
|
||||
the CLA until after you've submitted your code for review and a member has
|
||||
approved it, but you must do it before we can put your code into our codebase.
|
||||
Before you start working on a larger contribution, you should get in touch with
|
||||
us first through the issue tracker with your idea so that we can help out and
|
||||
possibly guide you. Coordinating up front makes it much easier to avoid
|
||||
frustration later on.
|
||||
|
||||
### Code reviews ###
|
||||
All submissions, including submissions by project members, require review. We
|
||||
use Github pull requests for this purpose.
|
||||
|
||||
### The small print ###
|
||||
Contributions made by corporations are covered by a different agreement than
|
||||
the one above, the Software Grant and Corporate Contributor License Agreement.
|
202
vendor/github.com/cweill/gotests/LICENSE
generated
vendored
Normal file
202
vendor/github.com/cweill/gotests/LICENSE
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
58
vendor/github.com/cweill/gotests/README.md
generated
vendored
Normal file
58
vendor/github.com/cweill/gotests/README.md
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
# gotests [](https://github.com/cweill/gotests/blob/master/LICENSE) [](https://godoc.org/github.com/cweill/gotests) [](https://travis-ci.org/cweill/gotests) [](https://coveralls.io/github/cweill/gotests?branch=master) [](https://codebeat.co/projects/github-com-cweill-gotests) [](https://goreportcard.com/report/github.com/cweill/gotests)
|
||||
|
||||
`gotests` makes writing Go tests easy. It's a Golang commandline tool that generates [table driven tests](https://github.com/golang/go/wiki/TableDrivenTests) based on its target source files' function and method signatures. Any new dependencies in the test files are automatically imported.
|
||||
|
||||
## Demo
|
||||
|
||||
The following shows `gotests` in action using the [official Sublime Text 3 plugin](https://github.com/cweill/GoTests-Sublime). Plugins also exist for [Emacs](https://github.com/damienlevin/GoTests-Emacs), also [Emacs](https://github.com/s-kostyaev/go-gen-test), [Vim](https://github.com/buoto/gotests-vim), [Atom Editor](https://atom.io/packages/gotests), [Visual Studio Code](https://github.com/Microsoft/vscode-go), and [IntelliJ Goland](https://www.jetbrains.com/help/go/run-debug-configuration-for-go-test.html).
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
|
||||
__Minimum Go version:__ Go 1.6
|
||||
|
||||
Use [`go get`](https://golang.org/cmd/go/#hdr-Download_and_install_packages_and_dependencies) to install and update:
|
||||
|
||||
```sh
|
||||
$ go get -u github.com/cweill/gotests/...
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
From the commandline, `gotests` can generate Go tests for specific source files or an entire directory. By default, it prints its output to `stdout`.
|
||||
|
||||
```sh
|
||||
$ gotests [options] PATH ...
|
||||
```
|
||||
|
||||
Available options:
|
||||
|
||||
```
|
||||
-all generate go tests for all functions and methods
|
||||
|
||||
-excl regexp. generate go tests for functions and methods that don't
|
||||
match. Takes precedence over -only, -exported, and -all
|
||||
|
||||
-exported generate go tests for exported functions and methods. Takes
|
||||
precedence over -only and -all
|
||||
|
||||
-i print test inputs in error messages
|
||||
|
||||
-only regexp. generate go tests for functions and methods that match only.
|
||||
Takes precedence over -all
|
||||
|
||||
-w write output to (test) files instead of stdout
|
||||
|
||||
-nosubtests disable subtest generation. Only available for Go 1.7+
|
||||
|
||||
-template_dir optional. Path to a directory containing custom test code templates
|
||||
```
|
||||
|
||||
## Contributions
|
||||
|
||||
Contributing guidelines are in [CONTRIBUTING.md](CONTRIBUTING.md).
|
||||
|
||||
## License
|
||||
|
||||
`gotests` is released under the [Apache 2.0 License](http://www.apache.org/licenses/LICENSE-2.0).
|
193
vendor/github.com/cweill/gotests/gotests.go
generated
vendored
Normal file
193
vendor/github.com/cweill/gotests/gotests.go
generated
vendored
Normal file
@ -0,0 +1,193 @@
|
||||
// Package gotests contains the core logic for generating table-driven tests.
|
||||
package gotests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/importer"
|
||||
"go/types"
|
||||
"path"
|
||||
"regexp"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/cweill/gotests/internal/goparser"
|
||||
"github.com/cweill/gotests/internal/input"
|
||||
"github.com/cweill/gotests/internal/models"
|
||||
"github.com/cweill/gotests/internal/output"
|
||||
)
|
||||
|
||||
// Options provides custom filters and parameters for generating tests.
|
||||
type Options struct {
|
||||
Only *regexp.Regexp // Includes only functions that match.
|
||||
Exclude *regexp.Regexp // Excludes functions that match.
|
||||
Exported bool // Include only exported methods
|
||||
PrintInputs bool // Print function parameters in error messages
|
||||
Subtests bool // Print tests using Go 1.7 subtests
|
||||
Importer func() types.Importer // A custom importer.
|
||||
TemplateDir string // Path to custom template set
|
||||
}
|
||||
|
||||
// A GeneratedTest contains information about a test file with generated tests.
|
||||
type GeneratedTest struct {
|
||||
Path string // The test file's absolute path.
|
||||
Functions []*models.Function // The functions with new test methods.
|
||||
Output []byte // The contents of the test file.
|
||||
}
|
||||
|
||||
// GenerateTests generates table-driven tests for the function and method
|
||||
// signatures defined in the target source path file(s). The source path
|
||||
// parameter can be either a Go source file or directory containing Go files.
|
||||
func GenerateTests(srcPath string, opt *Options) ([]*GeneratedTest, error) {
|
||||
if opt == nil {
|
||||
opt = &Options{}
|
||||
}
|
||||
srcFiles, err := input.Files(srcPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("input.Files: %v", err)
|
||||
}
|
||||
files, err := input.Files(path.Dir(srcPath))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("input.Files: %v", err)
|
||||
}
|
||||
if opt.Importer == nil || opt.Importer() == nil {
|
||||
opt.Importer = importer.Default
|
||||
}
|
||||
return parallelize(srcFiles, files, opt)
|
||||
}
|
||||
|
||||
// result stores a generateTest result.
|
||||
type result struct {
|
||||
gt *GeneratedTest
|
||||
err error
|
||||
}
|
||||
|
||||
// parallelize generates tests for the given source files concurrently.
|
||||
func parallelize(srcFiles, files []models.Path, opt *Options) ([]*GeneratedTest, error) {
|
||||
var wg sync.WaitGroup
|
||||
rs := make(chan *result, len(srcFiles))
|
||||
for _, src := range srcFiles {
|
||||
wg.Add(1)
|
||||
// Worker
|
||||
go func(src models.Path) {
|
||||
defer wg.Done()
|
||||
r := &result{}
|
||||
r.gt, r.err = generateTest(src, files, opt)
|
||||
rs <- r
|
||||
}(src)
|
||||
}
|
||||
// Closer.
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(rs)
|
||||
}()
|
||||
return readResults(rs)
|
||||
}
|
||||
|
||||
// readResults reads the result channel.
|
||||
func readResults(rs <-chan *result) ([]*GeneratedTest, error) {
|
||||
var gts []*GeneratedTest
|
||||
for r := range rs {
|
||||
if r.err != nil {
|
||||
return nil, r.err
|
||||
}
|
||||
if r.gt != nil {
|
||||
gts = append(gts, r.gt)
|
||||
}
|
||||
}
|
||||
return gts, nil
|
||||
}
|
||||
|
||||
func generateTest(src models.Path, files []models.Path, opt *Options) (*GeneratedTest, error) {
|
||||
p := &goparser.Parser{Importer: opt.Importer()}
|
||||
sr, err := p.Parse(string(src), files)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Parser.Parse source file: %v", err)
|
||||
}
|
||||
h := sr.Header
|
||||
h.Code = nil // Code is only needed from parsed test files.
|
||||
testPath := models.Path(src).TestPath()
|
||||
h, tf, err := parseTestFile(p, testPath, h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
funcs := testableFuncs(sr.Funcs, opt.Only, opt.Exclude, opt.Exported, tf)
|
||||
if len(funcs) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
b, err := output.Process(h, funcs, &output.Options{
|
||||
PrintInputs: opt.PrintInputs,
|
||||
Subtests: opt.Subtests,
|
||||
TemplateDir: opt.TemplateDir,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("output.Process: %v", err)
|
||||
}
|
||||
return &GeneratedTest{
|
||||
Path: testPath,
|
||||
Functions: funcs,
|
||||
Output: b,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func parseTestFile(p *goparser.Parser, testPath string, h *models.Header) (*models.Header, []string, error) {
|
||||
if !output.IsFileExist(testPath) {
|
||||
return h, nil, nil
|
||||
}
|
||||
tr, err := p.Parse(testPath, nil)
|
||||
if err != nil {
|
||||
if err == goparser.ErrEmptyFile {
|
||||
// Overwrite empty test files.
|
||||
return h, nil, nil
|
||||
}
|
||||
return nil, nil, fmt.Errorf("Parser.Parse test file: %v", err)
|
||||
}
|
||||
var testFuncs []string
|
||||
for _, fun := range tr.Funcs {
|
||||
testFuncs = append(testFuncs, fun.Name)
|
||||
}
|
||||
tr.Header.Imports = append(tr.Header.Imports, h.Imports...)
|
||||
h = tr.Header
|
||||
return h, testFuncs, nil
|
||||
}
|
||||
|
||||
func testableFuncs(funcs []*models.Function, only, excl *regexp.Regexp, exp bool, testFuncs []string) []*models.Function {
|
||||
sort.Strings(testFuncs)
|
||||
var fs []*models.Function
|
||||
for _, f := range funcs {
|
||||
if isTestFunction(f, testFuncs) || isExcluded(f, excl) || isUnexported(f, exp) || !isIncluded(f, only) || isInvalid(f) {
|
||||
continue
|
||||
}
|
||||
fs = append(fs, f)
|
||||
}
|
||||
return fs
|
||||
}
|
||||
|
||||
func isInvalid(f *models.Function) bool {
|
||||
if f.Name == "init" && f.IsNaked() {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isTestFunction(f *models.Function, testFuncs []string) bool {
|
||||
return len(testFuncs) > 0 && contains(testFuncs, f.TestName())
|
||||
}
|
||||
|
||||
func isExcluded(f *models.Function, excl *regexp.Regexp) bool {
|
||||
return excl != nil && (excl.MatchString(f.Name) || excl.MatchString(f.FullName()))
|
||||
}
|
||||
|
||||
func isUnexported(f *models.Function, exp bool) bool {
|
||||
return exp && !f.IsExported
|
||||
}
|
||||
|
||||
func isIncluded(f *models.Function, only *regexp.Regexp) bool {
|
||||
return only == nil || only.MatchString(f.Name) || only.MatchString(f.FullName())
|
||||
}
|
||||
|
||||
func contains(ss []string, s string) bool {
|
||||
if i := sort.SearchStrings(ss, s); i < len(ss) && ss[i] == s {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
313
vendor/github.com/cweill/gotests/internal/goparser/goparser.go
generated
vendored
Normal file
313
vendor/github.com/cweill/gotests/internal/goparser/goparser.go
generated
vendored
Normal file
@ -0,0 +1,313 @@
|
||||
// Package goparse contains logic for parsing Go files. Specifically it parses
|
||||
// source and test files into domain models for generating tests.
|
||||
package goparser
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"io/ioutil"
|
||||
|
||||
"strings"
|
||||
|
||||
"github.com/cweill/gotests/internal/models"
|
||||
)
|
||||
|
||||
// ErrEmptyFile represents an empty file error.
|
||||
var ErrEmptyFile = errors.New("file is empty")
|
||||
|
||||
// Result representats a parsed Go file.
|
||||
type Result struct {
|
||||
// The package name and imports of a Go file.
|
||||
Header *models.Header
|
||||
// All the functions and methods in a Go file.
|
||||
Funcs []*models.Function
|
||||
}
|
||||
|
||||
// Parser can parse Go files.
|
||||
type Parser struct {
|
||||
// The importer to resolve packages from import paths.
|
||||
Importer types.Importer
|
||||
}
|
||||
|
||||
// Parse parses a given Go file at srcPath, along any files that share the same
|
||||
// package, into a domain model for generating tests.
|
||||
func (p *Parser) Parse(srcPath string, files []models.Path) (*Result, error) {
|
||||
b, err := p.readFile(srcPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fset := token.NewFileSet()
|
||||
f, err := p.parseFile(fset, srcPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fs, err := p.parseFiles(fset, f, files)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Result{
|
||||
Header: &models.Header{
|
||||
Comments: parsePkgComment(f, f.Package),
|
||||
Package: f.Name.String(),
|
||||
Imports: parseImports(f.Imports),
|
||||
Code: goCode(b, f),
|
||||
},
|
||||
Funcs: p.parseFunctions(fset, f, fs),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *Parser) readFile(srcPath string) ([]byte, error) {
|
||||
b, err := ioutil.ReadFile(srcPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ioutil.ReadFile: %v", err)
|
||||
}
|
||||
if len(b) == 0 {
|
||||
return nil, ErrEmptyFile
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseFile(fset *token.FileSet, srcPath string) (*ast.File, error) {
|
||||
f, err := parser.ParseFile(fset, srcPath, nil, parser.ParseComments)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("target parser.ParseFile(): %v", err)
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseFiles(fset *token.FileSet, f *ast.File, files []models.Path) ([]*ast.File, error) {
|
||||
pkg := f.Name.String()
|
||||
var fs []*ast.File
|
||||
for _, file := range files {
|
||||
ff, err := parser.ParseFile(fset, string(file), nil, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("other file parser.ParseFile: %v", err)
|
||||
}
|
||||
if name := ff.Name.String(); name != pkg {
|
||||
continue
|
||||
}
|
||||
fs = append(fs, ff)
|
||||
}
|
||||
return fs, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseFunctions(fset *token.FileSet, f *ast.File, fs []*ast.File) []*models.Function {
|
||||
ul, el := p.parseTypes(fset, fs)
|
||||
var funcs []*models.Function
|
||||
for _, d := range f.Decls {
|
||||
fDecl, ok := d.(*ast.FuncDecl)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
funcs = append(funcs, parseFunc(fDecl, ul, el))
|
||||
}
|
||||
return funcs
|
||||
}
|
||||
|
||||
func (p *Parser) parseTypes(fset *token.FileSet, fs []*ast.File) (map[string]types.Type, map[*types.Struct]ast.Expr) {
|
||||
conf := &types.Config{
|
||||
Importer: p.Importer,
|
||||
// Adding a NO-OP error function ignores errors and performs best-effort
|
||||
// type checking. https://godoc.org/golang.org/x/tools/go/types#Config
|
||||
Error: func(error) {},
|
||||
}
|
||||
ti := &types.Info{
|
||||
Types: make(map[ast.Expr]types.TypeAndValue),
|
||||
}
|
||||
// Note: conf.Check can fail, but since Info is not required data, it's ok.
|
||||
conf.Check("", fset, fs, ti)
|
||||
ul := make(map[string]types.Type)
|
||||
el := make(map[*types.Struct]ast.Expr)
|
||||
for e, t := range ti.Types {
|
||||
// Collect the underlying types.
|
||||
ul[t.Type.String()] = t.Type.Underlying()
|
||||
// Collect structs to determine the fields of a receiver.
|
||||
if v, ok := t.Type.(*types.Struct); ok {
|
||||
el[v] = e
|
||||
}
|
||||
}
|
||||
return ul, el
|
||||
}
|
||||
|
||||
func parsePkgComment(f *ast.File, pkgPos token.Pos) []string {
|
||||
var comments []string
|
||||
var count int
|
||||
|
||||
for _, comment := range f.Comments {
|
||||
|
||||
if comment.End() >= pkgPos {
|
||||
break
|
||||
}
|
||||
for _, c := range comment.List {
|
||||
count += len(c.Text) + 1 // +1 for '\n'
|
||||
if count < int(c.End()) {
|
||||
n := int(c.End()) - count - 1
|
||||
comments = append(comments, strings.Repeat("\n", n))
|
||||
count++ // for last of '\n'
|
||||
}
|
||||
comments = append(comments, c.Text)
|
||||
}
|
||||
}
|
||||
|
||||
if int(pkgPos)-count > 1 {
|
||||
comments = append(comments, strings.Repeat("\n", int(pkgPos)-count-2))
|
||||
}
|
||||
return comments
|
||||
}
|
||||
|
||||
// Returns the Go code below the imports block.
|
||||
func goCode(b []byte, f *ast.File) []byte {
|
||||
furthestPos := f.Name.End()
|
||||
for _, node := range f.Imports {
|
||||
if pos := node.End(); pos > furthestPos {
|
||||
furthestPos = pos
|
||||
}
|
||||
}
|
||||
if furthestPos < token.Pos(len(b)) {
|
||||
furthestPos++
|
||||
|
||||
// Avoid wrong output on windows-encoded files
|
||||
if b[furthestPos-2] == '\r' && b[furthestPos-1] == '\n' && furthestPos < token.Pos(len(b)) {
|
||||
furthestPos++
|
||||
}
|
||||
}
|
||||
return b[furthestPos:]
|
||||
}
|
||||
|
||||
func parseFunc(fDecl *ast.FuncDecl, ul map[string]types.Type, el map[*types.Struct]ast.Expr) *models.Function {
|
||||
f := &models.Function{
|
||||
Name: fDecl.Name.String(),
|
||||
IsExported: fDecl.Name.IsExported(),
|
||||
Receiver: parseReceiver(fDecl.Recv, ul, el),
|
||||
Parameters: parseFieldList(fDecl.Type.Params, ul),
|
||||
}
|
||||
fs := parseFieldList(fDecl.Type.Results, ul)
|
||||
i := 0
|
||||
for _, fi := range fs {
|
||||
if fi.Type.String() == "error" {
|
||||
f.ReturnsError = true
|
||||
continue
|
||||
}
|
||||
fi.Index = i
|
||||
f.Results = append(f.Results, fi)
|
||||
i++
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func parseImports(imps []*ast.ImportSpec) []*models.Import {
|
||||
var is []*models.Import
|
||||
for _, imp := range imps {
|
||||
var n string
|
||||
if imp.Name != nil {
|
||||
n = imp.Name.String()
|
||||
}
|
||||
is = append(is, &models.Import{
|
||||
Name: n,
|
||||
Path: imp.Path.Value,
|
||||
})
|
||||
}
|
||||
return is
|
||||
}
|
||||
|
||||
func parseReceiver(fl *ast.FieldList, ul map[string]types.Type, el map[*types.Struct]ast.Expr) *models.Receiver {
|
||||
if fl == nil {
|
||||
return nil
|
||||
}
|
||||
r := &models.Receiver{
|
||||
Field: parseFieldList(fl, ul)[0],
|
||||
}
|
||||
t, ok := ul[r.Type.Value]
|
||||
if !ok {
|
||||
return r
|
||||
}
|
||||
s, ok := t.(*types.Struct)
|
||||
if !ok {
|
||||
return r
|
||||
}
|
||||
st, found := el[s]
|
||||
if !found {
|
||||
return r
|
||||
}
|
||||
r.Fields = append(r.Fields, parseFieldList(st.(*ast.StructType).Fields, ul)...)
|
||||
for i, f := range r.Fields {
|
||||
// https://github.com/cweill/gotests/issues/69
|
||||
if i >= s.NumFields() {
|
||||
break
|
||||
}
|
||||
f.Name = s.Field(i).Name()
|
||||
}
|
||||
return r
|
||||
|
||||
}
|
||||
|
||||
func parseFieldList(fl *ast.FieldList, ul map[string]types.Type) []*models.Field {
|
||||
if fl == nil {
|
||||
return nil
|
||||
}
|
||||
i := 0
|
||||
var fs []*models.Field
|
||||
for _, f := range fl.List {
|
||||
for _, pf := range parseFields(f, ul) {
|
||||
pf.Index = i
|
||||
fs = append(fs, pf)
|
||||
i++
|
||||
}
|
||||
}
|
||||
return fs
|
||||
}
|
||||
|
||||
func parseFields(f *ast.Field, ul map[string]types.Type) []*models.Field {
|
||||
t := parseExpr(f.Type, ul)
|
||||
if len(f.Names) == 0 {
|
||||
return []*models.Field{{
|
||||
Type: t,
|
||||
}}
|
||||
}
|
||||
var fs []*models.Field
|
||||
for _, n := range f.Names {
|
||||
fs = append(fs, &models.Field{
|
||||
Name: n.Name,
|
||||
Type: t,
|
||||
})
|
||||
}
|
||||
return fs
|
||||
}
|
||||
|
||||
func parseExpr(e ast.Expr, ul map[string]types.Type) *models.Expression {
|
||||
switch v := e.(type) {
|
||||
case *ast.StarExpr:
|
||||
val := types.ExprString(v.X)
|
||||
return &models.Expression{
|
||||
Value: val,
|
||||
IsStar: true,
|
||||
Underlying: underlying(val, ul),
|
||||
}
|
||||
case *ast.Ellipsis:
|
||||
exp := parseExpr(v.Elt, ul)
|
||||
return &models.Expression{
|
||||
Value: exp.Value,
|
||||
IsStar: exp.IsStar,
|
||||
IsVariadic: true,
|
||||
Underlying: underlying(exp.Value, ul),
|
||||
}
|
||||
default:
|
||||
val := types.ExprString(e)
|
||||
return &models.Expression{
|
||||
Value: val,
|
||||
Underlying: underlying(val, ul),
|
||||
IsWriter: val == "io.Writer",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func underlying(val string, ul map[string]types.Type) string {
|
||||
if ul[val] != nil {
|
||||
return ul[val].String()
|
||||
}
|
||||
return ""
|
||||
}
|
54
vendor/github.com/cweill/gotests/internal/input/input.go
generated
vendored
Normal file
54
vendor/github.com/cweill/gotests/internal/input/input.go
generated
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
package input
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"os"
|
||||
|
||||
"github.com/cweill/gotests/internal/models"
|
||||
)
|
||||
|
||||
// Returns all the Golang files for the given path. Ignores hidden files.
|
||||
func Files(srcPath string) ([]models.Path, error) {
|
||||
srcPath, err := filepath.Abs(srcPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("filepath.Abs: %v\n", err)
|
||||
}
|
||||
var fi os.FileInfo
|
||||
if fi, err = os.Stat(srcPath); err != nil {
|
||||
return nil, fmt.Errorf("os.Stat: %v\n", err)
|
||||
}
|
||||
if fi.IsDir() {
|
||||
return dirFiles(srcPath)
|
||||
}
|
||||
return file(srcPath)
|
||||
}
|
||||
|
||||
func dirFiles(srcPath string) ([]models.Path, error) {
|
||||
ps, err := filepath.Glob(path.Join(srcPath, "*.go"))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("filepath.Glob: %v\n", err)
|
||||
}
|
||||
var srcPaths []models.Path
|
||||
for _, p := range ps {
|
||||
src := models.Path(p)
|
||||
if isHiddenFile(p) || src.IsTestPath() {
|
||||
continue
|
||||
}
|
||||
srcPaths = append(srcPaths, src)
|
||||
}
|
||||
return srcPaths, nil
|
||||
}
|
||||
|
||||
func file(srcPath string) ([]models.Path, error) {
|
||||
src := models.Path(srcPath)
|
||||
if filepath.Ext(srcPath) != ".go" || isHiddenFile(srcPath) {
|
||||
return nil, fmt.Errorf("no Go source files found at %v", srcPath)
|
||||
}
|
||||
return []models.Path{src}, nil
|
||||
}
|
||||
|
||||
func isHiddenFile(path string) bool {
|
||||
return []rune(filepath.Base(path))[0] == '.'
|
||||
}
|
172
vendor/github.com/cweill/gotests/internal/models/models.go
generated
vendored
Normal file
172
vendor/github.com/cweill/gotests/internal/models/models.go
generated
vendored
Normal file
@ -0,0 +1,172 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
type Expression struct {
|
||||
Value string
|
||||
IsStar bool
|
||||
IsVariadic bool
|
||||
IsWriter bool
|
||||
Underlying string
|
||||
}
|
||||
|
||||
func (e *Expression) String() string {
|
||||
value := e.Value
|
||||
if e.IsStar {
|
||||
value = "*" + value
|
||||
}
|
||||
if e.IsVariadic {
|
||||
return "[]" + value
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
type Field struct {
|
||||
Name string
|
||||
Type *Expression
|
||||
Index int
|
||||
}
|
||||
|
||||
func (f *Field) IsWriter() bool {
|
||||
return f.Type.IsWriter
|
||||
}
|
||||
|
||||
func (f *Field) IsStruct() bool {
|
||||
return strings.HasPrefix(f.Type.Underlying, "struct")
|
||||
}
|
||||
|
||||
func (f *Field) IsBasicType() bool {
|
||||
return isBasicType(f.Type.String()) || isBasicType(f.Type.Underlying)
|
||||
}
|
||||
|
||||
func isBasicType(t string) bool {
|
||||
switch t {
|
||||
case "bool", "string", "int", "int8", "int16", "int32", "int64", "uint",
|
||||
"uint8", "uint16", "uint32", "uint64", "uintptr", "byte", "rune",
|
||||
"float32", "float64", "complex64", "complex128":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Field) IsNamed() bool {
|
||||
return f.Name != "" && f.Name != "_"
|
||||
}
|
||||
|
||||
func (f *Field) ShortName() string {
|
||||
return strings.ToLower(string([]rune(f.Type.Value)[0]))
|
||||
}
|
||||
|
||||
type Receiver struct {
|
||||
*Field
|
||||
Fields []*Field
|
||||
}
|
||||
|
||||
type Function struct {
|
||||
Name string
|
||||
IsExported bool
|
||||
Receiver *Receiver
|
||||
Parameters []*Field
|
||||
Results []*Field
|
||||
ReturnsError bool
|
||||
}
|
||||
|
||||
func (f *Function) TestParameters() []*Field {
|
||||
var ps []*Field
|
||||
for _, p := range f.Parameters {
|
||||
if p.IsWriter() {
|
||||
continue
|
||||
}
|
||||
ps = append(ps, p)
|
||||
}
|
||||
return ps
|
||||
}
|
||||
|
||||
func (f *Function) TestResults() []*Field {
|
||||
var ps []*Field
|
||||
ps = append(ps, f.Results...)
|
||||
for _, p := range f.Parameters {
|
||||
if !p.IsWriter() {
|
||||
continue
|
||||
}
|
||||
ps = append(ps, &Field{
|
||||
Name: p.Name,
|
||||
Type: &Expression{
|
||||
Value: "string",
|
||||
IsWriter: true,
|
||||
Underlying: "string",
|
||||
},
|
||||
Index: len(ps),
|
||||
})
|
||||
}
|
||||
return ps
|
||||
}
|
||||
|
||||
func (f *Function) ReturnsMultiple() bool {
|
||||
return len(f.Results) > 1
|
||||
}
|
||||
|
||||
func (f *Function) OnlyReturnsOneValue() bool {
|
||||
return len(f.Results) == 1 && !f.ReturnsError
|
||||
}
|
||||
|
||||
func (f *Function) OnlyReturnsError() bool {
|
||||
return len(f.Results) == 0 && f.ReturnsError
|
||||
}
|
||||
|
||||
func (f *Function) FullName() string {
|
||||
var r string
|
||||
if f.Receiver != nil {
|
||||
r = f.Receiver.Type.Value
|
||||
}
|
||||
return strings.Title(r) + strings.Title(f.Name)
|
||||
}
|
||||
|
||||
func (f *Function) TestName() string {
|
||||
if strings.HasPrefix(f.Name, "Test") {
|
||||
return f.Name
|
||||
}
|
||||
if f.Receiver != nil {
|
||||
receiverType := f.Receiver.Type.Value
|
||||
if unicode.IsLower([]rune(receiverType)[0]) {
|
||||
receiverType = "_" + receiverType
|
||||
}
|
||||
return "Test" + receiverType + "_" + f.Name
|
||||
}
|
||||
if unicode.IsLower([]rune(f.Name)[0]) {
|
||||
return "Test_" + f.Name
|
||||
}
|
||||
return "Test" + f.Name
|
||||
}
|
||||
|
||||
func (f *Function) IsNaked() bool {
|
||||
return f.Receiver == nil && len(f.Parameters) == 0 && len(f.Results) == 0
|
||||
}
|
||||
|
||||
type Import struct {
|
||||
Name, Path string
|
||||
}
|
||||
|
||||
type Header struct {
|
||||
Comments []string
|
||||
Package string
|
||||
Imports []*Import
|
||||
Code []byte
|
||||
}
|
||||
|
||||
type Path string
|
||||
|
||||
func (p Path) TestPath() string {
|
||||
if !p.IsTestPath() {
|
||||
return strings.TrimSuffix(string(p), ".go") + "_test.go"
|
||||
}
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p Path) IsTestPath() bool {
|
||||
return strings.HasSuffix(string(p), "_test.go")
|
||||
}
|
65
vendor/github.com/cweill/gotests/internal/output/output.go
generated
vendored
Normal file
65
vendor/github.com/cweill/gotests/internal/output/output.go
generated
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
package output
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"golang.org/x/tools/imports"
|
||||
|
||||
"github.com/cweill/gotests/internal/models"
|
||||
"github.com/cweill/gotests/internal/render"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
PrintInputs bool
|
||||
Subtests bool
|
||||
TemplateDir string
|
||||
}
|
||||
|
||||
func Process(head *models.Header, funcs []*models.Function, opt *Options) ([]byte, error) {
|
||||
if opt != nil && opt.TemplateDir != "" {
|
||||
err := render.LoadCustomTemplates(opt.TemplateDir)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("loading custom templates: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
tf, err := ioutil.TempFile("", "gotests_")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ioutil.TempFile: %v", err)
|
||||
}
|
||||
defer tf.Close()
|
||||
defer os.Remove(tf.Name())
|
||||
b := &bytes.Buffer{}
|
||||
if err := writeTests(b, head, funcs, opt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out, err := imports.Process(tf.Name(), b.Bytes(), nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("imports.Process: %v", err)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func IsFileExist(path string) bool {
|
||||
_, err := os.Stat(path)
|
||||
return !os.IsNotExist(err)
|
||||
}
|
||||
|
||||
func writeTests(w io.Writer, head *models.Header, funcs []*models.Function, opt *Options) error {
|
||||
b := bufio.NewWriter(w)
|
||||
if err := render.Header(b, head); err != nil {
|
||||
return fmt.Errorf("render.Header: %v", err)
|
||||
}
|
||||
for _, fun := range funcs {
|
||||
if err := render.TestFunction(b, fun, opt.PrintInputs, opt.Subtests); err != nil {
|
||||
return fmt.Errorf("render.TestFunction: %v", err)
|
||||
}
|
||||
}
|
||||
return b.Flush()
|
||||
}
|
7
vendor/github.com/cweill/gotests/internal/render/README.md
generated
vendored
Normal file
7
vendor/github.com/cweill/gotests/internal/render/README.md
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
bindata.go must be generated with https://github.com/jteeuwen/go-bindata.
|
||||
|
||||
From the gotests root run `$ go generate ./...`.
|
||||
|
||||
Or run `$ go-bindata -pkg=bindata -o "internal/render/bindata/bindata.go" internal/render/templates/`.
|
||||
|
||||
During development run `$ go-bindata -pkg=bindata -o "internal/render/bindata/bindata.go" -debug internal/render/templates/` instead.
|
323
vendor/github.com/cweill/gotests/internal/render/bindata/esc.go
generated
vendored
Normal file
323
vendor/github.com/cweill/gotests/internal/render/bindata/esc.go
generated
vendored
Normal file
@ -0,0 +1,323 @@
|
||||
// Code generated by "esc -o bindata/esc.go -pkg=bindata templates"; DO NOT EDIT.
|
||||
|
||||
package bindata
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type _escLocalFS struct{}
|
||||
|
||||
var _escLocal _escLocalFS
|
||||
|
||||
type _escStaticFS struct{}
|
||||
|
||||
var _escStatic _escStaticFS
|
||||
|
||||
type _escDirectory struct {
|
||||
fs http.FileSystem
|
||||
name string
|
||||
}
|
||||
|
||||
type _escFile struct {
|
||||
compressed string
|
||||
size int64
|
||||
modtime int64
|
||||
local string
|
||||
isDir bool
|
||||
|
||||
once sync.Once
|
||||
data []byte
|
||||
name string
|
||||
}
|
||||
|
||||
func (_escLocalFS) Open(name string) (http.File, error) {
|
||||
f, present := _escData[path.Clean(name)]
|
||||
if !present {
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
return os.Open(f.local)
|
||||
}
|
||||
|
||||
func (_escStaticFS) prepare(name string) (*_escFile, error) {
|
||||
f, present := _escData[path.Clean(name)]
|
||||
if !present {
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
var err error
|
||||
f.once.Do(func() {
|
||||
f.name = path.Base(name)
|
||||
if f.size == 0 {
|
||||
return
|
||||
}
|
||||
var gr *gzip.Reader
|
||||
b64 := base64.NewDecoder(base64.StdEncoding, bytes.NewBufferString(f.compressed))
|
||||
gr, err = gzip.NewReader(b64)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
f.data, err = ioutil.ReadAll(gr)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (fs _escStaticFS) Open(name string) (http.File, error) {
|
||||
f, err := fs.prepare(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return f.File()
|
||||
}
|
||||
|
||||
func (dir _escDirectory) Open(name string) (http.File, error) {
|
||||
return dir.fs.Open(dir.name + name)
|
||||
}
|
||||
|
||||
func (f *_escFile) File() (http.File, error) {
|
||||
type httpFile struct {
|
||||
*bytes.Reader
|
||||
*_escFile
|
||||
}
|
||||
return &httpFile{
|
||||
Reader: bytes.NewReader(f.data),
|
||||
_escFile: f,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (f *_escFile) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *_escFile) Readdir(count int) ([]os.FileInfo, error) {
|
||||
if !f.isDir {
|
||||
return nil, fmt.Errorf(" escFile.Readdir: '%s' is not directory", f.name)
|
||||
}
|
||||
|
||||
fis, ok := _escDirs[f.local]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(" escFile.Readdir: '%s' is directory, but we have no info about content of this dir, local=%s", f.name, f.local)
|
||||
}
|
||||
limit := count
|
||||
if count <= 0 || limit > len(fis) {
|
||||
limit = len(fis)
|
||||
}
|
||||
|
||||
if len(fis) == 0 && count > 0 {
|
||||
return nil, io.EOF
|
||||
}
|
||||
|
||||
return []os.FileInfo(fis[0:limit]), nil
|
||||
}
|
||||
|
||||
func (f *_escFile) Stat() (os.FileInfo, error) {
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (f *_escFile) Name() string {
|
||||
return f.name
|
||||
}
|
||||
|
||||
func (f *_escFile) Size() int64 {
|
||||
return f.size
|
||||
}
|
||||
|
||||
func (f *_escFile) Mode() os.FileMode {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (f *_escFile) ModTime() time.Time {
|
||||
return time.Unix(f.modtime, 0)
|
||||
}
|
||||
|
||||
func (f *_escFile) IsDir() bool {
|
||||
return f.isDir
|
||||
}
|
||||
|
||||
func (f *_escFile) Sys() interface{} {
|
||||
return f
|
||||
}
|
||||
|
||||
// FS returns a http.Filesystem for the embedded assets. If useLocal is true,
|
||||
// the filesystem's contents are instead used.
|
||||
func FS(useLocal bool) http.FileSystem {
|
||||
if useLocal {
|
||||
return _escLocal
|
||||
}
|
||||
return _escStatic
|
||||
}
|
||||
|
||||
// Dir returns a http.Filesystem for the embedded assets on a given prefix dir.
|
||||
// If useLocal is true, the filesystem's contents are instead used.
|
||||
func Dir(useLocal bool, name string) http.FileSystem {
|
||||
if useLocal {
|
||||
return _escDirectory{fs: _escLocal, name: name}
|
||||
}
|
||||
return _escDirectory{fs: _escStatic, name: name}
|
||||
}
|
||||
|
||||
// FSByte returns the named file from the embedded assets. If useLocal is
|
||||
// true, the filesystem's contents are instead used.
|
||||
func FSByte(useLocal bool, name string) ([]byte, error) {
|
||||
if useLocal {
|
||||
f, err := _escLocal.Open(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b, err := ioutil.ReadAll(f)
|
||||
_ = f.Close()
|
||||
return b, err
|
||||
}
|
||||
f, err := _escStatic.prepare(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return f.data, nil
|
||||
}
|
||||
|
||||
// FSMustByte is the same as FSByte, but panics if name is not present.
|
||||
func FSMustByte(useLocal bool, name string) []byte {
|
||||
b, err := FSByte(useLocal, name)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// FSString is the string version of FSByte.
|
||||
func FSString(useLocal bool, name string) (string, error) {
|
||||
b, err := FSByte(useLocal, name)
|
||||
return string(b), err
|
||||
}
|
||||
|
||||
// FSMustString is the string version of FSMustByte.
|
||||
func FSMustString(useLocal bool, name string) string {
|
||||
return string(FSMustByte(useLocal, name))
|
||||
}
|
||||
|
||||
var _escData = map[string]*_escFile{
|
||||
|
||||
"/templates/call.tmpl": {
|
||||
name: "call.tmpl",
|
||||
local: "templates/call.tmpl",
|
||||
size: 241,
|
||||
modtime: 1540446832,
|
||||
compressed: `
|
||||
H4sIAAAAAAAC/0SOQWrDQAxFryKMFy0YHaDQA3hTSlvatRjLrsCeFo2SEITuHsY4mdWHP2/el/vEs2SG
|
||||
LtG6dhHuF7FfwA9OLGfW2sgM+c8Ax/JpekoWYYbunKf6eicBI1qLb7RxxJO7Ul4Yehmg5xVeXgHfSWlj
|
||||
Yy2HvZeIAR5/296PitUbzJB0KU2/K+riTuPX9Z9xLN+kQpOkCMTG7vF85C0AAP//ZQi8iPEAAAA=
|
||||
`,
|
||||
},
|
||||
|
||||
"/templates/function.tmpl": {
|
||||
name: "function.tmpl",
|
||||
local: "templates/function.tmpl",
|
||||
size: 2392,
|
||||
modtime: 1540483824,
|
||||
compressed: `
|
||||
H4sIAAAAAAAC/7RWTW/jNhA9S79i1sgupMJh7g58aJC06KFx4QTNoSgKRh65RGnKJUcJDIL/vSBFfVpO
|
||||
c9kcImlIznvz5g0Ta3dYCoWwKGtVkKjUwrnU2mu4KmG1BuZcmvolsJY9o6FHfkDnMoIfCA0JtWfPOdg0
|
||||
8UfeBf0NbIsFijfUzqVJCIsS2C/miXRdUAh20Z8Eyp1pYgmdjghliIAJm33euFtztcfJgcTa8O1JBnqn
|
||||
I8YlfwTVLn51mG1o8D559ax8mb9xzQ9IqANYoMb1fkRsQOv8RAAMoTN2A8QxvhfUeNH/+HMAo/gBPaxQ
|
||||
+3h4RuaWO1e7XuuJXFHa5tEpIk2vWZvyXNAL4n0gWZIEvfyvmTMD3bZoakmmxXnhij6SrIPcItVamQet
|
||||
q6jBO1f0oDW8VpWc6OyFvLmB5839ZgU/7nbgtYaCGzQstKGsNFgrSsgqDeypfm2akamKvKCP/B/c5blz
|
||||
8NcSiHyTrA3JYynNdptC/GlZdpmcI7atVUbEfEeX4IdqOkYQOcN1L/tcty+M1VkPA83Qn9MRw2aunfsW
|
||||
qUeF2e9c1uicbVNcmLbEWtZM/wqIWOMjNpjBZZ+gn71kZiDPPiLezAi1Zb5oQV31o9FareHb64nQsLu6
|
||||
LFHbzwDGUWnau1HyNHRTfh7fKAwq5dAxIzwcJSeEhW4cvICrMvi2Xym4lE34EosZGyeijF2bEnMOUOum
|
||||
q3Mgt50pM7/vyxqUkLl/ErF2OmKbiYWUZbYY5jqgMXyPsRT0O2ANX9+W0B7/+rZYjuCFOtZd8aj1cgCW
|
||||
945ob4nRuIe1yZjoULC1zc1UVIqEqjEWNuewDy11DnnJU0H1nyvqB6fzGHsK12+W3w62NKoOL6zed9Jg
|
||||
xLjjRhSDP0xdc6/KOX/5oRxxGOoshcJpoz/N5zvhf9FYSiyI3SMeH/6tucy6DMsxoXzIqOveZ3zYEo5k
|
||||
f60liaMckY18eq/+j1Evkrz8D8PEp+ALGl7XLnVp2vr0vwAAAP//X+Qs81gJAAA=
|
||||
`,
|
||||
},
|
||||
|
||||
"/templates/header.tmpl": {
|
||||
name: "header.tmpl",
|
||||
local: "templates/header.tmpl",
|
||||
size: 142,
|
||||
modtime: 1540481163,
|
||||
compressed: `
|
||||
H4sIAAAAAAAC/0TMMQ7CMAyF4d2nsDrBQC7BxIK4gkUebYXiViGb9e6OlAi6/bL1voiM1+rQaYFl1ImU
|
||||
iGo+Q9N1KwXePmRE6g941gspuz3fNkMj0mMkKbKWfatNT4dw65cB3K2AHJO2/DhSzv/6BgAA///GzMM9
|
||||
jgAAAA==
|
||||
`,
|
||||
},
|
||||
|
||||
"/templates/inline.tmpl": {
|
||||
name: "inline.tmpl",
|
||||
local: "templates/inline.tmpl",
|
||||
size: 49,
|
||||
modtime: 1540446006,
|
||||
compressed: `
|
||||
H4sIAAAAAAAC/6quTklNy8xLVVDKzMvJzEtVqq1VqK4uSc0tyEksSVVQSk7MyVFS0AOLpual1NYCAgAA
|
||||
//+q60H/MQAAAA==
|
||||
`,
|
||||
},
|
||||
|
||||
"/templates/inputs.tmpl": {
|
||||
name: "inputs.tmpl",
|
||||
local: "templates/inputs.tmpl",
|
||||
size: 152,
|
||||
modtime: 1540446821,
|
||||
compressed: `
|
||||
H4sIAAAAAAAC/0yNMQoCQQxFrxKWLSUHEDyAneAJIptZptgomWz1yd1lRoupEh7/vw9sWqopLdU+Z7Ql
|
||||
E1gLXW/E/a2F7B3Ez/MV2qJlRrDJoRcC1LZ/Zi388GpxH5IOXWzXwcXl0FD/dcX3xsCgfWLyzOcbAAD/
|
||||
/468z9qYAAAA
|
||||
`,
|
||||
},
|
||||
|
||||
"/templates/message.tmpl": {
|
||||
name: "message.tmpl",
|
||||
local: "templates/message.tmpl",
|
||||
size: 201,
|
||||
modtime: 1540446006,
|
||||
compressed: `
|
||||
H4sIAAAAAAAC/zyN4WqDQBCE//sUiyi0oPsAhT5A/xRpS/9f4mgW9GLuTkNY9t2DB/HXDDPDN6o9BvGg
|
||||
ckaMbkRJrVmhKgP5ayL+XU8JMUWz+sakCt+bqd4lXYh/cIZsCHvCf48F/O+mFWZ8DPnbzTB7y0Tugvj0
|
||||
5Zd1B6oG50dQJQ1VmOjjk7hzwc1ICLmXgSoxa16/9XZws7wXqi1l+wwAAP//kC65UskAAAA=
|
||||
`,
|
||||
},
|
||||
|
||||
"/templates/results.tmpl": {
|
||||
name: "results.tmpl",
|
||||
local: "templates/results.tmpl",
|
||||
size: 168,
|
||||
modtime: 1540446006,
|
||||
compressed: `
|
||||
H4sIAAAAAAAC/1yNTQrCQAyFr/Iosyw9gOBS3HsDoRkJlAy8ma5C7i6pRcFVfr4vee6rVDXBROn7NvoU
|
||||
AXc+7SUoOqPIhssVy+ODI9y1omjEDHexNTf3NrBkc85a82DstH4jG1MW8uQ4hMbv0385A3/uUd8BAAD/
|
||||
/7BPz2GoAAAA
|
||||
`,
|
||||
},
|
||||
|
||||
"/templates": {
|
||||
name: "templates",
|
||||
local: `templates`,
|
||||
isDir: true,
|
||||
},
|
||||
}
|
||||
|
||||
var _escDirs = map[string][]os.FileInfo{
|
||||
|
||||
"templates": {
|
||||
_escData["/templates/call.tmpl"],
|
||||
_escData["/templates/function.tmpl"],
|
||||
_escData["/templates/header.tmpl"],
|
||||
_escData["/templates/inline.tmpl"],
|
||||
_escData["/templates/inputs.tmpl"],
|
||||
_escData["/templates/message.tmpl"],
|
||||
_escData["/templates/results.tmpl"],
|
||||
},
|
||||
}
|
23
vendor/github.com/cweill/gotests/internal/render/bindata/helper.go
generated
vendored
Normal file
23
vendor/github.com/cweill/gotests/internal/render/bindata/helper.go
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
// Package bindata
|
||||
// Helper with wrapper for backward compatibility with go-bindata
|
||||
// used only AssetNames func, because only this func has no analog on esc
|
||||
//
|
||||
// the reason for changing go-bindata to esc - is:
|
||||
// `go-bindata creator deleted their @github account and someone else created a new account with the same name.`
|
||||
//
|
||||
// https://github.com/jteeuwen/go-bindata/issues/5
|
||||
// https://twitter.com/francesc/status/961249107020001280
|
||||
//
|
||||
// After research some of alternatives - `esc` - is looks like one of the best choice
|
||||
// https://tech.townsourced.com/post/embedding-static-files-in-go/
|
||||
|
||||
package bindata
|
||||
|
||||
// AssetNames returns the names of the assets. (for compatible with go-bindata)
|
||||
func AssetNames() []string {
|
||||
names := make([]string, 0, len(_escData))
|
||||
for name := range _escData {
|
||||
names = append(names, name)
|
||||
}
|
||||
return names
|
||||
}
|
135
vendor/github.com/cweill/gotests/internal/render/render.go
generated
vendored
Normal file
135
vendor/github.com/cweill/gotests/internal/render/render.go
generated
vendored
Normal file
@ -0,0 +1,135 @@
|
||||
package render
|
||||
|
||||
//go:generate esc -o bindata/esc.go -pkg=bindata templates
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/cweill/gotests/internal/models"
|
||||
"github.com/cweill/gotests/internal/render/bindata"
|
||||
)
|
||||
|
||||
const name = "name"
|
||||
|
||||
var (
|
||||
tmpls *template.Template
|
||||
)
|
||||
|
||||
func init() {
|
||||
initEmptyTmpls()
|
||||
for _, name := range bindata.AssetNames() {
|
||||
tmpls = template.Must(tmpls.Parse(bindata.FSMustString(false, name)))
|
||||
}
|
||||
}
|
||||
|
||||
// LoadCustomTemplates allows to load in custom templates from a specified path.
|
||||
func LoadCustomTemplates(dir string) error {
|
||||
initEmptyTmpls()
|
||||
|
||||
files, err := ioutil.ReadDir(dir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("ioutil.ReadDir: %v", err)
|
||||
}
|
||||
|
||||
templateFiles := []string{}
|
||||
for _, f := range files {
|
||||
templateFiles = append(templateFiles, path.Join(dir, f.Name()))
|
||||
}
|
||||
tmpls, err = tmpls.ParseFiles(templateFiles...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("tmpls.ParseFiles: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func initEmptyTmpls() {
|
||||
tmpls = template.New("render").Funcs(map[string]interface{}{
|
||||
"Field": fieldName,
|
||||
"Receiver": receiverName,
|
||||
"Param": parameterName,
|
||||
"Want": wantName,
|
||||
"Got": gotName,
|
||||
})
|
||||
}
|
||||
|
||||
func fieldName(f *models.Field) string {
|
||||
var n string
|
||||
if f.IsNamed() {
|
||||
n = f.Name
|
||||
} else {
|
||||
n = f.Type.String()
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func receiverName(f *models.Receiver) string {
|
||||
var n string
|
||||
if f.IsNamed() {
|
||||
n = f.Name
|
||||
} else {
|
||||
n = f.ShortName()
|
||||
}
|
||||
if n == "name" {
|
||||
// Avoid conflict with test struct's "name" field.
|
||||
n = "n"
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func parameterName(f *models.Field) string {
|
||||
var n string
|
||||
if f.IsNamed() {
|
||||
n = f.Name
|
||||
} else {
|
||||
n = fmt.Sprintf("in%v", f.Index)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func wantName(f *models.Field) string {
|
||||
var n string
|
||||
if f.IsNamed() {
|
||||
n = "want" + strings.Title(f.Name)
|
||||
} else if f.Index == 0 {
|
||||
n = "want"
|
||||
} else {
|
||||
n = fmt.Sprintf("want%v", f.Index)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func gotName(f *models.Field) string {
|
||||
var n string
|
||||
if f.IsNamed() {
|
||||
n = "got" + strings.Title(f.Name)
|
||||
} else if f.Index == 0 {
|
||||
n = "got"
|
||||
} else {
|
||||
n = fmt.Sprintf("got%v", f.Index)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func Header(w io.Writer, h *models.Header) error {
|
||||
if err := tmpls.ExecuteTemplate(w, "header", h); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := w.Write(h.Code)
|
||||
return err
|
||||
}
|
||||
|
||||
func TestFunction(w io.Writer, f *models.Function, printInputs bool, subtests bool) error {
|
||||
return tmpls.ExecuteTemplate(w, "function", struct {
|
||||
*models.Function
|
||||
PrintInputs bool
|
||||
Subtests bool
|
||||
}{
|
||||
Function: f,
|
||||
PrintInputs: printInputs,
|
||||
Subtests: subtests,
|
||||
})
|
||||
}
|
Reference in New Issue
Block a user