From 168230f42725ebd0c9e61edc35b393109764cdca Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Tue, 10 Jan 2017 16:54:22 -0800 Subject: [PATCH 1/3] Revert "godep: Add go-multierror dependency" This reverts commit 67daea2fd27177668f1d4f31ec1d83927fe28198. We won't need these with granular TAP handling. Conflicts: Godeps/Godeps.json Signed-off-by: W. Trevor King --- Godeps/Godeps.json | 11 - .../src/github.com/hashicorp/errwrap/LICENSE | 354 ------------------ .../github.com/hashicorp/errwrap/README.md | 89 ----- .../github.com/hashicorp/errwrap/errwrap.go | 169 --------- .../hashicorp/go-multierror/.travis.yml | 12 - .../hashicorp/go-multierror/LICENSE | 353 ----------------- .../hashicorp/go-multierror/Makefile | 31 -- .../hashicorp/go-multierror/README.md | 97 ----- .../hashicorp/go-multierror/append.go | 41 -- .../hashicorp/go-multierror/flatten.go | 26 -- .../hashicorp/go-multierror/format.go | 27 -- .../hashicorp/go-multierror/multierror.go | 51 --- .../hashicorp/go-multierror/prefix.go | 37 -- 13 files changed, 1298 deletions(-) delete mode 100644 Godeps/_workspace/src/github.com/hashicorp/errwrap/LICENSE delete mode 100644 Godeps/_workspace/src/github.com/hashicorp/errwrap/README.md delete mode 100644 Godeps/_workspace/src/github.com/hashicorp/errwrap/errwrap.go delete mode 100644 Godeps/_workspace/src/github.com/hashicorp/go-multierror/.travis.yml delete mode 100644 Godeps/_workspace/src/github.com/hashicorp/go-multierror/LICENSE delete mode 100644 Godeps/_workspace/src/github.com/hashicorp/go-multierror/Makefile delete mode 100644 Godeps/_workspace/src/github.com/hashicorp/go-multierror/README.md delete mode 100644 Godeps/_workspace/src/github.com/hashicorp/go-multierror/append.go delete mode 100644 Godeps/_workspace/src/github.com/hashicorp/go-multierror/flatten.go delete mode 100644 Godeps/_workspace/src/github.com/hashicorp/go-multierror/format.go delete mode 100644 Godeps/_workspace/src/github.com/hashicorp/go-multierror/multierror.go delete mode 100644 Godeps/_workspace/src/github.com/hashicorp/go-multierror/prefix.go diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 6a514c4bf..57c568c4a 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -2,9 +2,6 @@ "ImportPath": "github.com/opencontainers/runtime-tools", "GoVersion": "go1.4", "GodepVersion": "v75", - "Packages": [ - "./..." - ], "Deps": [ { "ImportPath": "github.com/Sirupsen/logrus", @@ -16,14 +13,6 @@ "Comment": "v3.1.0", "Rev": "aea32c919a18e5ef4537bbd283ff29594b1b0165" }, - { - "ImportPath": "github.com/hashicorp/errwrap", - "Rev": "7554cd9344cec97297fa6649b055a8c98c2a1e55" - }, - { - "ImportPath": "github.com/hashicorp/go-multierror", - "Rev": "ed905158d87462226a13fe39ddf685ea65f1c11f" - }, { "ImportPath": "github.com/mndrix/tap-go", "Rev": "67c9553625499b7e7ed4ac4f2d8bf1cb8f5ecf52" diff --git a/Godeps/_workspace/src/github.com/hashicorp/errwrap/LICENSE b/Godeps/_workspace/src/github.com/hashicorp/errwrap/LICENSE deleted file mode 100644 index c33dcc7c9..000000000 --- a/Godeps/_workspace/src/github.com/hashicorp/errwrap/LICENSE +++ /dev/null @@ -1,354 +0,0 @@ -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. “Contributor” - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. “Contributor Version” - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor’s Contribution. - -1.3. “Contribution” - - means Covered Software of a particular Contributor. - -1.4. “Covered Software” - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. “Incompatible With Secondary Licenses” - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of version - 1.1 or earlier of the License, but not also under the terms of a - Secondary License. - -1.6. “Executable Form” - - means any form of the work other than Source Code Form. - -1.7. “Larger Work” - - means a work that combines Covered Software with other material, in a separate - file or files, that is not Covered Software. - -1.8. “License” - - means this document. - -1.9. “Licensable” - - means having the right to grant, to the maximum extent possible, whether at the - time of the initial grant or subsequently, any and all of the rights conveyed by - this License. - -1.10. “Modifications” - - means any of the following: - - a. any file in Source Code Form that results from an addition to, deletion - from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. “Patent Claims” of a Contributor - - means any patent claim(s), including without limitation, method, process, - and apparatus claims, in any patent Licensable by such Contributor that - would be infringed, but for the grant of the License, by the making, - using, selling, offering for sale, having made, import, or transfer of - either its Contributions or its Contributor Version. - -1.12. “Secondary License” - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. “Source Code Form” - - means the form of the work preferred for making modifications. - -1.14. “You” (or “Your”) - - means an individual or a legal entity exercising rights under this - License. For legal entities, “You” includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, “control” means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or as - part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its Contributions - or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution become - effective for each Contribution on the date the Contributor first distributes - such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under this - License. No additional rights or licenses will be implied from the distribution - or licensing of Covered Software under this License. Notwithstanding Section - 2.1(b) above, no patent license is granted by a Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party’s - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of its - Contributions. - - This License does not grant any rights in the trademarks, service marks, or - logos of any Contributor (except as may be necessary to comply with the - notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this License - (see Section 10.2) or under the terms of a Secondary License (if permitted - under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its Contributions - are its original creation(s) or it has sufficient rights to grant the - rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under applicable - copyright doctrines of fair use, fair dealing, or other equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under the - terms of this License. You must inform recipients that the Source Code Form - of the Covered Software is governed by the terms of this License, and how - they can obtain a copy of this License. You may not attempt to alter or - restrict the recipients’ rights in the Source Code Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this License, - or sublicense it under different terms, provided that the license for - the Executable Form does not attempt to limit or alter the recipients’ - rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for the - Covered Software. If the Larger Work is a combination of Covered Software - with a work governed by one or more Secondary Licenses, and the Covered - Software is not Incompatible With Secondary Licenses, this License permits - You to additionally distribute such Covered Software under the terms of - such Secondary License(s), so that the recipient of the Larger Work may, at - their option, further distribute the Covered Software under the terms of - either this License or such Secondary License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices (including - copyright notices, patent notices, disclaimers of warranty, or limitations - of liability) contained within the Source Code Form of the Covered - Software, except that You may alter any license notices to the extent - required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on behalf - of any Contributor. You must make it absolutely clear that any such - warranty, support, indemnity, or liability obligation is offered by You - alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, judicial - order, or regulation then You must: (a) comply with the terms of this License - to the maximum extent possible; and (b) describe the limitations and the code - they affect. Such description must be placed in a text file included with all - distributions of the Covered Software under this License. Except to the - extent prohibited by statute or regulation, such description must be - sufficiently detailed for a recipient of ordinary skill to be able to - understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing basis, - if such Contributor fails to notify You of the non-compliance by some - reasonable means prior to 60 days after You have come back into compliance. - Moreover, Your grants from a particular Contributor are reinstated on an - ongoing basis if such Contributor notifies You of the non-compliance by - some reasonable means, this is the first time You have received notice of - non-compliance with this License from such Contributor, and You become - compliant prior to 30 days after Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, counter-claims, - and cross-claims) alleging that a Contributor Version directly or - indirectly infringes any patent, then the rights granted to You by any and - all Contributors for the Covered Software under Section 2.1 of this License - shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an “as is” basis, without - warranty of any kind, either expressed, implied, or statutory, including, - without limitation, warranties that the Covered Software is free of defects, - merchantable, fit for a particular purpose or non-infringing. The entire - risk as to the quality and performance of the Covered Software is with You. - Should any Covered Software prove defective in any respect, You (not any - Contributor) assume the cost of any necessary servicing, repair, or - correction. This disclaimer of warranty constitutes an essential part of this - License. No use of any Covered Software is authorized under this License - except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from such - party’s negligence to the extent applicable law prohibits such limitation. - Some jurisdictions do not allow the exclusion or limitation of incidental or - consequential damages, so this exclusion and limitation may not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts of - a jurisdiction where the defendant maintains its principal place of business - and such litigation shall be governed by laws of that jurisdiction, without - reference to its conflict-of-law provisions. Nothing in this Section shall - prevent a party’s ability to bring cross-claims or counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject matter - hereof. If any provision of this License is held to be unenforceable, such - provision shall be reformed only to the extent necessary to make it - enforceable. Any law or regulation which provides that the language of a - contract shall be construed against the drafter shall not be used to construe - this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version of - the License under which You originally received the Covered Software, or - under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a modified - version of this License if you rename the license and remove any - references to the name of the license steward (except to note that such - modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses - If You choose to distribute Source Code Form that is Incompatible With - Secondary Licenses under the terms of this version of the License, the - notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, then -You may include the notice in a location (such as a LICENSE file in a relevant -directory) where a recipient would be likely to look for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - “Incompatible With Secondary Licenses” Notice - - This Source Code Form is “Incompatible - With Secondary Licenses”, as defined by - the Mozilla Public License, v. 2.0. - diff --git a/Godeps/_workspace/src/github.com/hashicorp/errwrap/README.md b/Godeps/_workspace/src/github.com/hashicorp/errwrap/README.md deleted file mode 100644 index 1c95f5978..000000000 --- a/Godeps/_workspace/src/github.com/hashicorp/errwrap/README.md +++ /dev/null @@ -1,89 +0,0 @@ -# errwrap - -`errwrap` is a package for Go that formalizes the pattern of wrapping errors -and checking if an error contains another error. - -There is a common pattern in Go of taking a returned `error` value and -then wrapping it (such as with `fmt.Errorf`) before returning it. The problem -with this pattern is that you completely lose the original `error` structure. - -Arguably the _correct_ approach is that you should make a custom structure -implementing the `error` interface, and have the original error as a field -on that structure, such [as this example](http://golang.org/pkg/os/#PathError). -This is a good approach, but you have to know the entire chain of possible -rewrapping that happens, when you might just care about one. - -`errwrap` formalizes this pattern (it doesn't matter what approach you use -above) by giving a single interface for wrapping errors, checking if a specific -error is wrapped, and extracting that error. - -## Installation and Docs - -Install using `go get github.com/hashicorp/errwrap`. - -Full documentation is available at -http://godoc.org/github.com/hashicorp/errwrap - -## Usage - -#### Basic Usage - -Below is a very basic example of its usage: - -```go -// A function that always returns an error, but wraps it, like a real -// function might. -func tryOpen() error { - _, err := os.Open("/i/dont/exist") - if err != nil { - return errwrap.Wrapf("Doesn't exist: {{err}}", err) - } - - return nil -} - -func main() { - err := tryOpen() - - // We can use the Contains helpers to check if an error contains - // another error. It is safe to do this with a nil error, or with - // an error that doesn't even use the errwrap package. - if errwrap.Contains(err, ErrNotExist) { - // Do something - } - if errwrap.ContainsType(err, new(os.PathError)) { - // Do something - } - - // Or we can use the associated `Get` functions to just extract - // a specific error. This would return nil if that specific error doesn't - // exist. - perr := errwrap.GetType(err, new(os.PathError)) -} -``` - -#### Custom Types - -If you're already making custom types that properly wrap errors, then -you can get all the functionality of `errwraps.Contains` and such by -implementing the `Wrapper` interface with just one function. Example: - -```go -type AppError { - Code ErrorCode - Err error -} - -func (e *AppError) WrappedErrors() []error { - return []error{e.Err} -} -``` - -Now this works: - -```go -err := &AppError{Err: fmt.Errorf("an error")} -if errwrap.ContainsType(err, fmt.Errorf("")) { - // This will work! -} -``` diff --git a/Godeps/_workspace/src/github.com/hashicorp/errwrap/errwrap.go b/Godeps/_workspace/src/github.com/hashicorp/errwrap/errwrap.go deleted file mode 100644 index a733bef18..000000000 --- a/Godeps/_workspace/src/github.com/hashicorp/errwrap/errwrap.go +++ /dev/null @@ -1,169 +0,0 @@ -// Package errwrap implements methods to formalize error wrapping in Go. -// -// All of the top-level functions that take an `error` are built to be able -// to take any error, not just wrapped errors. This allows you to use errwrap -// without having to type-check and type-cast everywhere. -package errwrap - -import ( - "errors" - "reflect" - "strings" -) - -// WalkFunc is the callback called for Walk. -type WalkFunc func(error) - -// Wrapper is an interface that can be implemented by custom types to -// have all the Contains, Get, etc. functions in errwrap work. -// -// When Walk reaches a Wrapper, it will call the callback for every -// wrapped error in addition to the wrapper itself. Since all the top-level -// functions in errwrap use Walk, this means that all those functions work -// with your custom type. -type Wrapper interface { - WrappedErrors() []error -} - -// Wrap defines that outer wraps inner, returning an error type that -// can be cleanly used with the other methods in this package, such as -// Contains, GetAll, etc. -// -// This function won't modify the error message at all (the outer message -// will be used). -func Wrap(outer, inner error) error { - return &wrappedError{ - Outer: outer, - Inner: inner, - } -} - -// Wrapf wraps an error with a formatting message. This is similar to using -// `fmt.Errorf` to wrap an error. If you're using `fmt.Errorf` to wrap -// errors, you should replace it with this. -// -// format is the format of the error message. The string '{{err}}' will -// be replaced with the original error message. -func Wrapf(format string, err error) error { - outerMsg := "" - if err != nil { - outerMsg = err.Error() - } - - outer := errors.New(strings.Replace( - format, "{{err}}", outerMsg, -1)) - - return Wrap(outer, err) -} - -// Contains checks if the given error contains an error with the -// message msg. If err is not a wrapped error, this will always return -// false unless the error itself happens to match this msg. -func Contains(err error, msg string) bool { - return len(GetAll(err, msg)) > 0 -} - -// ContainsType checks if the given error contains an error with -// the same concrete type as v. If err is not a wrapped error, this will -// check the err itself. -func ContainsType(err error, v interface{}) bool { - return len(GetAllType(err, v)) > 0 -} - -// Get is the same as GetAll but returns the deepest matching error. -func Get(err error, msg string) error { - es := GetAll(err, msg) - if len(es) > 0 { - return es[len(es)-1] - } - - return nil -} - -// GetType is the same as GetAllType but returns the deepest matching error. -func GetType(err error, v interface{}) error { - es := GetAllType(err, v) - if len(es) > 0 { - return es[len(es)-1] - } - - return nil -} - -// GetAll gets all the errors that might be wrapped in err with the -// given message. The order of the errors is such that the outermost -// matching error (the most recent wrap) is index zero, and so on. -func GetAll(err error, msg string) []error { - var result []error - - Walk(err, func(err error) { - if err.Error() == msg { - result = append(result, err) - } - }) - - return result -} - -// GetAllType gets all the errors that are the same type as v. -// -// The order of the return value is the same as described in GetAll. -func GetAllType(err error, v interface{}) []error { - var result []error - - var search string - if v != nil { - search = reflect.TypeOf(v).String() - } - Walk(err, func(err error) { - var needle string - if err != nil { - needle = reflect.TypeOf(err).String() - } - - if needle == search { - result = append(result, err) - } - }) - - return result -} - -// Walk walks all the wrapped errors in err and calls the callback. If -// err isn't a wrapped error, this will be called once for err. If err -// is a wrapped error, the callback will be called for both the wrapper -// that implements error as well as the wrapped error itself. -func Walk(err error, cb WalkFunc) { - if err == nil { - return - } - - switch e := err.(type) { - case *wrappedError: - cb(e.Outer) - Walk(e.Inner, cb) - case Wrapper: - cb(err) - - for _, err := range e.WrappedErrors() { - Walk(err, cb) - } - default: - cb(err) - } -} - -// wrappedError is an implementation of error that has both the -// outer and inner errors. -type wrappedError struct { - Outer error - Inner error -} - -func (w *wrappedError) Error() string { - return w.Outer.Error() -} - -func (w *wrappedError) WrappedErrors() []error { - return []error{w.Outer, w.Inner} -} diff --git a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/.travis.yml b/Godeps/_workspace/src/github.com/hashicorp/go-multierror/.travis.yml deleted file mode 100644 index 4b865d194..000000000 --- a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -sudo: false - -language: go - -go: - - 1.6 - -branches: - only: - - master - -script: make test testrace diff --git a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/LICENSE b/Godeps/_workspace/src/github.com/hashicorp/go-multierror/LICENSE deleted file mode 100644 index 82b4de97c..000000000 --- a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/LICENSE +++ /dev/null @@ -1,353 +0,0 @@ -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. “Contributor” - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. “Contributor Version” - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor’s Contribution. - -1.3. “Contribution” - - means Covered Software of a particular Contributor. - -1.4. “Covered Software” - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. “Incompatible With Secondary Licenses” - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of version - 1.1 or earlier of the License, but not also under the terms of a - Secondary License. - -1.6. “Executable Form” - - means any form of the work other than Source Code Form. - -1.7. “Larger Work” - - means a work that combines Covered Software with other material, in a separate - file or files, that is not Covered Software. - -1.8. “License” - - means this document. - -1.9. “Licensable” - - means having the right to grant, to the maximum extent possible, whether at the - time of the initial grant or subsequently, any and all of the rights conveyed by - this License. - -1.10. “Modifications” - - means any of the following: - - a. any file in Source Code Form that results from an addition to, deletion - from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. “Patent Claims” of a Contributor - - means any patent claim(s), including without limitation, method, process, - and apparatus claims, in any patent Licensable by such Contributor that - would be infringed, but for the grant of the License, by the making, - using, selling, offering for sale, having made, import, or transfer of - either its Contributions or its Contributor Version. - -1.12. “Secondary License” - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. “Source Code Form” - - means the form of the work preferred for making modifications. - -1.14. “You” (or “Your”) - - means an individual or a legal entity exercising rights under this - License. For legal entities, “You” includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, “control” means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or as - part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its Contributions - or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution become - effective for each Contribution on the date the Contributor first distributes - such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under this - License. No additional rights or licenses will be implied from the distribution - or licensing of Covered Software under this License. Notwithstanding Section - 2.1(b) above, no patent license is granted by a Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party’s - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of its - Contributions. - - This License does not grant any rights in the trademarks, service marks, or - logos of any Contributor (except as may be necessary to comply with the - notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this License - (see Section 10.2) or under the terms of a Secondary License (if permitted - under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its Contributions - are its original creation(s) or it has sufficient rights to grant the - rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under applicable - copyright doctrines of fair use, fair dealing, or other equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under the - terms of this License. You must inform recipients that the Source Code Form - of the Covered Software is governed by the terms of this License, and how - they can obtain a copy of this License. You may not attempt to alter or - restrict the recipients’ rights in the Source Code Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this License, - or sublicense it under different terms, provided that the license for - the Executable Form does not attempt to limit or alter the recipients’ - rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for the - Covered Software. If the Larger Work is a combination of Covered Software - with a work governed by one or more Secondary Licenses, and the Covered - Software is not Incompatible With Secondary Licenses, this License permits - You to additionally distribute such Covered Software under the terms of - such Secondary License(s), so that the recipient of the Larger Work may, at - their option, further distribute the Covered Software under the terms of - either this License or such Secondary License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices (including - copyright notices, patent notices, disclaimers of warranty, or limitations - of liability) contained within the Source Code Form of the Covered - Software, except that You may alter any license notices to the extent - required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on behalf - of any Contributor. You must make it absolutely clear that any such - warranty, support, indemnity, or liability obligation is offered by You - alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, judicial - order, or regulation then You must: (a) comply with the terms of this License - to the maximum extent possible; and (b) describe the limitations and the code - they affect. Such description must be placed in a text file included with all - distributions of the Covered Software under this License. Except to the - extent prohibited by statute or regulation, such description must be - sufficiently detailed for a recipient of ordinary skill to be able to - understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing basis, - if such Contributor fails to notify You of the non-compliance by some - reasonable means prior to 60 days after You have come back into compliance. - Moreover, Your grants from a particular Contributor are reinstated on an - ongoing basis if such Contributor notifies You of the non-compliance by - some reasonable means, this is the first time You have received notice of - non-compliance with this License from such Contributor, and You become - compliant prior to 30 days after Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, counter-claims, - and cross-claims) alleging that a Contributor Version directly or - indirectly infringes any patent, then the rights granted to You by any and - all Contributors for the Covered Software under Section 2.1 of this License - shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an “as is” basis, without - warranty of any kind, either expressed, implied, or statutory, including, - without limitation, warranties that the Covered Software is free of defects, - merchantable, fit for a particular purpose or non-infringing. The entire - risk as to the quality and performance of the Covered Software is with You. - Should any Covered Software prove defective in any respect, You (not any - Contributor) assume the cost of any necessary servicing, repair, or - correction. This disclaimer of warranty constitutes an essential part of this - License. No use of any Covered Software is authorized under this License - except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from such - party’s negligence to the extent applicable law prohibits such limitation. - Some jurisdictions do not allow the exclusion or limitation of incidental or - consequential damages, so this exclusion and limitation may not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts of - a jurisdiction where the defendant maintains its principal place of business - and such litigation shall be governed by laws of that jurisdiction, without - reference to its conflict-of-law provisions. Nothing in this Section shall - prevent a party’s ability to bring cross-claims or counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject matter - hereof. If any provision of this License is held to be unenforceable, such - provision shall be reformed only to the extent necessary to make it - enforceable. Any law or regulation which provides that the language of a - contract shall be construed against the drafter shall not be used to construe - this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version of - the License under which You originally received the Covered Software, or - under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a modified - version of this License if you rename the license and remove any - references to the name of the license steward (except to note that such - modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses - If You choose to distribute Source Code Form that is Incompatible With - Secondary Licenses under the terms of this version of the License, the - notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, then -You may include the notice in a location (such as a LICENSE file in a relevant -directory) where a recipient would be likely to look for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - “Incompatible With Secondary Licenses” Notice - - This Source Code Form is “Incompatible - With Secondary Licenses”, as defined by - the Mozilla Public License, v. 2.0. diff --git a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/Makefile b/Godeps/_workspace/src/github.com/hashicorp/go-multierror/Makefile deleted file mode 100644 index b97cd6ed0..000000000 --- a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -TEST?=./... - -default: test - -# test runs the test suite and vets the code. -test: generate - @echo "==> Running tests..." - @go list $(TEST) \ - | grep -v "/vendor/" \ - | xargs -n1 go test -timeout=60s -parallel=10 ${TESTARGS} - -# testrace runs the race checker -testrace: generate - @echo "==> Running tests (race)..." - @go list $(TEST) \ - | grep -v "/vendor/" \ - | xargs -n1 go test -timeout=60s -race ${TESTARGS} - -# updatedeps installs all the dependencies needed to run and build. -updatedeps: - @sh -c "'${CURDIR}/scripts/deps.sh' '${NAME}'" - -# generate runs `go generate` to build the dynamically generated source files. -generate: - @echo "==> Generating..." - @find . -type f -name '.DS_Store' -delete - @go list ./... \ - | grep -v "/vendor/" \ - | xargs -n1 go generate - -.PHONY: default test testrace updatedeps generate diff --git a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/README.md b/Godeps/_workspace/src/github.com/hashicorp/go-multierror/README.md deleted file mode 100644 index ead5830f7..000000000 --- a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/README.md +++ /dev/null @@ -1,97 +0,0 @@ -# go-multierror - -[![Build Status](http://img.shields.io/travis/hashicorp/go-multierror.svg?style=flat-square)][travis] -[![Go Documentation](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)][godocs] - -[travis]: https://travis-ci.org/hashicorp/go-multierror -[godocs]: https://godoc.org/github.com/hashicorp/go-multierror - -`go-multierror` is a package for Go that provides a mechanism for -representing a list of `error` values as a single `error`. - -This allows a function in Go to return an `error` that might actually -be a list of errors. If the caller knows this, they can unwrap the -list and access the errors. If the caller doesn't know, the error -formats to a nice human-readable format. - -`go-multierror` implements the -[errwrap](https://github.com/hashicorp/errwrap) interface so that it can -be used with that library, as well. - -## Installation and Docs - -Install using `go get github.com/hashicorp/go-multierror`. - -Full documentation is available at -http://godoc.org/github.com/hashicorp/go-multierror - -## Usage - -go-multierror is easy to use and purposely built to be unobtrusive in -existing Go applications/libraries that may not be aware of it. - -**Building a list of errors** - -The `Append` function is used to create a list of errors. This function -behaves a lot like the Go built-in `append` function: it doesn't matter -if the first argument is nil, a `multierror.Error`, or any other `error`, -the function behaves as you would expect. - -```go -var result error - -if err := step1(); err != nil { - result = multierror.Append(result, err) -} -if err := step2(); err != nil { - result = multierror.Append(result, err) -} - -return result -``` - -**Customizing the formatting of the errors** - -By specifying a custom `ErrorFormat`, you can customize the format -of the `Error() string` function: - -```go -var result *multierror.Error - -// ... accumulate errors here, maybe using Append - -if result != nil { - result.ErrorFormat = func([]error) string { - return "errors!" - } -} -``` - -**Accessing the list of errors** - -`multierror.Error` implements `error` so if the caller doesn't know about -multierror, it will work just fine. But if you're aware a multierror might -be returned, you can use type switches to access the list of errors: - -```go -if err := something(); err != nil { - if merr, ok := err.(*multierror.Error); ok { - // Use merr.Errors - } -} -``` - -**Returning a multierror only if there are errors** - -If you build a `multierror.Error`, you can use the `ErrorOrNil` function -to return an `error` implementation only if there are errors to return: - -```go -var result *multierror.Error - -// ... accumulate errors here - -// Return the `error` only if errors were added to the multierror, otherwise -// return nil since there are no errors. -return result.ErrorOrNil() -``` diff --git a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/append.go b/Godeps/_workspace/src/github.com/hashicorp/go-multierror/append.go deleted file mode 100644 index 775b6e753..000000000 --- a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/append.go +++ /dev/null @@ -1,41 +0,0 @@ -package multierror - -// Append is a helper function that will append more errors -// onto an Error in order to create a larger multi-error. -// -// If err is not a multierror.Error, then it will be turned into -// one. If any of the errs are multierr.Error, they will be flattened -// one level into err. -func Append(err error, errs ...error) *Error { - switch err := err.(type) { - case *Error: - // Typed nils can reach here, so initialize if we are nil - if err == nil { - err = new(Error) - } - - // Go through each error and flatten - for _, e := range errs { - switch e := e.(type) { - case *Error: - if e != nil { - err.Errors = append(err.Errors, e.Errors...) - } - default: - if e != nil { - err.Errors = append(err.Errors, e) - } - } - } - - return err - default: - newErrs := make([]error, 0, len(errs)+1) - if err != nil { - newErrs = append(newErrs, err) - } - newErrs = append(newErrs, errs...) - - return Append(&Error{}, newErrs...) - } -} diff --git a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/flatten.go b/Godeps/_workspace/src/github.com/hashicorp/go-multierror/flatten.go deleted file mode 100644 index aab8e9abe..000000000 --- a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/flatten.go +++ /dev/null @@ -1,26 +0,0 @@ -package multierror - -// Flatten flattens the given error, merging any *Errors together into -// a single *Error. -func Flatten(err error) error { - // If it isn't an *Error, just return the error as-is - if _, ok := err.(*Error); !ok { - return err - } - - // Otherwise, make the result and flatten away! - flatErr := new(Error) - flatten(err, flatErr) - return flatErr -} - -func flatten(err error, flatErr *Error) { - switch err := err.(type) { - case *Error: - for _, e := range err.Errors { - flatten(e, flatErr) - } - default: - flatErr.Errors = append(flatErr.Errors, err) - } -} diff --git a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/format.go b/Godeps/_workspace/src/github.com/hashicorp/go-multierror/format.go deleted file mode 100644 index 6c7a3cc91..000000000 --- a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/format.go +++ /dev/null @@ -1,27 +0,0 @@ -package multierror - -import ( - "fmt" - "strings" -) - -// ErrorFormatFunc is a function callback that is called by Error to -// turn the list of errors into a string. -type ErrorFormatFunc func([]error) string - -// ListFormatFunc is a basic formatter that outputs the number of errors -// that occurred along with a bullet point list of the errors. -func ListFormatFunc(es []error) string { - if len(es) == 1 { - return fmt.Sprintf("1 error occurred:\n\n* %s", es[0]) - } - - points := make([]string, len(es)) - for i, err := range es { - points[i] = fmt.Sprintf("* %s", err) - } - - return fmt.Sprintf( - "%d errors occurred:\n\n%s", - len(es), strings.Join(points, "\n")) -} diff --git a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/multierror.go b/Godeps/_workspace/src/github.com/hashicorp/go-multierror/multierror.go deleted file mode 100644 index 2ea082732..000000000 --- a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/multierror.go +++ /dev/null @@ -1,51 +0,0 @@ -package multierror - -import ( - "fmt" -) - -// Error is an error type to track multiple errors. This is used to -// accumulate errors in cases and return them as a single "error". -type Error struct { - Errors []error - ErrorFormat ErrorFormatFunc -} - -func (e *Error) Error() string { - fn := e.ErrorFormat - if fn == nil { - fn = ListFormatFunc - } - - return fn(e.Errors) -} - -// ErrorOrNil returns an error interface if this Error represents -// a list of errors, or returns nil if the list of errors is empty. This -// function is useful at the end of accumulation to make sure that the value -// returned represents the existence of errors. -func (e *Error) ErrorOrNil() error { - if e == nil { - return nil - } - if len(e.Errors) == 0 { - return nil - } - - return e -} - -func (e *Error) GoString() string { - return fmt.Sprintf("*%#v", *e) -} - -// WrappedErrors returns the list of errors that this Error is wrapping. -// It is an implementatin of the errwrap.Wrapper interface so that -// multierror.Error can be used with that library. -// -// This method is not safe to be called concurrently and is no different -// than accessing the Errors field directly. It is implementd only to -// satisfy the errwrap.Wrapper interface. -func (e *Error) WrappedErrors() []error { - return e.Errors -} diff --git a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/prefix.go b/Godeps/_workspace/src/github.com/hashicorp/go-multierror/prefix.go deleted file mode 100644 index 5c477abe4..000000000 --- a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/prefix.go +++ /dev/null @@ -1,37 +0,0 @@ -package multierror - -import ( - "fmt" - - "github.com/hashicorp/errwrap" -) - -// Prefix is a helper function that will prefix some text -// to the given error. If the error is a multierror.Error, then -// it will be prefixed to each wrapped error. -// -// This is useful to use when appending multiple multierrors -// together in order to give better scoping. -func Prefix(err error, prefix string) error { - if err == nil { - return nil - } - - format := fmt.Sprintf("%s {{err}}", prefix) - switch err := err.(type) { - case *Error: - // Typed nils can reach here, so initialize if we are nil - if err == nil { - err = new(Error) - } - - // Wrap each of the errors - for i, e := range err.Errors { - err.Errors[i] = errwrap.Wrapf(format, e) - } - - return err - default: - return errwrap.Wrapf(format, err) - } -} From 7d409aad7029fa8d2d8dcb14af2bd610f6163f5b Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sat, 14 Jan 2017 06:49:14 -0800 Subject: [PATCH 2/3] godep: Bump tap-go to pick up the Skip method I couldn't figure out how to do this with 'godep update', so I just copied the files over and bumped the hash by hand. Signed-off-by: W. Trevor King --- Godeps/Godeps.json | 2 +- .../src/github.com/mndrix/tap-go/Makefile | 2 +- .../src/github.com/mndrix/tap-go/tap.go | 35 +++++++++++++++---- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 57c568c4a..1f940e341 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -15,7 +15,7 @@ }, { "ImportPath": "github.com/mndrix/tap-go", - "Rev": "67c9553625499b7e7ed4ac4f2d8bf1cb8f5ecf52" + "Rev": "56cca451570bb0366b29f30e1aeb5cf9736a1e18" }, { "ImportPath": "github.com/opencontainers/runtime-spec/specs-go", diff --git a/Godeps/_workspace/src/github.com/mndrix/tap-go/Makefile b/Godeps/_workspace/src/github.com/mndrix/tap-go/Makefile index dda78b2b2..986541d7c 100644 --- a/Godeps/_workspace/src/github.com/mndrix/tap-go/Makefile +++ b/Godeps/_workspace/src/github.com/mndrix/tap-go/Makefile @@ -1,4 +1,4 @@ -TESTS = auto check diagnostic known failing writer +TESTS = auto check diagnostic failing known skip todo writer GOPATH = $(CURDIR)/gopath .PHONY: $(TESTS) diff --git a/Godeps/_workspace/src/github.com/mndrix/tap-go/tap.go b/Godeps/_workspace/src/github.com/mndrix/tap-go/tap.go index 240542636..477fddc3f 100644 --- a/Godeps/_workspace/src/github.com/mndrix/tap-go/tap.go +++ b/Godeps/_workspace/src/github.com/mndrix/tap-go/tap.go @@ -18,7 +18,7 @@ // 1..2 // ok 1 - first test // ok 2 - second test -package tap +package tap // import "github.com/mndrix/tap-go" import ( "fmt" @@ -31,7 +31,10 @@ import "testing/quick" // T is a type to encapsulate test state. Methods on this type generate TAP // output. type T struct { - nextTestNumber int + nextTestNumber *int + + // TODO toggles the TODO directive for Ok, Fail, Pass, and similar. + TODO bool // Writer indicates where TAP output should be sent. The default is os.Stdout. Writer io.Writer @@ -39,8 +42,9 @@ type T struct { // New creates a new Tap value func New() *T { + nextTestNumber := 1 return &T{ - nextTestNumber: 1, + nextTestNumber: &nextTestNumber, } } @@ -74,8 +78,12 @@ func (t *T) Ok(test bool, description string) { ok = "not ok" } - t.printf("%s %d - %s\n", ok, t.nextTestNumber, description) - t.nextTestNumber++ + if t.TODO { + t.printf("%s %d # TODO %s\n", ok, *t.nextTestNumber, description) + } else { + t.printf("%s %d - %s\n", ok, *t.nextTestNumber, description) + } + (*t.nextTestNumber)++ } // Fail indicates that a test has failed. This is typically only used when the @@ -105,7 +113,7 @@ func (t *T) Check(function interface{}, description string) { // Count returns the number of tests completed so far. func (t *T) Count() int { - return t.nextTestNumber - 1 + return *t.nextTestNumber - 1 } // AutoPlan generates a test plan based on the number of tests that were run. @@ -117,6 +125,21 @@ func escapeNewlines(s string) string { return strings.Replace(strings.TrimRight(s, "\n"), "\n", "\n# ", -1) } +// Todo returns copy of the test-state with TODO set. +func (t *T) Todo() *T { + newT := *t + newT.TODO = true + return &newT +} + +// Skip indicates that a test has been skipped. +func (t *T) Skip(count int, description string) { + for i := 0; i < count; i++ { + t.printf("ok %d # SKIP %s\n", *t.nextTestNumber, description) + (*t.nextTestNumber)++ + } +} + // Diagnostic generates a diagnostic from the message, // which may span multiple lines. func (t *T) Diagnostic(message string) { From cf0d0142cad5a0db3a9a1c542f7f9f86a26daf1d Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Wed, 11 Jan 2017 13:06:24 -0800 Subject: [PATCH 3/3] runtimetest: Make TAP output more granular Granular TAP output makes it easier to see what's being tested (and what's going wrong). You could feed this into any TAP harness you like, but I've chosen prove (it seems popular). You need a TAP harness looking for test failures, because runtimetest now returns zero when it successfully runs the tests (regardless of whether the tests all pass). With this commit, runtimetest will exit zero when it can successfully *run the tests* (regardless of whether all the tests pass). A TAP harness like prove should be used to consume the output TAP to decide if validation succeeded or not. To avoid confusing the TAP consumer, all of the non-TAP logging goes to stderr (and not stdout). Signed-off-by: W. Trevor King --- README.md | 22 +-- cmd/runtimetest/main.go | 413 +++++++++++++++++++--------------------- test_runtime.sh | 18 +- 3 files changed, 206 insertions(+), 247 deletions(-) diff --git a/README.md b/README.md index d8d406d96..62fff23c0 100644 --- a/README.md +++ b/README.md @@ -29,25 +29,25 @@ INFO[0000] Bundle validation succeeded. ## Testing OCI runtimes -```sh +You can run [`test_runtime.sh`][test_runtime.sh] with any [TAP consumer][tap-consumer]. +For example, with [prove][]: + +``` $ make $ sudo make install -$ sudo ./test_runtime.sh -r runc ------------------------------------------------------------------------------------ -VALIDATING RUNTIME: runc ------------------------------------------------------------------------------------ -validating container process -validating capabilities -validating hostname -validating rlimits -validating sysctls -Runtime runc passed validation +$ sudo prove ./test_runtime.sh -r /usr/bin/runc +./test_runtime.sh .. ok +All tests successful. +Files=1, Tests=90, 0 wallclock secs ( 0.02 usr 0.00 sys + 0.04 cusr 0.00 csys = 0.06 CPU) +Result: PASS ``` [bundle]: https://github.com/opencontainers/runtime-spec/blob/master/bundle.md [config.json]: https://github.com/opencontainers/runtime-spec/blob/master/config.md +[prove]: http://perldoc.perl.org/prove.html [runC]: https://github.com/opencontainers/runc [runtime-spec]: https://github.com/opencontainers/runtime-spec +[tap-consumer]: https://testanything.org/consumers.html [generate.1]: man/oci-runtime-tool-generate.1.md [validate.1]: man/oci-runtime-tool-validate.1.md diff --git a/cmd/runtimetest/main.go b/cmd/runtimetest/main.go index 371052c3b..d9d302df7 100644 --- a/cmd/runtimetest/main.go +++ b/cmd/runtimetest/main.go @@ -14,7 +14,6 @@ import ( "syscall" "github.com/Sirupsen/logrus" - "github.com/hashicorp/go-multierror" "github.com/mndrix/tap-go" rspec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-tools/cmd/runtimetest/mount" @@ -54,10 +53,7 @@ var ( } ) -type validation struct { - test func(*rspec.Spec) error - description string -} +type validator func(harness *tap.T, config *rspec.Spec) (err error) func loadSpecConfig() (spec *rspec.Spec, err error) { cf, err := os.Open(specConfig) @@ -75,14 +71,17 @@ func loadSpecConfig() (spec *rspec.Spec, err error) { } // should be included by other platform specified process validation -func validateGeneralProcess(spec *rspec.Spec) error { - if spec.Process.Cwd != "" { +func validateGeneralProcess(harness *tap.T, spec *rspec.Spec) error { + if spec.Process.Cwd == "" { + harness.Skip(1, "process.cwd not set") + } else { cwd, err := os.Getwd() if err != nil { return err } + harness.Ok(cwd == spec.Process.Cwd, "has expected working directory") if cwd != spec.Process.Cwd { - return fmt.Errorf("Cwd expected: %v, actual: %v", spec.Process.Cwd, cwd) + harness.Diagnosticf("working directory expected: %v, actual: %v", spec.Process.Cwd, cwd) } } @@ -91,26 +90,28 @@ func validateGeneralProcess(spec *rspec.Spec) error { key := parts[0] expectedValue := parts[1] actualValue := os.Getenv(key) + harness.Ok(expectedValue == actualValue, fmt.Sprintf("has expected environment variable %v", key)) if actualValue != expectedValue { - return fmt.Errorf("Env %v expected: %v, actual: %v", key, expectedValue, actualValue) + harness.Diagnosticf("environment variable %v expected: %v, actual: %v", key, expectedValue, actualValue) } } return nil } -func validateLinuxProcess(spec *rspec.Spec) error { - logrus.Debugf("validating container process") - - validateGeneralProcess(spec) +func validateLinuxProcess(harness *tap.T, spec *rspec.Spec) error { + validateGeneralProcess(harness, spec) uid := os.Getuid() + harness.Ok(uint32(uid) == spec.Process.User.UID, "has expected user ID") if uint32(uid) != spec.Process.User.UID { - return fmt.Errorf("UID expected: %v, actual: %v", spec.Process.User.UID, uid) + harness.Diagnosticf("user ID expected: %v, actual: %v", spec.Process.User.UID, uid) } + gid := os.Getgid() + harness.Ok(uint32(gid) == spec.Process.User.GID, "has expected group ID") if uint32(gid) != spec.Process.User.GID { - return fmt.Errorf("GID expected: %v, actual: %v", spec.Process.User.GID, gid) + harness.Diagnosticf("group ID expected: %v, actual: %v", spec.Process.User.GID, gid) } groups, err := os.Getgroups() @@ -124,9 +125,7 @@ func validateLinuxProcess(spec *rspec.Spec) error { } for _, g := range spec.Process.User.AdditionalGids { - if !groupsMap[int(g)] { - return fmt.Errorf("Groups expected: %v, actual (should be superset): %v", spec.Process.User.AdditionalGids, groups) - } + harness.Ok(groupsMap[int(g)], fmt.Sprintf("has expected additional group ID %v", g)) } cmdlineBytes, err := ioutil.ReadFile("/proc/1/cmdline") @@ -135,12 +134,14 @@ func validateLinuxProcess(spec *rspec.Spec) error { } args := bytes.Split(bytes.Trim(cmdlineBytes, "\x00"), []byte("\x00")) + harness.Ok(len(args) == len(spec.Process.Args), "has expected number of process arguments") if len(args) != len(spec.Process.Args) { - return fmt.Errorf("Process arguments expected: %v, actual: %v", len(spec.Process.Args), len(args)) + harness.Diagnosticf("expected process arguments: %v, actual: %v", spec.Process.Args, args) } for i, a := range args { + harness.Ok(string(a) == spec.Process.Args[i], fmt.Sprintf("has expected process argument %d", i)) if string(a) != spec.Process.Args[i] { - return fmt.Errorf("Process arguments expected: %v, actual: %v", string(a), spec.Process.Args[i]) + harness.Diagnosticf("expected process argument %d: %v, actual: %v", i, spec.Process.Args[i], string(a)) } } @@ -148,19 +149,13 @@ func validateLinuxProcess(spec *rspec.Spec) error { if errno != 0 { return errno } - if spec.Process.NoNewPrivileges && ret != 1 { - return fmt.Errorf("NoNewPrivileges expected: true, actual: false") - } - if !spec.Process.NoNewPrivileges && ret != 0 { - return fmt.Errorf("NoNewPrivileges expected: false, actual: true") - } + noNewPrivileges := ret == 1 + harness.Ok(spec.Process.NoNewPrivileges == noNewPrivileges, "has expected noNewPrivileges") return nil } -func validateCapabilities(spec *rspec.Spec) error { - logrus.Debugf("validating capabilities") - +func validateCapabilities(harness *tap.T, spec *rspec.Spec) error { last := capability.CAP_LAST_CAP // workaround for RHEL6 which has no /proc/sys/kernel/cap_last_cap if last == capability.Cap(63) { @@ -185,31 +180,33 @@ func validateCapabilities(spec *rspec.Spec) error { capKey := fmt.Sprintf("CAP_%s", strings.ToUpper(cap.String())) expectedSet := expectedCaps[capKey] actuallySet := processCaps.Get(capability.EFFECTIVE, cap) - if expectedSet != actuallySet { - if expectedSet { - return fmt.Errorf("Expected Capability %v not set for process", cap.String()) - } - return fmt.Errorf("Unexpected Capability %v set for process", cap.String()) + if expectedSet { + harness.Ok(actuallySet, fmt.Sprintf("expected capability %v set", capKey)) + } else { + harness.Ok(!actuallySet, fmt.Sprintf("unexpected capability %v not set", capKey)) } } return nil } -func validateHostname(spec *rspec.Spec) error { - logrus.Debugf("validating hostname") - hostname, err := os.Hostname() - if err != nil { - return err - } - if spec.Hostname != "" && hostname != spec.Hostname { - return fmt.Errorf("Hostname expected: %v, actual: %v", spec.Hostname, hostname) +func validateHostname(harness *tap.T, spec *rspec.Spec) error { + if spec.Hostname == "" { + harness.Skip(1, "hostname not set") + } else { + hostname, err := os.Hostname() + if err != nil { + return err + } + harness.Ok(hostname == spec.Hostname, "hostname matches expected value") + if hostname != spec.Hostname { + harness.Diagnosticf("hostname expected: %v, actual: %v", spec.Hostname, hostname) + } } return nil } -func validateRlimits(spec *rspec.Spec) error { - logrus.Debugf("validating rlimits") +func validateRlimits(harness *tap.T, spec *rspec.Spec) error { for _, r := range spec.Process.Rlimits { rl, err := strToRlimit(r.Type) if err != nil { @@ -221,18 +218,19 @@ func validateRlimits(spec *rspec.Spec) error { return err } + harness.Ok(rlimit.Cur == r.Soft, fmt.Sprintf("has expected soft %v", r.Type)) if rlimit.Cur != r.Soft { - return fmt.Errorf("%v rlimit soft expected: %v, actual: %v", r.Type, r.Soft, rlimit.Cur) + harness.Diagnosticf("soft %v expected: %v, actual: %v", r.Type, r.Soft, rlimit.Cur) } + harness.Ok(rlimit.Max == r.Hard, fmt.Sprintf("has expected hard %v", r.Type)) if rlimit.Max != r.Hard { - return fmt.Errorf("%v rlimit hard expected: %v, actual: %v", r.Type, r.Hard, rlimit.Max) + harness.Diagnosticf("hard %v expected: %v, actual: %v", r.Type, r.Hard, rlimit.Max) } } return nil } -func validateSysctls(spec *rspec.Spec) error { - logrus.Debugf("validating sysctls") +func validateSysctls(harness *tap.T, spec *rspec.Spec) error { for k, v := range spec.Linux.Sysctl { keyPath := filepath.Join("/proc/sys", strings.Replace(k, ".", "/", -1)) vBytes, err := ioutil.ReadFile(keyPath) @@ -240,40 +238,48 @@ func validateSysctls(spec *rspec.Spec) error { return err } value := strings.TrimSpace(string(bytes.Trim(vBytes, "\x00"))) + harness.Ok(value == v, fmt.Sprintf("has expected sysctl %v", k)) if value != v { - return fmt.Errorf("Sysctl %v value expected: %v, actual: %v", k, v, value) + harness.Diagnosticf("sysctl %v expected: %v, actual: %v", k, v, value) } } return nil } -func testWriteAccess(path string) error { +func testReadOnly(harness *tap.T, path string) error { tmpfile, err := ioutil.TempFile(path, "Test") + harness.Ok(err != nil, fmt.Sprintf("%v is readonly (cannot create sub-file)", path)) if err != nil { return err - } + } else { + tmpfile.Close() + if err != nil { + return err + } - tmpfile.Close() - os.RemoveAll(filepath.Join(path, tmpfile.Name())) + err = os.RemoveAll(filepath.Join(path, tmpfile.Name())) + if err != nil { + return err + } + } return nil } -func validateRootFS(spec *rspec.Spec) error { - logrus.Debugf("validating root filesystem") +func validateRootFS(harness *tap.T, spec *rspec.Spec) error { if spec.Root.Readonly { - err := testWriteAccess("/") - if err == nil { - return fmt.Errorf("Rootfs should be readonly") + err := testReadOnly(harness, "/") + if err != nil { + return err } + } else { + harness.Skip(1, "root.readonly falsy") } return nil } -func validateDefaultFS(spec *rspec.Spec) error { - logrus.Debugf("validating linux default filesystem") - +func validateDefaultFS(harness *tap.T, spec *rspec.Spec) error { mountInfos, err := mount.GetMounts() if err != nil { return err @@ -285,17 +291,19 @@ func validateDefaultFS(spec *rspec.Spec) error { } for fs, fstype := range defaultFS { + harness.Ok(mountsMap[fs] == fstype, fmt.Sprintf("mount %v has expected type", fs)) if !(mountsMap[fs] == fstype) { - return fmt.Errorf("%v must exist and expected type is %v", fs, fstype) + harness.Diagnosticf("mount %v type expected: %v, actual: %v", fs, fstype, mountsMap[fs]) } } return nil } -func validateLinuxDevices(spec *rspec.Spec) error { - logrus.Debugf("validating linux devices") - +func validateLinuxDevices(harness *tap.T, spec *rspec.Spec) error { + if len(spec.Linux.Devices) == 0 { + harness.Skip(1, "linux.devices (no devices configured)") + } for _, device := range spec.Linux.Devices { fi, err := os.Stat(device.Path) if err != nil { @@ -319,32 +327,47 @@ func validateLinuxDevices(spec *rspec.Spec) error { default: devType = "unmatched" } - if devType != device.Type || (devType == "c" && device.Type == "u") { - return fmt.Errorf("device %v expected type is %v, actual is %v", device.Path, device.Type, devType) + harness.Ok(devType == device.Type || (devType == "c" && device.Type == "u"), fmt.Sprintf("device %v has expected type", device.Path)) + if devType != device.Type && !(devType == "c" && device.Type == "u") { + harness.Diagnosticf("device %v type expected: %v, actual: %v", device.Path, device.Type, devType) } if devType != "p" { dev := fStat.Rdev major := (dev >> 8) & 0xfff minor := (dev & 0xff) | ((dev >> 12) & 0xfff00) - if int64(major) != device.Major || int64(minor) != device.Minor { - return fmt.Errorf("%v device number expected is %v:%v, actual is %v:%v", device.Path, device.Major, device.Minor, major, minor) + harness.Ok(int64(major) == device.Major, fmt.Sprintf("device %v has expected major number", device.Path)) + if int64(major) != device.Major { + harness.Diagnosticf("device %v major number expected: %v, actual: %v", device.Path, device.Major, major) + } + harness.Ok(int64(minor) == device.Minor, fmt.Sprintf("device %v has expected minor number", device.Path)) + if int64(minor) != device.Minor { + harness.Diagnosticf("device %v minor number expected: %v, actual: %v", device.Path, device.Minor, minor) } } - if device.FileMode != nil { + if device.FileMode == nil { + harness.Skip(1, fmt.Sprintf("device %v has unconfigured permissions", device.Path)) + } else { expectedPerm := *device.FileMode & os.ModePerm actualPerm := fi.Mode() & os.ModePerm - if expectedPerm != actualPerm { - return fmt.Errorf("%v filemode expected is %v, actual is %v", device.Path, expectedPerm, actualPerm) + harness.Ok(actualPerm == expectedPerm, fmt.Sprintf("device %v has expected permissions", device.Path)) + if actualPerm != expectedPerm { + harness.Diagnosticf("device %v permissions expected: %v, actual: %v", device.Path, expectedPerm, actualPerm) } } - if device.UID != nil { - if *device.UID != fStat.Uid { - return fmt.Errorf("%v uid expected is %v, actual is %v", device.Path, *device.UID, fStat.Uid) + if device.UID == nil { + harness.Skip(1, fmt.Sprintf("device %v has an unconfigured user ID", device.Path)) + } else { + harness.Ok(fStat.Uid == *device.UID, fmt.Sprintf("device %v has expected user ID", device.Path)) + if fStat.Uid != *device.UID { + harness.Diagnosticf("device %v user ID epected: %v, actual: %v", device.Path, *device.UID, fStat.Uid) } } - if device.GID != nil { - if *device.GID != fStat.Gid { - return fmt.Errorf("%v uid expected is %v, actual is %v", device.Path, *device.GID, fStat.Gid) + if device.GID == nil { + harness.Skip(1, fmt.Sprintf("device %v has an unconfigured group ID", device.Path)) + } else { + harness.Ok(fStat.Gid == *device.GID, fmt.Sprintf("device %v has expected group ID", device.Path)) + if fStat.Gid != *device.GID { + harness.Diagnosticf("device %v group ID epected: %v, actual: %v", device.Path, *device.GID, fStat.Gid) } } } @@ -352,102 +375,103 @@ func validateLinuxDevices(spec *rspec.Spec) error { return nil } -func validateDefaultSymlinks(spec *rspec.Spec) error { - logrus.Debugf("validating linux default symbolic links") - +func validateDefaultSymlinks(harness *tap.T, spec *rspec.Spec) error { for symlink, dest := range defaultSymlinks { fi, err := os.Lstat(symlink) + harness.Ok(err == nil, fmt.Sprintf("lstat default symlink %v", symlink)) if err != nil { - return err - } - if fi.Mode()&os.ModeSymlink != os.ModeSymlink { - return fmt.Errorf("%v is not a symbolic link as expected", symlink) - } - realDest, err := os.Readlink(symlink) - if err != nil { - return err - } - if realDest != dest { - return fmt.Errorf("link destation of %v expected is %v, actual is %v", symlink, dest, realDest) + harness.Skip(1, fmt.Sprintf("default symlink %v checks (failed lstat)", symlink)) + } else { + harness.Ok(fi.Mode()&os.ModeSymlink == os.ModeSymlink, fmt.Sprintf("default symlink %v is a symlink", symlink)) + realDest, err := os.Readlink(symlink) + if err != nil { + return err + } + harness.Ok(realDest == dest, fmt.Sprintf("default symlink %v has expected target", symlink)) + if realDest != dest { + harness.Diagnosticf("default symlink %v target expected: %v, actual: %v", symlink, dest, realDest) + } } } return nil } -func validateDefaultDevices(spec *rspec.Spec) error { - logrus.Debugf("validating linux default devices") - +func validateDefaultDevices(harness *tap.T, spec *rspec.Spec) error { if spec.Process.Terminal { defaultDevices = append(defaultDevices, "/dev/console") } for _, device := range defaultDevices { fi, err := os.Stat(device) + harness.Ok(err == nil, fmt.Sprintf("stat default device %v", device)) if err != nil { - if os.IsNotExist(err) { - return fmt.Errorf("device node %v not found", device) - } - return err - } - if fi.Mode()&os.ModeDevice != os.ModeDevice { - return fmt.Errorf("file %v is not a device as expected", device) + harness.Skip(1, fmt.Sprintf("default device %v checks (failed stat)", device)) + } else { + harness.Ok(fi.Mode()&os.ModeDevice == os.ModeDevice, fmt.Sprintf("default device %v is a device", device)) } } return nil } -func validateMaskedPaths(spec *rspec.Spec) error { - logrus.Debugf("validating maskedPaths") +func validateMaskedPaths(harness *tap.T, spec *rspec.Spec) error { for _, maskedPath := range spec.Linux.MaskedPaths { f, err := os.Open(maskedPath) + harness.Ok(err == nil, fmt.Sprintf("open masked path %v", maskedPath)) if err != nil { - return err - } - defer f.Close() - b := make([]byte, 1) - _, err = f.Read(b) - if err != io.EOF { - return fmt.Errorf("%v should not be readable", maskedPath) + harness.Skip(1, fmt.Sprintf("masked path %v checks (failed open)", maskedPath)) + } else { + defer f.Close() + b := make([]byte, 1) + _, err = f.Read(b) + harness.Ok(err == io.EOF, fmt.Sprintf("masked path %v is not readable", maskedPath)) } } return nil } -func validateROPaths(spec *rspec.Spec) error { - logrus.Debugf("validating readonlyPaths") +func validateROPaths(harness *tap.T, spec *rspec.Spec) error { for _, v := range spec.Linux.ReadonlyPaths { - err := testWriteAccess(v) - if err == nil { - return fmt.Errorf("%v should be readonly", v) + err := testReadOnly(harness, v) + if err != nil { + return err } } return nil } -func validateOOMScoreAdj(spec *rspec.Spec) error { - logrus.Debugf("validating oomScoreAdj") - if spec.Linux.Resources != nil && spec.Linux.Resources.OOMScoreAdj != nil { +func validateOOMScoreAdj(harness *tap.T, spec *rspec.Spec) error { + if spec.Linux.Resources == nil || spec.Linux.Resources.OOMScoreAdj == nil { + harness.Skip(1, "linux.resources.oomScoreAdj falsy") + } else { expected := *spec.Linux.Resources.OOMScoreAdj f, err := os.Open("/proc/1/oom_score_adj") + harness.Ok(err == nil, "open /proc/1/oom_score_adj") if err != nil { - return err + harness.Skip(1, "oomScoreAdj checks (failed open)") + return nil } defer f.Close() s := bufio.NewScanner(f) for s.Scan() { - if err := s.Err(); err != nil { - return err + err := s.Err() + harness.Ok(err == nil, "scan /proc/1/oom_score_adj") + if err != nil { + harness.Skip(1, "oomScoreAdj checks (failed scan)") + return nil } text := strings.TrimSpace(s.Text()) actual, err := strconv.Atoi(text) + harness.Ok(err == nil, "convert scanned /proc/1/oom_score_adj value to an integer") if err != nil { - return err + harness.Skip(1, "oomScoreAdj checks (failed integer conversion)") + return nil } + harness.Ok(actual == expected, "has expected oomScoreAdj") if actual != expected { - return fmt.Errorf("oomScoreAdj expected: %v, actual: %v", expected, actual) + harness.Diagnosticf("oomScoreAdj expected: %v, actual: %v", expected, actual) } } } @@ -492,13 +516,20 @@ func getIDMappings(path string) ([]rspec.IDMapping, error) { return idMaps, nil } -func validateIDMappings(mappings []rspec.IDMapping, path string, property string) error { +func validateIDMappings(harness *tap.T, mappings []rspec.IDMapping, path string, property string) error { + if len(mappings) == 0 { + harness.Skip(1, fmt.Sprintf("%s checks (no mappings specified)", property)) + return nil + } idMaps, err := getIDMappings(path) + harness.Ok(err == nil, fmt.Sprintf("get ID mappings from %s", path)) if err != nil { - return fmt.Errorf("can not get items: %v", err) + harness.Skip(1, fmt.Sprintf("%s checks (failed to get mappings)", property)) + return nil } - if len(mappings) != 0 && len(mappings) != len(idMaps) { - return fmt.Errorf("expected %d entries in %v, but acutal is %d", len(mappings), path, len(idMaps)) + harness.Ok(len(idMaps) == len(mappings), fmt.Sprintf("%s has expected number of mappings", path)) + if len(idMaps) != len(mappings) { + harness.Diagnosticf("expected %s mappings: %v, actual: %v", property, mappings, idMaps) } for _, v := range mappings { exist := false @@ -508,24 +539,21 @@ func validateIDMappings(mappings []rspec.IDMapping, path string, property string break } } + harness.Ok(exist, fmt.Sprintf("%s has expected mapping %v", path, v)) if !exist { - return fmt.Errorf("%v is not applied as expected", property) + harness.Diagnosticf("expected %s mappings: %v, actual: %v", property, mappings, idMaps) } } return nil } -func validateUIDMappings(spec *rspec.Spec) error { - logrus.Debugf("validating uidMappings") - - return validateIDMappings(spec.Linux.UIDMappings, "/proc/self/uid_map", "linux.uidMappings") +func validateUIDMappings(harness *tap.T, spec *rspec.Spec) error { + return validateIDMappings(harness, spec.Linux.UIDMappings, "/proc/self/uid_map", "linux.uidMappings") } -func validateGIDMappings(spec *rspec.Spec) error { - logrus.Debugf("validating gidMappings") - - return validateIDMappings(spec.Linux.GIDMappings, "/proc/self/gid_map", "linux.gidMappings") +func validateGIDMappings(harness *tap.T, spec *rspec.Spec) error { + return validateIDMappings(harness, spec.Linux.GIDMappings, "/proc/self/gid_map", "linux.gidMappings") } func mountMatch(specMount rspec.Mount, sysMount rspec.Mount) error { @@ -544,9 +572,7 @@ func mountMatch(specMount rspec.Mount, sysMount rspec.Mount) error { return nil } -func validateMountsExist(spec *rspec.Spec) error { - logrus.Debugf("validating mounts exist") - +func validateMountsExist(harness *tap.T, spec *rspec.Spec) error { mountInfos, err := mount.GetMounts() if err != nil { return err @@ -567,11 +593,12 @@ func validateMountsExist(spec *rspec.Spec) error { for _, sysMount := range mountsMap[filepath.Clean(specMount.Destination)] { if err := mountMatch(specMount, sysMount); err == nil { found = true + harness.Pass(fmt.Sprintf("mount %q found", specMount.Destination)) break } } if !found { - return fmt.Errorf("Expected mount %v does not exist", specMount) + harness.Fail(fmt.Sprintf("expected mount %q found", specMount.Destination)) } } @@ -579,112 +606,54 @@ func validateMountsExist(spec *rspec.Spec) error { } func validate(context *cli.Context) error { - logLevelString := context.String("log-level") - logLevel, err := logrus.ParseLevel(logLevelString) - if err != nil { - return err - } - logrus.SetLevel(logLevel) - spec, err := loadSpecConfig() if err != nil { return err } - defaultValidations := []validation{ - { - test: validateRootFS, - description: "root filesystem", - }, - { - test: validateHostname, - description: "hostname", - }, - { - test: validateMountsExist, - description: "mounts", - }, + defaultValidations := []validator{ + validateRootFS, + validateHostname, + validateMountsExist, } - linuxValidations := []validation{ - { - test: validateCapabilities, - description: "capabilities", - }, - { - test: validateDefaultSymlinks, - description: "default symlinks", - }, - { - test: validateDefaultFS, - description: "default file system", - }, - { - test: validateDefaultDevices, - description: "default devices", - }, - { - test: validateLinuxDevices, - description: "linux devices", - }, - { - test: validateLinuxProcess, - description: "linux process", - }, - { - test: validateMaskedPaths, - description: "masked paths", - }, - { - test: validateOOMScoreAdj, - description: "oom score adj", - }, - { - test: validateROPaths, - description: "read only paths", - }, - { - test: validateRlimits, - description: "rlimits", - }, - { - test: validateSysctls, - description: "sysctls", - }, - { - test: validateUIDMappings, - description: "uid mappings", - }, - { - test: validateGIDMappings, - description: "gid mappings", - }, + linuxValidations := []validator{ + validateCapabilities, + validateDefaultSymlinks, + validateDefaultFS, + validateDefaultDevices, + validateLinuxDevices, + validateLinuxProcess, + validateMaskedPaths, + validateOOMScoreAdj, + validateROPaths, + validateRlimits, + validateSysctls, + validateUIDMappings, + validateGIDMappings, } t := tap.New() t.Header(0) - var validationErrors error for _, v := range defaultValidations { - err := v.test(spec) - t.Ok(err == nil, v.description) + err := v(t, spec) if err != nil { - validationErrors = multierror.Append(validationErrors, err) + return err } } if spec.Platform.OS == "linux" { for _, v := range linuxValidations { - err := v.test(spec) - t.Ok(err == nil, v.description) + err := v(t, spec) if err != nil { - validationErrors = multierror.Append(validationErrors, err) + return err } } } t.AutoPlan() - return validationErrors + return nil } func main() { diff --git a/test_runtime.sh b/test_runtime.sh index c1ed0b152..dc5d8eddf 100755 --- a/test_runtime.sh +++ b/test_runtime.sh @@ -23,12 +23,12 @@ usage() { } error() { - echo $* + echo "$*" >&2 exit 1 } info() { - echo $* + echo "$*" >&2 } while getopts "l:r:kh" opt; do @@ -53,10 +53,6 @@ while getopts "l:r:kh" opt; do esac done -info "-----------------------------------------------------------------------------------" -info " VALIDATING RUNTIME: ${RUNTIME}" -info "-----------------------------------------------------------------------------------" - if ! command -v ${RUNTIME} > /dev/null; then error "Runtime ${RUNTIME} not found in the path" fi @@ -79,11 +75,5 @@ cp runtimetest ${TESTDIR} oci-runtime-tool generate --output "${TESTDIR}/config.json" "${TEST_ARGS[@]}" --rootfs-path '.' -TESTCMD="${RUNTIME} start $(uuidgen)" -pushd $TESTDIR > /dev/null -if ! ${TESTCMD}; then - error "Runtime ${RUNTIME} failed validation" -else - info "Runtime ${RUNTIME} passed validation" -fi -popd > /dev/null +cd ${TESTDIR} +${RUNTIME} start $(uuidgen)