diff --git a/.gitignore b/.gitignore index 199855319..8dd382f2a 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,6 @@ website/.bundle website/vendor packer-test*.log + +*.received.txt +*.received.json diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 548b82018..1d18273b0 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -66,6 +66,18 @@ "ImportPath": "github.com/armon/go-radix", "Rev": "4239b77079c7b5d1243b7b4736304ce8ddb6f0f2" }, + { + "ImportPath": "github.com/approvals/go-approval-tests", + "Rev": "ad96e53bea43a905c17beeb983a0f9ce087dc48d" + }, + { + "ImportPath": "github.com/approvals/go-approval-tests/reporters", + "Rev": "ad96e53bea43a905c17beeb983a0f9ce087dc48d" + }, + { + "ImportPath": "github.com/approvals/go-approval-tests/utils", + "Rev": "ad96e53bea43a905c17beeb983a0f9ce087dc48d" + }, { "ImportPath": "github.com/aws/aws-sdk-go/aws", "Comment": "v1.1.2", diff --git a/vendor/github.com/approvals/go-approval-tests/.gitignore b/vendor/github.com/approvals/go-approval-tests/.gitignore new file mode 100644 index 000000000..6ed91fe2c --- /dev/null +++ b/vendor/github.com/approvals/go-approval-tests/.gitignore @@ -0,0 +1,25 @@ +*.received.* +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/approvals/go-approval-tests/LICENSE.md b/vendor/github.com/approvals/go-approval-tests/LICENSE.md new file mode 100644 index 000000000..c0ee81299 --- /dev/null +++ b/vendor/github.com/approvals/go-approval-tests/LICENSE.md @@ -0,0 +1,201 @@ + 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. diff --git a/vendor/github.com/approvals/go-approval-tests/README.md b/vendor/github.com/approvals/go-approval-tests/README.md new file mode 100644 index 000000000..ef9b41761 --- /dev/null +++ b/vendor/github.com/approvals/go-approval-tests/README.md @@ -0,0 +1,53 @@ +# ApprovalTests.go + +ApprovalTests for go + +[![Build Status](https://travis-ci.org/approvals/go-approval-tests.png?branch=master)](https://travis-ci.org/approvals/go-approval-tests) + +# Golden master Verification Library +ApprovalTests allows for easy testing of larger objects, strings and anything else that can be saved to a file (images, sounds, csv, etc...) + +#Examples +##In Project +Note: ApprovalTests uses approvaltests to test itself. Therefore there are many examples in the code itself. + + * [approvals_test.go](approvals_test.go) + +##JSON +VerifyJSONBytes - Simple Formatting for easy comparison. Also uses the .json file extension + +```go +func TestVerifyJSON(t *testing.T) { + jsonb := []byte("{ \"foo\": \"bar\", \"age\": 42, \"bark\": \"woof\" }") + VerifyJSONBytes(t, jsonb) +} +``` +Matches file: approvals_test.TestVerifyJSON.received.json + +```json +{ + "age": 42, + "bark": "woof", + "foo": "bar" +} +``` + +##Reporters +ApprovalTests becomes *much* more powerful with reporters. Reporters launch programs on failure to help you understand, fix and approve results. + +You can make your own easily, [here's an example](reporters/beyond_compare.go) +You can also declare which one to use. Either at the +### Method level +```go +r := UseReporter(reporters.NewIntelliJ()) +defer r.Close() +``` +### Test Level +```go +func TestMain(m *testing.M) { + r := UseReporter(reporters.NewBeyondCompareReporter()) + defer r.Close() + + m.Run() +} +``` diff --git a/vendor/github.com/approvals/go-approval-tests/approval_name.go b/vendor/github.com/approvals/go-approval-tests/approval_name.go new file mode 100644 index 000000000..1ef043efc --- /dev/null +++ b/vendor/github.com/approvals/go-approval-tests/approval_name.go @@ -0,0 +1,130 @@ +package approvaltests + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "os" + "path" + "runtime" + "strings" +) + +type approvalName struct { + pc uintptr + fullName string + name string + fileName string + fileLine int +} + +func newApprovalName(pc uintptr, f *runtime.Func) (*approvalName, error) { + namer := &approvalName{ + pc: pc, + fullName: f.Name(), + } + + namer.fileName, namer.fileLine = f.FileLine(pc) + + splits := strings.Split(namer.fullName, ".") + namer.name = splits[len(splits)-1] + + return namer, nil +} + +// Walk the call stack, and try to find the test method that was executed. +// The test method is identified by looking for the test runner, which is +// *assumed* to be common across all callers. The test runner has a Name() of +// 'testing.tRunner'. The method immediately previous to this is the test +// method. +func getApprovalName() (*approvalName, error) { + pc := make([]uintptr, 100) + count := runtime.Callers(0, pc) + + i := 0 + var lastFunc *runtime.Func + + for ; i < count; i++ { + lastFunc = runtime.FuncForPC(pc[i]) + if isTestRunner(lastFunc) { + break + } + } + + if i == 0 || !isTestRunner(lastFunc) { + return nil, fmt.Errorf("approvals: could not find the test method") + } + + testMethod := runtime.FuncForPC(pc[i-1]) + return newApprovalName(pc[i-1], testMethod) +} + +func isTestRunner(f *runtime.Func) bool { + return f != nil && f.Name() == "testing.tRunner" +} + +func (s *approvalName) compare(approvalFile, receivedFile string, reader io.Reader) error { + received, err := ioutil.ReadAll(reader) + if err != nil { + return err + } + + // Ideally, this should only be written if + // 1. the approval file does not exist + // 2. the results differ + err = s.dumpReceivedTestResult(received, receivedFile) + if err != nil { + return err + } + + fh, err := os.Open(approvalFile) + if err != nil { + return err + } + defer fh.Close() + + approved, err := ioutil.ReadAll(fh) + if err != nil { + return err + } + + received = s.normalizeLineEndings(received) + approved = s.normalizeLineEndings(approved) + + // The two sides are identical, nothing more to do. + if bytes.Compare(received, approved) == 0 { + return nil + } + + return fmt.Errorf("failed to approved %s", s.name) +} + +func (s *approvalName) normalizeLineEndings(bs []byte) []byte { + return bytes.Replace(bs, []byte("\r\n"), []byte("\n"), -1) +} + +func (s *approvalName) dumpReceivedTestResult(bs []byte, receivedFile string) error { + err := ioutil.WriteFile(receivedFile, bs, 0644) + + return err +} + +func (s *approvalName) getFileName(extWithDot string, suffix string) string { + if !strings.HasPrefix(extWithDot, ".") { + extWithDot = fmt.Sprintf(".%s", extWithDot) + } + + baseName := path.Base(s.fileName) + baseWithoutExt := baseName[:len(baseName)-len(path.Ext(s.fileName))] + + return fmt.Sprintf("%s.%s.%s%s", baseWithoutExt, s.name, suffix, extWithDot) +} + +func (s *approvalName) getReceivedFile(extWithDot string) string { + return s.getFileName(extWithDot, "received") +} + +func (s *approvalName) getApprovalFile(extWithDot string) string { + return s.getFileName(extWithDot, "approved") +} diff --git a/vendor/github.com/approvals/go-approval-tests/approvals.go b/vendor/github.com/approvals/go-approval-tests/approvals.go new file mode 100644 index 000000000..f4b3a839e --- /dev/null +++ b/vendor/github.com/approvals/go-approval-tests/approvals.go @@ -0,0 +1,204 @@ +package approvaltests + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "os" + "strings" + + "encoding/xml" + "github.com/approvals/go-approval-tests/reporters" + "github.com/approvals/go-approval-tests/utils" + "reflect" +) + +var ( + defaultReporter = reporters.NewDiffReporter() + defaultFrontLoadedReporter = reporters.NewFrontLoadedReporter() +) + +// Failable is an interface wrapper around testing.T +type Failable interface { + Fail() +} + +// VerifyWithExtension Example: +// VerifyWithExtension(t, strings.NewReader("Hello"), ".txt") +func VerifyWithExtension(t Failable, reader io.Reader, extWithDot string) error { + namer, err := getApprovalName() + if err != nil { + return err + } + + reporter := getReporter() + err = namer.compare(namer.getApprovalFile(extWithDot), namer.getReceivedFile(extWithDot), reader) + if err != nil { + reporter.Report(namer.getApprovalFile(extWithDot), namer.getReceivedFile(extWithDot)) + t.Fail() + } else { + os.Remove(namer.getReceivedFile(extWithDot)) + } + + return err +} + +// Verify Example: +// Verify(t, strings.NewReader("Hello")) +func Verify(t Failable, reader io.Reader) error { + return VerifyWithExtension(t, reader, ".txt") +} + +// VerifyString Example: +// VerifyString(t, "Hello") +func VerifyString(t Failable, s string) error { + reader := strings.NewReader(s) + return Verify(t, reader) +} + +// VerifyXMLStruct Example: +// VerifyXMLStruct(t, xml) +func VerifyXMLStruct(t Failable, obj interface{}) error { + xmlb, err := xml.MarshalIndent(obj, "", " ") + if err != nil { + tip := "" + if reflect.TypeOf(obj).Name() == "" { + tip = "when using anonymous types be sure to include\n XMLName xml.Name `xml:\"Your_Name_Here\"`\n" + } + message := fmt.Sprintf("error while pretty printing XML\n%verror:\n %v\nXML:\n %v\n", tip, err, obj) + return VerifyWithExtension(t, strings.NewReader(message), ".xml") + } + + return VerifyWithExtension(t, bytes.NewReader(xmlb), ".xml") +} + +// VerifyXMLBytes Example: +// VerifyXMLBytes(t, []byte("")) +func VerifyXMLBytes(t Failable, bs []byte) error { + type node struct { + Attr []xml.Attr + XMLName xml.Name + Children []node `xml:",any"` + Text string `xml:",chardata"` + } + x := node{} + + err := xml.Unmarshal(bs, &x) + if err != nil { + message := fmt.Sprintf("error while parsing XML\nerror:\n %s\nXML:\n %s\n", err, string(bs)) + return VerifyWithExtension(t, strings.NewReader(message), ".xml") + } + + return VerifyXMLStruct(t, x) +} + +// VerifyJSONStruct Example: +// VerifyJSONStruct(t, json) +func VerifyJSONStruct(t Failable, obj interface{}) error { + jsonb, err := json.MarshalIndent(obj, "", " ") + if err != nil { + message := fmt.Sprintf("error while pretty printing JSON\nerror:\n %s\nJSON:\n %s\n", err, obj) + return VerifyWithExtension(t, strings.NewReader(message), ".json") + } + + return VerifyWithExtension(t, bytes.NewReader(jsonb), ".json") +} + +// VerifyJSONBytes Example: +// VerifyJSONBytes(t, []byte("{ \"Greeting\": \"Hello\" }")) +func VerifyJSONBytes(t Failable, bs []byte) error { + var obj map[string]interface{} + err := json.Unmarshal(bs, &obj) + if err != nil { + message := fmt.Sprintf("error while parsing JSON\nerror:\n %s\nJSON:\n %s\n", err, string(bs)) + return VerifyWithExtension(t, strings.NewReader(message), ".json") + } + + return VerifyJSONStruct(t, obj) +} + +// VerifyMap Example: +// VerifyMap(t, map[string][string] { "dog": "bark" }) +func VerifyMap(t Failable, m interface{}) error { + outputText := utils.PrintMap(m) + return VerifyString(t, outputText) +} + +// VerifyArray Example: +// VerifyArray(t, []string{"dog", "cat"}) +func VerifyArray(t Failable, array interface{}) error { + outputText := utils.PrintArray(array) + return VerifyString(t, outputText) +} + +// VerifyAll Example: +// VerifyAll(t, "uppercase", []string("dog", "cat"}, func(x interface{}) string { return strings.ToUpper(x.(string)) }) +func VerifyAll(t Failable, header string, collection interface{}, transform func(interface{}) string) error { + if len(header) != 0 { + header = fmt.Sprintf("%s\n\n\n", header) + } + + outputText := header + strings.Join(utils.MapToString(collection, transform), "\n") + return VerifyString(t, outputText) +} + +type reporterCloser struct { + reporter *reporters.Reporter +} + +func (s *reporterCloser) Close() error { + defaultReporter = s.reporter + return nil +} + +type frontLoadedReporterCloser struct { + reporter *reporters.Reporter +} + +func (s *frontLoadedReporterCloser) Close() error { + defaultFrontLoadedReporter = s.reporter + return nil +} + +// UseReporter configures which reporter to use on failure. +// Add at the test or method level to configure your reporter. +// +// The following examples shows how to use a reporter for all of your test cases +// in a package directory through go's setup feature. +// +// +// func TestMain(m *testing.M) { +// r := UseReporter(reporters.NewBeyondCompareReporter()) +// defer r.Close() +// +// os.Exit(m.Run()) +// } +// +func UseReporter(reporter reporters.Reporter) io.Closer { + closer := &reporterCloser{ + reporter: defaultReporter, + } + + defaultReporter = &reporter + return closer +} + +// UseFrontLoadedReporter configures reporters ahead of all other reporters to +// handle situations like CI. These reporters usually prevent reporting in +// scenarios that are headless. +func UseFrontLoadedReporter(reporter reporters.Reporter) io.Closer { + closer := &frontLoadedReporterCloser{ + reporter: defaultFrontLoadedReporter, + } + + defaultFrontLoadedReporter = &reporter + return closer +} + +func getReporter() reporters.Reporter { + return reporters.NewFirstWorkingReporter( + *defaultFrontLoadedReporter, + *defaultReporter, + ) +} diff --git a/vendor/github.com/approvals/go-approval-tests/combination_approvals.go b/vendor/github.com/approvals/go-approval-tests/combination_approvals.go new file mode 100644 index 000000000..9c775a823 --- /dev/null +++ b/vendor/github.com/approvals/go-approval-tests/combination_approvals.go @@ -0,0 +1,296 @@ +package approvaltests + +import ( + "fmt" + "strings" + + "reflect" +) + +type emptyType struct{} + +var ( + // SkipThisCombination should be returned if you do not want to process a particular combination + SkipThisCombination = "♬ SKIP THIS COMBINATION ♬" + + empty = emptyType{} + emptyCollection = []emptyType{empty} +) + +// VerifyAllCombinationsFor1 Example: +// VerifyAllCombinationsFor1(t, "uppercase", func(x interface{}) string { return strings.ToUpper(x.(string)) }, []string("dog", "cat"}) +func VerifyAllCombinationsFor1(t Failable, header string, transform func(interface{}) string, collection1 interface{}) error { + transform2 := func(p1, p2, p3, p4, p5, p6, p7, p8, p9 interface{}) string { + return transform(p1) + } + + return VerifyAllCombinationsFor9(t, header, transform2, collection1, + emptyCollection, + emptyCollection, + emptyCollection, + emptyCollection, + emptyCollection, + emptyCollection, + emptyCollection, + emptyCollection) +} + +// VerifyAllCombinationsFor2 Example: +// VerifyAllCombinationsFor2(t, "uppercase", func(x interface{}) string { return strings.ToUpper(x.(string)) }, []string("dog", "cat"}, []int{1,2) +func VerifyAllCombinationsFor2(t Failable, header string, transform func(interface{}, interface{}) string, collection1 interface{}, collection2 interface{}) error { + transform2 := func(p1, p2, p3, p4, p5, p6, p7, p8, p9 interface{}) string { + return transform(p1, p2) + } + + return VerifyAllCombinationsFor9(t, header, transform2, collection1, + collection2, + emptyCollection, + emptyCollection, + emptyCollection, + emptyCollection, + emptyCollection, + emptyCollection, + emptyCollection) +} + +// VerifyAllCombinationsFor3 is for combinations of 3. +func VerifyAllCombinationsFor3( + t Failable, + header string, + transform func(p1, p2, p3 interface{}) string, + collection1, collection2, collection3 interface{}) error { + + kerning := func(p1, p2, p3, p4, p5, p6, p7, p8, p9 interface{}) string { + return transform(p1, p2, p3) + } + + return VerifyAllCombinationsFor9(t, header, kerning, + collection1, + collection2, + collection3, + emptyCollection, + emptyCollection, + emptyCollection, + emptyCollection, + emptyCollection, + emptyCollection) +} + +// VerifyAllCombinationsFor4 is for combinations of 4. +func VerifyAllCombinationsFor4( + t Failable, + header string, + transform func(p1, p2, p3, p4 interface{}) string, + collection1, collection2, collection3, collection4 interface{}) error { + + kerning := func(p1, p2, p3, p4, p5, p6, p7, p8, p9 interface{}) string { + return transform(p1, p2, p3, p4) + } + + return VerifyAllCombinationsFor9(t, header, kerning, + collection1, + collection2, + collection3, + collection4, + emptyCollection, + emptyCollection, + emptyCollection, + emptyCollection, + emptyCollection) +} + +// VerifyAllCombinationsFor5 is for combinations of 5. +func VerifyAllCombinationsFor5( + t Failable, + header string, + transform func(p1, p2, p3, p4, p5 interface{}) string, + collection1, collection2, collection3, collection4, collection5 interface{}) error { + + kerning := func(p1, p2, p3, p4, p5, p6, p7, p8, p9 interface{}) string { + return transform(p1, p2, p3, p4, p5) + } + + return VerifyAllCombinationsFor9(t, header, kerning, + collection1, + collection2, + collection3, + collection4, + collection5, + emptyCollection, + emptyCollection, + emptyCollection, + emptyCollection) +} + +// VerifyAllCombinationsFor6 is for combinations of 6. +func VerifyAllCombinationsFor6( + t Failable, + header string, + transform func(p1, p2, p3, p4, p5, p6 interface{}) string, + collection1, collection2, collection3, collection4, collection5, collection6 interface{}) error { + + kerning := func(p1, p2, p3, p4, p5, p6, p7, p8, p9 interface{}) string { + return transform(p1, p2, p3, p4, p5, p6) + } + + return VerifyAllCombinationsFor9(t, header, kerning, + collection1, + collection2, + collection3, + collection4, + collection5, + collection6, + emptyCollection, + emptyCollection, + emptyCollection) +} + +// VerifyAllCombinationsFor7 is for combinations of 7. +func VerifyAllCombinationsFor7( + t Failable, + header string, + transform func(p1, p2, p3, p4, p5, p6, p7 interface{}) string, + collection1, collection2, collection3, collection4, collection5, collection6, collection7 interface{}) error { + + kerning := func(p1, p2, p3, p4, p5, p6, p7, p8, p9 interface{}) string { + return transform(p1, p2, p3, p4, p5, p6, p7) + } + + return VerifyAllCombinationsFor9(t, header, kerning, + collection1, + collection2, + collection3, + collection4, + collection5, + collection6, + collection7, + emptyCollection, + emptyCollection) +} + +// VerifyAllCombinationsFor8 is for combinations of 8. +func VerifyAllCombinationsFor8( + t Failable, + header string, + transform func(p1, p2, p3, p4, p5, p6, p7, p8 interface{}) string, + collection1, collection2, collection3, collection4, collection5, collection6, collection7, collection8 interface{}) error { + + kerning := func(p1, p2, p3, p4, p5, p6, p7, p8, p9 interface{}) string { + return transform(p1, p2, p3, p4, p5, p6, p7, p8) + } + + return VerifyAllCombinationsFor9(t, header, kerning, + collection1, + collection2, + collection3, + collection4, + collection5, + collection6, + collection7, + collection8, + emptyCollection) +} + +// VerifyAllCombinationsFor9 is for combinations of 9. +func VerifyAllCombinationsFor9( + t Failable, + header string, + transform func(a, b, c, d, e, f, g, h, i interface{}) string, + collection1, + collection2, + collection3, + collection4, + collection5, + collection6, + collection7, + collection8, + collection9 interface{}) error { + + if len(header) != 0 { + header = fmt.Sprintf("%s\n\n\n", header) + } + + var mapped []string + + slice1 := reflect.ValueOf(collection1) + slice2 := reflect.ValueOf(collection2) + slice3 := reflect.ValueOf(collection3) + slice4 := reflect.ValueOf(collection4) + slice5 := reflect.ValueOf(collection5) + slice6 := reflect.ValueOf(collection6) + slice7 := reflect.ValueOf(collection7) + slice8 := reflect.ValueOf(collection8) + slice9 := reflect.ValueOf(collection9) + + for i1 := 0; i1 < slice1.Len(); i1++ { + for i2 := 0; i2 < slice2.Len(); i2++ { + for i3 := 0; i3 < slice3.Len(); i3++ { + for i4 := 0; i4 < slice4.Len(); i4++ { + for i5 := 0; i5 < slice5.Len(); i5++ { + for i6 := 0; i6 < slice6.Len(); i6++ { + for i7 := 0; i7 < slice7.Len(); i7++ { + for i8 := 0; i8 < slice8.Len(); i8++ { + for i9 := 0; i9 < slice9.Len(); i9++ { + p1 := slice1.Index(i1).Interface() + p2 := slice2.Index(i2).Interface() + p3 := slice3.Index(i3).Interface() + p4 := slice4.Index(i4).Interface() + p5 := slice5.Index(i5).Interface() + p6 := slice6.Index(i6).Interface() + p7 := slice7.Index(i7).Interface() + p8 := slice8.Index(i8).Interface() + p9 := slice9.Index(i9).Interface() + + parameterText := getParameterText(p1, p2, p3, p4, p5, p6, p7, p8, p9) + transformText := getTransformText(transform, p1, p2, p3, p4, p5, p6, p7, p8, p9) + if transformText != SkipThisCombination { + mapped = append(mapped, fmt.Sprintf("%s => %s", parameterText, transformText)) + } + } + } + } + } + } + } + } + } + } + + outputText := header + strings.Join(mapped, "\n") + return VerifyString(t, outputText) +} + +func getParameterText(args ...interface{}) string { + parameterText := "[" + for _, x := range args { + if x != empty { + parameterText += fmt.Sprintf("%v,", x) + } + } + + parameterText = parameterText[0 : len(parameterText)-1] + parameterText += "]" + + return parameterText +} + +func getTransformText( + transform func(a, b, c, d, e, f, g, h, i interface{}) string, + p1, + p2, + p3, + p4, + p5, + p6, + p7, + p8, + p9 interface{}) (s string) { + defer func() { + r := recover() + if r != nil { + s = "panic occurred" + } + }() + + return transform(p1, p2, p3, p4, p5, p6, p7, p8, p9) +} diff --git a/vendor/github.com/approvals/go-approval-tests/reporters/all_failing.go b/vendor/github.com/approvals/go-approval-tests/reporters/all_failing.go new file mode 100644 index 000000000..788a1e3b0 --- /dev/null +++ b/vendor/github.com/approvals/go-approval-tests/reporters/all_failing.go @@ -0,0 +1,18 @@ +package reporters + +var ( + clipboardScratchData = "" +) + +type allFailing struct{} + +// NewAllFailingTestReporter copies move file command to your clipboard +func NewAllFailingTestReporter() Reporter { + return &allFailing{} +} + +func (s *allFailing) Report(approved, received string) bool { + move := getMoveCommandText(approved, received) + clipboardScratchData = clipboardScratchData + move + "\n" + return copyToClipboard(clipboardScratchData) +} diff --git a/vendor/github.com/approvals/go-approval-tests/reporters/beyond_compare.go b/vendor/github.com/approvals/go-approval-tests/reporters/beyond_compare.go new file mode 100644 index 000000000..81dccd25c --- /dev/null +++ b/vendor/github.com/approvals/go-approval-tests/reporters/beyond_compare.go @@ -0,0 +1,15 @@ +package reporters + +type beyondCompare struct{} + +// NewBeyondCompareReporter creates a new reporter for Beyond Compare 4. +func NewBeyondCompareReporter() Reporter { + return &beyondCompare{} +} + +func (s *beyondCompare) Report(approved, received string) bool { + xs := []string{received, approved} + programName := "C:/Program Files/Beyond Compare 4/BComp.exe" + + return launchProgram(programName, approved, xs...) +} diff --git a/vendor/github.com/approvals/go-approval-tests/reporters/clipboard.go b/vendor/github.com/approvals/go-approval-tests/reporters/clipboard.go new file mode 100644 index 000000000..4f4f9ffe9 --- /dev/null +++ b/vendor/github.com/approvals/go-approval-tests/reporters/clipboard.go @@ -0,0 +1,66 @@ +package reporters + +import ( + "fmt" + "os/exec" + "path/filepath" + "runtime" +) + +type clipboard struct{} + +// NewClipboardReporter copies move file command to your clipboard +func NewClipboardReporter() Reporter { + return &clipboard{} +} + +func (s *clipboard) Report(approved, received string) bool { + move := getMoveCommandText(approved, received) + return copyToClipboard(move) +} + +func copyToClipboard(move string) bool { + switch runtime.GOOS { + case "windows": + return copyToWindowsClipboard(move) + default: + return copyToDarwinClipboard(move) + } +} + +func getMoveCommandText(approved, received string) string { + receivedFull, _ := filepath.Abs(received) + approvedFull, _ := filepath.Abs(approved) + + var move string + + switch runtime.GOOS { + case "windows": + move = fmt.Sprintf("move /Y \"%s\" \"%s\"", receivedFull, approvedFull) + default: + move = fmt.Sprintf("mv %s %s", receivedFull, approvedFull) + } + + return move +} +func copyToWindowsClipboard(text string) bool { + return pipeToProgram("clip", text) +} + +func copyToDarwinClipboard(text string) bool { + return pipeToProgram("pbcopy", text) +} + +func pipeToProgram(programName, text string) bool { + c := exec.Command(programName) + pipe, err := c.StdinPipe() + if err != nil { + fmt.Printf("StdinPipe: err=%s", err) + return false + } + pipe.Write([]byte(text)) + pipe.Close() + + c.Start() + return true +} diff --git a/vendor/github.com/approvals/go-approval-tests/reporters/continuous_integration.go b/vendor/github.com/approvals/go-approval-tests/reporters/continuous_integration.go new file mode 100644 index 000000000..923feb793 --- /dev/null +++ b/vendor/github.com/approvals/go-approval-tests/reporters/continuous_integration.go @@ -0,0 +1,28 @@ +package reporters + +import ( + "os" + "strconv" +) + +type continuousIntegration struct{} + +// NewContinuousIntegrationReporter creates a new reporter for CI. +// +// The reporter checks the environment variable CI for a value of true. +func NewContinuousIntegrationReporter() Reporter { + return &continuousIntegration{} +} + +func (s *continuousIntegration) Report(approved, received string) bool { + value, exists := os.LookupEnv("CI") + + if exists { + ci, err := strconv.ParseBool(value) + if err == nil { + return ci + } + } + + return false +} diff --git a/vendor/github.com/approvals/go-approval-tests/reporters/diff_reporter.go b/vendor/github.com/approvals/go-approval-tests/reporters/diff_reporter.go new file mode 100644 index 000000000..630548e2a --- /dev/null +++ b/vendor/github.com/approvals/go-approval-tests/reporters/diff_reporter.go @@ -0,0 +1,40 @@ +package reporters + +import ( + "os/exec" + + "github.com/approvals/go-approval-tests/utils" +) + +// NewFrontLoadedReporter creates the default front loaded reporter. +func NewFrontLoadedReporter() *Reporter { + tmp := NewFirstWorkingReporter( + NewContinuousIntegrationReporter(), + ) + + return &tmp +} + +// NewDiffReporter creates the default diff reporter. +func NewDiffReporter() *Reporter { + tmp := NewFirstWorkingReporter( + NewBeyondCompareReporter(), + NewIntelliJReporter(), + NewPrintSupportedDiffProgramsReporter(), + NewQuietReporter(), + ) + + return &tmp +} + +func launchProgram(programName, approved string, args ...string) bool { + if !utils.DoesFileExist(programName) { + return false + } + + utils.EnsureExists(approved) + + cmd := exec.Command(programName, args...) + cmd.Start() + return true +} diff --git a/vendor/github.com/approvals/go-approval-tests/reporters/file_launcher.go b/vendor/github.com/approvals/go-approval-tests/reporters/file_launcher.go new file mode 100644 index 000000000..cb9bd5b2d --- /dev/null +++ b/vendor/github.com/approvals/go-approval-tests/reporters/file_launcher.go @@ -0,0 +1,27 @@ +package reporters + +import ( + "os/exec" + "runtime" +) + +type fileLauncher struct{} + +// NewFileLauncherReporter launches registered application of the received file's type only. +func NewFileLauncherReporter() Reporter { + return &fileLauncher{} +} + +func (s *fileLauncher) Report(approved, received string) bool { + var cmd *exec.Cmd + + switch runtime.GOOS { + case "windows": + cmd = exec.Command("cmd", "/C", "start", "Needed Title", received, "/B") + default: + cmd = exec.Command("open", received) + } + + cmd.Start() + return true +} diff --git a/vendor/github.com/approvals/go-approval-tests/reporters/intellij.go b/vendor/github.com/approvals/go-approval-tests/reporters/intellij.go new file mode 100644 index 000000000..63e9506aa --- /dev/null +++ b/vendor/github.com/approvals/go-approval-tests/reporters/intellij.go @@ -0,0 +1,15 @@ +package reporters + +type intellij struct{} + +// NewIntelliJReporter creates a new reporter for IntelliJ. +func NewIntelliJReporter() Reporter { + return &intellij{} +} + +func (s *intellij) Report(approved, received string) bool { + xs := []string{"diff", received, approved} + programName := "C:/Program Files (x86)/JetBrains/IntelliJ IDEA 2016/bin/idea.exe" + + return launchProgram(programName, approved, xs...) +} diff --git a/vendor/github.com/approvals/go-approval-tests/reporters/newbie.go b/vendor/github.com/approvals/go-approval-tests/reporters/newbie.go new file mode 100644 index 000000000..8e662bf84 --- /dev/null +++ b/vendor/github.com/approvals/go-approval-tests/reporters/newbie.go @@ -0,0 +1,18 @@ +package reporters + +import ( + "fmt" +) + +type printSupportedDiffPrograms struct{} + +// NewPrintSupportedDiffProgramsReporter creates a new reporter that states what reporters are supported. +func NewPrintSupportedDiffProgramsReporter() Reporter { + return &quiet{} +} + +func (s *printSupportedDiffPrograms) Report(approved, received string) bool { + fmt.Printf("no diff reporters found on your system\ncurrently supported reporters are [in order of preference]:\nBeyond Compare\nIntelliJ") + + return false +} diff --git a/vendor/github.com/approvals/go-approval-tests/reporters/quiet.go b/vendor/github.com/approvals/go-approval-tests/reporters/quiet.go new file mode 100644 index 000000000..a715c0eac --- /dev/null +++ b/vendor/github.com/approvals/go-approval-tests/reporters/quiet.go @@ -0,0 +1,29 @@ +package reporters + +import ( + "fmt" + "path/filepath" + + "github.com/approvals/go-approval-tests/utils" +) + +type quiet struct{} + +// NewQuietReporter creates a new reporter that does nothing. +func NewQuietReporter() Reporter { + return &quiet{} +} + +func (s *quiet) Report(approved, received string) bool { + approvedFull, _ := filepath.Abs(approved) + receivedFull, _ := filepath.Abs(received) + + if utils.DoesFileExist(approved) { + fmt.Printf("approval files did not match\napproved: %v\nreceived: %v\n", approvedFull, receivedFull) + + } else { + fmt.Printf("result never approved\napproved: %v\nreceived: %v\n", approvedFull, receivedFull) + } + + return true +} diff --git a/vendor/github.com/approvals/go-approval-tests/reporters/reporter.go b/vendor/github.com/approvals/go-approval-tests/reporters/reporter.go new file mode 100644 index 000000000..99d6866f6 --- /dev/null +++ b/vendor/github.com/approvals/go-approval-tests/reporters/reporter.go @@ -0,0 +1,53 @@ +package reporters + +// Reporter are called on failing approvals. +type Reporter interface { + // Report is called when the approved and received file do not match. + Report(approved, received string) bool +} + +// FirstWorkingReporter reports using the first possible reporter. +type FirstWorkingReporter struct { + Reporters []Reporter +} + +// Report is called when the approved and received file do not match. +func (s *FirstWorkingReporter) Report(approved, received string) bool { + for _, reporter := range s.Reporters { + result := reporter.Report(approved, received) + if result { + return true + } + } + + return false +} + +// NewFirstWorkingReporter creates in the order reporters are passed in. +func NewFirstWorkingReporter(reporters ...Reporter) Reporter { + return &FirstWorkingReporter{ + Reporters: reporters, + } +} + +// MultiReporter reports all reporters. +type MultiReporter struct { + Reporters []Reporter +} + +// Report is called when the approved and received file do not match. +func (s *MultiReporter) Report(approved, received string) bool { + result := false + for _, reporter := range s.Reporters { + result = reporter.Report(approved, received) || result + } + + return result +} + +// NewMultiReporter calls all reporters. +func NewMultiReporter(reporters ...Reporter) Reporter { + return &MultiReporter{ + Reporters: reporters, + } +} diff --git a/vendor/github.com/approvals/go-approval-tests/utils/collection_utils.go b/vendor/github.com/approvals/go-approval-tests/utils/collection_utils.go new file mode 100644 index 000000000..1602fa6e5 --- /dev/null +++ b/vendor/github.com/approvals/go-approval-tests/utils/collection_utils.go @@ -0,0 +1,77 @@ +package utils + +import ( + "fmt" + "reflect" + "sort" + "strings" +) + +// PrintMap prints a map +func PrintMap(m interface{}) string { + var outputText string + + v := reflect.ValueOf(m) + if v.Kind() != reflect.Map { + outputText = fmt.Sprintf("error while printing map\nreceived a %T\n %s\n", m, m) + } else { + + keys := v.MapKeys() + var xs []string + + for _, k := range keys { + xs = append(xs, fmt.Sprintf("[%s]=%s", k, v.MapIndex(k))) + } + + sort.Strings(xs) + if len(xs) == 0 { + outputText = "len(map) == 0" + } else { + outputText = strings.Join(xs, "\n") + } + } + + return outputText +} + +// PrintArray prints an array +func PrintArray(m interface{}) string { + var outputText string + + switch reflect.TypeOf(m).Kind() { + case reflect.Slice: + var xs []string + + slice := reflect.ValueOf(m) + for i := 0; i < slice.Len(); i++ { + xs = append(xs, fmt.Sprintf("[%d]=%s", i, slice.Index(i))) + } + + if len(xs) == 0 { + outputText = "len(array) == 0" + } else { + outputText = strings.Join(xs, "\n") + } + default: + outputText = fmt.Sprintf("error while printing array\nreceived a %T\n %s\n", m, m) + } + + return outputText +} + +// MapToString maps a collection to a string collection +func MapToString(collection interface{}, transform func(x interface{}) string) []string { + switch reflect.TypeOf(collection).Kind() { + case reflect.Slice: + var xs []string + + slice := reflect.ValueOf(collection) + for i := 0; i < slice.Len(); i++ { + xs = append(xs, transform(slice.Index(i).Interface())) + } + + return xs + default: + panic(fmt.Sprintf("error while mapping array to string\nreceived a %T\n %s\n", collection, collection)) + } +} diff --git a/vendor/github.com/approvals/go-approval-tests/utils/file_utils.go b/vendor/github.com/approvals/go-approval-tests/utils/file_utils.go new file mode 100644 index 000000000..bec3b950b --- /dev/null +++ b/vendor/github.com/approvals/go-approval-tests/utils/file_utils.go @@ -0,0 +1,24 @@ +package utils + +import ( + "io/ioutil" + "os" +) + +// DoesFileExist checks if a file exists. +func DoesFileExist(fileName string) bool { + _, err := os.Stat(fileName) + if os.IsNotExist(err) { + return false + } + return true +} + +// EnsureExists creates if the file does not already exist. +func EnsureExists(fileName string) { + if DoesFileExist(fileName) { + return + } + + ioutil.WriteFile(fileName, []byte(""), 0644) +} diff --git a/vendor/github.com/approvals/go-approval-tests/utils/testing_utils.go b/vendor/github.com/approvals/go-approval-tests/utils/testing_utils.go new file mode 100644 index 000000000..c6c9c8ab6 --- /dev/null +++ b/vendor/github.com/approvals/go-approval-tests/utils/testing_utils.go @@ -0,0 +1,11 @@ +package utils + +import "testing" + +// AssertEqual Example: +// AssertEqual(t, 10, number, "number") +func AssertEqual(t *testing.T, expected, actual interface{}, message string) { + if expected != actual { + t.Fatalf(message+"\n[expected != actual]\n[%s != %s]", expected, actual) + } +}