diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 11:40:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 11:40:59 +0000 |
commit | bc4e624732bd51c0dd1e9529cf228e8c23127732 (patch) | |
tree | d95dab8960e9d02d3b95f8653074ad2e54ca207c /dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d | |
parent | Initial commit. (diff) | |
download | icingadb-bc4e624732bd51c0dd1e9529cf228e8c23127732.tar.xz icingadb-bc4e624732bd51c0dd1e9529cf228e8c23127732.zip |
Adding upstream version 1.1.1.upstream/1.1.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d')
345 files changed, 25522 insertions, 0 deletions
diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/.gitattributes b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/.gitattributes new file mode 100644 index 0000000..d2f212e --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/.gitattributes @@ -0,0 +1,10 @@ +# Treat all files in this repo as binary, with no git magic updating +# line endings. Windows users contributing to Go will need to use a +# modern version of git and editors capable of LF line endings. +# +# We'll prevent accidental CRLF line endings from entering the repo +# via the git-review gofmt checks. +# +# See golang.org/issue/9281 + +* -text diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/.gitignore b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/.gitignore new file mode 100644 index 0000000..8339fd6 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/.gitignore @@ -0,0 +1,2 @@ +# Add no patterns to .hgignore except for files generated by the build. +last-change diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/AUTHORS b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/AUTHORS new file mode 100644 index 0000000..15167cd --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at http://tip.golang.org/AUTHORS. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/CONTRIBUTING.md b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/CONTRIBUTING.md new file mode 100644 index 0000000..d0485e8 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/CONTRIBUTING.md @@ -0,0 +1,26 @@ +# Contributing to Go + +Go is an open source project. + +It is the work of hundreds of contributors. We appreciate your help! + +## Filing issues + +When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions: + +1. What version of Go are you using (`go version`)? +2. What operating system and processor architecture are you using? +3. What did you do? +4. What did you expect to see? +5. What did you see instead? + +General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. +The gophers there will answer or ask you to file an issue if you've tripped over a bug. + +## Contributing code + +Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) +before sending patches. + +Unless otherwise noted, the Go source files are distributed under +the BSD-style license found in the LICENSE file. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/CONTRIBUTORS b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/CONTRIBUTORS new file mode 100644 index 0000000..1c4577e --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at http://tip.golang.org/CONTRIBUTORS. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/LICENSE b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/LICENSE new file mode 100644 index 0000000..6a66aea --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/PATENTS b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/PATENTS new file mode 100644 index 0000000..7330990 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google 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, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/README.md b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/README.md new file mode 100644 index 0000000..c5a95b1 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/README.md @@ -0,0 +1,22 @@ +# exp + +[![PkgGoDev](https://pkg.go.dev/badge/golang.org/x/exp)](https://pkg.go.dev/golang.org/x/exp) + +This subrepository holds experimental and deprecated (in the `old` +directory) packages. + +The idea for this subrepository originated as the `pkg/exp` directory +of the main repository, but its presence there made it unavailable +to users of the binary downloads of the Go installation. The +subrepository has therefore been created to make it possible to `go +get` these packages. + +**Warning:** Packages here are experimental and unreliable. Some may +one day be promoted to the main repository or other subrepository, +or they may be modified arbitrarily or even disappear altogether. + +In short, code in this subrepository is not subject to the Go 1 +compatibility promise. (No subrepo is, but the promise is even more +likely to be violated by go.exp than the others.) + +Caveat emptor. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/README.md b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/README.md new file mode 100644 index 0000000..3d9576c --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/README.md @@ -0,0 +1,624 @@ +# Checking Go Package API Compatibility + +The `apidiff` tool in this directory determines whether two versions of the same +package are compatible. The goal is to help the developer make an informed +choice of semantic version after they have changed the code of their module. + +`apidiff` reports two kinds of changes: incompatible ones, which require +incrementing the major part of the semantic version, and compatible ones, which +require a minor version increment. If no API changes are reported but there are +code changes that could affect client code, then the patch version should +be incremented. + +Because `apidiff` ignores package import paths, it may be used to display API +differences between any two packages, not just different versions of the same +package. + +The current version of `apidiff` compares only packages, not modules. + + +## Compatibility Desiderata + +Any tool that checks compatibility can offer only an approximation. No tool can +detect behavioral changes; and even if it could, whether a behavioral change is +a breaking change or not depends on many factors, such as whether it closes a +security hole or fixes a bug. Even a change that causes some code to fail to +compile may not be considered a breaking change by the developers or their +users. It may only affect code marked as experimental or unstable, for +example, or the break may only manifest in unlikely cases. + +For a tool to be useful, its notion of compatibility must be relaxed enough to +allow reasonable changes, like adding a field to a struct, but strict enough to +catch significant breaking changes. A tool that is too lax will miss important +incompatibilities, and users will stop trusting it; one that is too strict may +generate so much noise that users will ignore it. + +To a first approximation, this tool reports a change as incompatible if it could +cause client code to stop compiling. But `apidiff` ignores five ways in which +code may fail to compile after a change. Three of them are mentioned in the +[Go 1 Compatibility Guarantee](https://golang.org/doc/go1compat). + +### Unkeyed Struct Literals + +Code that uses an unkeyed struct literal would fail to compile if a field was +added to the struct, making any such addition an incompatible change. An example: + +``` +// old +type Point struct { X, Y int } + +// new +type Point struct { X, Y, Z int } + +// client +p := pkg.Point{1, 2} // fails in new because there are more fields than expressions +``` +Here and below, we provide three snippets: the code in the old version of the +package, the code in the new version, and the code written in a client of the package, +which refers to it by the name `pkg`. The client code compiles against the old +code but not the new. + +### Embedding and Shadowing + +Adding an exported field to a struct can break code that embeds that struct, +because the newly added field may conflict with an identically named field +at the same struct depth. A selector referring to the latter would become +ambiguous and thus erroneous. + + +``` +// old +type Point struct { X, Y int } + +// new +type Point struct { X, Y, Z int } + +// client +type z struct { Z int } + +var v struct { + pkg.Point + z +} + +_ = v.Z // fails in new +``` +In the new version, the last line fails to compile because there are two embedded `Z` +fields at the same depth, one from `z` and one from `pkg.Point`. + + +### Using an Identical Type Externally + +If it is possible for client code to write a type expression representing the +underlying type of a defined type in a package, then external code can use it in +assignments involving the package type, making any change to that type incompatible. +``` +// old +type Point struct { X, Y int } + +// new +type Point struct { X, Y, Z int } + +// client +var p struct { X, Y int } = pkg.Point{} // fails in new because of Point's extra field +``` +Here, the external code could have used the provided name `Point`, but chose not +to. I'll have more to say about this and related examples later. + +### unsafe.Sizeof and Friends + +Since `unsafe.Sizeof`, `unsafe.Offsetof` and `unsafe.Alignof` are constant +expressions, they can be used in an array type literal: + +``` +// old +type S struct{ X int } + +// new +type S struct{ X, y int } + +// client +var a [unsafe.Sizeof(pkg.S{})]int = [8]int{} // fails in new because S's size is not 8 +``` +Use of these operations could make many changes to a type potentially incompatible. + + +### Type Switches + +A package change that merges two different types (with same underlying type) +into a single new type may break type switches in clients that refer to both +original types: + +``` +// old +type T1 int +type T2 int + +// new +type T1 int +type T2 = T1 + +// client +switch x.(type) { +case T1: +case T2: +} // fails with new because two cases have the same type +``` +This sort of incompatibility is sufficiently esoteric to ignore; the tool allows +merging types. + +## First Attempt at a Definition + +Our first attempt at defining compatibility captures the idea that all the +exported names in the old package must have compatible equivalents in the new +package. + +A new package is compatible with an old one if and only if: +- For every exported package-level name in the old package, the same name is + declared in the new at package level, and +- the names denote the same kind of object (e.g. both are variables), and +- the types of the objects are compatible. + +We will work out the details (and make some corrections) below, but it is clear +already that we will need to determine what makes two types compatible. And +whatever the definition of type compatibility, it's certainly true that if two +types are the same, they are compatible. So we will need to decide what makes an +old and new type the same. We will call this sameness relation _correspondence_. + +## Type Correspondence + +Go already has a definition of when two types are the same: +[type identity](https://golang.org/ref/spec#Type_identity). +But identity isn't adequate for our purpose: it says that two defined +types are identical if they arise from the same definition, but it's unclear +what "same" means when talking about two different packages (or two versions of +a single package). + +The obvious change to the definition of identity is to require that old and new +[defined types](https://golang.org/ref/spec#Type_definitions) +have the same name instead. But that doesn't work either, for two +reasons. First, type aliases can equate two defined types with different names: + +``` +// old +type E int + +// new +type t int +type E = t +``` +Second, an unexported type can be renamed: + +``` +// old +type u1 int +var V u1 + +// new +type u2 int +var V u2 +``` +Here, even though `u1` and `u2` are unexported, their exported fields and +methods are visible to clients, so they are part of the API. But since the name +`u1` is not visible to clients, it can be changed compatibly. We say that `u1` +and `u2` are _exposed_: a type is exposed if a client package can declare variables of that type. + +We will say that an old defined type _corresponds_ to a new one if they have the +same name, or one can be renamed to the other without otherwise changing the +API. In the first example above, old `E` and new `t` correspond. In the second, +old `u1` and new `u2` correspond. + +Two or more old defined types can correspond to a single new type: we consider +"merging" two types into one to be a compatible change. As mentioned above, +code that uses both names in a type switch will fail, but we deliberately ignore +this case. However, a single old type can correspond to only one new type. + +So far, we've explained what correspondence means for defined types. To extend +the definition to all types, we parallel the language's definition of type +identity. So, for instance, an old and a new slice type correspond if their +element types correspond. + +## Definition of Compatibility + +We can now present the definition of compatibility used by `apidiff`. + +### Package Compatibility + +> A new package is compatible with an old one if: +>1. Each exported name in the old package's scope also appears in the new +>package's scope, and the object (constant, variable, function or type) denoted +>by that name in the old package is compatible with the object denoted by the +>name in the new package, and +>2. For every exposed type that implements an exposed interface in the old package, +> its corresponding type should implement the corresponding interface in the new package. +> +>Otherwise the packages are incompatible. + +As an aside, the tool also finds exported names in the new package that are not +exported in the old, and marks them as compatible changes. + +Clause 2 is discussed further in "Whole-Package Compatibility." + +### Object Compatibility + +This section provides compatibility rules for constants, variables, functions +and types. + +#### Constants + +>A new exported constant is compatible with an old one of the same name if and only if +>1. Their types correspond, and +>2. Their values are identical. + +It is tempting to allow changing a typed constant to an untyped one. That may +seem harmless, but it can break code like this: + +``` +// old +const C int64 = 1 + +// new +const C = 1 + +// client +var x = C // old type is int64, new is int +var y int64 = x // fails with new: different types in assignment +``` + +A change to the value of a constant can break compatibility if the value is used +in an array type: + +``` +// old +const C = 1 + +// new +const C = 2 + +// client +var a [C]int = [1]int{} // fails with new because [2]int and [1]int are different types +``` +Changes to constant values are rare, and determining whether they are compatible +or not is better left to the user, so the tool reports them. + +#### Variables + +>A new exported variable is compatible with an old one of the same name if and +>only if their types correspond. + +Correspondence doesn't look past names, so this rule does not prevent adding a +field to `MyStruct` if the package declares `var V MyStruct`. It does, however, mean that + +``` +var V struct { X int } +``` +is incompatible with +``` +var V struct { X, Y int } +``` +I discuss this at length below in the section "Compatibility, Types and Names." + +#### Functions + +>A new exported function or variable is compatible with an old function of the +>same name if and only if their types (signatures) correspond. + +This rule captures the fact that, although many signature changes are compatible +for all call sites, none are compatible for assignment: + +``` +var v func(int) = pkg.F +``` +Here, `F` must be of type `func(int)` and not, for instance, `func(...int)` or `func(interface{})`. + +Note that the rule permits changing a function to a variable. This is a common +practice, usually done for test stubbing, and cannot break any code at compile +time. + +#### Exported Types + +> A new exported type is compatible with an old one if and only if their +> names are the same and their types correspond. + +This rule seems far too strict. But, ignoring aliases for the moment, it demands only +that the old and new _defined_ types correspond. Consider: +``` +// old +type T struct { X int } + +// new +type T struct { X, Y int } +``` +The addition of `Y` is a compatible change, because this rule does not require +that the struct literals have to correspond, only that the defined types +denoted by `T` must correspond. (Remember that correspondence stops at type +names.) + +If one type is an alias that refers to the corresponding defined type, the +situation is the same: + +``` +// old +type T struct { X int } + +// new +type u struct { X, Y int } +type T = u +``` +Here, the only requirement is that old `T` corresponds to new `u`, not that the +struct types correspond. (We can't tell from this snippet that the old `T` and +the new `u` do correspond; that depends on whether `u` replaces `T` throughout +the API.) + +However, the following change is incompatible, because the names do not +denote corresponding types: + +``` +// old +type T = struct { X int } + +// new +type T = struct { X, Y int } +``` +### Type Literal Compatibility + +Only five kinds of types can differ compatibly: defined types, structs, +interfaces, channels and numeric types. We only consider the compatibility of +the last four when they are the underlying type of a defined type. See +"Compatibility, Types and Names" for a rationale. + +We justify the compatibility rules by enumerating all the ways a type +can be used, and by showing that the allowed changes cannot break any code that +uses values of the type in those ways. + +Values of all types can be used in assignments (including argument passing and +function return), but we do not require that old and new types are assignment +compatible. That is because we assume that the old and new packages are never +used together: any given binary will link in either the old package or the new. +So in describing how a type can be used in the sections below, we omit +assignment. + +Any type can also be used in a type assertion or conversion. The changes we allow +below may affect the run-time behavior of these operations, but they cannot affect +whether they compile. The only such breaking change would be to change +the type `T` in an assertion `x.T` so that it no longer implements the interface +type of `x`; but the rules for interfaces below disallow that. + +> A new type is compatible with an old one if and only if they correspond, or +> one of the cases below applies. + +#### Defined Types + +Other than assignment, the only ways to use a defined type are to access its +methods, or to make use of the properties of its underlying type. Rule 2 below +covers the latter, and rules 3 and 4 cover the former. + +> A new defined type is compatible with an old one if and only if all of the +> following hold: +>1. They correspond. +>2. Their underlying types are compatible. +>3. The new exported value method set is a superset of the old. +>4. The new exported pointer method set is a superset of the old. + +An exported method set is a method set with all unexported methods removed. +When comparing methods of a method set, we require identical names and +corresponding signatures. + +Removing an exported method is clearly a breaking change. But removing an +unexported one (or changing its signature) can be breaking as well, if it +results in the type no longer implementing an interface. See "Whole-Package +Compatibility," below. + +#### Channels + +> A new channel type is compatible with an old one if +> 1. The element types correspond, and +> 2. Either the directions are the same, or the new type has no direction. + +Other than assignment, the only ways to use values of a channel type are to send +and receive on them, to close them, and to use them as map keys. Changes to a +channel type cannot cause code that closes a channel or uses it as a map key to +fail to compile, so we need not consider those operations. + +Rule 1 ensures that any operations on the values sent or received will compile. +Rule 2 captures the fact that any program that compiles with a directed channel +must use either only sends, or only receives, so allowing the other operation +by removing the channel direction cannot break any code. + + +#### Interfaces + +> A new interface is compatible with an old one if and only if: +> 1. The old interface does not have an unexported method, and it corresponds +> to the new interfaces (i.e. they have the same method set), or +> 2. The old interface has an unexported method and the new exported method set is a +> superset of the old. + +Other than assignment, the only ways to use an interface are to implement it, +embed it, or call one of its methods. (Interface values can also be used as map +keys, but that cannot cause a compile-time error.) + +Certainly, removing an exported method from an interface could break a client +call, so neither rule allows it. + +Rule 1 also disallows adding a method to an interface without an existing unexported +method. Such an interface can be implemented in client code. If adding a method +were allowed, a type that implements the old interface could fail to implement +the new one: + +``` +type I interface { M1() } // old +type I interface { M1(); M2() } // new + +// client +type t struct{} +func (t) M1() {} +var i pkg.I = t{} // fails with new, because t lacks M2 +``` + +Rule 2 is based on the observation that if an interface has an unexported +method, the only way a client can implement it is to embed it. +Adding a method is compatible in this case, because the embedding struct will +continue to implement the interface. Adding a method also cannot break any call +sites, since no program that compiles could have any such call sites. + +#### Structs + +> A new struct is compatible with an old one if all of the following hold: +> 1. The new set of top-level exported fields is a superset of the old. +> 2. The new set of _selectable_ exported fields is a superset of the old. +> 3. If the old struct is comparable, so is the new one. + +The set of selectable exported fields is the set of exported fields `F` +such that `x.F` is a valid selector expression for a value `x` of the struct +type. `F` may be at the top level of the struct, or it may be a field of an +embedded struct. + +Two fields are the same if they have the same name and corresponding types. + +Other than assignment, there are only four ways to use a struct: write a struct +literal, select a field, use a value of the struct as a map key, or compare two +values for equality. The first clause ensures that struct literals compile; the +second, that selections compile; and the third, that equality expressions and +map index expressions compile. + +#### Numeric Types + +> A new numeric type is compatible with an old one if and only if they are +> both unsigned integers, both signed integers, both floats or both complex +> types, and the new one is at least as large as the old on both 32-bit and +> 64-bit architectures. + +Other than in assignments, numeric types appear in arithmetic and comparison +expressions. Since all arithmetic operations but shifts (see below) require that +operand types be identical, and by assumption the old and new types underly +defined types (see "Compatibility, Types and Names," below), there is no way for +client code to write an arithmetic expression that compiles with operands of the +old type but not the new. + +Numeric types can also appear in type switches and type assertions. Again, since +the old and new types underly defined types, type switches and type assertions +that compiled using the old defined type will continue to compile with the new +defined type. + +Going from an unsigned to a signed integer type is an incompatible change for +the sole reason that only an unsigned type can appear as the right operand of a +shift. If this rule is relaxed, then changes from an unsigned type to a larger +signed type would be compatible. See [this +issue](https://github.com/golang/go/issues/19113). + +Only integer types can be used in bitwise and shift operations, and for indexing +slices and arrays. That is why switching from an integer to a floating-point +type--even one that can represent all values of the integer type--is an +incompatible change. + + +Conversions from floating-point to complex types or vice versa are not permitted +(the predeclared functions real, imag, and complex must be used instead). To +prevent valid floating-point or complex conversions from becoming invalid, +changing a floating-point type to a complex type or vice versa is considered an +incompatible change. + +Although conversions between any two integer types are valid, assigning a +constant value to a variable of integer type that is too small to represent the +constant is not permitted. That is why the only compatible changes are to +a new type whose values are a superset of the old. The requirement that the new +set of values must include the old on both 32-bit and 64-bit machines allows +conversions from `int32` to `int` and from `int` to `int64`, but not the other +direction; and similarly for `uint`. + +Changing a type to or from `uintptr` is considered an incompatible change. Since +its size is not specified, there is no way to know whether the new type's values +are a superset of the old type's. + +## Whole-Package Compatibility + +Some changes that are compatible for a single type are not compatible when the +package is considered as a whole. For example, if you remove an unexported +method on a defined type, it may no longer implement an interface of the +package. This can break client code: + +``` +// old +type T int +func (T) m() {} +type I interface { m() } + +// new +type T int // no method m anymore + +// client +var i pkg.I = pkg.T{} // fails with new because T lacks m +``` + +Similarly, adding a method to an interface can cause defined types +in the package to stop implementing it. + +The second clause in the definition for package compatibility handles these +cases. To repeat: +> 2. For every exposed type that implements an exposed interface in the old package, +> its corresponding type should implement the corresponding interface in the new package. +Recall that a type is exposed if it is part of the package's API, even if it is +unexported. + +Other incompatibilities that involve more than one type in the package can arise +whenever two types with identical underlying types exist in the old or new +package. Here, a change "splits" an identical underlying type into two, breaking +conversions: + +``` +// old +type B struct { X int } +type C struct { X int } + +// new +type B struct { X int } +type C struct { X, Y int } + +// client +var b B +_ = C(b) // fails with new: cannot convert B to C +``` +Finally, changes that are compatible for the package in which they occur can +break downstream packages. That can happen even if they involve unexported +methods, thanks to embedding. + +The definitions given here don't account for these sorts of problems. + + +## Compatibility, Types and Names + +The above definitions state that the only types that can differ compatibly are +defined types and the types that underly them. Changes to other type literals +are considered incompatible. For instance, it is considered an incompatible +change to add a field to the struct in this variable declaration: + +``` +var V struct { X int } +``` +or this alias definition: +``` +type T = struct { X int } +``` + +We make this choice to keep the definition of compatibility (relatively) simple. +A more precise definition could, for instance, distinguish between + +``` +func F(struct { X int }) +``` +where any changes to the struct are incompatible, and + +``` +func F(struct { X, u int }) +``` +where adding a field is compatible (since clients cannot write the signature, +and thus cannot assign `F` to a variable of the signature type). The definition +should then also allow other function signature changes that only require +call-site compatibility, like + +``` +func F(struct { X, u int }, ...int) +``` +The result would be a much more complex definition with little benefit, since +the examples in this section rarely arise in practice. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/apidiff.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/apidiff.go new file mode 100644 index 0000000..76669d8 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/apidiff.go @@ -0,0 +1,220 @@ +// TODO: test swap corresponding types (e.g. u1 <-> u2 and u2 <-> u1) +// TODO: test exported alias refers to something in another package -- does correspondence work then? +// TODO: CODE COVERAGE +// TODO: note that we may miss correspondences because we bail early when we compare a signature (e.g. when lengths differ; we could do up to the shorter) +// TODO: if you add an unexported method to an exposed interface, you have to check that +// every exposed type that previously implemented the interface still does. Otherwise +// an external assignment of the exposed type to the interface type could fail. +// TODO: check constant values: large values aren't representable by some types. +// TODO: Document all the incompatibilities we don't check for. + +package apidiff + +import ( + "fmt" + "go/constant" + "go/token" + "go/types" +) + +// Changes reports on the differences between the APIs of the old and new packages. +// It classifies each difference as either compatible or incompatible (breaking.) For +// a detailed discussion of what constitutes an incompatible change, see the package +// documentation. +func Changes(old, new *types.Package) Report { + d := newDiffer(old, new) + d.checkPackage() + r := Report{} + for _, m := range d.incompatibles.collect() { + r.Changes = append(r.Changes, Change{Message: m, Compatible: false}) + } + for _, m := range d.compatibles.collect() { + r.Changes = append(r.Changes, Change{Message: m, Compatible: true}) + } + return r +} + +type differ struct { + old, new *types.Package + // Correspondences between named types. + // Even though it is the named types (*types.Named) that correspond, we use + // *types.TypeName as a map key because they are canonical. + // The values can be either named types or basic types. + correspondMap map[*types.TypeName]types.Type + + // Messages. + incompatibles messageSet + compatibles messageSet +} + +func newDiffer(old, new *types.Package) *differ { + return &differ{ + old: old, + new: new, + correspondMap: map[*types.TypeName]types.Type{}, + incompatibles: messageSet{}, + compatibles: messageSet{}, + } +} + +func (d *differ) incompatible(obj types.Object, part, format string, args ...interface{}) { + addMessage(d.incompatibles, obj, part, format, args) +} + +func (d *differ) compatible(obj types.Object, part, format string, args ...interface{}) { + addMessage(d.compatibles, obj, part, format, args) +} + +func addMessage(ms messageSet, obj types.Object, part, format string, args []interface{}) { + ms.add(obj, part, fmt.Sprintf(format, args...)) +} + +func (d *differ) checkPackage() { + // Old changes. + for _, name := range d.old.Scope().Names() { + oldobj := d.old.Scope().Lookup(name) + if !oldobj.Exported() { + continue + } + newobj := d.new.Scope().Lookup(name) + if newobj == nil { + d.incompatible(oldobj, "", "removed") + continue + } + d.checkObjects(oldobj, newobj) + } + // New additions. + for _, name := range d.new.Scope().Names() { + newobj := d.new.Scope().Lookup(name) + if newobj.Exported() && d.old.Scope().Lookup(name) == nil { + d.compatible(newobj, "", "added") + } + } + + // Whole-package satisfaction. + // For every old exposed interface oIface and its corresponding new interface nIface... + for otn1, nt1 := range d.correspondMap { + oIface, ok := otn1.Type().Underlying().(*types.Interface) + if !ok { + continue + } + nIface, ok := nt1.Underlying().(*types.Interface) + if !ok { + // If nt1 isn't an interface but otn1 is, then that's an incompatibility that + // we've already noticed, so there's no need to do anything here. + continue + } + // For every old type that implements oIface, its corresponding new type must implement + // nIface. + for otn2, nt2 := range d.correspondMap { + if otn1 == otn2 { + continue + } + if types.Implements(otn2.Type(), oIface) && !types.Implements(nt2, nIface) { + d.incompatible(otn2, "", "no longer implements %s", objectString(otn1)) + } + } + } +} + +func (d *differ) checkObjects(old, new types.Object) { + switch old := old.(type) { + case *types.Const: + if new, ok := new.(*types.Const); ok { + d.constChanges(old, new) + return + } + case *types.Var: + if new, ok := new.(*types.Var); ok { + d.checkCorrespondence(old, "", old.Type(), new.Type()) + return + } + case *types.Func: + switch new := new.(type) { + case *types.Func: + d.checkCorrespondence(old, "", old.Type(), new.Type()) + return + case *types.Var: + d.compatible(old, "", "changed from func to var") + d.checkCorrespondence(old, "", old.Type(), new.Type()) + return + + } + case *types.TypeName: + if new, ok := new.(*types.TypeName); ok { + d.checkCorrespondence(old, "", old.Type(), new.Type()) + return + } + default: + panic("unexpected obj type") + } + // Here if kind of type changed. + d.incompatible(old, "", "changed from %s to %s", + objectKindString(old), objectKindString(new)) +} + +// Compare two constants. +func (d *differ) constChanges(old, new *types.Const) { + ot := old.Type() + nt := new.Type() + // Check for change of type. + if !d.correspond(ot, nt) { + d.typeChanged(old, "", ot, nt) + return + } + // Check for change of value. + // We know the types are the same, so constant.Compare shouldn't panic. + if !constant.Compare(old.Val(), token.EQL, new.Val()) { + d.incompatible(old, "", "value changed from %s to %s", old.Val(), new.Val()) + } +} + +func objectKindString(obj types.Object) string { + switch obj.(type) { + case *types.Const: + return "const" + case *types.Var: + return "var" + case *types.Func: + return "func" + case *types.TypeName: + return "type" + default: + return "???" + } +} + +func (d *differ) checkCorrespondence(obj types.Object, part string, old, new types.Type) { + if !d.correspond(old, new) { + d.typeChanged(obj, part, old, new) + } +} + +func (d *differ) typeChanged(obj types.Object, part string, old, new types.Type) { + old = removeNamesFromSignature(old) + new = removeNamesFromSignature(new) + olds := types.TypeString(old, types.RelativeTo(d.old)) + news := types.TypeString(new, types.RelativeTo(d.new)) + d.incompatible(obj, part, "changed from %s to %s", olds, news) +} + +// go/types always includes the argument and result names when formatting a signature. +// Since these can change without affecting compatibility, we don't want users to +// be distracted by them, so we remove them. +func removeNamesFromSignature(t types.Type) types.Type { + sig, ok := t.(*types.Signature) + if !ok { + return t + } + + dename := func(p *types.Tuple) *types.Tuple { + var vars []*types.Var + for i := 0; i < p.Len(); i++ { + v := p.At(i) + vars = append(vars, types.NewVar(v.Pos(), v.Pkg(), "", v.Type())) + } + return types.NewTuple(vars...) + } + + return types.NewSignature(sig.Recv(), dename(sig.Params()), dename(sig.Results()), sig.Variadic()) +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/apidiff_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/apidiff_test.go new file mode 100644 index 0000000..9d55e14 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/apidiff_test.go @@ -0,0 +1,238 @@ +package apidiff + +import ( + "bufio" + "fmt" + "go/types" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "runtime" + "sort" + "strings" + "testing" + + "github.com/google/go-cmp/cmp" + "golang.org/x/tools/go/packages" +) + +func TestChanges(t *testing.T) { + dir, err := ioutil.TempDir("", "apidiff_test") + if err != nil { + t.Fatal(err) + } + dir = filepath.Join(dir, "go") + wanti, wantc := splitIntoPackages(t, dir) + defer os.RemoveAll(dir) + sort.Strings(wanti) + sort.Strings(wantc) + + oldpkg, err := load(t, "apidiff/old", dir) + if err != nil { + t.Fatal(err) + } + newpkg, err := load(t, "apidiff/new", dir) + if err != nil { + t.Fatal(err) + } + + report := Changes(oldpkg.Types, newpkg.Types) + + got := report.messages(false) + if diff := cmp.Diff(wanti, got); diff != "" { + t.Errorf("incompatibles: mismatch (-want, +got)\n%s", diff) + } + got = report.messages(true) + if diff := cmp.Diff(wantc, got); diff != "" { + t.Errorf("compatibles: mismatch (-want, +got)\n%s", diff) + } +} + +func splitIntoPackages(t *testing.T, dir string) (incompatibles, compatibles []string) { + // Read the input file line by line. + // Write a line into the old or new package, + // dependent on comments. + // Also collect expected messages. + f, err := os.Open("testdata/tests.go") + if err != nil { + t.Fatal(err) + } + defer f.Close() + + if err := os.MkdirAll(filepath.Join(dir, "src", "apidiff"), 0700); err != nil { + t.Fatal(err) + } + if err := ioutil.WriteFile(filepath.Join(dir, "src", "apidiff", "go.mod"), []byte("module apidiff\n"), 0666); err != nil { + t.Fatal(err) + } + + oldd := filepath.Join(dir, "src/apidiff/old") + newd := filepath.Join(dir, "src/apidiff/new") + if err := os.MkdirAll(oldd, 0700); err != nil { + t.Fatal(err) + } + if err := os.Mkdir(newd, 0700); err != nil && !os.IsExist(err) { + t.Fatal(err) + } + + oldf, err := os.Create(filepath.Join(oldd, "old.go")) + if err != nil { + t.Fatal(err) + } + newf, err := os.Create(filepath.Join(newd, "new.go")) + if err != nil { + t.Fatal(err) + } + + wl := func(f *os.File, line string) { + if _, err := fmt.Fprintln(f, line); err != nil { + t.Fatal(err) + } + } + writeBoth := func(line string) { wl(oldf, line); wl(newf, line) } + writeln := writeBoth + s := bufio.NewScanner(f) + for s.Scan() { + line := s.Text() + tl := strings.TrimSpace(line) + switch { + case tl == "// old": + writeln = func(line string) { wl(oldf, line) } + case tl == "// new": + writeln = func(line string) { wl(newf, line) } + case tl == "// both": + writeln = writeBoth + case strings.HasPrefix(tl, "// i "): + incompatibles = append(incompatibles, strings.TrimSpace(tl[4:])) + case strings.HasPrefix(tl, "// c "): + compatibles = append(compatibles, strings.TrimSpace(tl[4:])) + default: + writeln(line) + } + } + if s.Err() != nil { + t.Fatal(s.Err()) + } + return +} + +func load(t *testing.T, importPath, goPath string) (*packages.Package, error) { + needsGoPackages(t) + + cfg := &packages.Config{ + Mode: packages.LoadTypes, + } + if goPath != "" { + cfg.Env = append(os.Environ(), "GOPATH="+goPath) + cfg.Dir = filepath.Join(goPath, "src", filepath.FromSlash(importPath)) + } + pkgs, err := packages.Load(cfg, importPath) + if err != nil { + return nil, err + } + if len(pkgs[0].Errors) > 0 { + return nil, pkgs[0].Errors[0] + } + return pkgs[0], nil +} + +func TestExportedFields(t *testing.T) { + pkg, err := load(t, "golang.org/x/exp/apidiff/testdata/exported_fields", "") + if err != nil { + t.Fatal(err) + } + typeof := func(name string) types.Type { + return pkg.Types.Scope().Lookup(name).Type() + } + + s := typeof("S") + su := s.(*types.Named).Underlying().(*types.Struct) + + ef := exportedSelectableFields(su) + wants := []struct { + name string + typ types.Type + }{ + {"A1", typeof("A1")}, + {"D", types.Typ[types.Bool]}, + {"E", types.Typ[types.Int]}, + {"F", typeof("F")}, + {"S", types.NewPointer(s)}, + } + + if got, want := len(ef), len(wants); got != want { + t.Errorf("got %d fields, want %d\n%+v", got, want, ef) + } + for _, w := range wants { + if got := ef[w.name]; got != nil && !types.Identical(got.Type(), w.typ) { + t.Errorf("%s: got %v, want %v", w.name, got.Type(), w.typ) + } + } +} + +// needsGoPackages skips t if the go/packages driver (or 'go' tool) implied by +// the current process environment is not present in the path. +// +// Copied and adapted from golang.org/x/tools/internal/testenv. +func needsGoPackages(t *testing.T) { + t.Helper() + + tool := os.Getenv("GOPACKAGESDRIVER") + switch tool { + case "off": + // "off" forces go/packages to use the go command. + tool = "go" + case "": + if _, err := exec.LookPath("gopackagesdriver"); err == nil { + tool = "gopackagesdriver" + } else { + tool = "go" + } + } + + needsTool(t, tool) +} + +// needsTool skips t if the named tool is not present in the path. +// +// Copied and adapted from golang.org/x/tools/internal/testenv. +func needsTool(t *testing.T, tool string) { + _, err := exec.LookPath(tool) + if err == nil { + return + } + + t.Helper() + if allowMissingTool(tool) { + t.Skipf("skipping because %s tool not available: %v", tool, err) + } else { + t.Fatalf("%s tool not available: %v", tool, err) + } +} + +func allowMissingTool(tool string) bool { + if runtime.GOOS == "android" { + // Android builds generally run tests on a separate machine from the build, + // so don't expect any external tools to be available. + return true + } + + if tool == "go" && os.Getenv("GO_BUILDER_NAME") == "illumos-amd64-joyent" { + // Work around a misconfigured builder (see https://golang.org/issue/33950). + return true + } + + // If a developer is actively working on this test, we expect them to have all + // of its dependencies installed. However, if it's just a dependency of some + // other module (for example, being run via 'go test all'), we should be more + // tolerant of unusual environments. + return !packageMainIsDevel() +} + +// packageMainIsDevel reports whether the module containing package main +// is a development version (if module information is available). +// +// Builds in GOPATH mode and builds that lack module information are assumed to +// be development versions. +var packageMainIsDevel = func() bool { return true } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/compatibility.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/compatibility.go new file mode 100644 index 0000000..44238fb --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/compatibility.go @@ -0,0 +1,364 @@ +package apidiff + +import ( + "fmt" + "go/types" + "reflect" +) + +func (d *differ) checkCompatible(otn *types.TypeName, old, new types.Type) { + switch old := old.(type) { + case *types.Interface: + if new, ok := new.(*types.Interface); ok { + d.checkCompatibleInterface(otn, old, new) + return + } + + case *types.Struct: + if new, ok := new.(*types.Struct); ok { + d.checkCompatibleStruct(otn, old, new) + return + } + + case *types.Chan: + if new, ok := new.(*types.Chan); ok { + d.checkCompatibleChan(otn, old, new) + return + } + + case *types.Basic: + if new, ok := new.(*types.Basic); ok { + d.checkCompatibleBasic(otn, old, new) + return + } + + case *types.Named: + panic("unreachable") + + default: + d.checkCorrespondence(otn, "", old, new) + return + + } + // Here if old and new are different kinds of types. + d.typeChanged(otn, "", old, new) +} + +func (d *differ) checkCompatibleChan(otn *types.TypeName, old, new *types.Chan) { + d.checkCorrespondence(otn, ", element type", old.Elem(), new.Elem()) + if old.Dir() != new.Dir() { + if new.Dir() == types.SendRecv { + d.compatible(otn, "", "removed direction") + } else { + d.incompatible(otn, "", "changed direction") + } + } +} + +func (d *differ) checkCompatibleBasic(otn *types.TypeName, old, new *types.Basic) { + // Certain changes to numeric types are compatible. Approximately, the info must + // be the same, and the new values must be a superset of the old. + if old.Kind() == new.Kind() { + // old and new are identical + return + } + if compatibleBasics[[2]types.BasicKind{old.Kind(), new.Kind()}] { + d.compatible(otn, "", "changed from %s to %s", old, new) + } else { + d.typeChanged(otn, "", old, new) + } +} + +// All pairs (old, new) of compatible basic types. +var compatibleBasics = map[[2]types.BasicKind]bool{ + {types.Uint8, types.Uint16}: true, + {types.Uint8, types.Uint32}: true, + {types.Uint8, types.Uint}: true, + {types.Uint8, types.Uint64}: true, + {types.Uint16, types.Uint32}: true, + {types.Uint16, types.Uint}: true, + {types.Uint16, types.Uint64}: true, + {types.Uint32, types.Uint}: true, + {types.Uint32, types.Uint64}: true, + {types.Uint, types.Uint64}: true, + {types.Int8, types.Int16}: true, + {types.Int8, types.Int32}: true, + {types.Int8, types.Int}: true, + {types.Int8, types.Int64}: true, + {types.Int16, types.Int32}: true, + {types.Int16, types.Int}: true, + {types.Int16, types.Int64}: true, + {types.Int32, types.Int}: true, + {types.Int32, types.Int64}: true, + {types.Int, types.Int64}: true, + {types.Float32, types.Float64}: true, + {types.Complex64, types.Complex128}: true, +} + +// Interface compatibility: +// If the old interface has an unexported method, the new interface is compatible +// if its exported method set is a superset of the old. (Users could not implement, +// only embed.) +// +// If the old interface did not have an unexported method, the new interface is +// compatible if its exported method set is the same as the old, and it has no +// unexported methods. (Adding an unexported method makes the interface +// unimplementable outside the package.) +// +// TODO: must also check that if any methods were added or removed, every exposed +// type in the package that implemented the interface in old still implements it in +// new. Otherwise external assignments could fail. +func (d *differ) checkCompatibleInterface(otn *types.TypeName, old, new *types.Interface) { + // Method sets are checked in checkCompatibleDefined. + + // Does the old interface have an unexported method? + if unexportedMethod(old) != nil { + d.checkMethodSet(otn, old, new, additionsCompatible) + } else { + // Perform an equivalence check, but with more information. + d.checkMethodSet(otn, old, new, additionsIncompatible) + if u := unexportedMethod(new); u != nil { + d.incompatible(otn, u.Name(), "added unexported method") + } + } +} + +// Return an unexported method from the method set of t, or nil if there are none. +func unexportedMethod(t *types.Interface) *types.Func { + for i := 0; i < t.NumMethods(); i++ { + if m := t.Method(i); !m.Exported() { + return m + } + } + return nil +} + +// We need to check three things for structs: +// +// 1. The set of exported fields must be compatible. This ensures that keyed struct +// literals continue to compile. (There is no compatibility guarantee for unkeyed +// struct literals.) +// +// 2. The set of exported *selectable* fields must be compatible. This includes the exported +// fields of all embedded structs. This ensures that selections continue to compile. +// +// 3. If the old struct is comparable, so must the new one be. This ensures that equality +// expressions and uses of struct values as map keys continue to compile. +// +// An unexported embedded struct can't appear in a struct literal outside the +// package, so it doesn't have to be present, or have the same name, in the new +// struct. +// +// Field tags are ignored: they have no compile-time implications. +func (d *differ) checkCompatibleStruct(obj types.Object, old, new *types.Struct) { + d.checkCompatibleObjectSets(obj, exportedFields(old), exportedFields(new)) + d.checkCompatibleObjectSets(obj, exportedSelectableFields(old), exportedSelectableFields(new)) + // Removing comparability from a struct is an incompatible change. + if types.Comparable(old) && !types.Comparable(new) { + d.incompatible(obj, "", "old is comparable, new is not") + } +} + +// exportedFields collects all the immediate fields of the struct that are exported. +// This is also the set of exported keys for keyed struct literals. +func exportedFields(s *types.Struct) map[string]types.Object { + m := map[string]types.Object{} + for i := 0; i < s.NumFields(); i++ { + f := s.Field(i) + if f.Exported() { + m[f.Name()] = f + } + } + return m +} + +// exportedSelectableFields collects all the exported fields of the struct, including +// exported fields of embedded structs. +// +// We traverse the struct breadth-first, because of the rule that a lower-depth field +// shadows one at a higher depth. +func exportedSelectableFields(s *types.Struct) map[string]types.Object { + var ( + m = map[string]types.Object{} + next []*types.Struct // embedded structs at the next depth + seen []*types.Struct // to handle recursive embedding + ) + for cur := []*types.Struct{s}; len(cur) > 0; cur, next = next, nil { + seen = append(seen, cur...) + // We only want to consider unambiguous fields. Ambiguous fields (where there + // is more than one field of the same name at the same level) are legal, but + // cannot be selected. + for name, f := range unambiguousFields(cur) { + // Record an exported field we haven't seen before. If we have seen it, + // it occurred a lower depth, so it shadows this field. + if f.Exported() && m[name] == nil { + m[name] = f + } + // Remember embedded structs for processing at the next depth, + // but only if we haven't seen the struct at this depth or above. + if !f.Anonymous() { + continue + } + t := f.Type().Underlying() + if p, ok := t.(*types.Pointer); ok { + t = p.Elem().Underlying() + } + if t, ok := t.(*types.Struct); ok && !contains(seen, t) { + next = append(next, t) + } + } + } + return m +} + +func contains(ts []*types.Struct, t *types.Struct) bool { + for _, s := range ts { + if types.Identical(s, t) { + return true + } + } + return false +} + +// Given a set of structs at the same depth, the unambiguous fields are the ones whose +// names appear exactly once. +func unambiguousFields(structs []*types.Struct) map[string]*types.Var { + fields := map[string]*types.Var{} + seen := map[string]bool{} + for _, s := range structs { + for i := 0; i < s.NumFields(); i++ { + f := s.Field(i) + name := f.Name() + if seen[name] { + delete(fields, name) + } else { + seen[name] = true + fields[name] = f + } + } + } + return fields +} + +// Anything removed or change from the old set is an incompatible change. +// Anything added to the new set is a compatible change. +func (d *differ) checkCompatibleObjectSets(obj types.Object, old, new map[string]types.Object) { + for name, oldo := range old { + newo := new[name] + if newo == nil { + d.incompatible(obj, name, "removed") + } else { + d.checkCorrespondence(obj, name, oldo.Type(), newo.Type()) + } + } + for name := range new { + if old[name] == nil { + d.compatible(obj, name, "added") + } + } +} + +func (d *differ) checkCompatibleDefined(otn *types.TypeName, old *types.Named, new types.Type) { + // We've already checked that old and new correspond. + d.checkCompatible(otn, old.Underlying(), new.Underlying()) + // If there are different kinds of types (e.g. struct and interface), don't bother checking + // the method sets. + if reflect.TypeOf(old.Underlying()) != reflect.TypeOf(new.Underlying()) { + return + } + // Interface method sets are checked in checkCompatibleInterface. + if _, ok := old.Underlying().(*types.Interface); ok { + return + } + + // A new method set is compatible with an old if the new exported methods are a superset of the old. + d.checkMethodSet(otn, old, new, additionsCompatible) + d.checkMethodSet(otn, types.NewPointer(old), types.NewPointer(new), additionsCompatible) +} + +const ( + additionsCompatible = true + additionsIncompatible = false +) + +func (d *differ) checkMethodSet(otn *types.TypeName, oldt, newt types.Type, addcompat bool) { + // TODO: find a way to use checkCompatibleObjectSets for this. + oldMethodSet := exportedMethods(oldt) + newMethodSet := exportedMethods(newt) + msname := otn.Name() + if _, ok := oldt.(*types.Pointer); ok { + msname = "*" + msname + } + for name, oldMethod := range oldMethodSet { + newMethod := newMethodSet[name] + if newMethod == nil { + var part string + // Due to embedding, it's possible that the method's receiver type is not + // the same as the defined type whose method set we're looking at. So for + // a type T with removed method M that is embedded in some other type U, + // we will generate two "removed" messages for T.M, one for its own type + // T and one for the embedded type U. We want both messages to appear, + // but the messageSet dedup logic will allow only one message for a given + // object. So use the part string to distinguish them. + if receiverNamedType(oldMethod).Obj() != otn { + part = fmt.Sprintf(", method set of %s", msname) + } + d.incompatible(oldMethod, part, "removed") + } else { + obj := oldMethod + // If a value method is changed to a pointer method and has a signature + // change, then we can get two messages for the same method definition: one + // for the value method set that says it's removed, and another for the + // pointer method set that says it changed. To keep both messages (since + // messageSet dedups), use newMethod for the second. (Slight hack.) + if !hasPointerReceiver(oldMethod) && hasPointerReceiver(newMethod) { + obj = newMethod + } + d.checkCorrespondence(obj, "", oldMethod.Type(), newMethod.Type()) + } + } + + // Check for added methods. + for name, newMethod := range newMethodSet { + if oldMethodSet[name] == nil { + if addcompat { + d.compatible(newMethod, "", "added") + } else { + d.incompatible(newMethod, "", "added") + } + } + } +} + +// exportedMethods collects all the exported methods of type's method set. +func exportedMethods(t types.Type) map[string]types.Object { + m := map[string]types.Object{} + ms := types.NewMethodSet(t) + for i := 0; i < ms.Len(); i++ { + obj := ms.At(i).Obj() + if obj.Exported() { + m[obj.Name()] = obj + } + } + return m +} + +func receiverType(method types.Object) types.Type { + return method.Type().(*types.Signature).Recv().Type() +} + +func receiverNamedType(method types.Object) *types.Named { + switch t := receiverType(method).(type) { + case *types.Pointer: + return t.Elem().(*types.Named) + case *types.Named: + return t + default: + panic("unreachable") + } +} + +func hasPointerReceiver(method types.Object) bool { + _, ok := receiverType(method).(*types.Pointer) + return ok +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/correspondence.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/correspondence.go new file mode 100644 index 0000000..ee00bc0 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/correspondence.go @@ -0,0 +1,288 @@ +package apidiff + +import ( + "fmt" + "go/types" + "sort" +) + +// Two types are correspond if they are identical except for defined types, +// which must correspond. +// +// Two defined types correspond if they can be interchanged in the old and new APIs, +// possibly after a renaming. +// +// This is not a pure function. If we come across named types while traversing, +// we establish correspondence. +func (d *differ) correspond(old, new types.Type) bool { + return d.corr(old, new, nil) +} + +// corr determines whether old and new correspond. The argument p is a list of +// known interface identities, to avoid infinite recursion. +// +// corr calls itself recursively as much as possible, to establish more +// correspondences and so check more of the API. E.g. if the new function has more +// parameters than the old, compare all the old ones before returning false. +// +// Compare this to the implementation of go/types.Identical. +func (d *differ) corr(old, new types.Type, p *ifacePair) bool { + // Structure copied from types.Identical. + switch old := old.(type) { + case *types.Basic: + return types.Identical(old, new) + + case *types.Array: + if new, ok := new.(*types.Array); ok { + return d.corr(old.Elem(), new.Elem(), p) && old.Len() == new.Len() + } + + case *types.Slice: + if new, ok := new.(*types.Slice); ok { + return d.corr(old.Elem(), new.Elem(), p) + } + + case *types.Map: + if new, ok := new.(*types.Map); ok { + return d.corr(old.Key(), new.Key(), p) && d.corr(old.Elem(), new.Elem(), p) + } + + case *types.Chan: + if new, ok := new.(*types.Chan); ok { + return d.corr(old.Elem(), new.Elem(), p) && old.Dir() == new.Dir() + } + + case *types.Pointer: + if new, ok := new.(*types.Pointer); ok { + return d.corr(old.Elem(), new.Elem(), p) + } + + case *types.Signature: + if new, ok := new.(*types.Signature); ok { + pe := d.corr(old.Params(), new.Params(), p) + re := d.corr(old.Results(), new.Results(), p) + return old.Variadic() == new.Variadic() && pe && re + } + + case *types.Tuple: + if new, ok := new.(*types.Tuple); ok { + for i := 0; i < old.Len(); i++ { + if i >= new.Len() || !d.corr(old.At(i).Type(), new.At(i).Type(), p) { + return false + } + } + return old.Len() == new.Len() + } + + case *types.Struct: + if new, ok := new.(*types.Struct); ok { + for i := 0; i < old.NumFields(); i++ { + if i >= new.NumFields() { + return false + } + of := old.Field(i) + nf := new.Field(i) + if of.Anonymous() != nf.Anonymous() || + old.Tag(i) != new.Tag(i) || + !d.corr(of.Type(), nf.Type(), p) || + !d.corrFieldNames(of, nf) { + return false + } + } + return old.NumFields() == new.NumFields() + } + + case *types.Interface: + if new, ok := new.(*types.Interface); ok { + // Deal with circularity. See the comment in types.Identical. + q := &ifacePair{old, new, p} + for p != nil { + if p.identical(q) { + return true // same pair was compared before + } + p = p.prev + } + oldms := d.sortedMethods(old) + newms := d.sortedMethods(new) + for i, om := range oldms { + if i >= len(newms) { + return false + } + nm := newms[i] + if d.methodID(om) != d.methodID(nm) || !d.corr(om.Type(), nm.Type(), q) { + return false + } + } + return old.NumMethods() == new.NumMethods() + } + + case *types.Named: + if new, ok := new.(*types.Named); ok { + return d.establishCorrespondence(old, new) + } + if new, ok := new.(*types.Basic); ok { + // Basic types are defined types, too, so we have to support them. + + return d.establishCorrespondence(old, new) + } + + case *types.TypeParam: + if new, ok := new.(*types.TypeParam); ok { + if old.Index() == new.Index() { + return true + } + } + + default: + panic(fmt.Sprintf("unknown type kind %T", old)) + } + return false +} + +// Compare old and new field names. We are determining correspondence across packages, +// so just compare names, not packages. For an unexported, embedded field of named +// type (non-named embedded fields are possible with aliases), we check that the type +// names correspond. We check the types for correspondence before this is called, so +// we've established correspondence. +func (d *differ) corrFieldNames(of, nf *types.Var) bool { + if of.Anonymous() && nf.Anonymous() && !of.Exported() && !nf.Exported() { + if on, ok := of.Type().(*types.Named); ok { + nn := nf.Type().(*types.Named) + return d.establishCorrespondence(on, nn) + } + } + return of.Name() == nf.Name() +} + +// Establish that old corresponds with new if it does not already +// correspond to something else. +func (d *differ) establishCorrespondence(old *types.Named, new types.Type) bool { + oldname := old.Obj() + oldc := d.correspondMap[oldname] + if oldc == nil { + // For now, assume the types don't correspond unless they are from the old + // and new packages, respectively. + // + // This is too conservative. For instance, + // [old] type A = q.B; [new] type A q.C + // could be OK if in package q, B is an alias for C. + // Or, using p as the name of the current old/new packages: + // [old] type A = q.B; [new] type A int + // could be OK if in q, + // [old] type B int; [new] type B = p.A + // In this case, p.A and q.B name the same type in both old and new worlds. + // Note that this case doesn't imply circular package imports: it's possible + // that in the old world, p imports q, but in the new, q imports p. + // + // However, if we didn't do something here, then we'd incorrectly allow cases + // like the first one above in which q.B is not an alias for q.C + // + // What we should do is check that the old type, in the new world's package + // of the same path, doesn't correspond to something other than the new type. + // That is a bit hard, because there is no easy way to find a new package + // matching an old one. + if newn, ok := new.(*types.Named); ok { + if old.Obj().Pkg() != d.old || newn.Obj().Pkg() != d.new { + return old.Obj().Id() == newn.Obj().Id() + } + // Prior to generics, any two named types could correspond. + // Two named types cannot correspond if their type parameter lists don't match. + if !typeParamListsMatch(old.TypeParams(), newn.TypeParams()) { + return false + } + } + // If there is no correspondence, create one. + d.correspondMap[oldname] = new + // Check that the corresponding types are compatible. + d.checkCompatibleDefined(oldname, old, new) + return true + } + return typesEquivalent(oldc, new) +} + +// Two list of type parameters match if they are the same length, and +// the constraints of corresponding type parameters are identical. +func typeParamListsMatch(tps1, tps2 *types.TypeParamList) bool { + if tps1.Len() != tps2.Len() { + return false + } + for i := 0; i < tps1.Len(); i++ { + if !types.Identical(tps1.At(i).Constraint(), tps2.At(i).Constraint()) { + return false + } + } + return true +} + +// typesEquivalent reports whether two types are identical, or if +// the types have identical type param lists except that one type has nil +// constraints. +// +// This allows us to match a Type from a method receiver or arg to the Type from +// the declaration. +func typesEquivalent(old, new types.Type) bool { + if types.Identical(old, new) { + return true + } + // Handle two types with the same type params, one + // having constraints and one not. + oldn, ok := old.(*types.Named) + if !ok { + return false + } + newn, ok := new.(*types.Named) + if !ok { + return false + } + oldps := oldn.TypeParams() + newps := newn.TypeParams() + if oldps.Len() != newps.Len() { + return false + } + if oldps.Len() == 0 { + // Not generic types. + return false + } + for i := 0; i < oldps.Len(); i++ { + oldp := oldps.At(i) + newp := newps.At(i) + if oldp.Constraint() == nil || newp.Constraint() == nil { + return true + } + if !types.Identical(oldp.Constraint(), newp.Constraint()) { + return false + } + } + return true +} + +func (d *differ) sortedMethods(iface *types.Interface) []*types.Func { + ms := make([]*types.Func, iface.NumMethods()) + for i := 0; i < iface.NumMethods(); i++ { + ms[i] = iface.Method(i) + } + sort.Slice(ms, func(i, j int) bool { return d.methodID(ms[i]) < d.methodID(ms[j]) }) + return ms +} + +func (d *differ) methodID(m *types.Func) string { + // If the method belongs to one of the two packages being compared, use + // just its name even if it's unexported. That lets us treat unexported names + // from the old and new packages as equal. + if m.Pkg() == d.old || m.Pkg() == d.new { + return m.Name() + } + return m.Id() +} + +// Copied from the go/types package: + +// An ifacePair is a node in a stack of interface type pairs compared for identity. +type ifacePair struct { + x, y *types.Interface + prev *ifacePair +} + +func (p *ifacePair) identical(q *ifacePair) bool { + return p.x == q.x && p.y == q.y || p.x == q.y && p.y == q.x +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/messageset.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/messageset.go new file mode 100644 index 0000000..1354790 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/messageset.go @@ -0,0 +1,79 @@ +// TODO: show that two-non-empty dotjoin can happen, by using an anon struct as a field type +// TODO: don't report removed/changed methods for both value and pointer method sets? + +package apidiff + +import ( + "fmt" + "go/types" + "sort" + "strings" +) + +// There can be at most one message for each object or part thereof. +// Parts include interface methods and struct fields. +// +// The part thing is necessary. Method (Func) objects have sufficient info, but field +// Vars do not: they just have a field name and a type, without the enclosing struct. +type messageSet map[types.Object]map[string]string + +// Add a message for obj and part, overwriting a previous message +// (shouldn't happen). +// obj is required but part can be empty. +func (m messageSet) add(obj types.Object, part, msg string) { + s := m[obj] + if s == nil { + s = map[string]string{} + m[obj] = s + } + if f, ok := s[part]; ok && f != msg { + fmt.Printf("! second, different message for obj %s, part %q\n", obj, part) + fmt.Printf(" first: %s\n", f) + fmt.Printf(" second: %s\n", msg) + } + s[part] = msg +} + +func (m messageSet) collect() []string { + var s []string + for obj, parts := range m { + // Format each object name relative to its own package. + objstring := objectString(obj) + for part, msg := range parts { + var p string + + if strings.HasPrefix(part, ",") { + p = objstring + part + } else { + p = dotjoin(objstring, part) + } + s = append(s, p+": "+msg) + } + } + sort.Strings(s) + return s +} + +func objectString(obj types.Object) string { + if f, ok := obj.(*types.Func); ok { + sig := f.Type().(*types.Signature) + if recv := sig.Recv(); recv != nil { + tn := types.TypeString(recv.Type(), types.RelativeTo(obj.Pkg())) + if tn[0] == '*' { + tn = "(" + tn + ")" + } + return fmt.Sprintf("%s.%s", tn, obj.Name()) + } + } + return obj.Name() +} + +func dotjoin(s1, s2 string) string { + if s1 == "" { + return s2 + } + if s2 == "" { + return s1 + } + return s1 + "." + s2 +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/report.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/report.go new file mode 100644 index 0000000..ce79e27 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/report.go @@ -0,0 +1,71 @@ +package apidiff + +import ( + "bytes" + "fmt" + "io" +) + +// Report describes the changes detected by Changes. +type Report struct { + Changes []Change +} + +// A Change describes a single API change. +type Change struct { + Message string + Compatible bool +} + +func (r Report) messages(compatible bool) []string { + var msgs []string + for _, c := range r.Changes { + if c.Compatible == compatible { + msgs = append(msgs, c.Message) + } + } + return msgs +} + +func (r Report) String() string { + var buf bytes.Buffer + if err := r.Text(&buf); err != nil { + return fmt.Sprintf("!!%v", err) + } + return buf.String() +} + +func (r Report) Text(w io.Writer) error { + if err := r.TextIncompatible(w, true); err != nil { + return err + } + return r.TextCompatible(w) +} + +func (r Report) TextIncompatible(w io.Writer, withHeader bool) error { + if withHeader { + return r.writeMessages(w, "Incompatible changes:", r.messages(false)) + } + return r.writeMessages(w, "", r.messages(false)) +} + +func (r Report) TextCompatible(w io.Writer) error { + return r.writeMessages(w, "Compatible changes:", r.messages(true)) +} + +func (r Report) writeMessages(w io.Writer, header string, msgs []string) error { + if len(msgs) == 0 { + return nil + } + if header != "" { + if _, err := fmt.Fprintf(w, "%s\n", header); err != nil { + return err + } + } + for _, m := range msgs { + if _, err := fmt.Fprintf(w, "- %s\n", m); err != nil { + return err + } + } + return nil +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/testdata/exported_fields/ef.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/testdata/exported_fields/ef.go new file mode 100644 index 0000000..8e441e2 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/testdata/exported_fields/ef.go @@ -0,0 +1,38 @@ +package exported_fields + +// Used for testing exportedFields. +// Its exported fields are: +// +// A1 [1]int +// D bool +// E int +// F F +// S *S +type ( + S struct { + int + *embed2 + embed + E int // shadows embed.E + alias + A1 + *S + } + + A1 [1]int + + embed struct { + E string + } + + embed2 struct { + embed3 + F // shadows embed3.F + } + embed3 struct { + F bool + } + alias = struct{ D bool } + + F int +) diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/testdata/tests.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/testdata/tests.go new file mode 100644 index 0000000..92823b2 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/apidiff/testdata/tests.go @@ -0,0 +1,969 @@ +// This file is split into two packages, old and new. +// It is syntactically valid Go so that gofmt can process it. +// +// If a comment begins with: Then: +// old write subsequent lines to the "old" package +// new write subsequent lines to the "new" package +// both write subsequent lines to both packages +// c expect a compatible error with the following text +// i expect an incompatible error with the following text +package ignore + +// both +import "io" + +//////////////// Basics + +// Same type in both: OK. +// both +type A int + +// Changing the type is an incompatible change. +// old +type B int + +// new +// i B: changed from int to string +type B string + +// Adding a new type, whether alias or not, is a compatible change. +// new +// c AA: added +type AA = A + +// c B1: added +type B1 bool + +// Change of type for an unexported name doesn't matter... +// old +type t int + +// new +type t string // OK: t isn't part of the API + +// ...unless it is exposed. +// both +var V2 u + +// old +type u string + +// new +// i u: changed from string to int +type u int + +// An exposed, unexported type can be renamed. +// both +type u2 int + +// old +type u1 int + +var V5 u1 + +// new +var V5 u2 // OK: V5 has changed type, but old u1 corresopnds to new u2 + +// Splitting a single type into two is an incompatible change. +// both +type u3 int + +// old +type ( + Split1 = u1 + Split2 = u1 +) + +// new +type ( + Split1 = u2 // OK, since old u1 corresponds to new u2 + + // This tries to make u1 correspond to u3 + // i Split2: changed from u1 to u3 + Split2 = u3 +) + +// Merging two types into one is OK. +// old +type ( + GoodMerge1 = u2 + GoodMerge2 = u3 +) + +// new +type ( + GoodMerge1 = u3 + GoodMerge2 = u3 +) + +// Merging isn't OK here because a method is lost. +// both +type u4 int + +func (u4) M() {} + +// old +type ( + BadMerge1 = u3 + BadMerge2 = u4 +) + +// new +type ( + BadMerge1 = u3 + // i u4.M: removed + // What's really happening here is that old u4 corresponds to new u3, + // and new u3's method set is not a superset of old u4's. + BadMerge2 = u3 +) + +// old +type Rem int + +// new +// i Rem: removed + +//////////////// Constants + +// type changes +// old +const ( + C1 = 1 + C2 int = 2 + C3 = 3 + C4 u1 = 4 +) + +var V8 int + +// new +const ( + // i C1: changed from untyped int to untyped string + C1 = "1" + // i C2: changed from int to untyped int + C2 = -1 + // i C3: changed from untyped int to int + C3 int = 3 + // i V8: changed from var to const + V8 int = 1 + C4 u2 = 4 // OK: u1 corresponds to u2 +) + +// value change +// old +const ( + Cr1 = 1 + Cr2 = "2" + Cr3 = 3.5 + Cr4 = complex(0, 4.1) +) + +// new +const ( + // i Cr1: value changed from 1 to -1 + Cr1 = -1 + // i Cr2: value changed from "2" to "3" + Cr2 = "3" + // i Cr3: value changed from 3.5 to 3.8 + Cr3 = 3.8 + // i Cr4: value changed from (0 + 4.1i) to (4.1 + 0i) + Cr4 = complex(4.1, 0) +) + +//////////////// Variables + +// simple type changes +// old +var ( + V1 string + V3 A + V7 <-chan int +) + +// new +var ( + // i V1: changed from string to []string + V1 []string + V3 A // OK: same + // i V7: changed from <-chan int to chan int + V7 chan int +) + +// interface type changes +// old +var ( + V9 interface{ M() } + V10 interface{ M() } + V11 interface{ M() } +) + +// new +var ( + // i V9: changed from interface{M()} to interface{} + V9 interface{} + // i V10: changed from interface{M()} to interface{M(); M2()} + V10 interface { + M2() + M() + } + // i V11: changed from interface{M()} to interface{M(int)} + V11 interface{ M(int) } +) + +// struct type changes +// old +var ( + VS1 struct{ A, B int } + VS2 struct{ A, B int } + VS3 struct{ A, B int } + VS4 struct { + A int + u1 + } +) + +// new +var ( + // i VS1: changed from struct{A int; B int} to struct{B int; A int} + VS1 struct{ B, A int } + // i VS2: changed from struct{A int; B int} to struct{A int} + VS2 struct{ A int } + // i VS3: changed from struct{A int; B int} to struct{A int; B int; C int} + VS3 struct{ A, B, C int } + VS4 struct { + A int + u2 + } +) + +//////////////// Types + +// old +const C5 = 3 + +type ( + A1 [1]int + A2 [2]int + A3 [C5]int +) + +// new +// i C5: value changed from 3 to 4 +const C5 = 4 + +type ( + A1 [1]int + // i A2: changed from [2]int to [2]bool + A2 [2]bool + // i A3: changed from [3]int to [4]int + A3 [C5]int +) + +// old +type ( + Sl []int + P1 *int + P2 *u1 +) + +// new +type ( + // i Sl: changed from []int to []string + Sl []string + // i P1: changed from *int to **bool + P1 **bool + P2 *u2 // OK: u1 corresponds to u2 +) + +// old +type Bc1 int32 +type Bc2 uint +type Bc3 float32 +type Bc4 complex64 + +// new +// c Bc1: changed from int32 to int +type Bc1 int + +// c Bc2: changed from uint to uint64 +type Bc2 uint64 + +// c Bc3: changed from float32 to float64 +type Bc3 float64 + +// c Bc4: changed from complex64 to complex128 +type Bc4 complex128 + +// old +type Bi1 int32 +type Bi2 uint +type Bi3 float64 +type Bi4 complex128 + +// new +// i Bi1: changed from int32 to int16 +type Bi1 int16 + +// i Bi2: changed from uint to uint32 +type Bi2 uint32 + +// i Bi3: changed from float64 to float32 +type Bi3 float32 + +// i Bi4: changed from complex128 to complex64 +type Bi4 complex64 + +// old +type ( + M1 map[string]int + M2 map[string]int + M3 map[string]int +) + +// new +type ( + M1 map[string]int + // i M2: changed from map[string]int to map[int]int + M2 map[int]int + // i M3: changed from map[string]int to map[string]string + M3 map[string]string +) + +// old +type ( + Ch1 chan int + Ch2 <-chan int + Ch3 chan int + Ch4 <-chan int +) + +// new +type ( + // i Ch1, element type: changed from int to bool + Ch1 chan bool + // i Ch2: changed direction + Ch2 chan<- int + // i Ch3: changed direction + Ch3 <-chan int + // c Ch4: removed direction + Ch4 chan int +) + +// old +type I1 interface { + M1() + M2() +} + +// new +type I1 interface { + // M1() + // i I1.M1: removed + M2(int) + // i I1.M2: changed from func() to func(int) + M3() + // i I1.M3: added + m() + // i I1.m: added unexported method +} + +// old +type I2 interface { + M1() + m() +} + +// new +type I2 interface { + M1() + // m() Removing an unexported method is OK. + m2() // OK, because old already had an unexported method + // c I2.M2: added + M2() +} + +// old +type I3 interface { + io.Reader + M() +} + +// new +// OK: what matters is the method set; the name of the embedded +// interface isn't important. +type I3 interface { + M() + Read([]byte) (int, error) +} + +// old +type I4 io.Writer + +// new +// OK: in both, I4 is a distinct type from io.Writer, and +// the old and new I4s have the same method set. +type I4 interface { + Write([]byte) (int, error) +} + +// old +type I5 = io.Writer + +// new +// i I5: changed from io.Writer to I5 +// In old, I5 and io.Writer are the same type; in new, +// they are different. That can break something like: +// +// var _ func(io.Writer) = func(pkg.I6) {} +type I5 io.Writer + +// old +type I6 interface{ Write([]byte) (int, error) } + +// new +// i I6: changed from I6 to io.Writer +// Similar to the above. +type I6 = io.Writer + +//// correspondence with a basic type +// Basic types are technically defined types, but they aren't +// represented that way in go/types, so the cases below are special. + +// both +type T1 int + +// old +var VT1 T1 + +// new +// i VT1: changed from T1 to int +// This fails because old T1 corresponds to both int and new T1. +var VT1 int + +// old +type t2 int + +var VT2 t2 + +// new +// OK: t2 corresponds to int. It's fine that old t2 +// doesn't exist in new. +var VT2 int + +// both +type t3 int + +func (t3) M() {} + +// old +var VT3 t3 + +// new +// i t3.M: removed +// Here the change from t3 to int is incompatible +// because old t3 has an exported method. +var VT3 int + +// old +var VT4 int + +// new +type t4 int + +// i VT4: changed from int to t4 +// This is incompatible because of code like +// +// VT4 + int(1) +// +// which works in old but fails in new. +// The difference from the above cases is that +// in those, we were merging two types into one; +// here, we are splitting int into t4 and int. +var VT4 t4 + +//////////////// Functions + +// old +func F1(a int, b string) map[u1]A { return nil } +func F2(int) {} +func F3(int) {} +func F4(int) int { return 0 } +func F5(int) int { return 0 } +func F6(int) {} +func F7(interface{}) {} + +// new +func F1(c int, d string) map[u2]AA { return nil } //OK: same (since u1 corresponds to u2) + +// i F2: changed from func(int) to func(int) bool +func F2(int) bool { return true } + +// i F3: changed from func(int) to func(int, int) +func F3(int, int) {} + +// i F4: changed from func(int) int to func(bool) int +func F4(bool) int { return 0 } + +// i F5: changed from func(int) int to func(int) string +func F5(int) string { return "" } + +// i F6: changed from func(int) to func(...int) +func F6(...int) {} + +// i F7: changed from func(interface{}) to func(interface{x()}) +func F7(a interface{ x() }) {} + +// old +func F8(bool) {} + +// new +// c F8: changed from func to var +var F8 func(bool) + +// old +var F9 func(int) + +// new +// i F9: changed from var to func +func F9(int) {} + +// both +// OK, even though new S1 is incompatible with old S1 (see below) +func F10(S1) {} + +//////////////// Structs + +// old +type S1 struct { + A int + B string + C bool + d float32 +} + +// new +type S1 = s1 + +type s1 struct { + C chan int + // i S1.C: changed from bool to chan int + A int + // i S1.B: removed + // i S1: old is comparable, new is not + x []int + d float32 + E bool + // c S1.E: added +} + +// old +type embed struct { + E string +} + +type S2 struct { + A int + embed +} + +// new +type embedx struct { + E string +} + +type S2 struct { + embedx // OK: the unexported embedded field changed names, but the exported field didn't + A int +} + +// both +type F int + +// old +type S3 struct { + A int + embed +} + +// new +type embed struct{ F int } + +type S3 struct { + // i S3.E: removed + embed + // c S3.F: added + A int +} + +// old +type embed2 struct { + embed3 + F // shadows embed3.F +} + +type embed3 struct { + F bool +} + +type alias = struct{ D bool } + +type S4 struct { + int + *embed2 + embed + E int // shadows embed.E + alias + A1 + *S4 +} + +// new +type S4 struct { + // OK: removed unexported fields + // D and F marked as added because they are now part of the immediate fields + D bool + // c S4.D: added + E int // OK: same as in old + F F + // c S4.F: added + A1 // OK: same + *S4 // OK: same (recursive embedding) +} + +// Difference between exported selectable fields and exported immediate fields. +// both +type S5 struct{ A int } + +// old +// Exported immediate fields: A, S5 +// Exported selectable fields: A int, S5 S5 +type S6 struct { + S5 S5 + A int +} + +// new +// Exported immediate fields: S5 +// Exported selectable fields: A int, S5 S5. + +// i S6.A: removed +type S6 struct { + S5 +} + +// Ambiguous fields can exist; they just can't be selected. +// both +type ( + embed7a struct{ E int } + embed7b struct{ E bool } +) + +// old +type S7 struct { // legal, but no selectable fields + embed7a + embed7b +} + +// new +type S7 struct { + embed7a + embed7b + // c S7.E: added + E string +} + +//// Method sets + +// old +type SM struct { + embedm + Embedm +} + +func (SM) V1() {} +func (SM) V2() {} +func (SM) V3() {} +func (SM) V4() {} +func (SM) v() {} + +func (*SM) P1() {} +func (*SM) P2() {} +func (*SM) P3() {} +func (*SM) P4() {} +func (*SM) p() {} + +type embedm int + +func (embedm) EV1() {} +func (embedm) EV2() {} +func (embedm) EV3() {} +func (*embedm) EP1() {} +func (*embedm) EP2() {} +func (*embedm) EP3() {} + +type Embedm struct { + A int +} + +func (Embedm) FV() {} +func (*Embedm) FP() {} + +type RepeatEmbedm struct { + Embedm +} + +// new +type SM struct { + embedm2 + embedm3 + Embedm + // i SM.A: changed from int to bool +} + +// c SMa: added +type SMa = SM + +func (SM) V1() {} // OK: same + +// func (SM) V2() {} +// i SM.V2: removed + +// i SM.V3: changed from func() to func(int) +func (SM) V3(int) {} + +// c SM.V5: added +func (SM) V5() {} + +func (SM) v(int) {} // OK: unexported method change +func (SM) v2() {} // OK: unexported method added + +func (*SM) P1() {} // OK: same +//func (*SM) P2() {} +// i (*SM).P2: removed + +// i (*SM).P3: changed from func() to func(int) +func (*SMa) P3(int) {} + +// c (*SM).P5: added +func (*SM) P5() {} + +// func (*SM) p() {} // OK: unexported method removed + +// Changing from a value to a pointer receiver or vice versa +// just looks like adding and removing a method. + +// i SM.V4: removed +// i (*SM).V4: changed from func() to func(int) +func (*SM) V4(int) {} + +// c SM.P4: added +// P4 is not removed from (*SM) because value methods +// are in the pointer method set. +func (SM) P4() {} + +type embedm2 int + +// i embedm.EV1: changed from func() to func(int) +func (embedm2) EV1(int) {} + +// i embedm.EV2, method set of SM: removed +// i embedm.EV2, method set of *SM: removed + +// i (*embedm).EP2, method set of *SM: removed +func (*embedm2) EP1() {} + +type embedm3 int + +func (embedm3) EV3() {} // OK: compatible with old embedm.EV3 +func (*embedm3) EP3() {} // OK: compatible with old (*embedm).EP3 + +type Embedm struct { + // i Embedm.A: changed from int to bool + A bool +} + +// i Embedm.FV: changed from func() to func(int) +func (Embedm) FV(int) {} +func (*Embedm) FP() {} + +type RepeatEmbedm struct { + // i RepeatEmbedm.A: changed from int to bool + Embedm +} + +//////////////// Whole-package interface satisfaction + +// old +type WI1 interface { + M1() + m1() +} + +type WI2 interface { + M2() + m2() +} + +type WS1 int + +func (WS1) M1() {} +func (WS1) m1() {} + +type WS2 int + +func (WS2) M2() {} +func (WS2) m2() {} + +// new +type WI1 interface { + M1() + m() +} + +type WS1 int + +func (WS1) M1() {} + +// i WS1: no longer implements WI1 +//func (WS1) m1() {} + +type WI2 interface { + M2() + m2() + // i WS2: no longer implements WI2 + m3() +} + +type WS2 int + +func (WS2) M2() {} +func (WS2) m2() {} + +//////////////// Miscellany + +// This verifies that the code works even through +// multiple levels of unexported typed. + +// old +var Z w + +type w []x +type x []z +type z int + +// new +var Z w + +type w []x +type x []z + +// i z: changed from int to bool +type z bool + +// old +type H struct{} + +func (H) M() {} + +// new +// i H: changed from struct{} to interface{M()} +type H interface { + M() +} + +//// Splitting types + +// OK: in both old and new, {J1, K1, L1} name the same type. +// old +type ( + J1 = K1 + K1 = L1 + L1 int +) + +// new +type ( + J1 = K1 + K1 int + L1 = J1 +) + +// Old has one type, K2; new has J2 and K2. +// both +type K2 int + +// old +type J2 = K2 + +// new +// i K2: changed from K2 to K2 +type J2 K2 // old K2 corresponds with new J2 +// old K2 also corresponds with new K2: problem + +// both +type k3 int + +var Vj3 j3 // expose j3 + +// old +type j3 = k3 + +// new +// OK: k3 isn't exposed +type j3 k3 + +// both +type k4 int + +var Vj4 j4 // expose j4 +var VK4 k4 // expose k4 + +// old +type j4 = k4 + +// new +// i Vj4: changed from k4 to j4 +// e.g. p.Vj4 = p.Vk4 +type j4 k4 + +//// Generics + +// old +type G[T any] []T + +// new +// OK: param name change +type G[A any] []A + +// old +type GM[A, B comparable] map[A]B + +// new +// i GM: changed from map[A]B to map[B]A +type GM[A, B comparable] map[B]A + +// old +type GT[V any] struct { +} + +func (GT[V]) M(*GT[V]) {} + +// new +// OK +type GT[V any] struct { +} + +func (GT[V]) M(*GT[V]) {} + +// old +type GT2[V any] struct { +} + +func (GT2[V]) M(*GT2[V]) {} + +// new +// i GT2: changed from GT2[V any] to GT2[V comparable] +type GT2[V comparable] struct { +} + +func (GT2[V]) M(*GT2[V]) {} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/apidiff/main.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/apidiff/main.go new file mode 100644 index 0000000..92b763c --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/apidiff/main.go @@ -0,0 +1,163 @@ +// Command apidiff determines whether two versions of a package are compatible +package main + +import ( + "bufio" + "flag" + "fmt" + "go/token" + "go/types" + "os" + "strings" + + "golang.org/x/exp/apidiff" + "golang.org/x/tools/go/gcexportdata" + "golang.org/x/tools/go/packages" +) + +var ( + exportDataOutfile = flag.String("w", "", "file for export data") + incompatibleOnly = flag.Bool("incompatible", false, "display only incompatible changes") + allowInternal = flag.Bool("allow-internal", false, "allow apidiff to compare internal packages") +) + +func main() { + flag.Usage = func() { + w := flag.CommandLine.Output() + fmt.Fprintf(w, "usage:\n") + fmt.Fprintf(w, "apidiff OLD NEW\n") + fmt.Fprintf(w, " compares OLD and NEW package APIs\n") + fmt.Fprintf(w, " where OLD and NEW are either import paths or files of export data\n") + fmt.Fprintf(w, "apidiff -w FILE IMPORT_PATH\n") + fmt.Fprintf(w, " writes export data of the package at IMPORT_PATH to FILE\n") + fmt.Fprintf(w, " NOTE: In a GOPATH-less environment, this option consults the\n") + fmt.Fprintf(w, " module cache by default, unless used in the directory that\n") + fmt.Fprintf(w, " contains the go.mod module definition that IMPORT_PATH belongs\n") + fmt.Fprintf(w, " to. In most cases users want the latter behavior, so be sure\n") + fmt.Fprintf(w, " to cd to the exact directory which contains the module\n") + fmt.Fprintf(w, " definition of IMPORT_PATH.\n") + flag.PrintDefaults() + } + + flag.Parse() + if *exportDataOutfile != "" { + if len(flag.Args()) != 1 { + flag.Usage() + os.Exit(2) + } + pkg := mustLoadPackage(flag.Arg(0)) + if err := writeExportData(pkg, *exportDataOutfile); err != nil { + die("writing export data: %v", err) + } + } else { + if len(flag.Args()) != 2 { + flag.Usage() + os.Exit(2) + } + oldpkg := mustLoadOrRead(flag.Arg(0)) + newpkg := mustLoadOrRead(flag.Arg(1)) + if !*allowInternal { + if isInternalPackage(oldpkg.Path()) && isInternalPackage(newpkg.Path()) { + fmt.Fprintf(os.Stderr, "Ignoring internal package %s\n", oldpkg.Path()) + os.Exit(0) + } + } + report := apidiff.Changes(oldpkg, newpkg) + var err error + if *incompatibleOnly { + err = report.TextIncompatible(os.Stdout, false) + } else { + err = report.Text(os.Stdout) + } + if err != nil { + die("writing report: %v", err) + } + } +} + +func mustLoadOrRead(importPathOrFile string) *types.Package { + fileInfo, err := os.Stat(importPathOrFile) + if err == nil && fileInfo.Mode().IsRegular() { + pkg, err := readExportData(importPathOrFile) + if err != nil { + die("reading export data from %s: %v", importPathOrFile, err) + } + return pkg + } else { + return mustLoadPackage(importPathOrFile).Types + } +} + +func mustLoadPackage(importPath string) *packages.Package { + pkg, err := loadPackage(importPath) + if err != nil { + die("loading %s: %v", importPath, err) + } + return pkg +} + +func loadPackage(importPath string) (*packages.Package, error) { + cfg := &packages.Config{Mode: packages.LoadTypes | + packages.NeedName | packages.NeedTypes | packages.NeedImports | packages.NeedDeps, + } + pkgs, err := packages.Load(cfg, importPath) + if err != nil { + return nil, err + } + if len(pkgs) == 0 { + return nil, fmt.Errorf("found no packages for import %s", importPath) + } + if len(pkgs[0].Errors) > 0 { + return nil, pkgs[0].Errors[0] + } + return pkgs[0], nil +} + +func readExportData(filename string) (*types.Package, error) { + f, err := os.Open(filename) + if err != nil { + return nil, err + } + defer f.Close() + r := bufio.NewReader(f) + m := map[string]*types.Package{} + pkgPath, err := r.ReadString('\n') + if err != nil { + return nil, err + } + pkgPath = pkgPath[:len(pkgPath)-1] // remove delimiter + return gcexportdata.Read(r, token.NewFileSet(), m, pkgPath) +} + +func writeExportData(pkg *packages.Package, filename string) error { + f, err := os.Create(filename) + if err != nil { + return err + } + // Include the package path in the file. The exportdata format does + // not record the path of the package being written. + fmt.Fprintln(f, pkg.PkgPath) + err1 := gcexportdata.Write(f, pkg.Fset, pkg.Types) + err2 := f.Close() + if err1 != nil { + return err1 + } + return err2 +} + +func die(format string, args ...interface{}) { + fmt.Fprintf(os.Stderr, format+"\n", args...) + os.Exit(1) +} + +func isInternalPackage(pkgPath string) bool { + switch { + case strings.HasSuffix(pkgPath, "/internal"): + return true + case strings.Contains(pkgPath, "/internal/"): + return true + case pkgPath == "internal", strings.HasPrefix(pkgPath, "internal/"): + return true + } + return false +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/errors.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/errors.go new file mode 100644 index 0000000..d99f840 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/errors.go @@ -0,0 +1,81 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "errors" + "flag" + "fmt" + "os/exec" + "strings" + + "golang.org/x/mod/module" +) + +type usageError struct { + err error +} + +func usageErrorf(format string, args ...interface{}) error { + return &usageError{err: fmt.Errorf(format, args...)} +} + +const usageText = `usage: gorelease [-base=version] [-version=version]` + +func (e *usageError) Error() string { + msg := "" + if !errors.Is(e.err, flag.ErrHelp) { + msg = e.err.Error() + } + return usageText + "\n" + msg + "\nFor more information, run go doc golang.org/x/exp/cmd/gorelease" +} + +type baseVersionError struct { + err error + modPath string +} + +func (e *baseVersionError) Error() string { + firstVersion := "v0.1.0" + _, major, _ := module.SplitPathVersion(e.modPath) + if major != "" { + firstVersion = major[1:] + ".0.0" + } + + return fmt.Sprintf("could not find base version. Consider setting -version=%s if this is a first release, or explicitly set -base=none: %v", firstVersion, e.err) +} + +func (e *baseVersionError) Unwrap() error { + return e.err +} + +type downloadError struct { + m module.Version + err error +} + +func (e *downloadError) Error() string { + msg := e.err.Error() + sep := " " + if strings.Contains(msg, "\n") { + sep = "\n" + } + return fmt.Sprintf("error downloading module %s@%s:%s%s", e.m.Path, e.m.Version, sep, msg) +} + +// cleanCmdError simplifies error messages from os/exec.Cmd.Run. +// For ExitErrors, it trims and returns stderr. This is useful for go commands +// that print well-formatted errors. By default, ExitError prints the exit +// status but not stderr. +// +// cleanCmdError returns other errors unmodified. +func cleanCmdError(err error) error { + if xerr, ok := err.(*exec.ExitError); ok { + if stderr := strings.TrimSpace(string(xerr.Stderr)); stderr != "" { + return errors.New(stderr) + } + } + return err +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/gorelease.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/gorelease.go new file mode 100644 index 0000000..b0ee1e9 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/gorelease.go @@ -0,0 +1,1517 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// gorelease is an experimental tool that helps module authors avoid common +// problems before releasing a new version of a module. +// +// Usage: +// +// gorelease [-base={version|none}] [-version=version] +// +// Examples: +// +// # Compare with the latest version and suggest a new version. +// gorelease +// +// # Compare with a specific version and suggest a new version. +// gorelease -base=v1.2.3 +// +// # Compare with the latest version and check a specific new version for compatibility. +// gorelease -version=v1.3.0 +// +// # Compare with a specific version and check a specific new version for compatibility. +// gorelease -base=v1.2.3 -version=v1.3.0 +// +// gorelease analyzes changes in the public API and dependencies of the main +// module. It compares a base version (set with -base) with the currently +// checked out revision. Given a proposed version to release (set with +// -version), gorelease reports whether the changes are consistent with +// semantic versioning. If no version is proposed with -version, gorelease +// suggests the lowest version consistent with semantic versioning. +// +// If there are no visible changes in the module's public API, gorelease +// accepts versions that increment the minor or patch version numbers. For +// example, if the base version is "v2.3.1", gorelease would accept "v2.3.2" or +// "v2.4.0" or any prerelease of those versions, like "v2.4.0-beta". If no +// version is proposed, gorelease would suggest "v2.3.2". +// +// If there are only backward compatible differences in the module's public +// API, gorelease only accepts versions that increment the minor version. For +// example, if the base version is "v2.3.1", gorelease would accept "v2.4.0" +// but not "v2.3.2". +// +// If there are incompatible API differences for a proposed version with +// major version 1 or higher, gorelease will exit with a non-zero status. +// Incompatible differences may only be released in a new major version, which +// requires creating a module with a different path. For example, if +// incompatible changes are made in the module "example.com/mod", a +// new major version must be released as a new module, "example.com/mod/v2". +// For a proposed version with major version 0, which allows incompatible +// changes, gorelease will describe all changes, but incompatible changes +// will not affect its exit status. +// +// For more information on semantic versioning, see https://semver.org. +// +// Note: gorelease does not accept build metadata in releases (like +// v1.0.0+debug). Although it is valid semver, the Go tool and other tools in +// the ecosystem do not support it, so its use is not recommended. +// +// gorelease accepts the following flags: +// +// -base=version: The version that the current version of the module will be +// compared against. This may be a version like "v1.5.2", a version query like +// "latest", or "none". If the version is "none", gorelease will not compare the +// current version against any previous version; it will only validate the +// current version. This is useful for checking the first release of a new major +// version. The version may be preceded by a different module path and an '@', +// like -base=example.com/mod/v2@v2.5.2. This is useful to compare against +// an earlier major version or a fork. If -base is not specified, gorelease will +// attempt to infer a base version from the -version flag and available released +// versions. +// +// -version=version: The proposed version to be released. If specified, +// gorelease will confirm whether this version is consistent with changes made +// to the module's public API. gorelease will exit with a non-zero status if the +// version is not valid. +// +// gorelease is eventually intended to be merged into the go command +// as "go release". See golang.org/issues/26420. +package main + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "flag" + "fmt" + "go/build" + "io" + "io/ioutil" + "log" + "os" + "os/exec" + "path" + "path/filepath" + "sort" + "strings" + "unicode" + + "golang.org/x/exp/apidiff" + "golang.org/x/mod/modfile" + "golang.org/x/mod/module" + "golang.org/x/mod/semver" + "golang.org/x/mod/zip" + "golang.org/x/tools/go/packages" +) + +// IDEAS: +// * Should we suggest versions at all or should -version be mandatory? +// * Verify downstream modules have licenses. May need an API or library +// for this. Be clear that we can't provide legal advice. +// * Internal packages may be relevant to submodules (for example, +// golang.org/x/tools/internal/lsp is imported by golang.org/x/tools). +// gorelease should detect whether this is the case and include internal +// directories in comparison. It should be possible to opt out or specify +// a different list of submodules. +// * Decide what to do about build constraints, particularly GOOS and GOARCH. +// The API may be different on some platforms (e.g., x/sys). +// Should gorelease load packages in multiple configurations in the same run? +// Is it a compatible change if the same API is available for more platforms? +// Is it an incompatible change for fewer? +// How about cgo? Is adding a new cgo dependency an incompatible change? +// * Support splits and joins of nested modules. For example, if we are +// proposing to tag a particular commit as both cloud.google.com/go v0.46.2 +// and cloud.google.com/go/storage v1.0.0, we should ensure that the sets of +// packages provided by those modules are disjoint, and we should not report +// the packages moved from one to the other as an incompatible change (since +// the APIs are still compatible, just with a different module split). + +// TODO(jayconrod): +// * Clean up overuse of fmt.Errorf. +// * Support migration to modules after v2.x.y+incompatible. Requires comparing +// packages with different module paths. +// * Error when packages import from earlier major version of same module. +// (this may be intentional; look for real examples first). +// * Mechanism to suppress error messages. + +func main() { + log.SetFlags(0) + log.SetPrefix("gorelease: ") + wd, err := os.Getwd() + if err != nil { + log.Fatal(err) + } + ctx := context.WithValue(context.Background(), "env", append(os.Environ(), "GO111MODULE=on")) + success, err := runRelease(ctx, os.Stdout, wd, os.Args[1:]) + if err != nil { + if _, ok := err.(*usageError); ok { + fmt.Fprintln(os.Stderr, err) + os.Exit(2) + } else { + log.Fatal(err) + } + } + if !success { + os.Exit(1) + } +} + +// runRelease is the main function of gorelease. It's called by tests, so +// it writes to w instead of os.Stdout and returns an error instead of +// exiting. +func runRelease(ctx context.Context, w io.Writer, dir string, args []string) (success bool, err error) { + // Validate arguments and flags. We'll print our own errors, since we want to + // test without printing to stderr. + fs := flag.NewFlagSet("gorelease", flag.ContinueOnError) + fs.Usage = func() {} + fs.SetOutput(ioutil.Discard) + var baseOpt, releaseVersion string + fs.StringVar(&baseOpt, "base", "", "previous version to compare against") + fs.StringVar(&releaseVersion, "version", "", "proposed version to be released") + if err := fs.Parse(args); err != nil { + return false, &usageError{err: err} + } + + if len(fs.Args()) > 0 { + return false, usageErrorf("no arguments allowed") + } + + if releaseVersion != "" { + if semver.Build(releaseVersion) != "" { + return false, usageErrorf("release version %q is not a canonical semantic version: build metadata is not supported", releaseVersion) + } + if c := semver.Canonical(releaseVersion); c != releaseVersion { + return false, usageErrorf("release version %q is not a canonical semantic version", releaseVersion) + } + } + + var baseModPath, baseVersion string + if at := strings.Index(baseOpt, "@"); at >= 0 { + baseModPath = baseOpt[:at] + baseVersion = baseOpt[at+1:] + } else if dot, slash := strings.Index(baseOpt, "."), strings.Index(baseOpt, "/"); dot >= 0 && slash >= 0 && dot < slash { + baseModPath = baseOpt + } else { + baseVersion = baseOpt + } + if baseModPath == "" { + if baseVersion != "" && semver.Canonical(baseVersion) == baseVersion && releaseVersion != "" { + if cmp := semver.Compare(baseOpt, releaseVersion); cmp == 0 { + return false, usageErrorf("-base and -version must be different") + } else if cmp > 0 { + return false, usageErrorf("base version (%q) must be lower than release version (%q)", baseVersion, releaseVersion) + } + } + } else if baseModPath != "" && baseVersion == "none" { + return false, usageErrorf(`base version (%q) cannot have version "none" with explicit module path`, baseOpt) + } + + // Find the local module and repository root directories. + modRoot, err := findModuleRoot(dir) + if err != nil { + return false, err + } + repoRoot := findRepoRoot(modRoot) + + // Load packages for the version to be released from the local directory. + release, err := loadLocalModule(ctx, modRoot, repoRoot, releaseVersion) + if err != nil { + return false, err + } + + // Find the base version if there is one, download it, and load packages from + // the module cache. + var max string + if baseModPath == "" { + if baseVersion != "" && semver.Canonical(baseVersion) == baseVersion && module.Check(release.modPath, baseVersion) != nil { + // Base version was specified, but it's not consistent with the release + // module path, for example, the module path is example.com/m/v2, but + // the user said -base=v1.0.0. Instead of making the user explicitly + // specify the base module path, we'll adjust the major version suffix. + prefix, _, _ := module.SplitPathVersion(release.modPath) + major := semver.Major(baseVersion) + if strings.HasPrefix(prefix, "gopkg.in/") { + baseModPath = prefix + "." + semver.Major(baseVersion) + } else if major >= "v2" { + baseModPath = prefix + "/" + major + } else { + baseModPath = prefix + } + } else { + baseModPath = release.modPath + max = releaseVersion + } + } + base, err := loadDownloadedModule(ctx, baseModPath, baseVersion, max) + if err != nil { + return false, err + } + + // Compare packages and check for other issues. + report, err := makeReleaseReport(ctx, base, release) + if err != nil { + return false, err + } + if _, err := fmt.Fprint(w, report.String()); err != nil { + return false, err + } + return report.isSuccessful(), nil +} + +type moduleInfo struct { + modRoot string // module root directory + repoRoot string // repository root directory (may be "") + modPath string // module path in go.mod + version string // resolved version or "none" + versionQuery string // a query like "latest" or "dev-branch", if specified + versionInferred bool // true if the version was unspecified and inferred + highestTransitiveVersion string // version of the highest transitive self-dependency (cycle) + modPathMajor string // major version suffix like "/v3" or ".v2" + tagPrefix string // prefix for version tags if module not in repo root + + goModPath string // file path to go.mod + goModData []byte // content of go.mod + goSumData []byte // content of go.sum + goModFile *modfile.File // parsed go.mod file + + diagnostics []string // problems not related to loading specific packages + pkgs []*packages.Package // loaded packages with type information + + // Versions of this module which already exist. Only loaded for release + // (not base). + existingVersions []string +} + +// loadLocalModule loads information about a module and its packages from a +// local directory. +// +// modRoot is the directory containing the module's go.mod file. +// +// repoRoot is the root directory of the repository containing the module or "". +// +// version is a proposed version for the module or "". +func loadLocalModule(ctx context.Context, modRoot, repoRoot, version string) (m moduleInfo, err error) { + if repoRoot != "" && !hasFilePathPrefix(modRoot, repoRoot) { + return moduleInfo{}, fmt.Errorf("module root %q is not in repository root %q", modRoot, repoRoot) + } + + // Load the go.mod file and check the module path and go version. + m = moduleInfo{ + modRoot: modRoot, + repoRoot: repoRoot, + version: version, + goModPath: filepath.Join(modRoot, "go.mod"), + } + + if version != "" && semver.Compare(version, "v0.0.0-99999999999999-zzzzzzzzzzzz") < 0 { + m.diagnostics = append(m.diagnostics, fmt.Sprintf("Version %s is lower than most pseudo-versions. Consider releasing v0.1.0-0 instead.", version)) + } + + m.goModData, err = ioutil.ReadFile(m.goModPath) + if err != nil { + return moduleInfo{}, err + } + m.goModFile, err = modfile.ParseLax(m.goModPath, m.goModData, nil) + if err != nil { + return moduleInfo{}, err + } + if m.goModFile.Module == nil { + return moduleInfo{}, fmt.Errorf("%s: module directive is missing", m.goModPath) + } + m.modPath = m.goModFile.Module.Mod.Path + if err := checkModPath(m.modPath); err != nil { + return moduleInfo{}, err + } + var ok bool + _, m.modPathMajor, ok = module.SplitPathVersion(m.modPath) + if !ok { + // we just validated the path above. + panic(fmt.Sprintf("could not find version suffix in module path %q", m.modPath)) + } + if m.goModFile.Go == nil { + m.diagnostics = append(m.diagnostics, "go.mod: go directive is missing") + } + + // Determine the version tag prefix for the module within the repository. + if repoRoot != "" && modRoot != repoRoot { + if strings.HasPrefix(m.modPathMajor, ".") { + m.diagnostics = append(m.diagnostics, fmt.Sprintf("%s: module path starts with gopkg.in and must be declared in the root directory of the repository", m.modPath)) + } else { + codeDir := filepath.ToSlash(modRoot[len(repoRoot)+1:]) + var altGoModPath string + if m.modPathMajor == "" { + // module has no major version suffix. + // codeDir must be a suffix of modPath. + // tagPrefix is codeDir with a trailing slash. + if strings.HasSuffix(m.modPath, "/"+codeDir) { + m.tagPrefix = codeDir + "/" + } else { + m.diagnostics = append(m.diagnostics, fmt.Sprintf("%s: module path must end with %[2]q, since it is in subdirectory %[2]q", m.modPath, codeDir)) + } + } else { + if strings.HasSuffix(m.modPath, "/"+codeDir) { + // module has a major version suffix and is in a major version subdirectory. + // codeDir must be a suffix of modPath. + // tagPrefix must not include the major version. + m.tagPrefix = codeDir[:len(codeDir)-len(m.modPathMajor)+1] + altGoModPath = modRoot[:len(modRoot)-len(m.modPathMajor)+1] + "go.mod" + } else if strings.HasSuffix(m.modPath, "/"+codeDir+m.modPathMajor) { + // module has a major version suffix and is not in a major version subdirectory. + // codeDir + modPathMajor is a suffix of modPath. + // tagPrefix is codeDir with a trailing slash. + m.tagPrefix = codeDir + "/" + altGoModPath = filepath.Join(modRoot, m.modPathMajor[1:], "go.mod") + } else { + m.diagnostics = append(m.diagnostics, fmt.Sprintf("%s: module path must end with %[2]q or %q, since it is in subdirectory %[2]q", m.modPath, codeDir, codeDir+m.modPathMajor)) + } + } + + // Modules with major version suffixes can be defined in two places + // (e.g., sub/go.mod and sub/v2/go.mod). They must not be defined in both. + if altGoModPath != "" { + if data, err := ioutil.ReadFile(altGoModPath); err == nil { + if altModPath := modfile.ModulePath(data); m.modPath == altModPath { + goModRel, _ := filepath.Rel(repoRoot, m.goModPath) + altGoModRel, _ := filepath.Rel(repoRoot, altGoModPath) + m.diagnostics = append(m.diagnostics, fmt.Sprintf("module is defined in two locations:\n\t%s\n\t%s", goModRel, altGoModRel)) + } + } + } + } + } + + // Load the module's packages. + // We pack the module into a zip file and extract it to a temporary directory + // as if it were published and downloaded. We'll detect any errors that would + // occur (for example, invalid file names). We avoid loading it as the + // main module. + tmpModRoot, err := copyModuleToTempDir(repoRoot, m.modPath, m.modRoot) + if err != nil { + return moduleInfo{}, err + } + defer func() { + if rerr := os.RemoveAll(tmpModRoot); err == nil && rerr != nil { + err = fmt.Errorf("removing temporary module directory: %v", rerr) + } + }() + tmpLoadDir, tmpGoModData, tmpGoSumData, pkgPaths, prepareDiagnostics, err := prepareLoadDir(ctx, m.goModFile, m.modPath, tmpModRoot, version, false) + if err != nil { + return moduleInfo{}, err + } + defer func() { + if rerr := os.RemoveAll(tmpLoadDir); err == nil && rerr != nil { + err = fmt.Errorf("removing temporary load directory: %v", rerr) + } + }() + + var loadDiagnostics []string + m.pkgs, loadDiagnostics, err = loadPackages(ctx, m.modPath, tmpModRoot, tmpLoadDir, tmpGoModData, tmpGoSumData, pkgPaths) + if err != nil { + return moduleInfo{}, err + } + + m.diagnostics = append(m.diagnostics, prepareDiagnostics...) + m.diagnostics = append(m.diagnostics, loadDiagnostics...) + + highestVersion, err := findSelectedVersion(ctx, tmpLoadDir, m.modPath) + if err != nil { + return moduleInfo{}, err + } + + if highestVersion != "" { + // A version of the module is included in the transitive dependencies. + // Add it to the moduleInfo so that the release report stage can use it + // in verifying the version or suggestion a new version, depending on + // whether the user provided a version already. + m.highestTransitiveVersion = highestVersion + } + + retracted, err := loadRetractions(ctx, tmpLoadDir) + if err != nil { + return moduleInfo{}, err + } + m.diagnostics = append(m.diagnostics, retracted...) + + return m, nil +} + +// loadDownloadedModule downloads a module and loads information about it and +// its packages from the module cache. +// +// modPath is the module path used to fetch the module. The module's path in +// go.mod (m.modPath) may be different, for example in a soft fork intended as +// a replacement. +// +// version is the version to load. It may be "none" (indicating nothing should +// be loaded), "" (the highest available version below max should be used), a +// version query (to be resolved with 'go list'), or a canonical version. +// +// If version is "" and max is not "", available versions greater than or equal +// to max will not be considered. Typically, loadDownloadedModule is used to +// load the base version, and max is the release version. +func loadDownloadedModule(ctx context.Context, modPath, version, max string) (m moduleInfo, err error) { + // Check the module path and version. + // If the version is a query, resolve it to a canonical version. + m = moduleInfo{modPath: modPath} + if err := checkModPath(modPath); err != nil { + return moduleInfo{}, err + } + + var ok bool + _, m.modPathMajor, ok = module.SplitPathVersion(modPath) + if !ok { + // we just validated the path above. + panic(fmt.Sprintf("could not find version suffix in module path %q", modPath)) + } + + if version == "none" { + // We don't have a base version to compare against. + m.version = "none" + return m, nil + } + if version == "" { + // Unspecified version: use the highest version below max. + m.versionInferred = true + if m.version, err = inferBaseVersion(ctx, modPath, max); err != nil { + return moduleInfo{}, err + } + if m.version == "none" { + return m, nil + } + } else if version != module.CanonicalVersion(version) { + // Version query: find the real version. + m.versionQuery = version + if m.version, err = queryVersion(ctx, modPath, version); err != nil { + return moduleInfo{}, err + } + if m.version != "none" && max != "" && semver.Compare(m.version, max) >= 0 { + // TODO(jayconrod): reconsider this comparison for pseudo-versions in + // general. A query might match different pseudo-versions over time, + // depending on ancestor versions, so this might start failing with + // no local change. + return moduleInfo{}, fmt.Errorf("base version %s (%s) must be lower than release version %s", m.version, m.versionQuery, max) + } + } else { + // Canonical version: make sure it matches the module path. + if err := module.CheckPathMajor(version, m.modPathMajor); err != nil { + // TODO(golang.org/issue/39666): don't assume this is the base version + // or that we're comparing across major versions. + return moduleInfo{}, fmt.Errorf("can't compare major versions: base version %s does not belong to module %s", version, modPath) + } + m.version = version + } + + // Download the module into the cache and load the mod file. + // Note that goModPath is $GOMODCACHE/cache/download/$modPath/@v/$version.mod, + // which is not inside modRoot. This is what the go command uses. Even if + // the module didn't have a go.mod file, one will be synthesized there. + v := module.Version{Path: modPath, Version: m.version} + if m.modRoot, m.goModPath, err = downloadModule(ctx, v); err != nil { + return moduleInfo{}, err + } + if m.goModData, err = ioutil.ReadFile(m.goModPath); err != nil { + return moduleInfo{}, err + } + if m.goModFile, err = modfile.ParseLax(m.goModPath, m.goModData, nil); err != nil { + return moduleInfo{}, err + } + if m.goModFile.Module == nil { + return moduleInfo{}, fmt.Errorf("%s: missing module directive", m.goModPath) + } + m.modPath = m.goModFile.Module.Mod.Path + + // Load packages. + tmpLoadDir, tmpGoModData, tmpGoSumData, pkgPaths, _, err := prepareLoadDir(ctx, nil, m.modPath, m.modRoot, m.version, true) + if err != nil { + return moduleInfo{}, err + } + defer func() { + if rerr := os.RemoveAll(tmpLoadDir); err == nil && rerr != nil { + err = fmt.Errorf("removing temporary load directory: %v", err) + } + }() + + if m.pkgs, _, err = loadPackages(ctx, m.modPath, m.modRoot, tmpLoadDir, tmpGoModData, tmpGoSumData, pkgPaths); err != nil { + return moduleInfo{}, err + } + + // Calculate the existing versions. + ev, err := existingVersions(ctx, m.modPath, tmpLoadDir) + if err != nil { + return moduleInfo{}, err + } + m.existingVersions = ev + + return m, nil +} + +// makeReleaseReport returns a report comparing the current version of a +// module with a previously released version. The report notes any backward +// compatible and incompatible changes in the module's public API. It also +// diagnoses common problems, such as go.mod or go.sum being incomplete. +// The report recommends or validates a release version and indicates a +// version control tag to use (with an appropriate prefix, for modules not +// in the repository root directory). +func makeReleaseReport(ctx context.Context, base, release moduleInfo) (report, error) { + // Compare each pair of packages. + // Ignore internal packages. + // If we don't have a base version to compare against just check the new + // packages for errors. + shouldCompare := base.version != "none" + isInternal := func(modPath, pkgPath string) bool { + if !hasPathPrefix(pkgPath, modPath) { + panic(fmt.Sprintf("package %s not in module %s", pkgPath, modPath)) + } + for pkgPath != modPath { + if path.Base(pkgPath) == "internal" { + return true + } + pkgPath = path.Dir(pkgPath) + } + return false + } + r := report{ + base: base, + release: release, + } + for _, pair := range zipPackages(base.modPath, base.pkgs, release.modPath, release.pkgs) { + basePkg, releasePkg := pair.base, pair.release + switch { + case releasePkg == nil: + // Package removed + if internal := isInternal(base.modPath, basePkg.PkgPath); !internal || len(basePkg.Errors) > 0 { + pr := packageReport{ + path: basePkg.PkgPath, + baseErrors: basePkg.Errors, + } + if !internal { + pr.Report = apidiff.Report{ + Changes: []apidiff.Change{{ + Message: "package removed", + Compatible: false, + }}, + } + } + r.addPackage(pr) + } + + case basePkg == nil: + // Package added + if internal := isInternal(release.modPath, releasePkg.PkgPath); !internal && shouldCompare || len(releasePkg.Errors) > 0 { + pr := packageReport{ + path: releasePkg.PkgPath, + releaseErrors: releasePkg.Errors, + } + if !internal && shouldCompare { + // If we aren't comparing against a base version, don't say + // "package added". Only report packages with errors. + pr.Report = apidiff.Report{ + Changes: []apidiff.Change{{ + Message: "package added", + Compatible: true, + }}, + } + } + r.addPackage(pr) + } + + default: + // Matched packages + // Both packages are internal or neither; we only consider path components + // after the module path. + internal := isInternal(release.modPath, releasePkg.PkgPath) + if !internal && basePkg.Name != "main" && releasePkg.Name != "main" { + pr := packageReport{ + path: basePkg.PkgPath, + baseErrors: basePkg.Errors, + releaseErrors: releasePkg.Errors, + Report: apidiff.Changes(basePkg.Types, releasePkg.Types), + } + r.addPackage(pr) + } + } + } + + if r.canVerifyReleaseVersion() { + if release.version == "" { + r.suggestReleaseVersion() + } else { + r.validateReleaseVersion() + } + } + + return r, nil +} + +// existingVersions returns the versions that already exist for the given +// modPath. +func existingVersions(ctx context.Context, modPath, modRoot string) (versions []string, err error) { + defer func() { + if err != nil { + err = fmt.Errorf("listing versions of %s: %w", modPath, err) + } + }() + + type listVersions struct { + Versions []string + } + cmd := exec.CommandContext(ctx, "go", "list", "-json", "-m", "-versions", modPath) + cmd.Env = copyEnv(ctx, cmd.Env) + cmd.Dir = modRoot + out, err := cmd.Output() + if err != nil { + return nil, cleanCmdError(err) + } + if len(out) == 0 { + return nil, nil + } + + var lv listVersions + if err := json.Unmarshal(out, &lv); err != nil { + return nil, err + } + return lv.Versions, nil +} + +// findRepoRoot finds the root directory of the repository that contains dir. +// findRepoRoot returns "" if it can't find the repository root. +func findRepoRoot(dir string) string { + vcsDirs := []string{".git", ".hg", ".svn", ".bzr"} + d := filepath.Clean(dir) + for { + for _, vcsDir := range vcsDirs { + if _, err := os.Stat(filepath.Join(d, vcsDir)); err == nil { + return d + } + } + parent := filepath.Dir(d) + if parent == d { + return "" + } + d = parent + } +} + +// findModuleRoot finds the root directory of the module that contains dir. +func findModuleRoot(dir string) (string, error) { + d := filepath.Clean(dir) + for { + if fi, err := os.Stat(filepath.Join(d, "go.mod")); err == nil && !fi.IsDir() { + return dir, nil + } + parent := filepath.Dir(d) + if parent == d { + break + } + d = parent + } + return "", fmt.Errorf("%s: cannot find go.mod file", dir) +} + +// checkModPath is like golang.org/x/mod/module.CheckPath, but it returns +// friendlier error messages for common mistakes. +// +// TODO(jayconrod): update module.CheckPath and delete this function. +func checkModPath(modPath string) error { + if path.IsAbs(modPath) || filepath.IsAbs(modPath) { + // TODO(jayconrod): improve error message in x/mod instead of checking here. + return fmt.Errorf("module path %q must not be an absolute path.\nIt must be an address where your module may be found.", modPath) + } + if suffix := dirMajorSuffix(modPath); suffix == "v0" || suffix == "v1" { + return fmt.Errorf("module path %q has major version suffix %q.\nA major version suffix is only allowed for v2 or later.", modPath, suffix) + } else if strings.HasPrefix(suffix, "v0") { + return fmt.Errorf("module path %q has major version suffix %q.\nA major version may not have a leading zero.", modPath, suffix) + } else if strings.ContainsRune(suffix, '.') { + return fmt.Errorf("module path %q has major version suffix %q.\nA major version may not contain dots.", modPath, suffix) + } + return module.CheckPath(modPath) +} + +// inferBaseVersion returns an appropriate base version if one was not specified +// explicitly. +// +// If max is not "", inferBaseVersion returns the highest available release +// version of the module lower than max. Otherwise, inferBaseVersion returns the +// highest available release version. Pre-release versions are not considered. +// If there is no available version, and max appears to be the first release +// version (for example, "v0.1.0", "v2.0.0"), "none" is returned. +func inferBaseVersion(ctx context.Context, modPath, max string) (baseVersion string, err error) { + defer func() { + if err != nil { + err = &baseVersionError{err: err, modPath: modPath} + } + }() + + versions, err := loadVersions(ctx, modPath) + if err != nil { + return "", err + } + + for i := len(versions) - 1; i >= 0; i-- { + v := versions[i] + if semver.Prerelease(v) == "" && + (max == "" || semver.Compare(v, max) < 0) { + return v, nil + } + } + + if max == "" || maybeFirstVersion(max) { + return "none", nil + } + return "", fmt.Errorf("no versions found lower than %s", max) +} + +// queryVersion returns the canonical version for a given module version query. +func queryVersion(ctx context.Context, modPath, query string) (resolved string, err error) { + defer func() { + if err != nil { + err = fmt.Errorf("could not resolve version %s@%s: %w", modPath, query, err) + } + }() + if query == "upgrade" || query == "patch" { + return "", errors.New("query is based on requirements in main go.mod file") + } + + tmpDir, err := ioutil.TempDir("", "") + if err != nil { + return "", err + } + defer func() { + if rerr := os.Remove(tmpDir); rerr != nil && err == nil { + err = rerr + } + }() + arg := modPath + "@" + query + cmd := exec.CommandContext(ctx, "go", "list", "-m", "-f", "{{.Version}}", "--", arg) + cmd.Env = copyEnv(ctx, cmd.Env) + cmd.Dir = tmpDir + cmd.Env = append(cmd.Env, "GO111MODULE=on") + out, err := cmd.Output() + if err != nil { + return "", cleanCmdError(err) + } + return strings.TrimSpace(string(out)), nil +} + +// loadVersions loads the list of versions for the given module using +// 'go list -m -versions'. The returned versions are sorted in ascending +// semver order. +func loadVersions(ctx context.Context, modPath string) (versions []string, err error) { + defer func() { + if err != nil { + err = fmt.Errorf("could not load versions for %s: %v", modPath, err) + } + }() + + tmpDir, err := ioutil.TempDir("", "") + if err != nil { + return nil, err + } + defer func() { + if rerr := os.Remove(tmpDir); rerr != nil && err == nil { + err = rerr + } + }() + cmd := exec.CommandContext(ctx, "go", "list", "-m", "-versions", "--", modPath) + cmd.Env = copyEnv(ctx, cmd.Env) + cmd.Dir = tmpDir + out, err := cmd.Output() + if err != nil { + return nil, cleanCmdError(err) + } + versions = strings.Fields(string(out)) + if len(versions) > 0 { + versions = versions[1:] // skip module path + } + + // Sort versions defensively. 'go list -m -versions' should always returns + // a sorted list of versions, but it's fast and easy to sort them here, too. + sort.Slice(versions, func(i, j int) bool { + return semver.Compare(versions[i], versions[j]) < 0 + }) + return versions, nil +} + +// maybeFirstVersion returns whether v appears to be the first version +// of a module. +func maybeFirstVersion(v string) bool { + major, minor, patch, _, _, err := parseVersion(v) + if err != nil { + return false + } + if major == "0" { + return minor == "0" && patch == "0" || + minor == "0" && patch == "1" || + minor == "1" && patch == "0" + } + return minor == "0" && patch == "0" +} + +// dirMajorSuffix returns a major version suffix for a slash-separated path. +// For example, for the path "foo/bar/v2", dirMajorSuffix would return "v2". +// If no major version suffix is found, "" is returned. +// +// dirMajorSuffix is less strict than module.SplitPathVersion so that incorrect +// suffixes like "v0", "v02", "v1.2" can be detected. It doesn't handle +// special cases for gopkg.in paths. +func dirMajorSuffix(path string) string { + i := len(path) + for i > 0 && ('0' <= path[i-1] && path[i-1] <= '9') || path[i-1] == '.' { + i-- + } + if i <= 1 || i == len(path) || path[i-1] != 'v' || (i > 1 && path[i-2] != '/') { + return "" + } + return path[i-1:] +} + +// copyModuleToTempDir copies module files from modRoot to a subdirectory of +// scratchDir. Submodules, vendor directories, and irregular files are excluded. +// An error is returned if the module contains any files or directories that +// can't be included in a module zip file (due to special characters, +// excessive sizes, etc.). +func copyModuleToTempDir(repoRoot, modPath, modRoot string) (dir string, err error) { + // Generate a fake version consistent with modPath. We need a canonical + // version to create a zip file. + version := "v0.0.0-gorelease" + _, majorPathSuffix, _ := module.SplitPathVersion(modPath) + if majorPathSuffix != "" { + version = majorPathSuffix[1:] + ".0.0-gorelease" + } + m := module.Version{Path: modPath, Version: version} + + zipFile, err := ioutil.TempFile("", "gorelease-*.zip") + if err != nil { + return "", err + } + defer func() { + zipFile.Close() + os.Remove(zipFile.Name()) + }() + + dir, err = ioutil.TempDir("", "gorelease") + if err != nil { + return "", err + } + defer func() { + if err != nil { + os.RemoveAll(dir) + dir = "" + } + }() + + var fallbackToDir bool + if repoRoot != "" { + var err error + fallbackToDir, err = tryCreateFromVCS(zipFile, m, modRoot, repoRoot) + if err != nil { + return "", err + } + } + + if repoRoot == "" || fallbackToDir { + // Not a recognised repo: fall back to creating from dir. + if err := zip.CreateFromDir(zipFile, m, modRoot); err != nil { + var e zip.FileErrorList + if errors.As(err, &e) { + return "", e + } + return "", err + } + } + + if err := zipFile.Close(); err != nil { + return "", err + } + if err := zip.Unzip(dir, m, zipFile.Name()); err != nil { + return "", err + } + return dir, nil +} + +// tryCreateFromVCS tries to create a module zip file from VCS. If it succeeds, +// it returns fallBackToDir false and a nil err. If it fails in a recoverable +// way, it returns fallBackToDir true and a nil err. If it fails in an +// unrecoverable way, it returns a non-nil err. +func tryCreateFromVCS(zipFile io.Writer, m module.Version, modRoot, repoRoot string) (fallbackToDir bool, _ error) { + // We recognised a repo: create from VCS. + if !hasFilePathPrefix(modRoot, repoRoot) { + panic(fmt.Sprintf("repo root %q is not a prefix of mod root %q", repoRoot, modRoot)) + } + hasUncommitted, err := hasGitUncommittedChanges(repoRoot) + if err != nil { + // Fallback to CreateFromDir. + return true, nil + } + if hasUncommitted { + return false, fmt.Errorf("repo %s has uncommitted changes", repoRoot) + } + modRel := filepath.ToSlash(trimFilePathPrefix(modRoot, repoRoot)) + if err := zip.CreateFromVCS(zipFile, m, repoRoot, "HEAD", modRel); err != nil { + var fel zip.FileErrorList + if errors.As(err, &fel) { + return false, fel + } + var uve *zip.UnrecognizedVCSError + if errors.As(err, &uve) { + // Fallback to CreateFromDir. + return true, nil + } + return false, err + } + // Success! + return false, nil +} + +// downloadModule downloads a specific version of a module to the +// module cache using 'go mod download'. +func downloadModule(ctx context.Context, m module.Version) (modRoot, goModPath string, err error) { + defer func() { + if err != nil { + err = &downloadError{m: m, err: cleanCmdError(err)} + } + }() + + // Run 'go mod download' from a temporary directory to avoid needing to load + // go.mod from gorelease's working directory (or a parent). + // go.mod may be broken, and we don't need it. + // TODO(golang.org/issue/36812): 'go mod download' reads go.mod even though + // we don't need information about the main module or the build list. + // If it didn't read go.mod in this case, we wouldn't need a temp directory. + tmpDir, err := ioutil.TempDir("", "gorelease-download") + if err != nil { + return "", "", err + } + defer os.Remove(tmpDir) + cmd := exec.CommandContext(ctx, "go", "mod", "download", "-json", "--", m.Path+"@"+m.Version) + cmd.Env = copyEnv(ctx, cmd.Env) + cmd.Dir = tmpDir + out, err := cmd.Output() + var xerr *exec.ExitError + if err != nil { + var ok bool + if xerr, ok = err.(*exec.ExitError); !ok { + return "", "", err + } + } + + // If 'go mod download' exited unsuccessfully but printed well-formed JSON + // with an error, return that error. + parsed := struct{ Dir, GoMod, Error string }{} + if jsonErr := json.Unmarshal(out, &parsed); jsonErr != nil { + if xerr != nil { + return "", "", cleanCmdError(xerr) + } + return "", "", jsonErr + } + if parsed.Error != "" { + return "", "", errors.New(parsed.Error) + } + if xerr != nil { + return "", "", cleanCmdError(xerr) + } + return parsed.Dir, parsed.GoMod, nil +} + +// prepareLoadDir creates a temporary directory and a go.mod file that requires +// the module being loaded. go.sum is copied if present. It also creates a .go +// file that imports every package in the given modPath. This temporary module +// is useful for two reasons. First, replace and exclude directives from the +// target module aren't applied, so we have the same view as a dependent module. +// Second, we can run commands like 'go get' without modifying the original +// go.mod and go.sum files. +// +// modFile is the pre-parsed go.mod file. If non-nil, its requirements and +// go version will be copied so that incomplete and out-of-date requirements +// may be reported later. +// +// modPath is the module's path. +// +// modRoot is the module's root directory. +// +// version is the version of the module being loaded. If must be canonical +// for modules loaded from the cache. Otherwise, it may be empty (for example, +// when no release version is proposed). +// +// cached indicates whether the module is being loaded from the module cache. +// If cached is true, then the module lives in the cache at +// $GOMODCACHE/$modPath@$version/. Its go.mod file is at +// $GOMODCACHE/cache/download/$modPath/@v/$version.mod. It must be referenced +// with a simple require. A replace directive won't work because it may not have +// a go.mod file in modRoot. +// If cached is false, then modRoot is somewhere outside the module cache +// (ex /tmp). We'll reference it with a local replace directive. It must have a +// go.mod file in modRoot. +// +// dir is the location of the temporary directory. +// +// goModData and goSumData are the contents of the go.mod and go.sum files, +// respectively. +// +// pkgPaths are the import paths of the module being loaded, including the path +// to any main packages (as if they were importable). +func prepareLoadDir(ctx context.Context, modFile *modfile.File, modPath, modRoot, version string, cached bool) (dir string, goModData, goSumData []byte, pkgPaths []string, diagnostics []string, err error) { + defer func() { + if err != nil { + if cached { + err = fmt.Errorf("preparing to load packages for %s@%s: %w", modPath, version, err) + } else { + err = fmt.Errorf("preparing to load packages for %s: %w", modPath, err) + } + } + }() + + if module.Check(modPath, version) != nil { + // If no version is proposed or if the version isn't valid, use a fake + // version that matches the module's major version suffix. If the version + // is invalid, that will be reported elsewhere. + version = "v0.0.0-gorelease" + if _, pathMajor, _ := module.SplitPathVersion(modPath); pathMajor != "" { + version = pathMajor[1:] + ".0.0-gorelease" + } + } + + dir, err = ioutil.TempDir("", "gorelease-load") + if err != nil { + return "", nil, nil, nil, nil, err + } + + f := &modfile.File{} + f.AddModuleStmt("gorelease-load-module") + f.AddRequire(modPath, version) + if !cached { + f.AddReplace(modPath, version, modRoot, "") + } + if modFile != nil { + if modFile.Go != nil { + f.AddGoStmt(modFile.Go.Version) + } + for _, r := range modFile.Require { + f.AddRequire(r.Mod.Path, r.Mod.Version) + } + } + goModData, err = f.Format() + if err != nil { + return "", nil, nil, nil, nil, err + } + if err := ioutil.WriteFile(filepath.Join(dir, "go.mod"), goModData, 0666); err != nil { + return "", nil, nil, nil, nil, err + } + + goSumData, err = ioutil.ReadFile(filepath.Join(modRoot, "go.sum")) + if err != nil && !os.IsNotExist(err) { + return "", nil, nil, nil, nil, err + } + if err := ioutil.WriteFile(filepath.Join(dir, "go.sum"), goSumData, 0666); err != nil { + return "", nil, nil, nil, nil, err + } + + // Add a .go file with requirements, so that `go get` won't blat + // requirements. + fakeImports := &strings.Builder{} + fmt.Fprint(fakeImports, "package tmp\n") + imps, err := collectImportPaths(modPath, modRoot) + if err != nil { + return "", nil, nil, nil, nil, err + } + for _, imp := range imps { + fmt.Fprintf(fakeImports, "import _ %q\n", imp) + } + if err := ioutil.WriteFile(filepath.Join(dir, "tmp.go"), []byte(fakeImports.String()), 0666); err != nil { + return "", nil, nil, nil, nil, err + } + + // Add missing requirements. + cmd := exec.CommandContext(ctx, "go", "get", "-d", ".") + cmd.Env = copyEnv(ctx, cmd.Env) + cmd.Dir = dir + if _, err := cmd.Output(); err != nil { + return "", nil, nil, nil, nil, fmt.Errorf("looking for missing dependencies: %w", cleanCmdError(err)) + } + + // Report new requirements in go.mod. + goModPath := filepath.Join(dir, "go.mod") + loadReqs := func(data []byte) (reqs []module.Version, err error) { + modFile, err := modfile.ParseLax(goModPath, data, nil) + if err != nil { + return nil, err + } + for _, r := range modFile.Require { + reqs = append(reqs, r.Mod) + } + return reqs, nil + } + + oldReqs, err := loadReqs(goModData) + if err != nil { + return "", nil, nil, nil, nil, err + } + newGoModData, err := ioutil.ReadFile(goModPath) + if err != nil { + return "", nil, nil, nil, nil, err + } + newReqs, err := loadReqs(newGoModData) + if err != nil { + return "", nil, nil, nil, nil, err + } + + oldMap := make(map[module.Version]bool) + for _, req := range oldReqs { + oldMap[req] = true + } + var missing []module.Version + for _, req := range newReqs { + // Ignore cyclic imports, since a module never needs to require itself. + if req.Path == modPath { + continue + } + if !oldMap[req] { + missing = append(missing, req) + } + } + + if len(missing) > 0 { + var missingReqs []string + for _, m := range missing { + missingReqs = append(missingReqs, m.String()) + } + diagnostics = append(diagnostics, fmt.Sprintf("go.mod: the following requirements are needed\n\t%s\nRun 'go mod tidy' to add missing requirements.", strings.Join(missingReqs, "\n\t"))) + return dir, goModData, goSumData, imps, diagnostics, nil + } + + // Cached modules may have no go.sum. + // We skip comparison because a downloaded module is outside the user's + // control. + if !cached { + // Check if 'go get' added new hashes to go.sum. + goSumPath := filepath.Join(dir, "go.sum") + newGoSumData, err := ioutil.ReadFile(goSumPath) + if err != nil { + if !os.IsNotExist(err) { + return "", nil, nil, nil, nil, err + } + // If the sum doesn't exist, that's ok: we'll treat "no go.sum" like + // "empty go.sum". + } + + if !sumsMatchIgnoringPath(string(goSumData), string(newGoSumData), modPath) { + diagnostics = append(diagnostics, "go.sum: one or more sums are missing. Run 'go mod tidy' to add missing sums.") + } + } + + return dir, goModData, goSumData, imps, diagnostics, nil +} + +// sumsMatchIgnoringPath checks whether the two sums match. It ignores any lines +// which contains the given modPath. +func sumsMatchIgnoringPath(sum1, sum2, modPathToIgnore string) bool { + lines1 := make(map[string]bool) + for _, line := range strings.Split(string(sum1), "\n") { + if line == "" { + continue + } + lines1[line] = true + } + for _, line := range strings.Split(string(sum2), "\n") { + if line == "" { + continue + } + parts := strings.Fields(line) + if len(parts) < 1 { + panic(fmt.Sprintf("go.sum malformed: unexpected line %s", line)) + } + if parts[0] == modPathToIgnore { + continue + } + + if !lines1[line] { + return false + } + } + + lines2 := make(map[string]bool) + for _, line := range strings.Split(string(sum2), "\n") { + if line == "" { + continue + } + lines2[line] = true + } + for _, line := range strings.Split(string(sum1), "\n") { + if line == "" { + continue + } + parts := strings.Fields(line) + if len(parts) < 1 { + panic(fmt.Sprintf("go.sum malformed: unexpected line %s", line)) + } + if parts[0] == modPathToIgnore { + continue + } + + if !lines2[line] { + return false + } + } + + return true +} + +// collectImportPaths visits the given root and traverses its directories +// recursively, collecting the import paths of all importable packages in each +// directory along the way. +// +// modPath is the module path. +// root is the root directory of the module to collect imports for (the root +// of the modPath module). +// +// Note: the returned importPaths will include main if it exists in root. +func collectImportPaths(modPath, root string) (importPaths []string, _ error) { + err := filepath.Walk(root, func(walkPath string, fi os.FileInfo, err error) error { + if err != nil { + return err + } + + // Avoid .foo, _foo, and testdata subdirectory trees. + if !fi.IsDir() { + return nil + } + base := filepath.Base(walkPath) + if strings.HasPrefix(base, ".") || strings.HasPrefix(base, "_") || base == "testdata" || base == "internal" { + return filepath.SkipDir + } + + p, err := build.Default.ImportDir(walkPath, 0) + if err != nil { + if nogoErr := (*build.NoGoError)(nil); errors.As(err, &nogoErr) { + // No .go files found in directory. That's ok, we'll keep + // searching. + return nil + } + return err + } + + // Construct the import path. + importPath := path.Join(modPath, filepath.ToSlash(trimFilePathPrefix(p.Dir, root))) + importPaths = append(importPaths, importPath) + + return nil + }) + if err != nil { + return nil, fmt.Errorf("listing packages in %s: %v", root, err) + } + + return importPaths, nil +} + +// loadPackages returns a list of all packages in the module modPath, sorted by +// package path. modRoot is the module root directory, but packages are loaded +// from loadDir, which must contain go.mod and go.sum containing goModData and +// goSumData. +// +// We load packages from a temporary external module so that replace and exclude +// directives are not applied. The loading process may also modify go.mod and +// go.sum, and we want to detect and report differences. +// +// Package loading errors will be returned in the Errors field of each package. +// Other diagnostics (such as the go.sum file being incomplete) will be +// returned through diagnostics. +// err will be non-nil in case of a fatal error that prevented packages +// from being loaded. +func loadPackages(ctx context.Context, modPath, modRoot, loadDir string, goModData, goSumData []byte, pkgPaths []string) (pkgs []*packages.Package, diagnostics []string, err error) { + // Load packages. + // TODO(jayconrod): if there are errors loading packages in the release + // version, try loading in the release directory. Errors there would imply + // that packages don't load without replace / exclude directives. + cfg := &packages.Config{ + Mode: packages.NeedName | packages.NeedTypes | packages.NeedImports | packages.NeedDeps, + Dir: loadDir, + Context: ctx, + } + cfg.Env = copyEnv(ctx, cfg.Env) + if len(pkgPaths) > 0 { + pkgs, err = packages.Load(cfg, pkgPaths...) + if err != nil { + return nil, nil, err + } + } + + // Sort the returned packages by path. + // packages.Load makes no guarantee about the order of returned packages. + sort.Slice(pkgs, func(i, j int) bool { + return pkgs[i].PkgPath < pkgs[j].PkgPath + }) + + // Trim modRoot from file paths in errors. + prefix := modRoot + string(os.PathSeparator) + for _, pkg := range pkgs { + for i := range pkg.Errors { + pkg.Errors[i].Pos = strings.TrimPrefix(pkg.Errors[i].Pos, prefix) + } + } + + return pkgs, diagnostics, nil +} + +type packagePair struct { + base, release *packages.Package +} + +// zipPackages combines two lists of packages, sorted by package path, +// and returns a sorted list of pairs of packages with matching paths. +// If a package is in one list but not the other (because it was added or +// removed between releases), a pair will be returned with a nil +// base or release field. +func zipPackages(baseModPath string, basePkgs []*packages.Package, releaseModPath string, releasePkgs []*packages.Package) []packagePair { + baseIndex, releaseIndex := 0, 0 + var pairs []packagePair + for baseIndex < len(basePkgs) || releaseIndex < len(releasePkgs) { + var basePkg, releasePkg *packages.Package + var baseSuffix, releaseSuffix string + if baseIndex < len(basePkgs) { + basePkg = basePkgs[baseIndex] + baseSuffix = trimPathPrefix(basePkg.PkgPath, baseModPath) + } + if releaseIndex < len(releasePkgs) { + releasePkg = releasePkgs[releaseIndex] + releaseSuffix = trimPathPrefix(releasePkg.PkgPath, releaseModPath) + } + + var pair packagePair + if basePkg != nil && (releasePkg == nil || baseSuffix < releaseSuffix) { + // Package removed + pair = packagePair{basePkg, nil} + baseIndex++ + } else if releasePkg != nil && (basePkg == nil || releaseSuffix < baseSuffix) { + // Package added + pair = packagePair{nil, releasePkg} + releaseIndex++ + } else { + // Matched packages. + pair = packagePair{basePkg, releasePkg} + baseIndex++ + releaseIndex++ + } + pairs = append(pairs, pair) + } + return pairs +} + +// findSelectedVersion returns the highest version of the given modPath at +// modDir, if a module cycle exists. modDir should be a writable directory +// containing the go.mod for modPath. +// +// If no module cycle exists, it returns empty string. +func findSelectedVersion(ctx context.Context, modDir, modPath string) (latestVersion string, err error) { + defer func() { + if err != nil { + err = fmt.Errorf("could not find selected version for %s: %v", modPath, err) + } + }() + + cmd := exec.CommandContext(ctx, "go", "list", "-m", "-f", "{{.Version}}", "--", modPath) + cmd.Env = copyEnv(ctx, cmd.Env) + cmd.Dir = modDir + out, err := cmd.Output() + if err != nil { + return "", cleanCmdError(err) + } + return strings.TrimSpace(string(out)), nil +} + +func copyEnv(ctx context.Context, current []string) []string { + env, ok := ctx.Value("env").([]string) + if !ok { + return current + } + clone := make([]string, len(env)) + copy(clone, env) + return clone +} + +// loadRetractions lists all retracted deps found at the modRoot. +func loadRetractions(ctx context.Context, modRoot string) ([]string, error) { + cmd := exec.CommandContext(ctx, "go", "list", "-json", "-m", "-u", "all") + if env, ok := ctx.Value("env").([]string); ok { + cmd.Env = env + } + cmd.Dir = modRoot + out, err := cmd.Output() + if err != nil { + return nil, cleanCmdError(err) + } + + var retracted []string + type message struct { + Path string + Version string + Retracted []string + } + + dec := json.NewDecoder(bytes.NewBuffer(out)) + for { + var m message + if err := dec.Decode(&m); err == io.EOF { + break + } else if err != nil { + return nil, err + } + if len(m.Retracted) == 0 { + continue + } + rationale, ok := shortRetractionRationale(m.Retracted) + if ok { + retracted = append(retracted, fmt.Sprintf("required module %s@%s retracted by module author: %s", m.Path, m.Version, rationale)) + } else { + retracted = append(retracted, fmt.Sprintf("required module %s@%s retracted by module author", m.Path, m.Version)) + } + } + + return retracted, nil +} + +// ShortRetractionRationale returns a retraction rationale string that is safe +// to print in a terminal. It returns hard-coded strings if the rationale +// is empty, too long, or contains non-printable characters. +// +// It returns true if the rationale was printable, and false if it was not (too +// long, contains graphics, etc). +func shortRetractionRationale(rationales []string) (string, bool) { + if len(rationales) == 0 { + return "", false + } + rationale := rationales[0] + + const maxRationaleBytes = 500 + if i := strings.Index(rationale, "\n"); i >= 0 { + rationale = rationale[:i] + } + rationale = strings.TrimSpace(rationale) + if rationale == "" || rationale == "retracted by module author" { + return "", false + } + if len(rationale) > maxRationaleBytes { + return "", false + } + for _, r := range rationale { + if !unicode.IsGraphic(r) && !unicode.IsSpace(r) { + return "", false + } + } + // NOTE: the go.mod parser rejects invalid UTF-8, so we don't check that here. + return rationale, true +} + +// hasGitUncommittedChanges checks if the given directory has uncommitteed git +// changes. +func hasGitUncommittedChanges(dir string) (bool, error) { + stdout := &bytes.Buffer{} + cmd := exec.Command("git", "status", "--porcelain") + cmd.Dir = dir + cmd.Stdout = stdout + if err := cmd.Run(); err != nil { + return false, cleanCmdError(err) + } + return stdout.Len() != 0, nil +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/gorelease_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/gorelease_test.go new file mode 100644 index 0000000..216c747 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/gorelease_test.go @@ -0,0 +1,504 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "bytes" + "context" + "flag" + "fmt" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "strconv" + "strings" + "sync" + "testing" + + "golang.org/x/mod/module" + "golang.org/x/tools/txtar" +) + +var ( + testwork = flag.Bool("testwork", false, "preserve work directory") + updateGolden = flag.Bool("u", false, "update expected text in test files instead of failing") +) + +var hasGitCache struct { + once sync.Once + found bool +} + +// hasGit reports whether the git executable exists on the PATH. +func hasGit() bool { + hasGitCache.once.Do(func() { + if _, err := exec.LookPath("git"); err != nil { + return + } + hasGitCache.found = true + }) + return hasGitCache.found +} + +// prepareProxy creates a proxy dir and returns an associated ctx. +// +// proxyVersions must be a map of module version to true. If proxyVersions is +// empty, all modules in mod/ will be included in the proxy list. If proxy +// versions is non-empty, only those modules in mod/ that match an entry in +// proxyVersions will be included. +// +// ctx must be used in runRelease. +// cleanup must be called when the relevant tests are finished. +func prepareProxy(proxyVersions map[module.Version]bool, tests []*test) (ctx context.Context, cleanup func(), _ error) { + env := append(os.Environ(), "GO111MODULE=on", "GOSUMDB=off") + + proxyDir, proxyURL, err := buildProxyDir(proxyVersions, tests) + if err != nil { + return nil, nil, fmt.Errorf("error building proxy dir: %v", err) + } + env = append(env, fmt.Sprintf("GOPROXY=%s", proxyURL)) + + cacheDir, err := ioutil.TempDir("", "gorelease_test-gocache") + if err != nil { + return nil, nil, err + } + env = append(env, fmt.Sprintf("GOPATH=%s", cacheDir)) + + return context.WithValue(context.Background(), "env", env), func() { + if *testwork { + fmt.Fprintf(os.Stderr, "test cache dir: %s\n", cacheDir) + fmt.Fprintf(os.Stderr, "test proxy dir: %s\ntest proxy URL: %s\n", proxyDir, proxyURL) + } else { + cmd := exec.Command("go", "clean", "-modcache") + cmd.Env = env + if err := cmd.Run(); err != nil { + fmt.Fprintln(os.Stderr, fmt.Errorf("error running go clean: %v", err)) + } + + if err := os.RemoveAll(cacheDir); err != nil { + fmt.Fprintln(os.Stderr, fmt.Errorf("error removing cache dir %s: %v", cacheDir, err)) + } + if err := os.RemoveAll(proxyDir); err != nil { + fmt.Fprintln(os.Stderr, fmt.Errorf("error removing proxy dir %s: %v", proxyDir, err)) + } + } + }, nil +} + +// test describes an individual test case, written as a .test file in the +// testdata directory. +// +// Each test is a txtar archive (see golang.org/x/tools/txtar). The comment +// section (before the first file) contains a sequence of key=value pairs +// (one per line) that configure the test. +// +// Most tests include a file named "want". The output of gorelease is compared +// against this file. If the -u flag is set, this file is replaced with the +// actual output of gorelease, and the test is written back to disk. This is +// useful for updating tests after cosmetic changes. +type test struct { + txtar.Archive + + // testPath is the name of the .test file describing the test. + testPath string + + // modPath (set with mod=...) is the path of the module being tested. Used + // to retrieve files from the test proxy. + modPath string + + // version (set with version=...) is the name of a version to check out + // from the test proxy into the working directory. Some tests use this + // instead of specifying files they need in the txtar archive. + version string + + // baseVersion (set with base=...) is the value of the -base flag to pass + // to gorelease. + baseVersion string + + // releaseVersion (set with release=...) is the value of the -version flag + // to pass to gorelease. + releaseVersion string + + // dir (set with dir=...) is the directory where gorelease should be invoked. + // If unset, gorelease is invoked in the directory where the txtar archive + // is unpacked. This is useful for invoking gorelease in a subdirectory. + dir string + + // wantError (set with error=...) is true if the test expects a hard error + // (returned by runRelease). + wantError bool + + // wantSuccess (set with success=...) is true if the test expects a report + // to be returned without errors or diagnostics. True by default. + wantSuccess bool + + // skip (set with skip=...) is non-empty if the test should be skipped. + skip string + + // want is set to the contents of the file named "want" in the txtar archive. + want []byte + + // proxyVersions is used to set the exact contents of the GOPROXY. + // + // If empty, all of testadata/mod/ will be included in the proxy. + // If it is not empty, each entry must be of the form <modpath>@v<version> + // and exist in testdata/mod/. + proxyVersions map[module.Version]bool + + // vcs is used to set the VCS that the root of the test should + // emulate. Allowed values are git, and hg. + vcs string +} + +// readTest reads and parses a .test file with the given name. +func readTest(testPath string) (*test, error) { + arc, err := txtar.ParseFile(testPath) + if err != nil { + return nil, err + } + t := &test{ + Archive: *arc, + testPath: testPath, + wantSuccess: true, + } + + for n, line := range bytes.Split(t.Comment, []byte("\n")) { + lineNum := n + 1 + if i := bytes.IndexByte(line, '#'); i >= 0 { + line = line[:i] + } + line = bytes.TrimSpace(line) + if len(line) == 0 { + continue + } + + var key, value string + if i := bytes.IndexByte(line, '='); i < 0 { + return nil, fmt.Errorf("%s:%d: no '=' found", testPath, lineNum) + } else { + key = strings.TrimSpace(string(line[:i])) + value = strings.TrimSpace(string(line[i+1:])) + } + switch key { + case "mod": + t.modPath = value + case "version": + t.version = value + case "base": + t.baseVersion = value + case "release": + t.releaseVersion = value + case "dir": + t.dir = value + case "skip": + t.skip = value + case "success": + t.wantSuccess, err = strconv.ParseBool(value) + if err != nil { + return nil, fmt.Errorf("%s:%d: %v", testPath, lineNum, err) + } + case "error": + t.wantError, err = strconv.ParseBool(value) + if err != nil { + return nil, fmt.Errorf("%s:%d: %v", testPath, lineNum, err) + } + case "proxyVersions": + if len(value) == 0 { + break + } + proxyVersions := make(map[module.Version]bool) + parts := strings.Split(value, ",") + for _, modpathWithVersion := range parts { + vParts := strings.Split(modpathWithVersion, "@") + if len(vParts) != 2 { + return nil, fmt.Errorf("proxyVersions entry %s is invalid: it should be of the format <modpath>@v<semver> (ex: github.com/foo/bar@v1.2.3)", modpathWithVersion) + } + modPath, version := vParts[0], vParts[1] + mv := module.Version{ + Path: modPath, + Version: version, + } + proxyVersions[mv] = true + } + t.proxyVersions = proxyVersions + case "vcs": + t.vcs = value + default: + return nil, fmt.Errorf("%s:%d: unknown key: %q", testPath, lineNum, key) + } + } + if t.modPath == "" && (t.version != "" || (t.baseVersion != "" && t.baseVersion != "none")) { + return nil, fmt.Errorf("%s: version or base was set but mod was not set", testPath) + } + + haveFiles := false + for _, f := range t.Files { + if f.Name == "want" { + t.want = bytes.TrimSpace(f.Data) + continue + } + haveFiles = true + } + + if haveFiles && t.version != "" { + return nil, fmt.Errorf("%s: version is set but files are present", testPath) + } + + return t, nil +} + +// updateTest replaces the contents of the file named "want" within a test's +// txtar archive, then formats and writes the test file. +func updateTest(t *test, want []byte) error { + var wantFile *txtar.File + for i := range t.Files { + if t.Files[i].Name == "want" { + wantFile = &t.Files[i] + break + } + } + if wantFile == nil { + t.Files = append(t.Files, txtar.File{Name: "want"}) + wantFile = &t.Files[len(t.Files)-1] + } + + wantFile.Data = want + data := txtar.Format(&t.Archive) + return ioutil.WriteFile(t.testPath, data, 0666) +} + +func TestRelease(t *testing.T) { + testPaths, err := filepath.Glob(filepath.FromSlash("testdata/*/*.test")) + if err != nil { + t.Fatal(err) + } + if len(testPaths) == 0 { + t.Fatal("no .test files found in testdata directory") + } + + var tests []*test + for _, testPath := range testPaths { + test, err := readTest(testPath) + if err != nil { + t.Fatal(err) + } + tests = append(tests, test) + } + + defaultContext, cleanup, err := prepareProxy(nil, tests) + if err != nil { + t.Fatalf("preparing test proxy: %v", err) + } + t.Cleanup(cleanup) + + for _, test := range tests { + testName := strings.TrimSuffix(strings.TrimPrefix(filepath.ToSlash(test.testPath), "testdata/"), ".test") + t.Run(testName, testRelease(defaultContext, tests, test)) + } +} + +func TestRelease_gitRepo_uncommittedChanges(t *testing.T) { + ctx := context.Background() + buf := &bytes.Buffer{} + releaseDir, err := ioutil.TempDir("", "") + if err != nil { + t.Fatal(err) + } + + goModInit(t, releaseDir) + gitInit(t, releaseDir) + + // Create an uncommitted change. + bContents := `package b +const B = "b"` + if err := ioutil.WriteFile(filepath.Join(releaseDir, "b.go"), []byte(bContents), 0644); err != nil { + t.Fatal(err) + } + + success, err := runRelease(ctx, buf, releaseDir, nil) + if got, want := err.Error(), fmt.Sprintf("repo %s has uncommitted changes", releaseDir); got != want { + t.Errorf("runRelease:\ngot error:\n%q\nwant error\n%q", got, want) + } + if success { + t.Errorf("runRelease: expected failure, got success") + } +} + +func testRelease(ctx context.Context, tests []*test, test *test) func(t *testing.T) { + return func(t *testing.T) { + if test.skip != "" { + t.Skip(test.skip) + } + + t.Parallel() + + if len(test.proxyVersions) > 0 { + var cleanup func() + var err error + ctx, cleanup, err = prepareProxy(test.proxyVersions, tests) + if err != nil { + t.Fatalf("preparing test proxy: %v", err) + } + t.Cleanup(cleanup) + } + + // Extract the files in the release version. They may be part of the + // test archive or in testdata/mod. + testDir, err := ioutil.TempDir("", "") + if err != nil { + t.Fatal(err) + } + if *testwork { + fmt.Fprintf(os.Stderr, "test dir: %s\n", testDir) + } else { + t.Cleanup(func() { + os.RemoveAll(testDir) + }) + } + + var arc *txtar.Archive + if test.version != "" { + arcBase := fmt.Sprintf("%s_%s.txt", strings.ReplaceAll(test.modPath, "/", "_"), test.version) + arcPath := filepath.Join("testdata/mod", arcBase) + var err error + arc, err = txtar.ParseFile(arcPath) + if err != nil { + t.Fatal(err) + } + } else { + arc = &test.Archive + } + if err := extractTxtar(testDir, arc); err != nil { + t.Fatal(err) + } + + switch test.vcs { + case "git": + // Convert testDir to a git repository with a single commit, to + // simulate a real user's module-in-a-git-repo. + gitInit(t, testDir) + case "hg": + // Convert testDir to a mercurial repository to simulate a real + // user's module-in-a-hg-repo. + hgInit(t, testDir) + case "": + // No VCS. + default: + t.Fatalf("unknown vcs %q", test.vcs) + } + + // Generate the report and compare it against the expected text. + var args []string + if test.baseVersion != "" { + args = append(args, "-base="+test.baseVersion) + } + if test.releaseVersion != "" { + args = append(args, "-version="+test.releaseVersion) + } + buf := &bytes.Buffer{} + releaseDir := filepath.Join(testDir, test.dir) + success, err := runRelease(ctx, buf, releaseDir, args) + if err != nil { + if !test.wantError { + t.Fatalf("unexpected error: %v", err) + } + if errMsg := []byte(err.Error()); !bytes.Equal(errMsg, bytes.TrimSpace(test.want)) { + if *updateGolden { + if err := updateTest(test, errMsg); err != nil { + t.Fatal(err) + } + } else { + t.Fatalf("got error: %s; want error: %s", errMsg, test.want) + } + } + return + } + if test.wantError { + t.Fatalf("got success; want error %s", test.want) + } + + got := bytes.TrimSpace(buf.Bytes()) + if filepath.Separator != '/' { + got = bytes.ReplaceAll(got, []byte{filepath.Separator}, []byte{'/'}) + } + if !bytes.Equal(got, test.want) { + if *updateGolden { + if err := updateTest(test, got); err != nil { + t.Fatal(err) + } + } else { + t.Fatalf("got:\n%s\n\nwant:\n%s", got, test.want) + } + } + if success != test.wantSuccess { + t.Fatalf("got success: %v; want success %v", success, test.wantSuccess) + } + } +} + +// hgInit initialises a directory as a mercurial repo. +func hgInit(t *testing.T, dir string) { + t.Helper() + + if err := os.Mkdir(filepath.Join(dir, ".hg"), 0777); err != nil { + t.Fatal(err) + } + + if err := ioutil.WriteFile(filepath.Join(dir, ".hg", "branch"), []byte("default"), 0777); err != nil { + t.Fatal(err) + } +} + +// gitInit initialises a directory as a git repo, and adds a simple commit. +func gitInit(t *testing.T, dir string) { + t.Helper() + + if !hasGit() { + t.Skip("PATH does not contain git") + } + + stdout := &bytes.Buffer{} + stderr := &bytes.Buffer{} + + for _, args := range [][]string{ + {"git", "init"}, + {"git", "config", "user.name", "Gopher"}, + {"git", "config", "user.email", "gopher@golang.org"}, + {"git", "checkout", "-b", "test"}, + {"git", "add", "-A"}, + {"git", "commit", "-m", "test"}, + } { + cmd := exec.Command(args[0], args[1:]...) + cmd.Dir = dir + cmd.Stdout = stdout + cmd.Stderr = stderr + if err := cmd.Run(); err != nil { + cmdArgs := strings.Join(args, " ") + t.Fatalf("%s\n%s\nerror running %q on dir %s: %v", stdout.String(), stderr.String(), cmdArgs, dir, err) + } + } +} + +// goModInit runs `go mod init` in the given directory. +func goModInit(t *testing.T, dir string) { + t.Helper() + + aContents := `package a +const A = "a"` + if err := ioutil.WriteFile(filepath.Join(dir, "a.go"), []byte(aContents), 0644); err != nil { + t.Fatal(err) + } + + stdout := &bytes.Buffer{} + stderr := &bytes.Buffer{} + cmd := exec.Command("go", "mod", "init", "example.com/uncommitted") + cmd.Stdout = stdout + cmd.Stderr = stderr + cmd.Dir = dir + if err := cmd.Run(); err != nil { + t.Fatalf("error running `go mod init`: %s, %v", stderr.String(), err) + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/path.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/path.go new file mode 100644 index 0000000..bfe1f20 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/path.go @@ -0,0 +1,87 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "path/filepath" + "strings" +) + +// hasPathPrefix reports whether the slash-separated path s +// begins with the elements in prefix. +// Copied from cmd/go/internal/str.HasPathPrefix. +func hasPathPrefix(s, prefix string) bool { + if len(s) == len(prefix) { + return s == prefix + } + if prefix == "" { + return true + } + if len(s) > len(prefix) { + if prefix[len(prefix)-1] == '/' || s[len(prefix)] == '/' { + return s[:len(prefix)] == prefix + } + } + return false +} + +// hasFilePathPrefix reports whether the filesystem path s +// begins with the elements in prefix. +// Copied from cmd/go/internal/str.HasFilePathPrefix. +func hasFilePathPrefix(s, prefix string) bool { + sv := strings.ToUpper(filepath.VolumeName(s)) + pv := strings.ToUpper(filepath.VolumeName(prefix)) + s = s[len(sv):] + prefix = prefix[len(pv):] + switch { + default: + return false + case pv != "" && sv != pv: + return false + case len(s) == len(prefix): + return s == prefix + case prefix == "": + return true + case len(s) > len(prefix): + if prefix[len(prefix)-1] == filepath.Separator { + return strings.HasPrefix(s, prefix) + } + return s[len(prefix)] == filepath.Separator && s[:len(prefix)] == prefix + } +} + +// trimFilePathPrefix returns the given filesystem path s without the leading +// prefix. +func trimFilePathPrefix(s, prefix string) string { + sv := strings.ToUpper(filepath.VolumeName(s)) + pv := strings.ToUpper(filepath.VolumeName(prefix)) + s = s[len(sv):] + prefix = prefix[len(pv):] + + if !hasFilePathPrefix(s, prefix) || len(prefix) == 0 { + return s + } + if len(s) == len(prefix) { + return "" + } + if prefix[len(prefix)-1] == filepath.Separator { + return strings.TrimPrefix(s, prefix) + } + return s[len(prefix)+1:] +} + +// trimPathPrefix returns p without the leading prefix. Unlike +// strings.TrimPrefix, the prefix will only match on slash-separted component +// boundaries, so trimPathPrefix("aa/b", "aa") returns "b", but +// trimPathPrefix("aa/b", "a") returns "aa/b". +func trimPathPrefix(p, prefix string) string { + if prefix == "" { + return p + } + if prefix == p { + return "" + } + return strings.TrimPrefix(p, prefix+"/") +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/path_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/path_test.go new file mode 100644 index 0000000..57dfd98 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/path_test.go @@ -0,0 +1,227 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "runtime" + "testing" +) + +func TestHasPathPrefix(t *testing.T) { + for _, test := range []struct { + desc, path, prefix string + want bool + }{ + { + desc: "empty_prefix", + path: "a/b", + prefix: "", + want: true, + }, { + desc: "partial_prefix", + path: "a/b", + prefix: "a", + want: true, + }, { + desc: "full_prefix", + path: "a/b", + prefix: "a/b", + want: true, + }, { + desc: "partial_component", + path: "aa/b", + prefix: "a", + want: false, + }, + } { + t.Run(test.desc, func(t *testing.T) { + if got := hasPathPrefix(test.path, test.prefix); got != test.want { + t.Errorf("hasPathPrefix(%q, %q): got %v, want %v", test.path, test.prefix, got, test.want) + } + }) + } +} + +func TestHasFilePathPrefix(t *testing.T) { + type test struct { + desc, path, prefix string + want bool + } + var tests []test + if runtime.GOOS == "windows" { + tests = []test{ + { + desc: "empty_prefix", + path: `c:\a\b`, + prefix: "", + want: true, + }, { + desc: "drive_prefix", + path: `c:\a\b`, + prefix: `c:\`, + want: true, + }, { + desc: "partial_prefix", + path: `c:\a\b`, + prefix: `c:\a`, + want: true, + }, { + desc: "full_prefix", + path: `c:\a\b`, + prefix: `c:\a\b`, + want: true, + }, { + desc: "partial_component", + path: `c:\aa\b`, + prefix: `c:\a`, + want: false, + }, + } + } else { + tests = []test{ + { + desc: "empty_prefix", + path: "/a/b", + prefix: "", + want: true, + }, { + desc: "partial_prefix", + path: "/a/b", + prefix: "/a", + want: true, + }, { + desc: "full_prefix", + path: "/a/b", + prefix: "/a/b", + want: true, + }, { + desc: "partial_component", + path: "/aa/b", + prefix: "/a", + want: false, + }, + } + } + for _, test := range tests { + t.Run(test.desc, func(t *testing.T) { + if got := hasFilePathPrefix(test.path, test.prefix); got != test.want { + t.Errorf("hasFilePathPrefix(%q, %q): got %v, want %v", test.path, test.prefix, got, test.want) + } + }) + } +} + +func TestTrimFilePathPrefix(t *testing.T) { + type test struct { + desc, path, prefix, want string + } + var tests []test + if runtime.GOOS == "windows" { + tests = []test{ + // Note: these two cases in which the result preserves the leading \ + // don't come up in reality in gorelease. That's because prefix is + // always far to the right of the path parts (ex github.com/foo/bar + // in C:\Users\foo\AppData\Local\Temp\...\github.com\foo\bar). + { + desc: "empty_prefix", + path: `c:\a\b`, + prefix: "", + want: `\a\b`, + }, { + desc: "partial_component", + path: `c:\aa\b`, + prefix: `c:\a`, + want: `\aa\b`, + }, + + { + desc: "drive_prefix", + path: `c:\a\b`, + prefix: `c:\`, + want: `a\b`, + }, { + desc: "partial_prefix", + path: `c:\a\b`, + prefix: `c:\a`, + want: `b`, + }, { + desc: "full_prefix", + path: `c:\a\b`, + prefix: `c:\a\b`, + want: "", + }, + } + } else { + tests = []test{ + { + desc: "empty_prefix", + path: "/a/b", + prefix: "", + want: "/a/b", + }, { + desc: "partial_prefix", + path: "/a/b", + prefix: "/a", + want: "b", + }, { + desc: "full_prefix", + path: "/a/b", + prefix: "/a/b", + want: "", + }, { + desc: "partial_component", + path: "/aa/b", + prefix: "/a", + want: "/aa/b", + }, + } + } + for _, test := range tests { + t.Run(test.desc, func(t *testing.T) { + if got := trimFilePathPrefix(test.path, test.prefix); got != test.want { + t.Errorf("hasFilePathPrefix(%q, %q): got %v, want %v", test.path, test.prefix, got, test.want) + } + }) + } +} + +func TestTrimPathPrefix(t *testing.T) { + for _, test := range []struct { + desc, path, prefix, want string + }{ + { + desc: "empty_prefix", + path: "a/b", + prefix: "", + want: "a/b", + }, { + desc: "abs_empty_prefix", + path: "/a/b", + prefix: "", + want: "/a/b", + }, { + desc: "partial_prefix", + path: "a/b", + prefix: "a", + want: "b", + }, { + desc: "full_prefix", + path: "a/b", + prefix: "a/b", + want: "", + }, { + desc: "partial_component", + path: "aa/b", + prefix: "a", + want: "aa/b", + }, + } { + t.Run(test.desc, func(t *testing.T) { + if got := trimPathPrefix(test.path, test.prefix); got != test.want { + t.Errorf("trimPathPrefix(%q, %q): got %q, want %q", test.path, test.prefix, got, test.want) + } + }) + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/proxy_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/proxy_test.go new file mode 100644 index 0000000..d91d983 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/proxy_test.go @@ -0,0 +1,207 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "sort" + "strings" + "time" + + "golang.org/x/mod/module" + "golang.org/x/mod/semver" + "golang.org/x/mod/zip" + "golang.org/x/tools/txtar" +) + +// buildProxyDir constructs a temporary directory suitable for use as a +// module proxy with a file:// URL. The caller is responsible for deleting +// the directory when it's no longer needed. +// +// proxyVersions must be a map of module version true. If proxyVersions is +// empty, all modules in mod/ will be included in the proxy list. If proxy +// versions is non-empty, only those modules in mod/ that match an entry in +// proxyVersions will be included. +func buildProxyDir(proxyVersions map[module.Version]bool, tests []*test) (proxyDir, proxyURL string, err error) { + proxyDir, err = ioutil.TempDir("", "gorelease-proxy") + if err != nil { + return "", "", err + } + + txtarPaths, err := filepath.Glob(filepath.FromSlash("testdata/mod/*.txt")) + if err != nil { + return "", "", err + } + + // Map of modPath to versions for that modPath. + versionLists := make(map[string][]string) + + for _, t := range tests { + versionLists[t.modPath] = []string{} + modDir := filepath.Join(proxyDir, t.modPath, "@v") + if err := os.MkdirAll(modDir, 0777); err != nil { + return "", "", err + } + } + + for _, txtarPath := range txtarPaths { + base := filepath.Base(txtarPath) + stem := base[:len(base)-len(".txt")] + i := strings.LastIndexByte(base, '_') + if i < 0 { + return "", "", fmt.Errorf("invalid module archive: %s", base) + } + modPath := strings.ReplaceAll(stem[:i], "_", "/") + version := stem[i+1:] + mv := module.Version{ + Path: modPath, + Version: version, + } + + // User has supplied proxyVersions. Honor proxy versions by only + // accepting those versions supplied in proxyVersions. + if len(proxyVersions) > 0 { + if !proxyVersions[mv] { + // modPath@version is not in proxyVersions: skip. + continue + } + } + + versionLists[modPath] = append(versionLists[modPath], version) + + modDir := filepath.Join(proxyDir, modPath, "@v") + if err := os.MkdirAll(modDir, 0777); err != nil { + return "", "", err + } + + arc, err := txtar.ParseFile(txtarPath) + if err != nil { + return "", "", err + } + + isCanonical := version == module.CanonicalVersion(version) + var zipContents []zip.File + var haveInfo, haveMod bool + var goMod txtar.File + for _, af := range arc.Files { + if !isCanonical && af.Name != ".info" { + return "", "", fmt.Errorf("%s: version is non-canonical but contains files other than .info", txtarPath) + } + if af.Name == ".info" || af.Name == ".mod" { + if af.Name == ".info" { + haveInfo = true + } else { + haveMod = true + } + outPath := filepath.Join(modDir, version+af.Name) + if err := ioutil.WriteFile(outPath, af.Data, 0666); err != nil { + return "", "", err + } + continue + } + if af.Name == "go.mod" { + goMod = af + } + + zipContents = append(zipContents, txtarFile{af}) + } + if !isCanonical && !haveInfo { + return "", "", fmt.Errorf("%s: version is non-canonical but does not have .info", txtarPath) + } + + if !haveInfo { + outPath := filepath.Join(modDir, version+".info") + outContent := fmt.Sprintf(`{"Version":"%s"}`, version) + if err := ioutil.WriteFile(outPath, []byte(outContent), 0666); err != nil { + return "", "", err + } + } + if !haveMod && goMod.Name != "" { + outPath := filepath.Join(modDir, version+".mod") + if err := ioutil.WriteFile(outPath, goMod.Data, 0666); err != nil { + return "", "", err + } + } + + if len(zipContents) > 0 { + zipPath := filepath.Join(modDir, version+".zip") + zipFile, err := os.Create(zipPath) + if err != nil { + return "", "", err + } + defer zipFile.Close() + if err := zip.Create(zipFile, module.Version{Path: modPath, Version: version}, zipContents); err != nil { + return "", "", err + } + if err := zipFile.Close(); err != nil { + return "", "", err + } + } + } + + buf := &bytes.Buffer{} + for modPath, versions := range versionLists { + outPath := filepath.Join(proxyDir, modPath, "@v", "list") + sort.Slice(versions, func(i, j int) bool { + return semver.Compare(versions[i], versions[j]) < 0 + }) + for _, v := range versions { + fmt.Fprintln(buf, v) + } + if err := ioutil.WriteFile(outPath, buf.Bytes(), 0666); err != nil { + return "", "", err + } + buf.Reset() + } + + // Make sure the URL path starts with a slash on Windows. Absolute paths + // normally start with a drive letter. + // TODO(golang.org/issue/32456): use url.FromFilePath when implemented. + if strings.HasPrefix(proxyDir, "/") { + proxyURL = "file://" + proxyDir + } else { + proxyURL = "file:///" + filepath.FromSlash(proxyDir) + } + return proxyDir, proxyURL, nil +} + +type txtarFile struct { + f txtar.File +} + +func (f txtarFile) Path() string { return f.f.Name } +func (f txtarFile) Lstat() (os.FileInfo, error) { return txtarFileInfo{f.f}, nil } +func (f txtarFile) Open() (io.ReadCloser, error) { + return ioutil.NopCloser(bytes.NewReader(f.f.Data)), nil +} + +type txtarFileInfo struct { + f txtar.File +} + +func (f txtarFileInfo) Name() string { return f.f.Name } +func (f txtarFileInfo) Size() int64 { return int64(len(f.f.Data)) } +func (f txtarFileInfo) Mode() os.FileMode { return 0444 } +func (f txtarFileInfo) ModTime() time.Time { return time.Time{} } +func (f txtarFileInfo) IsDir() bool { return false } +func (f txtarFileInfo) Sys() interface{} { return nil } + +func extractTxtar(destDir string, arc *txtar.Archive) error { + for _, f := range arc.Files { + outPath := filepath.Join(destDir, f.Name) + if err := os.MkdirAll(filepath.Dir(outPath), 0777); err != nil { + return err + } + if err := ioutil.WriteFile(outPath, f.Data, 0666); err != nil { + return err + } + } + return nil +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/report.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/report.go new file mode 100644 index 0000000..3895c98 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/report.go @@ -0,0 +1,463 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + "strings" + + "golang.org/x/exp/apidiff" + "golang.org/x/mod/module" + "golang.org/x/mod/semver" + "golang.org/x/tools/go/packages" +) + +// report describes the differences in the public API between two versions +// of a module. +type report struct { + // base contains information about the "old" module version being compared + // against. base.version may be "none", indicating there is no base version + // (for example, if this is the first release). base.version may not be "". + base moduleInfo + + // release contains information about the version of the module to release. + // The version may be set explicitly with -version or suggested using + // suggestVersion, in which case release.versionInferred is true. + release moduleInfo + + // packages is a list of package reports, describing the differences + // for individual packages, sorted by package path. + packages []packageReport + + // versionInvalid explains why the proposed or suggested version is not valid. + versionInvalid *versionMessage + + // haveCompatibleChanges is true if there are any backward-compatible + // changes in non-internal packages. + haveCompatibleChanges bool + + // haveIncompatibleChanges is true if there are any backward-incompatible + // changes in non-internal packages. + haveIncompatibleChanges bool + + // haveBaseErrors is true if there were errors loading packages + // in the base version. + haveBaseErrors bool + + // haveReleaseErrors is true if there were errors loading packages + // in the release version. + haveReleaseErrors bool +} + +// String returns a human-readable report that lists errors, compatible changes, +// and incompatible changes in each package. If releaseVersion is set, the +// report states whether releaseVersion is valid (and why). If releaseVersion is +// not set, it suggests a new version. +func (r *report) String() string { + buf := &strings.Builder{} + for _, p := range r.packages { + buf.WriteString(p.String()) + } + + if !r.canVerifyReleaseVersion() { + return buf.String() + } + + if len(r.release.diagnostics) > 0 { + buf.WriteString("# diagnostics\n") + for _, d := range r.release.diagnostics { + fmt.Fprintln(buf, d) + } + buf.WriteByte('\n') + } + + buf.WriteString("# summary\n") + baseVersion := r.base.version + if r.base.modPath != r.release.modPath { + baseVersion = r.base.modPath + "@" + baseVersion + } + if r.base.versionInferred { + fmt.Fprintf(buf, "Inferred base version: %s\n", baseVersion) + } else if r.base.versionQuery != "" { + fmt.Fprintf(buf, "Base version: %s (%s)\n", baseVersion, r.base.versionQuery) + } + + if r.versionInvalid != nil { + fmt.Fprintln(buf, r.versionInvalid) + } else if r.release.versionInferred { + if r.release.tagPrefix == "" { + fmt.Fprintf(buf, "Suggested version: %s\n", r.release.version) + } else { + fmt.Fprintf(buf, "Suggested version: %[1]s (with tag %[2]s%[1]s)\n", r.release.version, r.release.tagPrefix) + } + } else if r.release.version != "" { + if r.release.tagPrefix == "" { + fmt.Fprintf(buf, "%s is a valid semantic version for this release.\n", r.release.version) + + if semver.Compare(r.release.version, "v0.0.0-99999999999999-zzzzzzzzzzzz") < 0 { + fmt.Fprintf(buf, `Note: %s sorts lower in MVS than pseudo-versions, which may be +unexpected for users. So, it may be better to choose a different suffix.`, r.release.version) + } + } else { + fmt.Fprintf(buf, "%[1]s (with tag %[2]s%[1]s) is a valid semantic version for this release\n", r.release.version, r.release.tagPrefix) + } + } + + if r.versionInvalid == nil && r.haveBaseErrors { + fmt.Fprintln(buf, "Errors were found in the base version. Some API changes may be omitted.") + } + + return buf.String() +} + +func (r *report) addPackage(p packageReport) { + r.packages = append(r.packages, p) + if len(p.baseErrors) == 0 && len(p.releaseErrors) == 0 { + // Only count compatible and incompatible changes if there were no errors. + // When there are errors, definitions may be missing, and fixes may appear + // incompatible when they are not. Changes will still be reported, but + // they won't affect version validation or suggestions. + for _, c := range p.Changes { + if !c.Compatible && len(p.releaseErrors) == 0 { + r.haveIncompatibleChanges = true + } else if c.Compatible && len(p.baseErrors) == 0 && len(p.releaseErrors) == 0 { + r.haveCompatibleChanges = true + } + } + } + if len(p.baseErrors) > 0 { + r.haveBaseErrors = true + } + if len(p.releaseErrors) > 0 { + r.haveReleaseErrors = true + } +} + +// validateReleaseVersion checks whether r.release.version is valid. +// If r.release.version is not valid, an error is returned explaining why. +// r.release.version must be set. +func (r *report) validateReleaseVersion() { + if r.release.version == "" { + panic("validateVersion called without version") + } + setNotValid := func(format string, args ...interface{}) { + r.versionInvalid = &versionMessage{ + message: fmt.Sprintf("%s is not a valid semantic version for this release.", r.release.version), + reason: fmt.Sprintf(format, args...), + } + } + + if r.haveReleaseErrors { + if r.haveReleaseErrors { + setNotValid("Errors were found in one or more packages.") + return + } + } + + // TODO(jayconrod): link to documentation for all of these errors. + + // Check that the major version matches the module path. + _, suffix, ok := module.SplitPathVersion(r.release.modPath) + if !ok { + setNotValid("%s: could not find version suffix in module path", r.release.modPath) + return + } + if suffix != "" { + if suffix[0] != '/' && suffix[0] != '.' { + setNotValid("%s: unknown module path version suffix: %q", r.release.modPath, suffix) + return + } + pathMajor := suffix[1:] + major := semver.Major(r.release.version) + if pathMajor != major { + setNotValid(`The major version %s does not match the major version suffix +in the module path: %s`, major, r.release.modPath) + return + } + } else if major := semver.Major(r.release.version); major != "v0" && major != "v1" { + setNotValid(`The module path does not end with the major version suffix /%s, +which is required for major versions v2 or greater.`, major) + return + } + + for _, v := range r.base.existingVersions { + if semver.Compare(v, r.release.version) == 0 { + setNotValid("version %s already exists", v) + } + } + + // Check that compatible / incompatible changes are consistent. + if semver.Major(r.base.version) == "v0" || r.base.modPath != r.release.modPath { + return + } + if r.haveIncompatibleChanges { + setNotValid("There are incompatible changes.") + return + } + if r.haveCompatibleChanges && semver.MajorMinor(r.base.version) == semver.MajorMinor(r.release.version) { + setNotValid(`There are compatible changes, but the minor version is not incremented +over the base version (%s).`, r.base.version) + return + } + + if r.release.highestTransitiveVersion != "" && semver.Compare(r.release.highestTransitiveVersion, r.release.version) > 0 { + setNotValid(`Module indirectly depends on a higher version of itself (%s). + `, r.release.highestTransitiveVersion) + } +} + +// suggestReleaseVersion suggests a new version consistent with observed +// changes. +func (r *report) suggestReleaseVersion() { + setNotValid := func(format string, args ...interface{}) { + r.versionInvalid = &versionMessage{ + message: "Cannot suggest a release version.", + reason: fmt.Sprintf(format, args...), + } + } + setVersion := func(v string) { + r.release.version = v + r.release.versionInferred = true + } + + if r.base.modPath != r.release.modPath { + setNotValid("Base module path is different from release.") + return + } + + if r.haveReleaseErrors || r.haveBaseErrors { + setNotValid("Errors were found.") + return + } + + var major, minor, patch, pre string + if r.base.version != "none" { + minVersion := r.base.version + if r.release.highestTransitiveVersion != "" && semver.Compare(r.release.highestTransitiveVersion, minVersion) > 0 { + setNotValid("Module indirectly depends on a higher version of itself (%s) than the base version (%s).", r.release.highestTransitiveVersion, r.base.version) + return + } + + var err error + major, minor, patch, pre, _, err = parseVersion(minVersion) + if err != nil { + panic(fmt.Sprintf("could not parse base version: %v", err)) + } + } + + if r.haveIncompatibleChanges && r.base.version != "none" && pre == "" && major != "0" { + setNotValid("Incompatible changes were detected.") + return + // TODO(jayconrod): briefly explain how to prepare major version releases + // and link to documentation. + } + + // Check whether we're comparing to the latest version of base. + // + // This could happen further up, but we want the more pressing errors above + // to take precedence. + var latestForBaseMajor string + for _, v := range r.base.existingVersions { + if semver.Major(v) != semver.Major(r.base.version) { + continue + } + if latestForBaseMajor == "" || semver.Compare(latestForBaseMajor, v) < 0 { + latestForBaseMajor = v + } + } + if latestForBaseMajor != "" && latestForBaseMajor != r.base.version { + setNotValid(fmt.Sprintf("Can only suggest a release version when compared against the most recent version of this major: %s.", latestForBaseMajor)) + return + } + + if r.base.version == "none" { + if _, pathMajor, ok := module.SplitPathVersion(r.release.modPath); !ok { + panic(fmt.Sprintf("could not parse module path %q", r.release.modPath)) + } else if pathMajor == "" { + setVersion("v0.1.0") + } else { + setVersion(pathMajor[1:] + ".0.0") + } + return + } + + if pre != "" { + // suggest non-prerelease version + } else if r.haveCompatibleChanges || (r.haveIncompatibleChanges && major == "0") || r.requirementsChanged() { + minor = incDecimal(minor) + patch = "0" + } else { + patch = incDecimal(patch) + } + setVersion(fmt.Sprintf("v%s.%s.%s", major, minor, patch)) + return +} + +// canVerifyReleaseVersion returns true if we can safely suggest a new version +// or if we can verify the version passed in with -version is safe to tag. +func (r *report) canVerifyReleaseVersion() bool { + // For now, return true if the base and release module paths are the same, + // ignoring the major version suffix. + // TODO(#37562, #39192, #39666, #40267): there are many more situations when + // we can't verify a new version. + basePath := strings.TrimSuffix(r.base.modPath, r.base.modPathMajor) + releasePath := strings.TrimSuffix(r.release.modPath, r.release.modPathMajor) + return basePath == releasePath +} + +// requirementsChanged reports whether requirements have changed from base to +// version. +// +// requirementsChanged reports true for, +// - A requirement was upgraded to a higher minor version. +// - A requirement was added. +// - The version of Go was incremented. +// +// It does not report true when, for example, a requirement was downgraded or +// remove. We care more about the former since that might force dependent +// modules that have the same dependency to upgrade. +func (r *report) requirementsChanged() bool { + if r.base.goModFile == nil { + // There wasn't a modfile before, and now there is. + return true + } + + // baseReqs is a map of module path to MajorMinor of the base module + // requirements. + baseReqs := make(map[string]string) + for _, r := range r.base.goModFile.Require { + baseReqs[r.Mod.Path] = r.Mod.Version + } + + for _, r := range r.release.goModFile.Require { + if _, ok := baseReqs[r.Mod.Path]; !ok { + // A module@version was added to the "require" block between base + // and release. + return true + } + if semver.Compare(semver.MajorMinor(r.Mod.Version), semver.MajorMinor(baseReqs[r.Mod.Path])) > 0 { + // The version of r.Mod.Path increased from base to release. + return true + } + } + + if r.release.goModFile.Go != nil && r.base.goModFile.Go != nil { + if r.release.goModFile.Go.Version > r.base.goModFile.Go.Version { + // The Go version increased from base to release. + return true + } + } + + return false +} + +// isSuccessful returns true the module appears to be safe to release at the +// proposed or suggested version. +func (r *report) isSuccessful() bool { + return len(r.release.diagnostics) == 0 && r.versionInvalid == nil +} + +type versionMessage struct { + message, reason string +} + +func (m versionMessage) String() string { + return m.message + "\n" + m.reason + "\n" +} + +// incDecimal returns the decimal string incremented by 1. +func incDecimal(decimal string) string { + // Scan right to left turning 9s to 0s until you find a digit to increment. + digits := []byte(decimal) + i := len(digits) - 1 + for ; i >= 0 && digits[i] == '9'; i-- { + digits[i] = '0' + } + if i >= 0 { + digits[i]++ + } else { + // digits is all zeros + digits[0] = '1' + digits = append(digits, '0') + } + return string(digits) +} + +type packageReport struct { + apidiff.Report + path string + baseErrors, releaseErrors []packages.Error +} + +func (p *packageReport) String() string { + if len(p.Changes) == 0 && len(p.baseErrors) == 0 && len(p.releaseErrors) == 0 { + return "" + } + buf := &strings.Builder{} + fmt.Fprintf(buf, "# %s\n", p.path) + if len(p.baseErrors) > 0 { + fmt.Fprintf(buf, "## errors in base version:\n") + for _, e := range p.baseErrors { + fmt.Fprintln(buf, e) + } + buf.WriteByte('\n') + } + if len(p.releaseErrors) > 0 { + fmt.Fprintf(buf, "## errors in release version:\n") + for _, e := range p.releaseErrors { + fmt.Fprintln(buf, e) + } + buf.WriteByte('\n') + } + if len(p.Changes) > 0 { + var compatible, incompatible []apidiff.Change + for _, c := range p.Changes { + if c.Compatible { + compatible = append(compatible, c) + } else { + incompatible = append(incompatible, c) + } + } + if len(incompatible) > 0 { + fmt.Fprintf(buf, "## incompatible changes\n") + for _, c := range incompatible { + fmt.Fprintln(buf, c.Message) + } + } + if len(compatible) > 0 { + fmt.Fprintf(buf, "## compatible changes\n") + for _, c := range compatible { + fmt.Fprintln(buf, c.Message) + } + } + buf.WriteByte('\n') + } + return buf.String() +} + +// parseVersion returns the major, minor, and patch numbers, prerelease text, +// and metadata for a given version. +// +// TODO(jayconrod): extend semver to do this and delete this function. +func parseVersion(vers string) (major, minor, patch, pre, meta string, err error) { + if !strings.HasPrefix(vers, "v") { + return "", "", "", "", "", fmt.Errorf("version %q does not start with 'v'", vers) + } + base := vers[1:] + if i := strings.IndexByte(base, '+'); i >= 0 { + meta = base[i+1:] + base = base[:i] + } + if i := strings.IndexByte(base, '-'); i >= 0 { + pre = base[i+1:] + base = base[:i] + } + parts := strings.Split(base, ".") + if len(parts) != 3 { + return "", "", "", "", "", fmt.Errorf("version %q should have three numbers", vers) + } + major, minor, patch = parts[0], parts[1], parts[2] + return major, minor, patch, pre, meta, nil +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/README.md b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/README.md new file mode 100644 index 0000000..3c4880a --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/README.md @@ -0,0 +1,95 @@ +This directory contains most tests for gorelease. Each test runs gorelease (the +`runRelease` function) with a given set of flags in a temporary directory +populated with files specified in the test itself or files from the module test +proxy. The output is compared against a golden `want` file specified in the +test. + +## Test flags + +A specific test may be run with a command like: + + go test -run=TestRelease/basic/v0_patch_suggest + +where `basic/v0_patch_suggest` matches the file +`testdata/basic/v0_patch_suggest.test`. + +The `-u` flag adds or updates the `want` file in each test to match the output. +This is useful for fixing tests after an intended change in behavior. + + go test -run=TestRelease/basic/v0_patch_suggest -u + +The `-testwork` flag instructs the test framework to leave the test's temporary +directory and module proxy in place after running the test. This is useful +for debugging. + +## Test format + +Tests are written in `.test` files in `testdata` subdirectories. Each `.test` +file is a valid txtar file (see `golang.org/x/tools/txtar`). The comment section +contains the test parameters, which are a series of `key=value` pairs. Blank +lines and comments starting with `#` are allowed in this section. Valid keys +are: + +* `mod`: sets the module path. Must be specified together with `version`. Copies + the content of a module out of the test proxy into a temporary directory + where `gorelease` is run. +* `version`: specified together with `mod`, it sets the version to retrieve from + the test proxy. See more information below. +* `base`: the value of the `-base` flag passed to `gorelease`. +* `release`: the value of the `-version` flag passed to `gorelease`. +* `dir`: the directory where `gorelease` should be invoked. Useful when the test + describes a whole repository, and `gorelease` should be invoked in a + subdirectory. +* `error`: true if the test expects a hard error. False by default. +* `success`: true if the test expects a report to be printed with no errors + or diagnostics. True by default. +* `skip`: non-empty if the test should be skipped. The value is a string passed + to `t.Skip`. +* `proxyVersions`: empty if the test should include all `mod/` entries in the + proxy, or else a comma-separated list of the modpath@version's it should + include. + +Test archives have a file named `want`, containing the expected output of the +test. A test will fail if the actual output differs from `want`. + +If the `mod` and `version` parameters are not set, other files will be extracted +to the temporary directory where `gorelease` runs. + +## Populating module contents + +When building a test in `testdata/`, there are two ways to populate the module +directory being tested: + +### Option 1: inline + +You can inline files in the `.test` folder as described in +https://pkg.go.dev/golang.org/x/tools/txtar#hdr-Txtar_format. For example, + +``` +-- some.file -- +the contents +of the file +``` + +### Option 2: specify an existing file + +Often, multiple tests want to share the same setup - the same files. So, users +can write these common files in `testdata/mod/`, and use one of these files as +the module directory contents. + +To specify a file in `testdata/mod/` to use as the module contents. + +## Module format + +Tests run with `GOPROXY` set to a local URL that points to a test proxy. The +test proxy serves modules described by `.txt` files in the `testdata/mod/` +subdirectory. + +Each module is a txtar archive named `$modpath_$version.txt` where `$modpath` +is the module path (with slashes replaced with underscores) and `$version` is +the version. If the archive contains a file named `.mod`, that will be used to +respond to `.mod` requests; otherwise, `go.mod` will be used (`.mod` is only +necessary for modules that lack `go.mod` files). If the archive contains a +file named `.info`, that will be used to respond to `.info` requests; otherwise, +`.info` is synthesized from the version. All other files in the archive are +packed into a `.zip` file to satisfy `.zip` requests. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/alreadyexists/alreadyexists_suggest_major.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/alreadyexists/alreadyexists_suggest_major.test new file mode 100644 index 0000000..bea8be6 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/alreadyexists/alreadyexists_suggest_major.test @@ -0,0 +1,24 @@ +mod=example.com/basic +base=v1.0.1 +success=false +# A() was removed, which is a breaking change: it shouldn't try to suggest a +# higher version. +-- want -- +# example.com/basic/a +## incompatible changes +A: removed +## compatible changes +B: added + +# summary +Cannot suggest a release version. +Incompatible changes were detected. +-- go.mod -- +module example.com/basic + +go 1.12 +-- a/a.go -- +package a + +func B() int { return 0 } + diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/alreadyexists/alreadyexists_suggest_minor.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/alreadyexists/alreadyexists_suggest_minor.test new file mode 100644 index 0000000..40eda64 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/alreadyexists/alreadyexists_suggest_minor.test @@ -0,0 +1,23 @@ +mod=example.com/basic +base=v0.0.1 +success=false +# B() was added, so now it should suggest a new minor version. But, there's a +# later version that already exists: so it should not try to suggest anything at +# all. +-- want -- +# example.com/basic/a +## compatible changes +B: added + +# summary +Cannot suggest a release version. +Can only suggest a release version when compared against the most recent version of this major: v0.1.2. +-- go.mod -- +module example.com/basic + +go 1.12 +-- a/a.go -- +package a + +func A() int { return 0 } +func B() int { return 0 } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/alreadyexists/alreadyexists_suggest_patch.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/alreadyexists/alreadyexists_suggest_patch.test new file mode 100644 index 0000000..209d9a9 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/alreadyexists/alreadyexists_suggest_patch.test @@ -0,0 +1,23 @@ +mod=example.com/basic +base=v0.1.0 +success=false +# A() was changed in a small way, so now it should suggest a new patch version. +# But, there's a later version that already exists: so it should not try to +# suggest anything at all. +-- want -- +# summary +Cannot suggest a release version. +Can only suggest a release version when compared against the most recent version of this major: v0.1.2. +-- go.mod -- +module example.com/basic + +go 1.12 +-- a/a.go -- +package a + +func A() int { return 1 } +func A2() int { return 2 } +-- b/b.go -- +package b + +func B() int { return 3 } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/alreadyexists/alreadyexists_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/alreadyexists/alreadyexists_verify.test new file mode 100644 index 0000000..8ba7cfc --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/alreadyexists/alreadyexists_verify.test @@ -0,0 +1,18 @@ +mod=example.com/basic +base=v0.0.1 +release=v0.1.0 +success=false +# The contents below are a copy of the v0.0.1 contents - nothing has changed. +# But v0.1.0 already exists, so it should present a diagnostic. +-- want -- +# summary +v0.1.0 is not a valid semantic version for this release. +version v0.1.0 already exists +-- go.mod -- +module example.com/basic + +go 1.12 +-- a/a.go -- +package a + +func A() int { return 0 } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/README.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/README.txt new file mode 100644 index 0000000..708a0c1 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/README.txt @@ -0,0 +1,11 @@ +Module example.com/basic tests basic functionality of gorelease. +It verifies that versions are correctly suggested or verified after +various changes. + +All revisions are stored in the mod directory. The same series of +changes is made across three major versions, v0, v1, and v2: + +vX.0.1 - simple package +vX.1.0 - compatible change: add a function and a package +vX.1.1 - internal change: function returns different value +vX.1.2 - incompatible change: delete a function and a package diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_compatible_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_compatible_suggest.test new file mode 100644 index 0000000..6560f55 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_compatible_suggest.test @@ -0,0 +1,15 @@ +mod=example.com/basic +version=v0.1.0 +base=v0.0.1 +proxyVersions=example.com/basic@v0.0.1 +-- want -- +# example.com/basic/a +## compatible changes +A2: added + +# example.com/basic/b +## compatible changes +package added + +# summary +Suggested version: v0.1.0 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_compatible_suggest_git.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_compatible_suggest_git.test new file mode 100644 index 0000000..080cafd --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_compatible_suggest_git.test @@ -0,0 +1,16 @@ +mod=example.com/basic +version=v0.1.0 +base=v0.0.1 +proxyVersions=example.com/basic@v0.0.1 +vcs=git +-- want -- +# example.com/basic/a +## compatible changes +A2: added + +# example.com/basic/b +## compatible changes +package added + +# summary +Suggested version: v0.1.0 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_compatible_suggest_hg.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_compatible_suggest_hg.test new file mode 100644 index 0000000..329ea88 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_compatible_suggest_hg.test @@ -0,0 +1,16 @@ +mod=example.com/basic +version=v0.1.0 +base=v0.0.1 +proxyVersions=example.com/basic@v0.0.1 +vcs=hg +-- want -- +# example.com/basic/a +## compatible changes +A2: added + +# example.com/basic/b +## compatible changes +package added + +# summary +Suggested version: v0.1.0 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_compatible_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_compatible_verify.test new file mode 100644 index 0000000..b5c726d --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_compatible_verify.test @@ -0,0 +1,16 @@ +mod=example.com/basic +version=v0.1.0 +base=v0.0.1 +release=v0.1.0 +proxyVersions=example.com/basic@v0.0.1 +-- want -- +# example.com/basic/a +## compatible changes +A2: added + +# example.com/basic/b +## compatible changes +package added + +# summary +v0.1.0 is a valid semantic version for this release. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_incompatible_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_incompatible_suggest.test new file mode 100644 index 0000000..d07a48f --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_incompatible_suggest.test @@ -0,0 +1,15 @@ +mod=example.com/basic +version=v0.1.2 +base=v0.1.1 +proxyVersions=example.com/basic@v0.1.1 +-- want -- +# example.com/basic/a +## incompatible changes +A2: removed + +# example.com/basic/b +## incompatible changes +package removed + +# summary +Suggested version: v0.2.0 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_incompatible_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_incompatible_verify.test new file mode 100644 index 0000000..b8355ea --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_incompatible_verify.test @@ -0,0 +1,16 @@ +mod=example.com/basic +version=v0.1.2 +base=v0.1.1 +release=v0.1.2 +proxyVersions=example.com/basic@v0.1.1 +-- want -- +# example.com/basic/a +## incompatible changes +A2: removed + +# example.com/basic/b +## incompatible changes +package removed + +# summary +v0.1.2 is a valid semantic version for this release. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_nobase_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_nobase_suggest.test new file mode 100644 index 0000000..b059fc0 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_nobase_suggest.test @@ -0,0 +1,6 @@ +mod=example.com/basic +version=v0.1.1 +base=none +-- want -- +# summary +Suggested version: v0.1.0 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_patch_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_patch_suggest.test new file mode 100644 index 0000000..a5f957a --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_patch_suggest.test @@ -0,0 +1,7 @@ +mod=example.com/basic +version=v0.1.1 +base=v0.1.0 +proxyVersions=example.com/basic@v0.1.0 +-- want -- +# summary +Suggested version: v0.1.1 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_patch_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_patch_verify.test new file mode 100644 index 0000000..d26ff70 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_patch_verify.test @@ -0,0 +1,8 @@ +mod=example.com/basic +version=v0.1.1 +base=v0.1.0 +release=v0.1.1 +proxyVersions=example.com/basic@v0.1.0 +-- want -- +# summary +v0.1.1 is a valid semantic version for this release. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_pre_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_pre_suggest.test new file mode 100644 index 0000000..ca45c40 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_pre_suggest.test @@ -0,0 +1,15 @@ +mod=example.com/basic +version=v0.1.2 +base=v0.1.1-pre +proxyVersions=example.com/basic@v0.1.1-pre +-- want -- +# example.com/basic/a +## incompatible changes +A2: removed + +# example.com/basic/b +## incompatible changes +package removed + +# summary +Suggested version: v0.1.1 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_v1_incompatible_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_v1_incompatible_verify.test new file mode 100644 index 0000000..7a68306 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v0_v1_incompatible_verify.test @@ -0,0 +1,15 @@ +mod=example.com/basic +version=v0.1.2 +base=v0.1.1 +release=v1.0.0 +-- want -- +# example.com/basic/a +## incompatible changes +A2: removed + +# example.com/basic/b +## incompatible changes +package removed + +# summary +v1.0.0 is a valid semantic version for this release. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_autobase_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_autobase_suggest.test new file mode 100644 index 0000000..100cc4c --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_autobase_suggest.test @@ -0,0 +1,6 @@ +mod=example.com/basic +version=v0.1.2 +-- want -- +# summary +Inferred base version: v1.1.2 +Suggested version: v1.1.3 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_autobase_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_autobase_verify.test new file mode 100644 index 0000000..6df9c6e --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_autobase_verify.test @@ -0,0 +1,7 @@ +mod=example.com/basic +version=v1.0.1 +release=v1.0.2 +-- want -- +# summary +Inferred base version: v1.0.1 +v1.0.2 is a valid semantic version for this release. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_compatible_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_compatible_suggest.test new file mode 100644 index 0000000..fe63e75 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_compatible_suggest.test @@ -0,0 +1,15 @@ +mod=example.com/basic +version=v1.1.0 +base=v1.0.1 +proxyVersions=example.com/basic@v1.0.1 +-- want -- +# example.com/basic/a +## compatible changes +A2: added + +# example.com/basic/b +## compatible changes +package added + +# summary +Suggested version: v1.1.0 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_compatible_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_compatible_verify.test new file mode 100644 index 0000000..f552aef --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_compatible_verify.test @@ -0,0 +1,16 @@ +mod=example.com/basic +version=v1.1.0 +base=v1.0.1 +release=v1.1.0 +proxyVersions=example.com/basic@v1.0.1 +-- want -- +# example.com/basic/a +## compatible changes +A2: added + +# example.com/basic/b +## compatible changes +package added + +# summary +v1.1.0 is a valid semantic version for this release. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_fork_base_modpath_version_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_fork_base_modpath_version_verify.test new file mode 100644 index 0000000..a662cb1 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_fork_base_modpath_version_verify.test @@ -0,0 +1,11 @@ +mod=example.com/basicfork +base=example.com/basic@v1.1.1 +version=v1.1.2 +release=v1.1.2 +proxyVersions=example.com/basic@v1.1.1 +-- want -- +# example.com/basic/a +## incompatible changes +A2: removed +## compatible changes +A3: added diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_fork_base_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_fork_base_verify.test new file mode 100644 index 0000000..ff3faab --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_fork_base_verify.test @@ -0,0 +1,15 @@ +# Compare a fork (with module path example.com/basic, downloaded from +# example.com/basicfork) with a local module (with module path +# example.com/basic). +mod=example.com/basic +version=v1.1.2 +base=example.com/basicfork@v1.1.2 +release=v1.1.3 +-- want -- +# example.com/basicfork/a +## incompatible changes +A3: removed + +# example.com/basicfork/b +## incompatible changes +package removed diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_incompatible_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_incompatible_suggest.test new file mode 100644 index 0000000..a955b10 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_incompatible_suggest.test @@ -0,0 +1,16 @@ +mod=example.com/basic +version=v1.1.2 +base=v1.1.1 +success=false +-- want -- +# example.com/basic/a +## incompatible changes +A2: removed + +# example.com/basic/b +## incompatible changes +package removed + +# summary +Cannot suggest a release version. +Incompatible changes were detected. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_incompatible_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_incompatible_verify.test new file mode 100644 index 0000000..655ed6a --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_incompatible_verify.test @@ -0,0 +1,18 @@ +mod=example.com/basic +version=v1.1.2 +base=v1.1.1 +success=false +release=v1.1.2 +proxyVersions=example.com/basic@v1.1.1 +-- want -- +# example.com/basic/a +## incompatible changes +A2: removed + +# example.com/basic/b +## incompatible changes +package removed + +# summary +v1.1.2 is not a valid semantic version for this release. +There are incompatible changes. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_patch_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_patch_suggest.test new file mode 100644 index 0000000..936f26a --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_patch_suggest.test @@ -0,0 +1,7 @@ +mod=example.com/basic +version=v1.1.1 +base=v1.1.0 +proxyVersions=example.com/basic@v1.1.0 +-- want -- +# summary +Suggested version: v1.1.1 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_patch_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_patch_verify.test new file mode 100644 index 0000000..f134744 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_patch_verify.test @@ -0,0 +1,8 @@ +mod=example.com/basic +version=v1.1.1 +base=v1.1.0 +release=v1.1.1 +proxyVersions=example.com/basic@v1.1.0 +-- want -- +# summary +v1.1.1 is a valid semantic version for this release. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_pre_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_pre_suggest.test new file mode 100644 index 0000000..c715603 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_pre_suggest.test @@ -0,0 +1,15 @@ +mod=example.com/basic +version=v1.1.2 +base=v1.1.1-pre +proxyVersions=example.com/basic@v1.1.1-pre +-- want -- +# example.com/basic/a +## incompatible changes +A2: removed + +# example.com/basic/b +## incompatible changes +package removed + +# summary +Suggested version: v1.1.1 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_querybase_higher.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_querybase_higher.test new file mode 100644 index 0000000..ba6838f --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_querybase_higher.test @@ -0,0 +1,7 @@ +mod=example.com/basic +version=v1.0.1 +release=v1.0.1 +base=>v1.0.1 +error=true +-- want -- +base version v1.1.0 (>v1.0.1) must be lower than release version v1.0.1 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_querybase_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_querybase_suggest.test new file mode 100644 index 0000000..c1dfb9d --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_querybase_suggest.test @@ -0,0 +1,8 @@ +mod=example.com/basic +version=v1.0.1 +base=version-1.0.1 +proxyVersions=example.com/basic@version-1.0.1,example.com/basic@v1.0.1 +-- want -- +# summary +Base version: v1.0.1 (version-1.0.1) +Suggested version: v1.0.2 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_querybase_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_querybase_verify.test new file mode 100644 index 0000000..9383c3f --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_querybase_verify.test @@ -0,0 +1,8 @@ +mod=example.com/basic +version=v1.0.1 +base=version-1.0.1 +release=v1.0.2 +-- want -- +# summary +Base version: v1.0.1 (version-1.0.1) +v1.0.2 is a valid semantic version for this release. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_v2_base_modpath_query_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_v2_base_modpath_query_verify.test new file mode 100644 index 0000000..ce6b674 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_v2_base_modpath_query_verify.test @@ -0,0 +1,17 @@ +mod=example.com/basic/v2 +base=example.com/basic@>=v1.1.0 +version=v2.0.1 +release=v2.0.1 +proxyVersions=example.com/basic@v1.1.0 +-- want -- +# example.com/basic/a +## incompatible changes +A2: removed + +# example.com/basic/b +## incompatible changes +package removed + +# summary +Base version: example.com/basic@v1.1.0 (>=v1.1.0) +v2.0.1 is a valid semantic version for this release. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_v2_base_modpath_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_v2_base_modpath_suggest.test new file mode 100644 index 0000000..d70ecc9 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_v2_base_modpath_suggest.test @@ -0,0 +1,17 @@ +mod=example.com/basic/v2 +base=example.com/basic +version=v2.1.0 +success=false +-- want -- +# example.com/basic/a +## compatible changes +A2: added + +# example.com/basic/v2/b +## compatible changes +package added + +# summary +Inferred base version: example.com/basic@v1.1.2 +Cannot suggest a release version. +Base module path is different from release. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_v2_base_modpath_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_v2_base_modpath_verify.test new file mode 100644 index 0000000..85f7f86 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_v2_base_modpath_verify.test @@ -0,0 +1,17 @@ +mod=example.com/basic/v2 +base=example.com/basic +version=v2.1.0 +release=v2.1.0 +proxyVersions=example.com/basic@v1.1.2 +-- want -- +# example.com/basic/a +## compatible changes +A2: added + +# example.com/basic/v2/b +## compatible changes +package added + +# summary +Inferred base version: example.com/basic@v1.1.2 +v2.1.0 is a valid semantic version for this release. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_v2_base_modpath_version_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_v2_base_modpath_version_verify.test new file mode 100644 index 0000000..63d3322 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_v2_base_modpath_version_verify.test @@ -0,0 +1,16 @@ +mod=example.com/basic/v2 +base=example.com/basic@v1.1.0 +version=v2.0.1 +release=v2.0.1 +proxyVersions=example.com/basic@v1.1.0 +-- want -- +# example.com/basic/a +## incompatible changes +A2: removed + +# example.com/basic/b +## incompatible changes +package removed + +# summary +v2.0.1 is a valid semantic version for this release. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_v2_base_version_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_v2_base_version_suggest.test new file mode 100644 index 0000000..683bb33 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_v2_base_version_suggest.test @@ -0,0 +1,8 @@ +mod=example.com/basic/v2 +base=v1.1.0 +version=v2.1.0 +success=false +-- want -- +# summary +Cannot suggest a release version. +Base module path is different from release. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_v2_base_version_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_v2_base_version_verify.test new file mode 100644 index 0000000..bc8e31a --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_v2_base_version_verify.test @@ -0,0 +1,7 @@ +mod=example.com/basic/v2 +base=v1.1.0 +version=v2.1.0 +release=v2.1.0 +-- want -- +# summary +v2.1.0 is a valid semantic version for this release. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_v2_incompatible_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_v2_incompatible_verify.test new file mode 100644 index 0000000..07bbde9 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v1_v2_incompatible_verify.test @@ -0,0 +1,18 @@ +mod=example.com/basic +version=v1.1.2 +base=v1.1.1 +release=v2.0.0 +success=false +-- want -- +# example.com/basic/a +## incompatible changes +A2: removed + +# example.com/basic/b +## incompatible changes +package removed + +# summary +v2.0.0 is not a valid semantic version for this release. +The module path does not end with the major version suffix /v2, +which is required for major versions v2 or greater. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v2_compatible_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v2_compatible_suggest.test new file mode 100644 index 0000000..86e60cb --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v2_compatible_suggest.test @@ -0,0 +1,15 @@ +mod=example.com/basic/v2 +version=v2.1.0 +base=v2.0.1 +proxyVersions=example.com/basic/v2@v2.0.1 +-- want -- +# example.com/basic/v2/a +## compatible changes +A2: added + +# example.com/basic/v2/b +## compatible changes +package added + +# summary +Suggested version: v2.1.0 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v2_compatible_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v2_compatible_verify.test new file mode 100644 index 0000000..79eca35 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v2_compatible_verify.test @@ -0,0 +1,16 @@ +mod=example.com/basic/v2 +version=v2.1.0 +base=v2.0.1 +release=v2.1.0 +proxyVersions=example.com/basic/v2@v2.0.1 +-- want -- +# example.com/basic/v2/a +## compatible changes +A2: added + +# example.com/basic/v2/b +## compatible changes +package added + +# summary +v2.1.0 is a valid semantic version for this release. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v2_incompatible_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v2_incompatible_suggest.test new file mode 100644 index 0000000..43aa3fe --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v2_incompatible_suggest.test @@ -0,0 +1,16 @@ +mod=example.com/basic/v2 +version=v2.1.2 +base=v2.1.1 +success=false +-- want -- +# example.com/basic/v2/a +## incompatible changes +A2: removed + +# example.com/basic/v2/b +## incompatible changes +package removed + +# summary +Cannot suggest a release version. +Incompatible changes were detected. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v2_incompatible_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v2_incompatible_verify.test new file mode 100644 index 0000000..68b7321 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v2_incompatible_verify.test @@ -0,0 +1,18 @@ +mod=example.com/basic/v2 +version=v2.1.2 +base=v2.1.1 +success=false +release=v2.1.2 +proxyVersions=example.com/basic/v2@v2.1.1 +-- want -- +# example.com/basic/v2/a +## incompatible changes +A2: removed + +# example.com/basic/v2/b +## incompatible changes +package removed + +# summary +v2.1.2 is not a valid semantic version for this release. +There are incompatible changes. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v2_nobase_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v2_nobase_suggest.test new file mode 100644 index 0000000..605edf9 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v2_nobase_suggest.test @@ -0,0 +1,6 @@ +mod=example.com/basic/v2 +version=v2.1.1 +base=none +-- want -- +# summary +Suggested version: v2.0.0 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v2_patch_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v2_patch_suggest.test new file mode 100644 index 0000000..b16a863 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v2_patch_suggest.test @@ -0,0 +1,7 @@ +mod=example.com/basic/v2 +version=v2.1.1 +base=v2.1.0 +proxyVersions=example.com/basic/v2@v2.1.0 +-- want -- +# summary +Suggested version: v2.1.1 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v2_patch_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v2_patch_verify.test new file mode 100644 index 0000000..35d617a --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v2_patch_verify.test @@ -0,0 +1,8 @@ +mod=example.com/basic/v2 +version=v2.1.1 +base=v2.1.0 +release=v2.1.1 +proxyVersions=example.com/basic/v2@v2.1.0 +-- want -- +# summary +v2.1.1 is a valid semantic version for this release. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v2_pre_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v2_pre_suggest.test new file mode 100644 index 0000000..75d0c39 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v2_pre_suggest.test @@ -0,0 +1,15 @@ +mod=example.com/basic/v2 +version=v2.1.2 +base=v2.1.1-pre +proxyVersions=example.com/basic/v2@v2.1.1-pre +-- want -- +# example.com/basic/v2/a +## incompatible changes +A2: removed + +# example.com/basic/v2/b +## incompatible changes +package removed + +# summary +Suggested version: v2.1.1 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v3_autobase_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v3_autobase_suggest.test new file mode 100644 index 0000000..eda87d2 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v3_autobase_suggest.test @@ -0,0 +1,9 @@ +mod=example.com/basic/v3 +-- go.mod -- +module example.com/basic/v3 + +go 1.13 +-- want -- +# summary +Inferred base version: none +Suggested version: v3.0.0 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v3_autobase_verify_error.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v3_autobase_verify_error.test new file mode 100644 index 0000000..9519d65 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v3_autobase_verify_error.test @@ -0,0 +1,6 @@ +mod=example.com/basic/v3 +version=v3.0.0-ignore +release=v3.1.0 +error=true +-- want -- +could not find base version. Consider setting -version=v3.0.0 if this is a first release, or explicitly set -base=none: no versions found lower than v3.1.0 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v3_autobase_verify_first.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v3_autobase_verify_first.test new file mode 100644 index 0000000..1cae913 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/basic/v3_autobase_verify_first.test @@ -0,0 +1,7 @@ +mod=example.com/basic/v3 +version=v3.0.0-ignore +release=v3.0.0 +-- want -- +# summary +Inferred base version: none +v3.0.0 is a valid semantic version for this release. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/cgo/README.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/cgo/README.txt new file mode 100644 index 0000000..8bbf9c6 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/cgo/README.txt @@ -0,0 +1,7 @@ +Module example.com/cgo is used to test that packages with cgo code +can be loaded without errors when cgo is enabled. + +TODO(jayconrod): test modules with cgo-only and cgo / pure Go implementations +with CGO_ENABLED=0 and 1. But first, decide how multiple platforms and +build constraints should be handled. Currently, gorelease only considers +the same configuration as 'go list'.
\ No newline at end of file diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/cgo/cgo.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/cgo/cgo.test new file mode 100644 index 0000000..b6cea21 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/cgo/cgo.test @@ -0,0 +1,16 @@ +base=none +release=v1.0.0 +-- go.mod -- +module example.com/cgo + +go 1.13 +-- c.go -- +package cgo + +// const int x = 12; +import "C" + +func X() int { return int(C.x) } +-- want -- +# summary +v1.0.0 is a valid semantic version for this release. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/cycle/README.md b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/cycle/README.md new file mode 100644 index 0000000..3596c8b --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/cycle/README.md @@ -0,0 +1 @@ +This directory is for tests related to module cycles.
\ No newline at end of file diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/cycle/cycle_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/cycle/cycle_suggest.test new file mode 100644 index 0000000..fc108d7 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/cycle/cycle_suggest.test @@ -0,0 +1,6 @@ +mod=example.com/cycle/v2 +version=v2.0.0 +-- want -- +# summary +Inferred base version: v2.0.0 +Suggested version: v2.0.1 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/cycle/cycle_suggest_error.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/cycle/cycle_suggest_error.test new file mode 100644 index 0000000..133e4e3 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/cycle/cycle_suggest_error.test @@ -0,0 +1,8 @@ +mod=example.com/cycle +base=v1.0.0 +version=v1.0.0 +success=false +-- want -- +# summary +Cannot suggest a release version. +Module indirectly depends on a higher version of itself (v1.5.0) than the base version (v1.0.0). diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/cycle/cycle_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/cycle/cycle_verify.test new file mode 100644 index 0000000..84b4106 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/cycle/cycle_verify.test @@ -0,0 +1,9 @@ +mod=example.com/cycle +base=v1.0.0 +version=v1.0.0 +release=v1.0.1 +success=false +-- want -- +# summary +v1.0.1 is not a valid semantic version for this release. +Module indirectly depends on a higher version of itself (v1.5.0). diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/empty/README.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/empty/README.txt new file mode 100644 index 0000000..283befa --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/empty/README.txt @@ -0,0 +1,2 @@ +Module example.com/empty is used to test that gorelease works +in a module with no packages. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/empty/empty.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/empty/empty.test new file mode 100644 index 0000000..e9bebb4 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/empty/empty.test @@ -0,0 +1,8 @@ +mod=example.com/empty +base=v0.0.1 +version=v0.0.2 +release=v0.0.2 +proxyVersions=example.com/empty@v0.0.1 +-- want -- +# summary +v0.0.2 is a valid semantic version for this release. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/errors/README.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/errors/README.txt new file mode 100644 index 0000000..071708a --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/errors/README.txt @@ -0,0 +1,2 @@ +Tests in this directory check that user errors invoking gorelease +are correctly reported. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/errors/bad_filenames.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/errors/bad_filenames.test new file mode 100644 index 0000000..c8bf6e0 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/errors/bad_filenames.test @@ -0,0 +1,17 @@ +mod=example.com/ziperrors +dir=x +base=none +error=true +vcs=git +-- want -- +testdata/this_file_also_has_a_bad_filename'.txt: malformed file path "testdata/this_file_also_has_a_bad_filename'.txt": invalid char '\'' +testdata/this_file_has_a_bad_filename'.txt: malformed file path "testdata/this_file_has_a_bad_filename'.txt": invalid char '\'' +-- x/go.mod -- +module example.com/x + +go 1.12 +-- x/testdata/this_file_has_a_bad_filename'.txt -- +-- x/testdata/this_file_also_has_a_bad_filename'.txt -- +# Verify that errors in submodules are not reported. +-- x/y/go.mod -- +-- x/y/submodule_bad_filename'.txt --
\ No newline at end of file diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/errors/bad_release.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/errors/bad_release.test new file mode 100644 index 0000000..74dc009 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/errors/bad_release.test @@ -0,0 +1,8 @@ +mod=example.com/errors +base=v0.1.0 +release=master +error=true +-- want -- +usage: gorelease [-base=version] [-version=version] +release version "master" is not a canonical semantic version +For more information, run go doc golang.org/x/exp/cmd/gorelease diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/errors/base_higher.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/errors/base_higher.test new file mode 100644 index 0000000..a2325f9 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/errors/base_higher.test @@ -0,0 +1,8 @@ +mod=example.com/errors +base=v0.2.0 +release=v0.1.0 +error=true +-- want -- +usage: gorelease [-base=version] [-version=version] +base version ("v0.2.0") must be lower than release version ("v0.1.0") +For more information, run go doc golang.org/x/exp/cmd/gorelease diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/errors/base_modpath_none.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/errors/base_modpath_none.test new file mode 100644 index 0000000..74a6946 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/errors/base_modpath_none.test @@ -0,0 +1,7 @@ +mod=example.com/basic/v2 +base=example.com/basic@none +error=true +-- want -- +usage: gorelease [-base=version] [-version=version] +base version ("example.com/basic@none") cannot have version "none" with explicit module path +For more information, run go doc golang.org/x/exp/cmd/gorelease diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/errors/errors.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/errors/errors.test new file mode 100644 index 0000000..81adeb5 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/errors/errors.test @@ -0,0 +1,38 @@ +mod=example.com/errors +version=v0.2.0 +base=v0.1.0 +release=v0.2.0 +success=false +proxyVersions=example.com/errors@v0.1.0 +-- want -- +# example.com/errors/added +## errors in release version: +added/added.go:3:15: undeclared name: Missing + +## compatible changes +package added + +# example.com/errors/broken +## errors in release version: +broken/broken.go:3:15: undeclared name: Missing + +## incompatible changes +X: value changed from 12 to unknown + +# example.com/errors/deleted +## errors in base version: +deleted/deleted.go:3:15: undeclared name: Missing + +## incompatible changes +package removed + +# example.com/errors/fixed +## errors in base version: +fixed/fixed.go:3:15: undeclared name: Missing + +## incompatible changes +X: value changed from unknown to 12 + +# summary +v0.2.0 is not a valid semantic version for this release. +Errors were found in one or more packages. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/errors/same_base_release.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/errors/same_base_release.test new file mode 100644 index 0000000..4da457b --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/errors/same_base_release.test @@ -0,0 +1,8 @@ +mod=example.com/errors +base=v0.1.0 +release=v0.1.0 +error=true +-- want -- +usage: gorelease [-base=version] [-version=version] +-base and -version must be different +For more information, run go doc golang.org/x/exp/cmd/gorelease diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/errors/upgrade_base.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/errors/upgrade_base.test new file mode 100644 index 0000000..994b3b7 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/errors/upgrade_base.test @@ -0,0 +1,6 @@ +mod=example.com/errors +version=v0.1.0 +base=upgrade +error=true +-- want -- +could not resolve version example.com/errors@upgrade: query is based on requirements in main go.mod file diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/README.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/README.txt new file mode 100644 index 0000000..c735527 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/README.txt @@ -0,0 +1 @@ +Module example.com/first is used to test the first tag for a major version. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v0_0_0.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v0_0_0.test new file mode 100644 index 0000000..5d473ee --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v0_0_0.test @@ -0,0 +1,12 @@ +mod=example.com/first +base=none +release=v0.0.0 +-- want -- +# summary +v0.0.0 is a valid semantic version for this release. +-- go.mod -- +module example.com/first + +go 1.12 +-- p.go -- +package p diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v0_0_1.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v0_0_1.test new file mode 100644 index 0000000..f32c69e --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v0_0_1.test @@ -0,0 +1,12 @@ +mod=example.com/first +base=none +release=v0.0.1 +-- want -- +# summary +v0.0.1 is a valid semantic version for this release. +-- go.mod -- +module example.com/first + +go 1.12 +-- p.go -- +package p diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v0_1_0-alpha.1.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v0_1_0-alpha.1.test new file mode 100644 index 0000000..90985ee --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v0_1_0-alpha.1.test @@ -0,0 +1,12 @@ +mod=example.com/first +base=none +release=v0.1.0-alpha.1 +-- want -- +# summary +v0.1.0-alpha.1 is a valid semantic version for this release. +-- go.mod -- +module example.com/first + +go 1.12 +-- p.go -- +package p diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v0_1_0.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v0_1_0.test new file mode 100644 index 0000000..05eef2a --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v0_1_0.test @@ -0,0 +1,12 @@ +mod=example.com/first +base=none +release=v0.1.0 +-- want -- +# summary +v0.1.0 is a valid semantic version for this release. +-- go.mod -- +module example.com/first + +go 1.12 +-- p.go -- +package p diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v0_err.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v0_err.test new file mode 100644 index 0000000..c655554 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v0_err.test @@ -0,0 +1,19 @@ +mod=example.com/first +base=none +release=v0.0.0 +success=false + +# TODO(golang.org/issue/36087): go list doesn't report positions in correct +# place for scanner errors. +skip=packages.Load gives error with extra "-: " prefix +-- want -- +example.com/first +----------------- +errors in new version: + p.go:1:9: illegal character U+003F '?' +-- go.mod -- +module example.com/first + +go 1.12 +-- p.go -- +package ? diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v1_0_0.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v1_0_0.test new file mode 100644 index 0000000..c7400dc --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v1_0_0.test @@ -0,0 +1,12 @@ +mod=example.com/first +base=none +release=v1.0.0 +-- want -- +# summary +v1.0.0 is a valid semantic version for this release. +-- go.mod -- +module example.com/first + +go 1.12 +-- p.go -- +package p diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v1_2_3_explicit_none_base.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v1_2_3_explicit_none_base.test new file mode 100644 index 0000000..2e1588f --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v1_2_3_explicit_none_base.test @@ -0,0 +1,13 @@ +mod=example.com/first +base=none +release=v1.2.3 +proxyVersions= +-- want -- +# summary +v1.2.3 is a valid semantic version for this release. +-- go.mod -- +module example.com/first + +go 1.12 +-- p.go -- +package p diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v2_err.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v2_err.test new file mode 100644 index 0000000..dfc71d5 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v2_err.test @@ -0,0 +1,19 @@ +mod=example.com/first/v2 +base=none +release=v2.0.0 +success=false + +# TODO(golang.org/issue/36087): go list doesn't report positions in correct +# place for scanner errors. +skip=packages.Load gives error with extra "-: " prefix +-- want -- +example.com/first +----------------- +errors in new version: + p.go:1:9: illegal character U+003F '?' +-- go.mod -- +module example.com/first + +go 1.12 +-- p.go -- +package ? diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v2_moderr.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v2_moderr.test new file mode 100644 index 0000000..833cfa9 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/first/v2_moderr.test @@ -0,0 +1,15 @@ +mod=example.com/first +base=none +release=v2.0.0 +success=false +-- want -- +# summary +v2.0.0 is not a valid semantic version for this release. +The module path does not end with the major version suffix /v2, +which is required for major versions v2 or greater. +-- go.mod -- +module example.com/first + +go 1.12 +-- p.go -- +package p diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/README.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/README.txt new file mode 100644 index 0000000..e153198 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/README.txt @@ -0,0 +1,7 @@ +Tests in this directory cover scenarios where errors in a package are fixed. + +v1.0.0 is used as the base version for all tests. +It has an error: the return type of bad.Broken is undefined. + +Each test fixes the error and may make other changes (compatible or not). +Note that fixing a type error in the API appears to be an incompatible change. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/compatible_other_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/compatible_other_suggest.test new file mode 100644 index 0000000..d545be8 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/compatible_other_suggest.test @@ -0,0 +1,19 @@ +mod=example.com/fix +base=v1.0.0 +version=v1.1.0-compatible-other +success=false +-- want -- +# example.com/fix/bad +## errors in base version: +bad/bad.go:3:15: undeclared name: NOTYPE + +## incompatible changes +Broken: changed from func() invalid type to func() int + +# example.com/fix/good +## compatible changes +Better: added + +# summary +Cannot suggest a release version. +Errors were found. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/compatible_other_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/compatible_other_verify.test new file mode 100644 index 0000000..484c2af --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/compatible_other_verify.test @@ -0,0 +1,19 @@ +mod=example.com/fix +base=v1.0.0 +version=v1.1.0-compatible-other +release=v1.1.0 +-- want -- +# example.com/fix/bad +## errors in base version: +bad/bad.go:3:15: undeclared name: NOTYPE + +## incompatible changes +Broken: changed from func() invalid type to func() int + +# example.com/fix/good +## compatible changes +Better: added + +# summary +v1.1.0 is a valid semantic version for this release. +Errors were found in the base version. Some API changes may be omitted. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/compatible_other_verify_err.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/compatible_other_verify_err.test new file mode 100644 index 0000000..d8d3a92 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/compatible_other_verify_err.test @@ -0,0 +1,21 @@ +mod=example.com/fix +base=v1.0.0 +version=v1.1.0-compatible-other +release=v1.0.1 +success=false +-- want -- +# example.com/fix/bad +## errors in base version: +bad/bad.go:3:15: undeclared name: NOTYPE + +## incompatible changes +Broken: changed from func() invalid type to func() int + +# example.com/fix/good +## compatible changes +Better: added + +# summary +v1.0.1 is not a valid semantic version for this release. +There are compatible changes, but the minor version is not incremented +over the base version (v1.0.0). diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/compatible_same_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/compatible_same_suggest.test new file mode 100644 index 0000000..a57baa2 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/compatible_same_suggest.test @@ -0,0 +1,17 @@ +mod=example.com/fix +base=v1.0.0 +version=v1.1.0-compatible-same +success=false +-- want -- +# example.com/fix/bad +## errors in base version: +bad/bad.go:3:15: undeclared name: NOTYPE + +## incompatible changes +Broken: changed from func() invalid type to func() int +## compatible changes +Worse: added + +# summary +Cannot suggest a release version. +Errors were found. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/compatible_same_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/compatible_same_verify.test new file mode 100644 index 0000000..6f1c335 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/compatible_same_verify.test @@ -0,0 +1,17 @@ +mod=example.com/fix +base=v1.0.0 +version=v1.1.0-compatible-same +release=v1.0.1 # not actually valid, but gorelease can't tell +-- want -- +# example.com/fix/bad +## errors in base version: +bad/bad.go:3:15: undeclared name: NOTYPE + +## incompatible changes +Broken: changed from func() invalid type to func() int +## compatible changes +Worse: added + +# summary +v1.0.1 is a valid semantic version for this release. +Errors were found in the base version. Some API changes may be omitted. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/incompatible_other_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/incompatible_other_suggest.test new file mode 100644 index 0000000..6432119 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/incompatible_other_suggest.test @@ -0,0 +1,19 @@ +mod=example.com/fix +base=v1.0.0 +version=v1.1.0-incompatible-other +success=false +-- want -- +# example.com/fix/bad +## errors in base version: +bad/bad.go:3:15: undeclared name: NOTYPE + +## incompatible changes +Broken: changed from func() invalid type to func() int + +# example.com/fix/good +## incompatible changes +Good: changed from func() int to func() string + +# summary +Cannot suggest a release version. +Errors were found. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/incompatible_other_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/incompatible_other_verify.test new file mode 100644 index 0000000..f6fa31c --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/incompatible_other_verify.test @@ -0,0 +1,20 @@ +mod=example.com/fix +base=v1.0.0 +version=v1.1.0-incompatible-other +release=v1.1.0 +success=false +-- want -- +# example.com/fix/bad +## errors in base version: +bad/bad.go:3:15: undeclared name: NOTYPE + +## incompatible changes +Broken: changed from func() invalid type to func() int + +# example.com/fix/good +## incompatible changes +Good: changed from func() int to func() string + +# summary +v1.1.0 is not a valid semantic version for this release. +There are incompatible changes. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/incompatible_same_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/incompatible_same_suggest.test new file mode 100644 index 0000000..6ad492c --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/incompatible_same_suggest.test @@ -0,0 +1,16 @@ +mod=example.com/fix +base=v1.0.0 +version=v1.1.0-incompatible-same +success=false +-- want -- +# example.com/fix/bad +## errors in base version: +bad/bad.go:3:15: undeclared name: NOTYPE + +## incompatible changes +Bad: changed from func() int to func() string +Broken: changed from func() invalid type to func() int + +# summary +Cannot suggest a release version. +Errors were found. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/incompatible_same_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/incompatible_same_verify.test new file mode 100644 index 0000000..e210aec --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/incompatible_same_verify.test @@ -0,0 +1,16 @@ +mod=example.com/fix +base=v1.0.0 +version=v1.1.0-incompatible-same +release=v1.0.1 # not actually valid, but gorelease can't tell +-- want -- +# example.com/fix/bad +## errors in base version: +bad/bad.go:3:15: undeclared name: NOTYPE + +## incompatible changes +Bad: changed from func() int to func() string +Broken: changed from func() invalid type to func() int + +# summary +v1.0.1 is a valid semantic version for this release. +Errors were found in the base version. Some API changes may be omitted. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/patch_suggest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/patch_suggest.test new file mode 100644 index 0000000..20360d6 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/patch_suggest.test @@ -0,0 +1,15 @@ +mod=example.com/fix +base=v1.0.0 +version=v1.0.1-patch +success=false +-- want -- +# example.com/fix/bad +## errors in base version: +bad/bad.go:3:15: undeclared name: NOTYPE + +## incompatible changes +Broken: changed from func() invalid type to func() int + +# summary +Cannot suggest a release version. +Errors were found. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/patch_verify.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/patch_verify.test new file mode 100644 index 0000000..50b55be --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/fix/patch_verify.test @@ -0,0 +1,15 @@ +mod=example.com/fix +base=v1.0.0 +version=v1.0.1-patch +release=v1.0.1 +-- want -- +# example.com/fix/bad +## errors in base version: +bad/bad.go:3:15: undeclared name: NOTYPE + +## incompatible changes +Broken: changed from func() invalid type to func() int + +# summary +v1.0.1 is a valid semantic version for this release. +Errors were found in the base version. Some API changes may be omitted. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/generics/changed_param.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/generics/changed_param.test new file mode 100644 index 0000000..8415e48 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/generics/changed_param.test @@ -0,0 +1,25 @@ +mod=example.com/generics +base=v0.0.1 +-- want -- +# example.com/generics/a +## incompatible changes +Foo: changed from Foo[V any] to Foo[V Number] +## compatible changes +Number: added + +# summary +Suggested version: v0.1.0 +-- go.mod -- +module example.com/generics + +go 1.18 +-- a/a.go -- +package a + +type Number interface { + int64 | float64 +} + +type Foo[V Number] interface { + Value() any +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/generics/changed_return.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/generics/changed_return.test new file mode 100644 index 0000000..1592d64 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/generics/changed_return.test @@ -0,0 +1,19 @@ +mod=example.com/generics +base=v0.0.1 +-- want -- +# example.com/generics/a +## incompatible changes +Foo[V any].Value: changed from func() V to func() int + +# summary +Suggested version: v0.1.0 +-- go.mod -- +module example.com/generics + +go 1.18 +-- a/a.go -- +package a + +type Foo[V any] interface { + Value() int +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/generics/unchanged.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/generics/unchanged.test new file mode 100644 index 0000000..6cf0d05 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/generics/unchanged.test @@ -0,0 +1,15 @@ +mod=example.com/generics +base=v0.0.1 +-- want -- +# summary +Suggested version: v0.0.2 +-- go.mod -- +module example.com/generics + +go 1.18 +-- a/a.go -- +package a + +type Foo[V any] interface { + Value() V +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/internalcompat/README.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/internalcompat/README.txt new file mode 100644 index 0000000..e3de7e5 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/internalcompat/README.txt @@ -0,0 +1,20 @@ +Modules example.com/internalcompat/{a,b} are copies. One could be a fork +of the other. An external package p exposes a type from a package q +within the same module. + +gorelease should not report differences between these packages. The types +are distinct, but they correspond (in apidiff terminology), which is the +important property when considering differences between modules. + +There are three use cases to consider: + +1. One module substitutes for the other via a `replace` directive. + Only the replacement module is used, and the package paths are effectively + identical, so the types are not distinct. +2. One module subsititutes for the other by rewriting `import` statements + globally. All references to the original type become references to the + new type, so there is no conflict. +3. One module substitutes for the other by rewriting some `import` statements + but not others (for example, those within a specific consumer package). + In this case, the types are distinct, and even if there are no changes, + the types are not compatible. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/internalcompat/internalcompat.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/internalcompat/internalcompat.test new file mode 100644 index 0000000..9bf59a3 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/internalcompat/internalcompat.test @@ -0,0 +1,5 @@ +mod=example.com/internalcompat/b +version=v1.0.0 +release=v1.0.1 +base=example.com/internalcompat/a@v1.0.0 +-- want -- diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/main/README.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/main/README.txt new file mode 100644 index 0000000..a8d8104 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/main/README.txt @@ -0,0 +1,3 @@ +Module example.com/main is used to test changes in main packages. +Main packages aren't importable, so changes to exported functions should not +be reported. But we should still report when packages are added or deleted. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/main/add.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/main/add.test new file mode 100644 index 0000000..26089ad --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/main/add.test @@ -0,0 +1,21 @@ +mod=example.com/main +base=v0.0.1 +-- want -- +# example.com/main/b +## compatible changes +package added + +# summary +Suggested version: v0.1.0 +-- go.mod -- +module example.com/main + +go 1.14 +-- a/a.go -- +package main + +func main() {} +-- b/b.go -- +package main + +func main() {} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/main/change.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/main/change.test new file mode 100644 index 0000000..6960373 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/main/change.test @@ -0,0 +1,15 @@ +mod=example.com/main +base=v0.0.1 +-- want -- +# summary +Suggested version: v0.0.2 +-- go.mod -- +module example.com/main + +go 1.14 +-- a/a.go -- +package main + +func Foo() {} + +func main() { Foo() } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/main/remove.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/main/remove.test new file mode 100644 index 0000000..702e1d1 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/main/remove.test @@ -0,0 +1,13 @@ +mod=example.com/main +base=v0.0.1 +-- want -- +# example.com/main/a +## incompatible changes +package removed + +# summary +Suggested version: v0.1.0 +-- go.mod -- +module example.com/main + +go 1.14 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v0.0.1.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v0.0.1.txt new file mode 100644 index 0000000..e5352bf --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v0.0.1.txt @@ -0,0 +1,8 @@ +-- go.mod -- +module example.com/basic + +go 1.12 +-- a/a.go -- +package a + +func A() int { return 0 } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v0.1.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v0.1.0.txt new file mode 100644 index 0000000..bb39290 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v0.1.0.txt @@ -0,0 +1,13 @@ +-- go.mod -- +module example.com/basic + +go 1.12 +-- a/a.go -- +package a + +func A() int { return 0 } +func A2() int { return 2 } +-- b/b.go -- +package b + +func B() int { return 3 } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v0.1.1-pre.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v0.1.1-pre.txt new file mode 100644 index 0000000..743517b --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v0.1.1-pre.txt @@ -0,0 +1,13 @@ +-- go.mod -- +module example.com/basic + +go 1.12 +-- a/a.go -- +package a + +func A() int { return 1 } +func A2() int { return 2 } +-- b/b.go -- +package b + +func B() int { return 3 } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v0.1.1.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v0.1.1.txt new file mode 100644 index 0000000..743517b --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v0.1.1.txt @@ -0,0 +1,13 @@ +-- go.mod -- +module example.com/basic + +go 1.12 +-- a/a.go -- +package a + +func A() int { return 1 } +func A2() int { return 2 } +-- b/b.go -- +package b + +func B() int { return 3 } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v0.1.2.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v0.1.2.txt new file mode 100644 index 0000000..4055eaa --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v0.1.2.txt @@ -0,0 +1,8 @@ +-- go.mod -- +module example.com/basic + +go 1.12 +-- a/a.go -- +package a + +func A() int { return 1 } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v1.0.1.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v1.0.1.txt new file mode 100644 index 0000000..e5352bf --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v1.0.1.txt @@ -0,0 +1,8 @@ +-- go.mod -- +module example.com/basic + +go 1.12 +-- a/a.go -- +package a + +func A() int { return 0 } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v1.1.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v1.1.0.txt new file mode 100644 index 0000000..bb39290 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v1.1.0.txt @@ -0,0 +1,13 @@ +-- go.mod -- +module example.com/basic + +go 1.12 +-- a/a.go -- +package a + +func A() int { return 0 } +func A2() int { return 2 } +-- b/b.go -- +package b + +func B() int { return 3 } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v1.1.1-pre.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v1.1.1-pre.txt new file mode 100644 index 0000000..743517b --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v1.1.1-pre.txt @@ -0,0 +1,13 @@ +-- go.mod -- +module example.com/basic + +go 1.12 +-- a/a.go -- +package a + +func A() int { return 1 } +func A2() int { return 2 } +-- b/b.go -- +package b + +func B() int { return 3 } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v1.1.1.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v1.1.1.txt new file mode 100644 index 0000000..743517b --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v1.1.1.txt @@ -0,0 +1,13 @@ +-- go.mod -- +module example.com/basic + +go 1.12 +-- a/a.go -- +package a + +func A() int { return 1 } +func A2() int { return 2 } +-- b/b.go -- +package b + +func B() int { return 3 } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v1.1.2.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v1.1.2.txt new file mode 100644 index 0000000..4055eaa --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v1.1.2.txt @@ -0,0 +1,8 @@ +-- go.mod -- +module example.com/basic + +go 1.12 +-- a/a.go -- +package a + +func A() int { return 1 } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v2_v2.0.1.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v2_v2.0.1.txt new file mode 100644 index 0000000..97ea69f --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v2_v2.0.1.txt @@ -0,0 +1,8 @@ +-- go.mod -- +module example.com/basic/v2 + +go 1.12 +-- a/a.go -- +package a + +func A() int { return 0 } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v2_v2.1.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v2_v2.1.0.txt new file mode 100644 index 0000000..e3593b9 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v2_v2.1.0.txt @@ -0,0 +1,13 @@ +-- go.mod -- +module example.com/basic/v2 + +go 1.12 +-- a/a.go -- +package a + +func A() int { return 0 } +func A2() int { return 2 } +-- b/b.go -- +package b + +func B() int { return 3 } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v2_v2.1.1-pre.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v2_v2.1.1-pre.txt new file mode 100644 index 0000000..aaa86be --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v2_v2.1.1-pre.txt @@ -0,0 +1,13 @@ +-- go.mod -- +module example.com/basic/v2 + +go 1.12 +-- a/a.go -- +package a + +func A() int { return 1 } +func A2() int { return 2 } +-- b/b.go -- +package b + +func B() int { return 3 } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v2_v2.1.1.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v2_v2.1.1.txt new file mode 100644 index 0000000..aaa86be --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v2_v2.1.1.txt @@ -0,0 +1,13 @@ +-- go.mod -- +module example.com/basic/v2 + +go 1.12 +-- a/a.go -- +package a + +func A() int { return 1 } +func A2() int { return 2 } +-- b/b.go -- +package b + +func B() int { return 3 } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v2_v2.1.2.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v2_v2.1.2.txt new file mode 100644 index 0000000..0d950c1 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v2_v2.1.2.txt @@ -0,0 +1,8 @@ +-- go.mod -- +module example.com/basic/v2 + +go 1.12 +-- a/a.go -- +package a + +func A() int { return 1 } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v3_v3.0.0-ignore.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v3_v3.0.0-ignore.txt new file mode 100644 index 0000000..8e3cecf --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_v3_v3.0.0-ignore.txt @@ -0,0 +1,6 @@ +-- .info -- +{"Version":"v3.0.0-ignore"} +-- go.mod -- +module example.com/basic/v3 + +go 1.13 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_version-1.0.1.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_version-1.0.1.txt new file mode 100644 index 0000000..34e769e --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basic_version-1.0.1.txt @@ -0,0 +1,2 @@ +-- .info -- +{"Version":"v1.0.1"} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basicfork_v1.1.2.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basicfork_v1.1.2.txt new file mode 100644 index 0000000..63cb887 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_basicfork_v1.1.2.txt @@ -0,0 +1,13 @@ +-- go.mod -- +module example.com/basicfork + +go 1.12 +-- a/a.go -- +package a + +func A() int { return 1 } +func A3() int { return 4 } +-- b/b.go -- +package b + +func B() int { return 3 } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_cycle_v1.0.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_cycle_v1.0.0.txt new file mode 100644 index 0000000..8f073b0 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_cycle_v1.0.0.txt @@ -0,0 +1,15 @@ +-- go.sum -- +example.com/cycle v1.5.0 h1:OkE6KLRVRM5XqIH9MMFIvoYCVjxMh8kqsxUzx5481s4= +example.com/cycle v1.5.0/go.mod h1://AqZbyNHeLOKZB3J/UPPXaBvk3nCqvqVRbPkffDx60= +example.com/cycledep v1.0.0 h1:5UDqvIlbZsKzzbZCOaHkxV+X0H6Fi4othxBS57NtjSs= +example.com/cycledep v1.0.0/go.mod h1:Gc4hO1S1BMZaxOcGHwCRmdVcQP8+jAu/PyEgLdGe0xU= +-- go.mod -- +module example.com/cycle + +go 1.12 + +require example.com/cycledep v1.0.0 +-- main.go -- +package main + +import _ "example.com/cycledep"
\ No newline at end of file diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_cycle_v1.5.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_cycle_v1.5.0.txt new file mode 100644 index 0000000..98e8fe8 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_cycle_v1.5.0.txt @@ -0,0 +1,6 @@ +-- go.mod -- +module example.com/cycle + +go 1.12 +-- a.go -- +package a
\ No newline at end of file diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_cycle_v2_v2.0.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_cycle_v2_v2.0.0.txt new file mode 100644 index 0000000..95ae8d4 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_cycle_v2_v2.0.0.txt @@ -0,0 +1,19 @@ +# Note: "go get -d ." will add another example.com/cycle/v2 line. That line is +# non-deterministic, since the module is generate by prepareLoadDir each time. +# However, gorelease should ignore new go.sum entries for the module it's +# testing, since the requirement on that module is fake (a simulation: the user +# isn't actually relying on their own module). +-- go.sum -- +example.com/cycle/v2 v2.0.0/go.mod h1:lkmoN54Yqku+pnE3i6U+PjV87yiHyv3Rbei+phlzGGU= +example.com/cycledep/v2 v2.0.0 h1:B8tgq8pxH4IbvvozFpGx7k+HUeLoAPcmCixOXPZiuTE= +example.com/cycledep/v2 v2.0.0/go.mod h1:wBHRfgrlyovU4csu71ja8ySemxEOKOr8PpAiMU82nLw= +-- go.mod -- +module example.com/cycle/v2 + +go 1.12 + +require example.com/cycledep/v2 v2.0.0 +-- a.go -- +package a + +import _ "example.com/cycledep/v2"
\ No newline at end of file diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_cycledep_v1.0.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_cycledep_v1.0.0.txt new file mode 100644 index 0000000..83f7e34 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_cycledep_v1.0.0.txt @@ -0,0 +1,10 @@ +-- go.mod -- +module example.com/cycledep + +go 1.12 + +require example.com/cycle v1.5.0 +-- a.go -- +package a + +import _ "example.com/cycle" diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_cycledep_v2_v2.0.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_cycledep_v2_v2.0.0.txt new file mode 100644 index 0000000..7496524 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_cycledep_v2_v2.0.0.txt @@ -0,0 +1,12 @@ +-- go.mod -- +module example.com/cycledep/v2 + +go 1.12 + +require example.com/cycle/v2 v2.0.0 +-- b.go -- +package b +-- c/c.go -- +package c + +import _ "example.com/cycle/v2" diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_empty_v0.0.1.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_empty_v0.0.1.txt new file mode 100644 index 0000000..8e7df04 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_empty_v0.0.1.txt @@ -0,0 +1,4 @@ +-- go.mod -- +module example.com/empty + +go 1.14 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_empty_v0.0.2.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_empty_v0.0.2.txt new file mode 100644 index 0000000..8e7df04 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_empty_v0.0.2.txt @@ -0,0 +1,4 @@ +-- go.mod -- +module example.com/empty + +go 1.14 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_errors_v0.1.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_errors_v0.1.0.txt new file mode 100644 index 0000000..3ba57c4 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_errors_v0.1.0.txt @@ -0,0 +1,26 @@ +Module example.com/errors is used to compare modules with errors across +two versions. + +* Package "fixed" has type errors in v0.1.0, fixed in v0.2.0. +* Package "deleted" has type errors in v0.1.0, deleted in v0.2.0. +* Package "broken" is correct in v0.1.0, has type errors in v0.2.0. +* Package "added" doesn't exist in v0.1.0, has type errors in v0.2.0. + +-- go.mod -- +module example.com/errors + +go 1.12 +-- fixed/fixed.go -- +package fixed + +const X int = Missing + +-- deleted/deleted.go -- +package deleted + +const X int = Missing + +-- broken/broken.go -- +package broken + +const X int = 12 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_errors_v0.2.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_errors_v0.2.0.txt new file mode 100644 index 0000000..668d59b --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_errors_v0.2.0.txt @@ -0,0 +1,18 @@ +-- go.mod -- +module example.com/errors + +go 1.12 +-- fixed/fixed.go -- +package fixed + +const X int = 12 + +-- broken/broken.go -- +package broken + +const X int = Missing + +-- added/added.go -- +package added + +const X int = Missing diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_fix_v1.0.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_fix_v1.0.0.txt new file mode 100644 index 0000000..21daf65 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_fix_v1.0.0.txt @@ -0,0 +1,13 @@ +-- go.mod -- +module example.com/fix + +go 1.13 +-- bad/bad.go -- +package bad + +func Broken() NOTYPE { return 0 } +func Bad() int { return 1 } +-- good/good.go -- +package good + +func Good() int { return 1 } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_fix_v1.0.1-patch.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_fix_v1.0.1-patch.txt new file mode 100644 index 0000000..56c1c66 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_fix_v1.0.1-patch.txt @@ -0,0 +1,13 @@ +-- go.mod -- +module example.com/fix + +go 1.13 +-- bad/bad.go -- +package bad + +func Broken() int { return 0 } +func Bad() int { return 1 } +-- good/good.go -- +package good + +func Good() int { return 1 } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_fix_v1.1.0-compatible-other.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_fix_v1.1.0-compatible-other.txt new file mode 100644 index 0000000..068ed8f --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_fix_v1.1.0-compatible-other.txt @@ -0,0 +1,14 @@ +-- go.mod -- +module example.com/fix + +go 1.13 +-- bad/bad.go -- +package bad + +func Broken() int { return 0 } +func Bad() int { return 1 } +-- good/good.go -- +package good + +func Good() int { return 1 } +func Better() int { return 2 } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_fix_v1.1.0-compatible-same.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_fix_v1.1.0-compatible-same.txt new file mode 100644 index 0000000..6ff9299 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_fix_v1.1.0-compatible-same.txt @@ -0,0 +1,14 @@ +-- go.mod -- +module example.com/fix + +go 1.13 +-- bad/bad.go -- +package bad + +func Broken() int { return 0 } +func Bad() int { return 1 } +func Worse() int { return -1 } +-- good/good.go -- +package good + +func Good() int { return 1 } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_fix_v1.1.0-incompatible-other.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_fix_v1.1.0-incompatible-other.txt new file mode 100644 index 0000000..a7013b8 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_fix_v1.1.0-incompatible-other.txt @@ -0,0 +1,13 @@ +-- go.mod -- +module example.com/fix + +go 1.13 +-- bad/bad.go -- +package bad + +func Broken() int { return 0 } +func Bad() int { return 1 } +-- good/good.go -- +package good + +func Good() string { return "1" } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_fix_v1.1.0-incompatible-same.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_fix_v1.1.0-incompatible-same.txt new file mode 100644 index 0000000..1fb4891 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_fix_v1.1.0-incompatible-same.txt @@ -0,0 +1,13 @@ +-- go.mod -- +module example.com/fix + +go 1.13 +-- bad/bad.go -- +package bad + +func Broken() int { return 0 } +func Bad() string { return "1" } +-- good/good.go -- +package good + +func Good() int { return 1 } diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_generics_v0.0.1.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_generics_v0.0.1.txt new file mode 100644 index 0000000..f706512 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_generics_v0.0.1.txt @@ -0,0 +1,10 @@ +-- go.mod -- +module example.com/generics + +go 1.18 +-- a/a.go -- +package a + +type Foo[V any] interface { + Value() V +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_internalcompat_a_v1.0.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_internalcompat_a_v1.0.0.txt new file mode 100644 index 0000000..5f15418 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_internalcompat_a_v1.0.0.txt @@ -0,0 +1,16 @@ +-- go.mod -- +module example.com/internalcompat/a + +go 1.15 + +-- p/p.go -- +package p + +import "example.com/internalcompat/a/q" + +var V q.Q + +-- q/q.go -- +package q + +type Q struct{} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_internalcompat_b_v1.0.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_internalcompat_b_v1.0.0.txt new file mode 100644 index 0000000..318db36 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_internalcompat_b_v1.0.0.txt @@ -0,0 +1,16 @@ +-- go.mod -- +module example.com/internalcompat/b + +go 1.15 + +-- p/p.go -- +package p + +import "example.com/internalcompat/b/q" + +var V q.Q + +-- q/q.go -- +package q + +type Q struct{} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_issue37756_v1.0.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_issue37756_v1.0.0.txt new file mode 100644 index 0000000..b576df8 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_issue37756_v1.0.0.txt @@ -0,0 +1,18 @@ +-- go.mod -- +module example.com/issue37756 + +go 1.14 +-- a/a.go -- +package a + +import _ "example.com/issue37756/b" + +func A1() {} +-- b/b.go -- +package b + +func B1() {} +-- c/c.go -- +package c + +func C1() {} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_issue37756_v1.1.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_issue37756_v1.1.0.txt new file mode 100644 index 0000000..e35bc51 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_issue37756_v1.1.0.txt @@ -0,0 +1,21 @@ +-- go.mod -- +module example.com/issue37756 + +go 1.14 +-- a/a.go -- +package a + +import _ "example.com/issue37756/c" + +func A1() {} +func A2() {} +-- b/b.go -- +package b + +func B1() {} +func B2() {} +-- c/c.go -- +package c + +func C1() {} +func C2() {} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_main_v0.0.1.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_main_v0.0.1.txt new file mode 100644 index 0000000..a76b5b2 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_main_v0.0.1.txt @@ -0,0 +1,8 @@ +-- go.mod -- +module example.com/main + +go 1.14 +-- a/a.go -- +package main + +func main() {} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_nomod_v0.0.1.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_nomod_v0.0.1.txt new file mode 100644 index 0000000..760a8e8 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_nomod_v0.0.1.txt @@ -0,0 +1,6 @@ +-- .mod -- +module example.com/nomod +-- p/p.go -- +package p // import "example.com/something/different" + +// The import comment above is ignored by gorelease and by modules. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_nomod_v0.0.2.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_nomod_v0.0.2.txt new file mode 100644 index 0000000..06e2024 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_nomod_v0.0.2.txt @@ -0,0 +1,6 @@ +-- go.mod -- +module example.com/nomod + +go 1.12 +-- p/p.go -- +package p diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_prerelease_v0.0.0-20300101000000-000000000000.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_prerelease_v0.0.0-20300101000000-000000000000.txt new file mode 100644 index 0000000..e165690 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_prerelease_v0.0.0-20300101000000-000000000000.txt @@ -0,0 +1,4 @@ +-- go.mod -- +module example.com/prerelease + +go 1.12 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_private_v1.0.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_private_v1.0.0.txt new file mode 100644 index 0000000..ca71c99 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_private_v1.0.0.txt @@ -0,0 +1,17 @@ +-- go.mod -- +module example.com/private + +go 1.12 +-- p/p.go -- +package p + +import "example.com/private/internal/i" + +type P i.I + +-- internal/i/i.go -- +package i + +type I interface{} + +func Delete() {} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_private_v1.0.1.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_private_v1.0.1.txt new file mode 100644 index 0000000..1fe445c --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_private_v1.0.1.txt @@ -0,0 +1,15 @@ +-- go.mod -- +module example.com/private + +go 1.12 +-- p/p.go -- +package p + +import "example.com/private/internal/i" + +type P i.I + +-- internal/i/i.go -- +package i + +type I interface{} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_private_v1.0.2-break.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_private_v1.0.2-break.txt new file mode 100644 index 0000000..84e3616 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_private_v1.0.2-break.txt @@ -0,0 +1,17 @@ +-- go.mod -- +module example.com/private + +go 1.12 +-- p/p.go -- +package p + +import "example.com/private/internal/i" + +type P i.I + +-- internal/i/i.go -- +package i + +type I interface{ + Foo() +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_require_v0.0.1.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_require_v0.0.1.txt new file mode 100644 index 0000000..bc7200f --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_require_v0.0.1.txt @@ -0,0 +1,6 @@ +-- go.mod -- +module example.com/require + +go 1.12 +-- require.go -- +package require diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_require_v0.1.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_require_v0.1.0.txt new file mode 100644 index 0000000..8f858bf --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_require_v0.1.0.txt @@ -0,0 +1,14 @@ +-- go.mod -- +module example.com/require + +go 1.12 + +require example.com/basic v1.0.1 +-- go.sum -- +example.com/basic v1.0.1/go.mod h1:pv9xTX7lhV6R1XNYo1EcI/DQqKxDyhNTN+K1DjHW2Oo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +-- require.go -- +package require + diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_require_v0.1.1.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_require_v0.1.1.txt new file mode 100644 index 0000000..620bf66 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_require_v0.1.1.txt @@ -0,0 +1,13 @@ +-- go.mod -- +module example.com/require + +go 1.12 + +require example.com/basic v1.1.0 +-- go.sum -- +example.com/basic v1.1.0/go.mod h1:pv9xTX7lhV6R1XNYo1EcI/DQqKxDyhNTN+K1DjHW2Oo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +-- require.go -- +package require diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_retract_v0.0.1.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_retract_v0.0.1.txt new file mode 100644 index 0000000..b1466d0 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_retract_v0.0.1.txt @@ -0,0 +1,13 @@ +-- go.mod -- +module example.com/retract + +go 1.12 + +require example.com/retractdep v1.0.0 +-- go.sum -- +example.com/retractdep v1.0.0 h1:SOVn6jA2ygQY+v8/5aAwxVUJ9teuLrdH/UmbUtp2C44= +example.com/retractdep v1.0.0/go.mod h1:UjjWSH/ulfbAGgQQwm7pAZ988MFRngUSkJnzcuPsYDI= +-- a.go -- +package a + +import _ "example.com/retractdep" diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_retractdep_v1.0.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_retractdep_v1.0.0.txt new file mode 100644 index 0000000..36aa3d9 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_retractdep_v1.0.0.txt @@ -0,0 +1,8 @@ +-- go.mod -- +module example.com/retractdep + +go 1.12 +-- a.go -- +package a + +const A = "a"
\ No newline at end of file diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_retractdep_v1.0.1.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_retractdep_v1.0.1.txt new file mode 100644 index 0000000..7548ed2 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_retractdep_v1.0.1.txt @@ -0,0 +1,11 @@ +-- go.mod -- +module example.com/retractdep + +go 1.12 + +// Remote-triggered crash in package foo. See CVE-2021-01234. +retract v1.0.0 +-- a.go -- +package a + +const A = "a"
\ No newline at end of file diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_retractdep_v2_v2.0.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_retractdep_v2_v2.0.0.txt new file mode 100644 index 0000000..77619e3 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_retractdep_v2_v2.0.0.txt @@ -0,0 +1,12 @@ +# Identical to v1.0.0: just need a new version so that we can test different +# error messages based on the vX.0.1 retraction comments. We can't test them in +# the same major version because go mod will always use the latest version's +# error message. +-- go.mod -- +module example.com/retractdep/v2 + +go 1.12 +-- a.go -- +package a + +const A = "a"
\ No newline at end of file diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_retractdep_v2_v2.0.1.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_retractdep_v2_v2.0.1.txt new file mode 100644 index 0000000..5682baa --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_retractdep_v2_v2.0.1.txt @@ -0,0 +1,10 @@ +-- go.mod -- +module example.com/retractdep/v2 + +go 1.12 + +retract v2.0.0 +-- a.go -- +package a + +const A = "a"
\ No newline at end of file diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_retractdep_v3_v3.0.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_retractdep_v3_v3.0.0.txt new file mode 100644 index 0000000..1d526a9 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_retractdep_v3_v3.0.0.txt @@ -0,0 +1,12 @@ +# Identical to v1.0.0: just need a new version so that we can test different +# error messages based on the vX.0.1 retraction comments. We can't test them in +# the same major version because go mod will always use the latest version's +# error message. +-- go.mod -- +module example.com/retractdep/v3 + +go 1.12 +-- a.go -- +package a + +const A = "a"
\ No newline at end of file diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_retractdep_v3_v3.0.1.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_retractdep_v3_v3.0.1.txt new file mode 100644 index 0000000..ed39efb --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_retractdep_v3_v3.0.1.txt @@ -0,0 +1,11 @@ +-- go.mod -- +module example.com/retractdep/v3 + +go 1.12 + +// This is a very long message. This is a very long message. This is a very long message. This is a very long message. This is a very long message. This is a very long message. This is a very long message. This is a very long message. This is a very long message. This is a very long message. This is a very long message. This is a very long message. This is a very long message. This is a very long message. This is a very long message. This is a very long message. This is a very long message. This is a very long message. +retract v3.0.0 +-- a.go -- +package a + +const A = "a"
\ No newline at end of file diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_retracttransitive_v0.0.1.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_retracttransitive_v0.0.1.txt new file mode 100644 index 0000000..885906f --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_retracttransitive_v0.0.1.txt @@ -0,0 +1,15 @@ +-- go.mod -- +module example.com/retracttransitive + +go 1.12 + +require example.com/retract v0.0.1 +-- go.sum -- +example.com/retract v0.0.1 h1:Afj8efoHilltHZNLlEARzpc1Vkc5d6ugWKIE/YDmXuQ= +example.com/retract v0.0.1/go.mod h1:DUqXjcGF3aJhkjxsUjQ0DG65b51DDBvFrEbcr9kkyto= +example.com/retractdep v1.0.0 h1:SOVn6jA2ygQY+v8/5aAwxVUJ9teuLrdH/UmbUtp2C44= +example.com/retractdep v1.0.0/go.mod h1:UjjWSH/ulfbAGgQQwm7pAZ988MFRngUSkJnzcuPsYDI= +-- a.go -- +package a + +import _ "example.com/retract" diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_sub_nest_v1.0.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_sub_nest_v1.0.0.txt new file mode 100644 index 0000000..36f5b33 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_sub_nest_v1.0.0.txt @@ -0,0 +1,6 @@ +-- go.mod -- +module example.com/sub/nest + +go 1.12 +-- nest.go -- +package nest diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_sub_nest_v2_v2.0.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_sub_nest_v2_v2.0.0.txt new file mode 100644 index 0000000..b7dc8a7 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_sub_nest_v2_v2.0.0.txt @@ -0,0 +1,6 @@ +-- go.mod -- +module example.com/sub/nest/v2 + +go 1.12 +-- nest.go -- +package nest diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_sub_v2_v2.0.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_sub_v2_v2.0.0.txt new file mode 100644 index 0000000..488f2dc --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_sub_v2_v2.0.0.txt @@ -0,0 +1,6 @@ +-- go.mod -- +module example.com/sub/v2 + +go 1.12 +-- sub.go -- +package sub diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_tidy_a_v0.1.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_tidy_a_v0.1.0.txt new file mode 100644 index 0000000..d9c71aa --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_tidy_a_v0.1.0.txt @@ -0,0 +1,10 @@ +-- go.mod -- +module example.com/tidy/a + +go 1.12 + +require example.com/tidy/b v0.2.0 +-- p.go -- +package a + +import _ "example.com/tidy/b" diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_tidy_b_v0.1.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_tidy_b_v0.1.0.txt new file mode 100644 index 0000000..d169972 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_tidy_b_v0.1.0.txt @@ -0,0 +1,6 @@ +-- go.mod -- +module example.com/tidy/b + +go 1.12 +-- p.go -- +package b diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_tidy_b_v0.2.0.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_tidy_b_v0.2.0.txt new file mode 100644 index 0000000..470b743 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_tidy_b_v0.2.0.txt @@ -0,0 +1,8 @@ +-- go.mod -- +module example.com/tidy/b + +go 1.12 +-- p.go -- +package b + +func B() {} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_tidy_v0.0.1.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_tidy_v0.0.1.txt new file mode 100644 index 0000000..f6e7fff --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/mod/example.com_tidy_v0.0.1.txt @@ -0,0 +1,6 @@ +-- go.mod -- +module example.com/tidy + +go 1.12 +-- tidy.go -- +package tidy diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/nomod/README.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/nomod/README.txt new file mode 100644 index 0000000..ed50bb0 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/nomod/README.txt @@ -0,0 +1,2 @@ +Module example.com/nomod is used to test situations where no go.mod file +is present. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/nomod/nomod.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/nomod/nomod.test new file mode 100644 index 0000000..c307d13 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/nomod/nomod.test @@ -0,0 +1,8 @@ +mod=example.com/nomod +version=v0.0.2 +base=v0.0.1 +release=v0.0.2 +proxyVersions=example.com/nomod@v0.0.1 +-- want -- +# summary +v0.0.2 is a valid semantic version for this release. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/README.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/README.txt new file mode 100644 index 0000000..82f95f1 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/README.txt @@ -0,0 +1 @@ +Module example.com/patherrors tests errors related to paths.
\ No newline at end of file diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/abspath.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/abspath.test new file mode 100644 index 0000000..317364e --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/abspath.test @@ -0,0 +1,8 @@ +mod=example.com/patherrors +base=none +error=true +-- want -- +module path "/home/gopher/go/src/mymod" must not be an absolute path. +It must be an address where your module may be found. +-- go.mod -- +module /home/gopher/go/src/mymod diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/badmajor.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/badmajor.test new file mode 100644 index 0000000..4f5d027 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/badmajor.test @@ -0,0 +1,10 @@ +mod=example.com/patherrors +base=none +error=true +-- want -- +module path "example.com/patherrors/v0" has major version suffix "v0". +A major version suffix is only allowed for v2 or later. +-- go.mod -- +module example.com/patherrors/v0 + +go 1.12 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/dup_roots_branch.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/dup_roots_branch.test new file mode 100644 index 0000000..66f79bb --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/dup_roots_branch.test @@ -0,0 +1,20 @@ +dir=dup +base=none +success=false +vcs=git +-- dup/go.mod -- +module example.com/dup/v2 + +go 1.13 +-- dup/v2/go.mod -- +module example.com/dup/v2 + +go 1.13 +-- want -- +# diagnostics +module is defined in two locations: + dup/go.mod + dup/v2/go.mod + +# summary +Suggested version: v2.0.0 (with tag dup/v2.0.0) diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/dup_roots_dir.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/dup_roots_dir.test new file mode 100644 index 0000000..3898da4 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/dup_roots_dir.test @@ -0,0 +1,20 @@ +dir=dup/v2 +base=none +success=false +vcs=git +-- dup/go.mod -- +module example.com/dup/v2 + +go 1.13 +-- dup/v2/go.mod -- +module example.com/dup/v2 + +go 1.13 +-- want -- +# diagnostics +module is defined in two locations: + dup/v2/go.mod + dup/go.mod + +# summary +Suggested version: v2.0.0 (with tag dup/v2.0.0) diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/dup_roots_ok.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/dup_roots_ok.test new file mode 100644 index 0000000..afd157c --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/dup_roots_ok.test @@ -0,0 +1,14 @@ +dir=dup/v2 +base=none +vcs=git +-- dup/go.mod -- +module example.com/dup + +go 1.13 +-- dup/v2/go.mod -- +module example.com/dup/v2 + +go 1.13 +-- want -- +# summary +Suggested version: v2.0.0 (with tag dup/v2.0.0) diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/gopkginsub.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/gopkginsub.test new file mode 100644 index 0000000..2c2fb7c --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/gopkginsub.test @@ -0,0 +1,16 @@ +mod=example.com/patherrors +base=none +dir=yaml +success=false +vcs=git +-- want -- +# diagnostics +go.mod: go directive is missing +gopkg.in/yaml.v2: module path starts with gopkg.in and must be declared in the root directory of the repository + +# summary +Suggested version: v2.0.0 +-- .mod -- +module example.com/patherrors +-- yaml/go.mod -- +module gopkg.in/yaml.v2 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/pathsub.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/pathsub.test new file mode 100644 index 0000000..000c02a --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/pathsub.test @@ -0,0 +1,17 @@ +mod=example.com/patherrors +dir=x +base=none +success=false +vcs=git +-- want -- +# diagnostics +example.com/y: module path must end with "x", since it is in subdirectory "x" + +# summary +Suggested version: v0.1.0 +-- .mod -- +module example.com/patherrors +-- x/go.mod -- +module example.com/y + +go 1.12 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/pathsubv2.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/pathsubv2.test new file mode 100644 index 0000000..8ab2c80 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/patherrors/pathsubv2.test @@ -0,0 +1,17 @@ +mod=example.com/patherrors +base=none +dir=x +success=false +vcs=git +-- want -- +# diagnostics +example.com/y/v2: module path must end with "x" or "x/v2", since it is in subdirectory "x" + +# summary +Suggested version: v2.0.0 +-- .mod -- +module example.com/patherrors +-- x/go.mod -- +module example.com/y/v2 + +go 1.12 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/prerelease/README.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/prerelease/README.txt new file mode 100644 index 0000000..64a4c96 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/prerelease/README.txt @@ -0,0 +1 @@ +This directory contains tests for pre-release versions.
\ No newline at end of file diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/prerelease/prerelease_2.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/prerelease/prerelease_2.test new file mode 100644 index 0000000..0597098 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/prerelease/prerelease_2.test @@ -0,0 +1,16 @@ +mod=example.com/prerelease +release=v0.0.0-2 +success=false +-- want -- +# diagnostics +Version v0.0.0-2 is lower than most pseudo-versions. Consider releasing v0.1.0-0 instead. + +# summary +Inferred base version: none +v0.0.0-2 is a valid semantic version for this release. +Note: v0.0.0-2 sorts lower in MVS than pseudo-versions, which may be +unexpected for users. So, it may be better to choose a different suffix. +-- go.mod -- +module example.com/prerelease + +go 1.12 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/prerelease/prerelease_3.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/prerelease/prerelease_3.test new file mode 100644 index 0000000..7f6b26f --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/prerelease/prerelease_3.test @@ -0,0 +1,16 @@ +mod=example.com/prerelease +release=v0.0.0-3 +success=false +-- want -- +# diagnostics +Version v0.0.0-3 is lower than most pseudo-versions. Consider releasing v0.1.0-0 instead. + +# summary +Inferred base version: none +v0.0.0-3 is a valid semantic version for this release. +Note: v0.0.0-3 sorts lower in MVS than pseudo-versions, which may be +unexpected for users. So, it may be better to choose a different suffix. +-- go.mod -- +module example.com/prerelease + +go 1.12 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/prerelease/prerelease_beta2.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/prerelease/prerelease_beta2.test new file mode 100644 index 0000000..b265a86 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/prerelease/prerelease_beta2.test @@ -0,0 +1,10 @@ +mod=example.com/prerelease +release=v0.0.0-beta2 +-- want -- +# summary +Inferred base version: none +v0.0.0-beta2 is a valid semantic version for this release. +-- go.mod -- +module example.com/prerelease + +go 1.12 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/prerelease/prerelease_build_metadata.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/prerelease/prerelease_build_metadata.test new file mode 100644 index 0000000..4d3be83 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/prerelease/prerelease_build_metadata.test @@ -0,0 +1,11 @@ +mod=example.com/prerelease +release=v1.0.0-alpha+001 +error=true +-- want -- +usage: gorelease [-base=version] [-version=version] +release version "v1.0.0-alpha+001" is not a canonical semantic version: build metadata is not supported +For more information, run go doc golang.org/x/exp/cmd/gorelease +-- go.mod -- +module example.com/prerelease + +go 1.12
\ No newline at end of file diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/prerelease/prerelease_wordsonly.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/prerelease/prerelease_wordsonly.test new file mode 100644 index 0000000..a59aa40 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/prerelease/prerelease_wordsonly.test @@ -0,0 +1,10 @@ +mod=example.com/prerelease +release=v0.0.0-some-words-only-suffix +-- want -- +# summary +Inferred base version: none +v0.0.0-some-words-only-suffix is a valid semantic version for this release. +-- go.mod -- +module example.com/prerelease + +go 1.12 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/private/README.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/private/README.txt new file mode 100644 index 0000000..226b06d --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/private/README.txt @@ -0,0 +1,3 @@ +Module example.com/private is used to test that changes to +internal packages are not reported unless they affect the exported +API of non-internal packages. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/private/break.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/private/break.test new file mode 100644 index 0000000..3e4ec87 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/private/break.test @@ -0,0 +1,12 @@ +mod=example.com/private +version=v1.0.2-break +base=v1.0.1 +success=false +-- want -- +# example.com/private/p +## incompatible changes +I.Foo: added + +# summary +Cannot suggest a release version. +Incompatible changes were detected. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/private/unreported.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/private/unreported.test new file mode 100644 index 0000000..20567b6 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/private/unreported.test @@ -0,0 +1,7 @@ +mod=example.com/private +version=v1.0.1 +base=v1.0.0 +proxyVersions=example.com/private@v1.0.0 +-- want -- +# summary +Suggested version: v1.0.1 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/regress/README.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/regress/README.txt new file mode 100644 index 0000000..ee55a78 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/regress/README.txt @@ -0,0 +1 @@ +This directory contains unrelated tests, used to verify issues are fixed.
\ No newline at end of file diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/regress/issue37756.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/regress/issue37756.test new file mode 100644 index 0000000..07b6017 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/regress/issue37756.test @@ -0,0 +1,21 @@ +# Verifies golang.org/issue/37756. +# Packages should be compared in lexical order by package path. +mod=example.com/issue37756 +version=v1.1.0 +base=v1.0.0 +proxyVersions=example.com/issue37756@v1.0.0 +-- want -- +# example.com/issue37756/a +## compatible changes +A2: added + +# example.com/issue37756/b +## compatible changes +B2: added + +# example.com/issue37756/c +## compatible changes +C2: added + +# summary +Suggested version: v1.1.0 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/require/README.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/require/README.txt new file mode 100644 index 0000000..f905232 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/require/README.txt @@ -0,0 +1,2 @@ +This directory contain tests that assert gorelease behavior when module +requirements (and require statements in the go.mod) have changed.
\ No newline at end of file diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/require/add_requirement.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/require/add_requirement.test new file mode 100644 index 0000000..59ef3db --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/require/add_requirement.test @@ -0,0 +1,19 @@ +mod=example.com/require +base=v0.0.1 +proxyVersions=example.com/require@v0.0.1,example.com/basic@v1.0.1 +-- want -- +# summary +Suggested version: v0.1.0 +-- go.mod -- +module example.com/require + +go 1.12 + +require example.com/basic v1.0.1 +-- go.sum -- +example.com/basic v1.0.1/go.mod h1:pv9xTX7lhV6R1XNYo1EcI/DQqKxDyhNTN+K1DjHW2Oo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +-- require.go -- +package require diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/require/decrement_go_version.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/require/decrement_go_version.test new file mode 100644 index 0000000..ce461d5 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/require/decrement_go_version.test @@ -0,0 +1,13 @@ +mod=example.com/require +base=v0.0.1 +proxyVersions=example.com/require@v0.0.1 +-- want -- +# summary +Suggested version: v0.0.2 +-- go.mod -- +module example.com/require + +go 1.11 +-- go.sum -- +-- require.go -- +package require diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/require/decrement_requirement_minor.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/require/decrement_requirement_minor.test new file mode 100644 index 0000000..f64e3e3 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/require/decrement_requirement_minor.test @@ -0,0 +1,18 @@ +mod=example.com/require +base=v0.1.1 +-- want -- +# summary +Suggested version: v0.1.2 +-- go.mod -- +module example.com/require + +go 1.12 + +require example.com/basic v0.0.1 +-- go.sum -- +example.com/basic v0.0.1/go.mod h1:pv9xTX7lhV6R1XNYo1EcI/DQqKxDyhNTN+K1DjHW2Oo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +-- require.go -- +package require diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/require/increment_go_version.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/require/increment_go_version.test new file mode 100644 index 0000000..802ac6e --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/require/increment_go_version.test @@ -0,0 +1,13 @@ +mod=example.com/require +base=v0.0.1 +proxyVersions=example.com/require@v0.0.1 +-- want -- +# summary +Suggested version: v0.1.0 +-- go.mod -- +module example.com/require + +go 1.13 +-- go.sum -- +-- require.go -- +package require diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/require/increment_requirement_minor.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/require/increment_requirement_minor.test new file mode 100644 index 0000000..821ff2a --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/require/increment_requirement_minor.test @@ -0,0 +1,19 @@ +mod=example.com/require +base=v0.1.0 +proxyVersions=example.com/require@v0.1.0,example.com/basic@v1.1.0,example.com/basic@v1.0.1 +-- want -- +# summary +Suggested version: v0.2.0 +-- go.mod -- +module example.com/require + +go 1.12 + +require example.com/basic v1.1.0 +-- go.sum -- +example.com/basic v1.1.0/go.mod h1:pv9xTX7lhV6R1XNYo1EcI/DQqKxDyhNTN+K1DjHW2Oo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +-- require.go -- +package require diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/require/increment_requirement_patch.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/require/increment_requirement_patch.test new file mode 100644 index 0000000..d183300 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/require/increment_requirement_patch.test @@ -0,0 +1,19 @@ +mod=example.com/require +base=v0.1.1 +proxyVersions=example.com/require@v0.1.1,example.com/basic@v1.1.1,example.com/basic@v1.1.0 +-- want -- +# summary +Suggested version: v0.1.2 +-- go.mod -- +module example.com/require + +go 1.12 + +require example.com/basic v1.1.1 +-- go.sum -- +example.com/basic v1.1.1/go.mod h1:pv9xTX7lhV6R1XNYo1EcI/DQqKxDyhNTN+K1DjHW2Oo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +-- require.go -- +package require diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/require/remove_requirements.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/require/remove_requirements.test new file mode 100644 index 0000000..91a8837 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/require/remove_requirements.test @@ -0,0 +1,13 @@ +mod=example.com/require +base=v0.0.1 +proxyVersions=example.com/require@v0.0.1 +-- want -- +# summary +Suggested version: v0.0.2 +-- go.mod -- +module example.com/require + +go 1.12 +-- go.sum -- +-- require.go -- +package require diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/retract/retract_verify_direct_dep.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/retract/retract_verify_direct_dep.test new file mode 100644 index 0000000..7777dff --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/retract/retract_verify_direct_dep.test @@ -0,0 +1,10 @@ +mod=example.com/retract +version=v0.0.1 +success=false +-- want -- +# diagnostics +required module example.com/retractdep@v1.0.0 retracted by module author: Remote-triggered crash in package foo. See CVE-2021-01234. + +# summary +Inferred base version: v0.0.1 +Suggested version: v0.0.2 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/retract/retract_verify_long_msg.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/retract/retract_verify_long_msg.test new file mode 100644 index 0000000..1f2776f --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/retract/retract_verify_long_msg.test @@ -0,0 +1,22 @@ +mod=example.com/retract +success=false +-- want -- +# diagnostics +required module example.com/retractdep/v3@v3.0.0 retracted by module author + +# summary +Inferred base version: v0.0.1 +Suggested version: v0.1.0 +-- go.mod -- +module example.com/retract + +go 1.12 + +require example.com/retractdep/v3 v3.0.0 +-- go.sum -- +example.com/retractdep/v3 v3.0.0 h1:LEaqsEpt7J4Er+qSPqL7bENpIkRdZdaOE6KaUaiNB5I= +example.com/retractdep/v3 v3.0.0/go.mod h1:B2rEwAWayv3FJ2jyeiq9O3UBbxSvdDqZUtxmKsLyg6k= +-- a.go -- +package a + +import _ "example.com/retractdep/v3" diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/retract/retract_verify_no_msg.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/retract/retract_verify_no_msg.test new file mode 100644 index 0000000..7a748f7 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/retract/retract_verify_no_msg.test @@ -0,0 +1,22 @@ +mod=example.com/retract +success=false +-- want -- +# diagnostics +required module example.com/retractdep/v2@v2.0.0 retracted by module author + +# summary +Inferred base version: v0.0.1 +Suggested version: v0.1.0 +-- go.mod -- +module example.com/retract + +go 1.12 + +require example.com/retractdep/v2 v2.0.0 +-- go.sum -- +example.com/retractdep/v2 v2.0.0 h1:ehV4yfX3A3jNlRnBmHPxq1TyVs1EhmCYI5miEva6Gv8= +example.com/retractdep/v2 v2.0.0/go.mod h1:rV+p/Yqwnupg15GPVGFRq+un/MYczBZcF1IZ8ubecag= +-- a.go -- +package a + +import _ "example.com/retractdep/v2" diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/retract/retract_verify_transitive_dep.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/retract/retract_verify_transitive_dep.test new file mode 100644 index 0000000..681702a --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/retract/retract_verify_transitive_dep.test @@ -0,0 +1,12 @@ +# When a retracted version is transitively depended upon, it should still +# result in a retraction error. +mod=example.com/retracttransitive +version=v0.0.1 +success=false +-- want -- +# diagnostics +required module example.com/retractdep@v1.0.0 retracted by module author: Remote-triggered crash in package foo. See CVE-2021-01234. + +# summary +Inferred base version: v0.0.1 +Suggested version: v0.0.2 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/sub/README.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/sub/README.txt new file mode 100644 index 0000000..54ff480 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/sub/README.txt @@ -0,0 +1,10 @@ +This directory contains tests for modules that aren't at the root +of the repository, which is marked with a .git directory. +We're comparing against an earlier published version with a +trivial package. Nothing has changed except the location of the +module within the repository. + + example.com/sub - corresponds to the root directory. Not a module. + example.com/sub/v2 - may be in v2 subdirectory. + example.com/sub/nest - nested module in subdirectory + example.com/sub/nest/v2 - may be in nest or nest/v2. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/sub/nest.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/sub/nest.test new file mode 100644 index 0000000..c2a6436 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/sub/nest.test @@ -0,0 +1,13 @@ +mod=example.com/sub/nest +dir=nest +base=v1.0.0 +vcs=git +-- want -- +# summary +Suggested version: v1.0.1 (with tag nest/v1.0.1) +-- nest/go.mod -- +module example.com/sub/nest + +go 1.12 +-- nest/nest.go -- +package nest diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/sub/nest_v2.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/sub/nest_v2.test new file mode 100644 index 0000000..6d8bf0c --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/sub/nest_v2.test @@ -0,0 +1,13 @@ +mod=example.com/sub/nest/v2 +dir=nest +base=v2.0.0 +vcs=git +-- want -- +# summary +Suggested version: v2.0.1 (with tag nest/v2.0.1) +-- nest/go.mod -- +module example.com/sub/nest/v2 + +go 1.12 +-- nest/nest.go -- +package nest diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/sub/nest_v2_dir.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/sub/nest_v2_dir.test new file mode 100644 index 0000000..7e99c1e --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/sub/nest_v2_dir.test @@ -0,0 +1,13 @@ +mod=example.com/sub/nest/v2 +dir=nest/v2 +base=v2.0.0 +vcs=git +-- want -- +# summary +Suggested version: v2.0.1 (with tag nest/v2.0.1) +-- nest/v2/go.mod -- +module example.com/sub/nest/v2 + +go 1.12 +-- nest/v2/nest.go -- +package nest diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/sub/v2_dir.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/sub/v2_dir.test new file mode 100644 index 0000000..ed07eb9 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/sub/v2_dir.test @@ -0,0 +1,13 @@ +mod=example.com/sub/v2 +dir=v2 +base=v2.0.0 +vcs=git +-- want -- +# summary +Suggested version: v2.0.1 +-- v2/go.mod -- +module example.com/sub/v2 + +go 1.12 +-- v2/sub.go -- +package sub diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/sub/v2_root.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/sub/v2_root.test new file mode 100644 index 0000000..1a34c67 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/sub/v2_root.test @@ -0,0 +1,12 @@ +mod=example.com/sub/v2 +base=v2.0.0 +vcs=git +-- want -- +# summary +Suggested version: v2.0.1 +-- go.mod -- +module example.com/sub/v2 + +go 1.12 +-- sub.go -- +package sub diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/README.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/README.txt new file mode 100644 index 0000000..0ca2fb4 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/README.txt @@ -0,0 +1,5 @@ +Module example.com/tidy tests versions that do not have tidy +go.mod or go.sum files. + +v0.0.1 has a trivial package with no imports. It has no requirements +and no go.sum, so it is tidy. Tests make changes on top of this. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/empty_sum.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/empty_sum.test new file mode 100644 index 0000000..69a51fb --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/empty_sum.test @@ -0,0 +1,20 @@ +mod=example.com/tidy +base=v0.0.1 +success=false +-- want -- +# diagnostics +go.sum: one or more sums are missing. Run 'go mod tidy' to add missing sums. + +# summary +Suggested version: v0.1.0 +-- go.mod -- +module example.com/tidy + +go 1.12 + +require example.com/basic v1.0.1 +-- go.sum -- +-- tidy.go -- +package tidy + +import _ "example.com/basic/a" diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/misleading_req.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/misleading_req.test new file mode 100644 index 0000000..b4b2954 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/misleading_req.test @@ -0,0 +1,31 @@ +mod=example.com/tidy +base=none +success=false +-- go.mod -- +module example.com/tidy + +go 1.12 + +require ( + example.com/tidy/a v0.1.0 // actually transitively requires v0.2.0 + example.com/tidy/b v0.1.0 +) +-- go.sum -- +example.com/tidy/a v0.1.0 h1:hxFAdyLfJ6TV25ffYI2oA+g3ffLp+XJgo6lrVkT8ufU= +example.com/tidy/a v0.1.0/go.mod h1:/KTGkbP1cnyJLO5kGL/QSCswh5I8R66epCmEAxgAK+I= +example.com/tidy/b v0.1.0/go.mod h1:92saqyRYqaI4eqrr6LGMnPfBDXc2yofWznwSxsvqfEw= +example.com/tidy/b v0.2.0 h1:dSh97fZcMRg87GDb1Gqwy8/mebsrmE4kX3S7d+KeSZU= +example.com/tidy/b v0.2.0/go.mod h1:92saqyRYqaI4eqrr6LGMnPfBDXc2yofWznwSxsvqfEw= +-- tidy.go -- +package tidy + +import _ "example.com/tidy/a" +import _ "example.com/tidy/b" +-- want -- +# diagnostics +go.mod: the following requirements are needed + example.com/tidy/b@v0.2.0 +Run 'go mod tidy' to add missing requirements. + +# summary +Suggested version: v0.1.0 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/missing_go.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/missing_go.test new file mode 100644 index 0000000..99ca05a --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/missing_go.test @@ -0,0 +1,13 @@ +mod=example.com/tidy +base=v0.0.1 +success=0 +-- want -- +# diagnostics +go.mod: go directive is missing + +# summary +Suggested version: v0.0.2 +-- go.mod -- +module example.com/tidy +-- tidy.go -- +package tidy diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/missing_req_basic.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/missing_req_basic.test new file mode 100644 index 0000000..97a95a3 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/missing_req_basic.test @@ -0,0 +1,19 @@ +mod=example.com/tidy +base=v0.0.1 +success=false +-- want -- +# diagnostics +go.mod: the following requirements are needed + example.com/basic@v1.1.2 +Run 'go mod tidy' to add missing requirements. + +# summary +Suggested version: v0.0.2 +-- go.mod -- +module example.com/tidy + +go 1.12 +-- tidy.go -- +package tidy + +import _ "example.com/basic/a" diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/missing_req_nested.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/missing_req_nested.test new file mode 100644 index 0000000..1533d6a --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/missing_req_nested.test @@ -0,0 +1,25 @@ +mod=example.com/tidy +base=v0.0.1 +success=false +-- want -- +# example.com/tidy/subdir +## compatible changes +package added + +# diagnostics +go.mod: the following requirements are needed + example.com/basic@v1.1.2 +Run 'go mod tidy' to add missing requirements. + +# summary +Suggested version: v0.1.0 +-- go.mod -- +module example.com/tidy + +go 1.12 +-- tidy.go -- +package tidy +-- subdir/tidy.go -- +package subpkg + +import _ "example.com/basic/a" diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/missing_req_submodule.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/missing_req_submodule.test new file mode 100644 index 0000000..e210c2d --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/missing_req_submodule.test @@ -0,0 +1,20 @@ +mod=example.com/tidy +base=v0.0.1 +success=true +-- want -- +# summary +Suggested version: v0.0.2 +-- go.mod -- +module example.com/tidy + +go 1.12 +-- foo/go.mod -- +module example.com/tidy/foo + +go 1.12 +-- tidy.go -- +package tidy +-- foo/tidy.go -- +package subpkg + +import _ "example.com/basic/a" diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/missing_req_twice_nested.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/missing_req_twice_nested.test new file mode 100644 index 0000000..c06f465 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/missing_req_twice_nested.test @@ -0,0 +1,25 @@ +mod=example.com/tidy +base=v0.0.1 +success=false +-- want -- +# example.com/tidy/subdir/subsubdir +## compatible changes +package added + +# diagnostics +go.mod: the following requirements are needed + example.com/basic@v1.1.2 +Run 'go mod tidy' to add missing requirements. + +# summary +Suggested version: v0.1.0 +-- go.mod -- +module example.com/tidy + +go 1.12 +-- tidy.go -- +package tidy +-- subdir/subsubdir/tidy.go -- +package subpkg + +import _ "example.com/basic/a" diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/no_sum.test b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/no_sum.test new file mode 100644 index 0000000..f4ff48b --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/gorelease/testdata/tidy/no_sum.test @@ -0,0 +1,19 @@ +mod=example.com/tidy +base=v0.0.1 +success=false +-- want -- +# diagnostics +go.sum: one or more sums are missing. Run 'go mod tidy' to add missing sums. + +# summary +Suggested version: v0.1.0 +-- go.mod -- +module example.com/tidy + +go 1.12 + +require example.com/basic v1.1.2 +-- tidy.go -- +package tidy + +import _ "example.com/basic/a" diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/macos-roots-test/main.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/macos-roots-test/main.go new file mode 100644 index 0000000..db2bfe6 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/macos-roots-test/main.go @@ -0,0 +1,122 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin +// +build darwin + +// Command macOS-roots-test runs crypto/x509.TestSystemRoots as a +// stand-alone binary for crowdsourced testing. +package main + +import ( + "crypto/x509" + "fmt" + "log" + "os" + "os/exec" + "time" + "unsafe" +) + +type CertPool struct { + bySubjectKeyId map[string][]int + byName map[string][]int + certs []*x509.Certificate +} + +func (s *CertPool) contains(cert *x509.Certificate) bool { + if s == nil { + return false + } + + candidates := s.byName[string(cert.RawSubject)] + for _, c := range candidates { + if s.certs[c].Equal(cert) { + return true + } + } + + return false +} + +func main() { + var failed bool + + t0 := time.Now() + sysRootsExt, err := loadSystemRoots() // actual system roots + sysRootsDuration := time.Since(t0) + + if err != nil { + log.Fatalf("failed to read system roots (cgo): %v", err) + } + sysRoots := (*CertPool)(unsafe.Pointer(sysRootsExt)) + + t1 := time.Now() + execRootsExt, err := execSecurityRoots() // non-cgo roots + execSysRootsDuration := time.Since(t1) + + if err != nil { + log.Fatalf("failed to read system roots (nocgo): %v", err) + } + execRoots := (*CertPool)(unsafe.Pointer(execRootsExt)) + + fmt.Printf(" cgo sys roots: %v\n", sysRootsDuration) + fmt.Printf("non-cgo sys roots: %v\n", execSysRootsDuration) + + // On Mavericks, there are 212 bundled certs, at least there was at + // one point in time on one machine. (Maybe it was a corp laptop + // with extra certs?) Other OS X users report 135, 142, 145... + // Let's try requiring at least 100, since this is just a sanity + // check. + if want, have := 100, len(sysRoots.certs); have < want { + failed = true + fmt.Printf("want at least %d system roots, have %d\n", want, have) + } + + // Check that the two cert pools are the same. + sysPool := make(map[string]*x509.Certificate, len(sysRoots.certs)) + for _, c := range sysRoots.certs { + sysPool[string(c.Raw)] = c + } + for _, c := range execRoots.certs { + if _, ok := sysPool[string(c.Raw)]; ok { + delete(sysPool, string(c.Raw)) + } else { + // verify-cert lets in certificates that are not trusted roots, but are + // signed by trusted roots. This should not be a problem, so confirm that's + // the case and skip them. + if _, err := c.Verify(x509.VerifyOptions{ + Roots: sysRootsExt, + Intermediates: execRootsExt, // the intermediates for EAP certs are stored in the keychain + KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny}, + }); err != nil { + failed = true + fmt.Printf("certificate only present in non-cgo pool: %v (verify error: %v)\n", c.Subject, err) + } else { + fmt.Printf("signed certificate only present in non-cgo pool (acceptable): %v\n", c.Subject) + } + } + } + for _, c := range sysPool { + failed = true + fmt.Printf("certificate only present in cgo pool: %v\n", c.Subject) + } + + if failed && debugDarwinRoots { + cmd := exec.Command("security", "dump-trust-settings") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Run() + cmd = exec.Command("security", "dump-trust-settings", "-d") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Run() + } + + if failed { + fmt.Printf("\n\n!!! The test failed!\n\nPlease report *the whole output* at https://github.com/golang/go/issues/24652 wrapping it in ``` a code block ```\nThank you!\n") + } else { + fmt.Printf("\n\nThe test passed, no need to report the output. Thank you.\n") + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/macos-roots-test/root_cgo_darwin.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/macos-roots-test/root_cgo_darwin.go new file mode 100644 index 0000000..591098f --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/macos-roots-test/root_cgo_darwin.go @@ -0,0 +1,290 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +/* +#cgo CFLAGS: -mmacosx-version-min=10.10 -D__MAC_OS_X_VERSION_MAX_ALLOWED=101300 +#cgo LDFLAGS: -framework CoreFoundation -framework Security + +#include <errno.h> +#include <sys/sysctl.h> + +#include <CoreFoundation/CoreFoundation.h> +#include <Security/Security.h> + +void CFReleaseIfNotNULL(CFTypeRef cf) { + if (cf != NULL) CFRelease(cf); +} + +static bool isSSLPolicy(SecPolicyRef policyRef) { + if (!policyRef) { + return false; + } + CFDictionaryRef properties = SecPolicyCopyProperties(policyRef); + if (properties == NULL) { + return false; + } + CFTypeRef value = NULL; + if (CFDictionaryGetValueIfPresent(properties, kSecPolicyOid, (const void **)&value)) { + CFRelease(properties); + return CFEqual(value, kSecPolicyAppleSSL); + } + CFRelease(properties); + return false; +} + +// sslTrustSettingsResult obtains the final kSecTrustSettingsResult value +// for a certificate in the user or admin domain, combining usage constraints +// for the SSL SecTrustSettingsPolicy, ignoring SecTrustSettingsKeyUsage, +// kSecTrustSettingsAllowedError and kSecTrustSettingsPolicyString. +// https://developer.apple.com/documentation/security/1400261-sectrustsettingscopytrustsetting +static SInt32 sslTrustSettingsResult(SecCertificateRef cert) { + CFArrayRef trustSettings = NULL; + OSStatus err = SecTrustSettingsCopyTrustSettings(cert, kSecTrustSettingsDomainUser, &trustSettings); + + // According to Apple's SecTrustServer.c, "user trust settings overrule admin trust settings", + // but the rules of the override are unclear. Let's assume admin trust settings are applicable + // if and only if user trust settings fail to load or are NULL. + if (err != errSecSuccess || trustSettings == NULL) { + CFReleaseIfNotNULL(trustSettings); + err = SecTrustSettingsCopyTrustSettings(cert, kSecTrustSettingsDomainAdmin, &trustSettings); + } + + // > no trust settings [...] means "this certificate must be verified to a known trusted certificate” + if (err != errSecSuccess || trustSettings == NULL) { + CFReleaseIfNotNULL(trustSettings); + return kSecTrustSettingsResultUnspecified; + } + + // > An empty trust settings array means "always trust this certificate” with an + // > overall trust setting for the certificate of kSecTrustSettingsResultTrustRoot. + if (CFArrayGetCount(trustSettings) == 0) { + CFReleaseIfNotNULL(trustSettings); + return kSecTrustSettingsResultTrustRoot; + } + + // kSecTrustSettingsResult is defined as CFSTR("kSecTrustSettingsResult"), + // but the Go linker's internal linking mode can't handle CFSTR relocations. + // Create our own dynamic string instead and release it below. + CFStringRef _kSecTrustSettingsResult = CFStringCreateWithCString( + NULL, "kSecTrustSettingsResult", kCFStringEncodingUTF8); + CFStringRef _kSecTrustSettingsPolicy = CFStringCreateWithCString( + NULL, "kSecTrustSettingsPolicy", kCFStringEncodingUTF8); + + CFIndex m; SInt32 result = 0; + for (m = 0; m < CFArrayGetCount(trustSettings); m++) { + CFDictionaryRef tSetting = (CFDictionaryRef)CFArrayGetValueAtIndex(trustSettings, m); + + // First, check if this trust setting applies to our policy. We assume + // only one will. The docs suggest that there might be multiple applying + // but don't explain how to combine them. + SecPolicyRef policyRef; + if (CFDictionaryGetValueIfPresent(tSetting, _kSecTrustSettingsPolicy, (const void**)&policyRef)) { + if (!isSSLPolicy(policyRef)) { + continue; + } + } else { + continue; + } + + CFNumberRef cfNum; + if (CFDictionaryGetValueIfPresent(tSetting, _kSecTrustSettingsResult, (const void**)&cfNum)) { + CFNumberGetValue(cfNum, kCFNumberSInt32Type, &result); + } else { + // > If the value of the kSecTrustSettingsResult component is not + // > kSecTrustSettingsResultUnspecified for a usage constraints dictionary that has + // > no constraints, the default value kSecTrustSettingsResultTrustRoot is assumed. + result = kSecTrustSettingsResultTrustRoot; + } + + break; + } + + // If trust settings are present, but none of them match the policy... + // the docs don't tell us what to do. + // + // "Trust settings for a given use apply if any of the dictionaries in the + // certificate’s trust settings array satisfies the specified use." suggests + // that it's as if there were no trust settings at all, so we should probably + // fallback to the admin trust settings. TODO. + if (result == 0) { + result = kSecTrustSettingsResultUnspecified; + } + + CFRelease(_kSecTrustSettingsResult); + CFRelease(trustSettings); + + return result; +} + +// FetchPEMRoots fetches the system's list of trusted X.509 root certificates +// for the kSecTrustSettingsPolicy SSL. +// +// On success it returns 0 and fills pemRoots with a CFDataRef that contains the extracted root +// certificates of the system. On failure, the function returns -1. +// Additionally, it fills untrustedPemRoots with certs that must be removed from pemRoots. +// +// Note: The CFDataRef returned in pemRoots and untrustedPemRoots must +// be released (using CFRelease) after we've consumed its content. +int _FetchPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots, bool debugDarwinRoots) { + int i; + + if (debugDarwinRoots) { + printf("crypto/x509: kSecTrustSettingsResultInvalid = %d\n", kSecTrustSettingsResultInvalid); + printf("crypto/x509: kSecTrustSettingsResultTrustRoot = %d\n", kSecTrustSettingsResultTrustRoot); + printf("crypto/x509: kSecTrustSettingsResultTrustAsRoot = %d\n", kSecTrustSettingsResultTrustAsRoot); + printf("crypto/x509: kSecTrustSettingsResultDeny = %d\n", kSecTrustSettingsResultDeny); + printf("crypto/x509: kSecTrustSettingsResultUnspecified = %d\n", kSecTrustSettingsResultUnspecified); + } + + // Get certificates from all domains, not just System, this lets + // the user add CAs to their "login" keychain, and Admins to add + // to the "System" keychain + SecTrustSettingsDomain domains[] = { kSecTrustSettingsDomainSystem, + kSecTrustSettingsDomainAdmin, + kSecTrustSettingsDomainUser }; + + int numDomains = sizeof(domains)/sizeof(SecTrustSettingsDomain); + if (pemRoots == NULL) { + return -1; + } + + CFMutableDataRef combinedData = CFDataCreateMutable(kCFAllocatorDefault, 0); + CFMutableDataRef combinedUntrustedData = CFDataCreateMutable(kCFAllocatorDefault, 0); + for (i = 0; i < numDomains; i++) { + int j; + CFArrayRef certs = NULL; + OSStatus err = SecTrustSettingsCopyCertificates(domains[i], &certs); + if (err != noErr) { + continue; + } + + CFIndex numCerts = CFArrayGetCount(certs); + for (j = 0; j < numCerts; j++) { + CFDataRef data = NULL; + CFArrayRef trustSettings = NULL; + SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, j); + if (cert == NULL) { + continue; + } + + SInt32 result; + if (domains[i] == kSecTrustSettingsDomainSystem) { + // Certs found in the system domain are always trusted. If the user + // configures "Never Trust" on such a cert, it will also be found in the + // admin or user domain, causing it to be added to untrustedPemRoots. The + // Go code will then clean this up. + result = kSecTrustSettingsResultTrustAsRoot; + } else { + result = sslTrustSettingsResult(cert); + if (debugDarwinRoots) { + CFErrorRef errRef = NULL; + CFStringRef summary = SecCertificateCopyShortDescription(NULL, cert, &errRef); + if (errRef != NULL) { + printf("crypto/x509: SecCertificateCopyShortDescription failed\n"); + CFRelease(errRef); + continue; + } + + CFIndex length = CFStringGetLength(summary); + CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1; + char *buffer = malloc(maxSize); + if (CFStringGetCString(summary, buffer, maxSize, kCFStringEncodingUTF8)) { + printf("crypto/x509: %s returned %d\n", buffer, result); + } + free(buffer); + CFRelease(summary); + } + } + + CFMutableDataRef appendTo; + if (result == kSecTrustSettingsResultTrustRoot) { + // "can only be applied to root (self-signed) certificates", so + // make sure Subject and Issuer Name match. + CFErrorRef errRef = NULL; + CFDataRef subjectName = SecCertificateCopyNormalizedSubjectContent(cert, &errRef); + if (errRef != NULL) { + CFRelease(errRef); + continue; + } + CFDataRef issuerName = SecCertificateCopyNormalizedIssuerContent(cert, &errRef); + if (errRef != NULL) { + CFRelease(subjectName); + CFRelease(errRef); + continue; + } + Boolean equal = CFEqual(subjectName, issuerName); + CFRelease(subjectName); + CFRelease(issuerName); + if (!equal) { + continue; + } + + appendTo = combinedData; + } else if (result == kSecTrustSettingsResultTrustAsRoot) { + // In theory "can only be applied to non-root certificates", but ignore + // this for now, also because it's the state we assume for the system domain. + appendTo = combinedData; + } else if (result == kSecTrustSettingsResultDeny) { + appendTo = combinedUntrustedData; + } else if (result == kSecTrustSettingsResultUnspecified) { + continue; + } else { + continue; + } + + err = SecItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data); + if (err != noErr) { + continue; + } + if (data != NULL) { + CFDataAppendBytes(appendTo, CFDataGetBytePtr(data), CFDataGetLength(data)); + CFRelease(data); + } + } + CFRelease(certs); + } + *pemRoots = combinedData; + *untrustedPemRoots = combinedUntrustedData; + return 0; +} +*/ +import "C" +import ( + "crypto/x509" + "errors" + "unsafe" +) + +func loadSystemRoots() (*x509.CertPool, error) { + roots := x509.NewCertPool() + + var data C.CFDataRef = 0 + var untrustedData C.CFDataRef = 0 + err := C._FetchPEMRoots(&data, &untrustedData, C.bool(debugDarwinRoots)) + if err == -1 { + // TODO: better error message + return nil, errors.New("crypto/x509: failed to load darwin system roots with cgo") + } + + defer C.CFRelease(C.CFTypeRef(data)) + buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data))) + roots.AppendCertsFromPEM(buf) + if untrustedData == 0 { + return roots, nil + } + defer C.CFRelease(C.CFTypeRef(untrustedData)) + buf = C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(untrustedData)), C.int(C.CFDataGetLength(untrustedData))) + untrustedRoots := x509.NewCertPool() + untrustedRoots.AppendCertsFromPEM(buf) + + trustedRoots := x509.NewCertPool() + for _, c := range (*CertPool)(unsafe.Pointer(roots)).certs { + if !(*CertPool)(unsafe.Pointer(untrustedRoots)).contains(c) { + trustedRoots.AddCert(c) + } + } + return trustedRoots, nil +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/macos-roots-test/root_darwin.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/macos-roots-test/root_darwin.go new file mode 100644 index 0000000..b5bf0f7 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/macos-roots-test/root_darwin.go @@ -0,0 +1,174 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "bytes" + "crypto/x509" + "encoding/pem" + "fmt" + "io/ioutil" + "os" + "os/exec" + "os/user" + "path/filepath" + "sync" +) + +var debugDarwinRoots = true + +// This code is only used when compiling without cgo. +// It is here, instead of root_nocgo_darwin.go, so that tests can check it +// even if the tests are run with cgo enabled. +// The linker will not include these unused functions in binaries built with cgo enabled. + +// execSecurityRoots finds the macOS list of trusted root certificates +// using only command-line tools. This is our fallback path when cgo isn't available. +// +// The strategy is as follows: +// +// 1. Run "security find-certificate" to dump the list of system root +// CAs in PEM format. +// +// 2. For each dumped cert, conditionally verify it with "security +// verify-cert" if that cert was not in the SystemRootCertificates +// keychain, which can't have custom trust policies. +// +// We need to run "verify-cert" for all certificates not in SystemRootCertificates +// because there might be certificates in the keychains without a corresponding +// trust entry, in which case the logic is complicated (see root_cgo_darwin.go). +// +// TODO: actually parse the "trust-settings-export" output and apply the full +// logic. See Issue 26830. +func execSecurityRoots() (*x509.CertPool, error) { + keychains := []string{"/Library/Keychains/System.keychain"} + + // Note that this results in trusting roots from $HOME/... (the environment + // variable), which might not be expected. + u, err := user.Current() + if err != nil { + if debugDarwinRoots { + fmt.Printf("crypto/x509: get current user: %v\n", err) + } + } else { + keychains = append(keychains, + filepath.Join(u.HomeDir, "/Library/Keychains/login.keychain"), + + // Fresh installs of Sierra use a slightly different path for the login keychain + filepath.Join(u.HomeDir, "/Library/Keychains/login.keychain-db"), + ) + } + + var ( + mu sync.Mutex + roots = x509.NewCertPool() + numVerified int // number of execs of 'security verify-cert', for debug stats + wg sync.WaitGroup + verifyCh = make(chan *x509.Certificate) + ) + + // Using 4 goroutines to pipe into verify-cert seems to be + // about the best we can do. The verify-cert binary seems to + // just RPC to another server with coarse locking anyway, so + // running 16 at a time for instance doesn't help at all. + for i := 0; i < 4; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for cert := range verifyCh { + valid := verifyCertWithSystem(cert) + + mu.Lock() + numVerified++ + if valid { + roots.AddCert(cert) + } + mu.Unlock() + } + }() + } + err = forEachCertInKeychains(keychains, func(cert *x509.Certificate) { + verifyCh <- cert + }) + if err != nil { + return nil, err + } + close(verifyCh) + wg.Wait() + + if debugDarwinRoots { + fmt.Printf("crypto/x509: ran security verify-cert %d times\n", numVerified) + } + + err = forEachCertInKeychains([]string{ + "/System/Library/Keychains/SystemRootCertificates.keychain", + }, roots.AddCert) + if err != nil { + return nil, err + } + + return roots, nil +} + +func forEachCertInKeychains(paths []string, f func(*x509.Certificate)) error { + args := append([]string{"find-certificate", "-a", "-p"}, paths...) + cmd := exec.Command("/usr/bin/security", args...) + data, err := cmd.Output() + if err != nil { + return err + } + for len(data) > 0 { + var block *pem.Block + block, data = pem.Decode(data) + if block == nil { + break + } + if block.Type != "CERTIFICATE" || len(block.Headers) != 0 { + continue + } + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + continue + } + f(cert) + } + return nil +} + +func verifyCertWithSystem(cert *x509.Certificate) bool { + data := pem.EncodeToMemory(&pem.Block{ + Type: "CERTIFICATE", Bytes: cert.Raw, + }) + + f, err := ioutil.TempFile("", "cert") + if err != nil { + fmt.Fprintf(os.Stderr, "can't create temporary file for cert: %v", err) + return false + } + defer os.Remove(f.Name()) + if _, err := f.Write(data); err != nil { + fmt.Fprintf(os.Stderr, "can't write temporary file for cert: %v", err) + return false + } + if err := f.Close(); err != nil { + fmt.Fprintf(os.Stderr, "can't write temporary file for cert: %v", err) + return false + } + cmd := exec.Command("/usr/bin/security", "verify-cert", "-p", "ssl", "-c", f.Name(), "-l", "-L") + var stderr bytes.Buffer + if debugDarwinRoots { + cmd.Stderr = &stderr + } + if err := cmd.Run(); err != nil { + if debugDarwinRoots { + fmt.Printf("crypto/x509: verify-cert rejected %s: %q\n", cert.Subject, bytes.TrimSpace(stderr.Bytes())) + } + return false + } + if debugDarwinRoots { + fmt.Printf("crypto/x509: verify-cert approved %s\n", cert.Subject) + } + return true +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/macos-roots-test/root_nocgo_darwin.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/macos-roots-test/root_nocgo_darwin.go new file mode 100644 index 0000000..cdf44d4 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/macos-roots-test/root_nocgo_darwin.go @@ -0,0 +1,17 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !cgo +// +build !cgo + +package main + +import ( + "crypto/x509" + "errors" +) + +func loadSystemRoots() (*x509.CertPool, error) { + return nil, errors.New("can't load system roots: cgo not enabled") +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/modgraphviz/main.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/modgraphviz/main.go new file mode 100644 index 0000000..a0351dc --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/modgraphviz/main.go @@ -0,0 +1,166 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Modgraphviz converts “go mod graph” output into Graphviz's DOT language, +// for use with Graphviz visualization and analysis tools like dot, dotty, and sccmap. +// +// Usage: +// +// go mod graph | modgraphviz > graph.dot +// go mod graph | modgraphviz | dot -Tpng -o graph.png +// +// Modgraphviz takes no options or arguments; it reads a graph in the format +// generated by “go mod graph” on standard input and writes DOT language +// on standard output. +// +// For each module, the node representing the greatest version (i.e., the +// version chosen by Go's minimal version selection algorithm) is colored green. +// Other nodes, which aren't in the final build list, are colored grey. +// +// See http://www.graphviz.org/doc/info/lang.html for details of the DOT language +// and http://www.graphviz.org/about/ for Graphviz itself. +// +// See also golang.org/x/tools/cmd/digraph for general queries and analysis +// of “go mod graph” output. +package main + +import ( + "bufio" + "bytes" + "flag" + "fmt" + "io" + "log" + "os" + "sort" + "strings" + + "golang.org/x/mod/semver" +) + +func usage() { + fmt.Fprintf(os.Stderr, `Usage: go mod graph | modgraphviz | dot -Tpng -o graph.png + +For each module, the node representing the greatest version (i.e., the +version chosen by Go's minimal version selection algorithm) is colored green. +Other nodes, which aren't in the final build list, are colored grey. +`) + os.Exit(2) +} + +func main() { + log.SetFlags(0) + log.SetPrefix("modgraphviz: ") + + flag.Usage = usage + flag.Parse() + if flag.NArg() != 0 { + usage() + } + + if err := modgraphviz(os.Stdin, os.Stdout); err != nil { + log.Fatal(err) + } +} + +func modgraphviz(in io.Reader, out io.Writer) error { + graph, err := convert(in) + if err != nil { + return err + } + + fmt.Fprintf(out, "digraph gomodgraph {\n") + fmt.Fprintf(out, "\tnode [ shape=rectangle fontsize=12 ]\n") + out.Write(graph.edgesAsDOT()) + for _, n := range graph.mvsPicked { + fmt.Fprintf(out, "\t%q [style = filled, fillcolor = green]\n", n) + } + for _, n := range graph.mvsUnpicked { + fmt.Fprintf(out, "\t%q [style = filled, fillcolor = gray]\n", n) + } + fmt.Fprintf(out, "}\n") + + return nil +} + +type edge struct{ from, to string } +type graph struct { + edges []edge + mvsPicked []string + mvsUnpicked []string +} + +// convert reads “go mod graph” output from r and returns a graph, recording +// MVS picked and unpicked nodes along the way. +func convert(r io.Reader) (*graph, error) { + scanner := bufio.NewScanner(r) + var g graph + seen := map[string]bool{} + mvsPicked := map[string]string{} // module name -> module version + + for scanner.Scan() { + l := scanner.Text() + if l == "" { + continue + } + parts := strings.Fields(l) + if len(parts) != 2 { + return nil, fmt.Errorf("expected 2 words in line, but got %d: %s", len(parts), l) + } + from := parts[0] + to := parts[1] + g.edges = append(g.edges, edge{from: from, to: to}) + + for _, node := range []string{from, to} { + if _, ok := seen[node]; ok { + // Skip over nodes we've already seen. + continue + } + seen[node] = true + + var m, v string + if i := strings.IndexByte(node, '@'); i >= 0 { + m, v = node[:i], node[i+1:] + } else { + // Root node doesn't have a version. + continue + } + + if maxV, ok := mvsPicked[m]; ok { + if semver.Compare(maxV, v) < 0 { + // This version is higher - replace it and consign the old + // max to the unpicked list. + g.mvsUnpicked = append(g.mvsUnpicked, m+"@"+maxV) + mvsPicked[m] = v + } else { + // Other version is higher - stick this version in the + // unpicked list. + g.mvsUnpicked = append(g.mvsUnpicked, node) + } + } else { + mvsPicked[m] = v + } + } + } + if err := scanner.Err(); err != nil { + return nil, err + } + + for m, v := range mvsPicked { + g.mvsPicked = append(g.mvsPicked, m+"@"+v) + } + + // Make this function deterministic. + sort.Strings(g.mvsPicked) + return &g, nil +} + +// edgesAsDOT returns the edges in DOT notation. +func (g *graph) edgesAsDOT() []byte { + var buf bytes.Buffer + for _, e := range g.edges { + fmt.Fprintf(&buf, "\t%q -> %q\n", e.from, e.to) + } + return buf.Bytes() +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/modgraphviz/main_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/modgraphviz/main_test.go new file mode 100644 index 0000000..bec88cf --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/modgraphviz/main_test.go @@ -0,0 +1,116 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "bytes" + "fmt" + "reflect" + "testing" +) + +func TestRun(t *testing.T) { + out := &bytes.Buffer{} + in := bytes.NewBuffer([]byte(` +test.com/A@v1.0.0 test.com/B@v1.2.3 +test.com/B@v1.0.0 test.com/C@v4.5.6 +`)) + if err := modgraphviz(in, out); err != nil { + t.Fatal(err) + } + + gotGraph := string(out.Bytes()) + wantGraph := `digraph gomodgraph { + node [ shape=rectangle fontsize=12 ] + "test.com/A@v1.0.0" -> "test.com/B@v1.2.3" + "test.com/B@v1.0.0" -> "test.com/C@v4.5.6" + "test.com/A@v1.0.0" [style = filled, fillcolor = green] + "test.com/B@v1.2.3" [style = filled, fillcolor = green] + "test.com/C@v4.5.6" [style = filled, fillcolor = green] + "test.com/B@v1.0.0" [style = filled, fillcolor = gray] +} +` + if gotGraph != wantGraph { + t.Fatalf("\ngot: %s\nwant: %s", gotGraph, wantGraph) + } +} + +func TestMVSPicking(t *testing.T) { + for _, tc := range []struct { + name string + in []string + wantPicked []string + wantUnpicked []string + }{ + { + name: "single node", + in: []string{"foo@v0.0.1"}, + wantPicked: []string{"foo@v0.0.1"}, + wantUnpicked: nil, + }, + { + name: "duplicate same node", + in: []string{"foo@v0.0.1", "foo@v0.0.1"}, + wantPicked: []string{"foo@v0.0.1"}, + wantUnpicked: nil, + }, + { + name: "multiple semver - same major", + in: []string{"foo@v1.0.0", "foo@v1.3.7", "foo@v1.2.0", "foo@v1.0.1"}, + wantPicked: []string{"foo@v1.3.7"}, + wantUnpicked: []string{"foo@v1.0.0", "foo@v1.2.0", "foo@v1.0.1"}, + }, + { + name: "multiple semver - multiple major", + in: []string{"foo@v1.0.0", "foo@v1.3.7", "foo/v2@v2.2.0", "foo/v2@v2.0.1", "foo@v1.1.1"}, + wantPicked: []string{"foo/v2@v2.2.0", "foo@v1.3.7"}, + wantUnpicked: []string{"foo@v1.0.0", "foo/v2@v2.0.1", "foo@v1.1.1"}, + }, + { + name: "semver and pseudo version", + in: []string{"foo@v1.0.0", "foo@v1.3.7", "foo/v2@v2.2.0", "foo/v2@v2.0.1", "foo@v1.1.1", "foo@v0.0.0-20190311183353-d8887717615a"}, + wantPicked: []string{"foo/v2@v2.2.0", "foo@v1.3.7"}, + wantUnpicked: []string{"foo@v1.0.0", "foo/v2@v2.0.1", "foo@v1.1.1", "foo@v0.0.0-20190311183353-d8887717615a"}, + }, + { + name: "multiple pseudo version", + in: []string{ + "foo@v0.0.0-20190311183353-d8887717615a", + "foo@v0.0.0-20190227222117-0694c2d4d067", + "foo@v0.0.0-20190312151545-0bb0c0a6e846", + }, + wantPicked: []string{"foo@v0.0.0-20190312151545-0bb0c0a6e846"}, + wantUnpicked: []string{ + "foo@v0.0.0-20190227222117-0694c2d4d067", + "foo@v0.0.0-20190311183353-d8887717615a", + }, + }, + { + name: "semver and suffix", + in: []string{"foo@v1.0.0", "foo@v1.3.8-rc1", "foo@v1.3.7"}, + wantPicked: []string{"foo@v1.3.8-rc1"}, + wantUnpicked: []string{"foo@v1.0.0", "foo@v1.3.7"}, + }, + } { + t.Run(tc.name, func(t *testing.T) { + buf := bytes.Buffer{} + for _, node := range tc.in { + fmt.Fprintf(&buf, "A %s\n", node) + } + + g, err := convert(&buf) + if err != nil { + t.Fatal(err) + } + + if !reflect.DeepEqual(g.mvsPicked, tc.wantPicked) { + t.Fatalf("picked: got %v, want %v", g.mvsPicked, tc.wantPicked) + } + if !reflect.DeepEqual(g.mvsUnpicked, tc.wantUnpicked) { + t.Fatalf("unpicked: got %v, want %v", g.mvsUnpicked, tc.wantUnpicked) + } + }) + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/txtar/txtar.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/txtar/txtar.go new file mode 100644 index 0000000..9beb163 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/txtar/txtar.go @@ -0,0 +1,196 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// The txtar command writes or extracts a text-based file archive in the format +// provided by the golang.org/x/tools/txtar package. +// +// The default behavior is to read a comment from stdin and write the archive +// file containing the recursive contents of the named files and directories, +// including hidden files, to stdout. Any non-flag arguments to the command name +// the files and/or directories to include, with the contents of directories +// included recursively. An empty argument list is equivalent to ".". +// +// The --extract (or -x) flag instructs txtar to instead read the archive file +// from stdin and extract all of its files to corresponding locations relative +// to the current, writing the archive's comment to stdout. +// +// Archive files are by default extracted only to the current directory or its +// subdirectories. To allow extracting outside the current directory, use the +// --unsafe flag. +// +// Shell variables in paths are expanded (using os.Expand) if the corresponding +// variable is set in the process environment. When writing an archive, the +// variables (before expansion) are preserved in the archived paths. +// +// Example usage: +// +// txtar *.go <README >testdata/example.txt +// +// txtar --extract <playground_example.txt >main.go +package main + +import ( + "bytes" + "flag" + "fmt" + "io/ioutil" + "os" + "path" + "path/filepath" + "regexp" + "strings" + "time" + + "golang.org/x/tools/txtar" +) + +var ( + extractFlag = flag.Bool("extract", false, "if true, extract files from the archive instead of writing to it") + unsafeFlag = flag.Bool("unsafe", false, "allow extraction of files outside the current directory") +) + +func init() { + flag.BoolVar(extractFlag, "x", *extractFlag, "short alias for --extract") +} + +func main() { + flag.Parse() + + var err error + if *extractFlag { + if len(flag.Args()) > 0 { + fmt.Fprintln(os.Stderr, "Usage: txtar --extract <archive.txt") + os.Exit(2) + } + err = extract() + } else { + paths := flag.Args() + if len(paths) == 0 { + paths = []string{"."} + } + err = archive(paths) + } + + if err != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + os.Exit(1) + } +} + +func extract() (err error) { + b, err := ioutil.ReadAll(os.Stdin) + if err != nil { + return err + } + + ar := txtar.Parse(b) + + if !*unsafeFlag { + // Check that no files are extracted outside the current directory + wd, err := os.Getwd() + if err != nil { + return err + } + // Add trailing separator to terminate wd. + // This prevents extracting to outside paths which prefix wd, + // e.g. extracting to /home/foobar when wd is /home/foo + if !strings.HasSuffix(wd, string(filepath.Separator)) { + wd += string(filepath.Separator) + } + + for _, f := range ar.Files { + fileName := filepath.Clean(expand(f.Name)) + + if strings.HasPrefix(fileName, "..") || + (filepath.IsAbs(fileName) && !strings.HasPrefix(fileName, wd)) { + return fmt.Errorf("file path '%s' is outside the current directory", f.Name) + } + } + } + + for _, f := range ar.Files { + fileName := filepath.FromSlash(path.Clean(expand(f.Name))) + if err := os.MkdirAll(filepath.Dir(fileName), 0777); err != nil { + return err + } + if err := ioutil.WriteFile(fileName, f.Data, 0666); err != nil { + return err + } + } + + if len(ar.Comment) > 0 { + os.Stdout.Write(ar.Comment) + } + return nil +} + +func archive(paths []string) (err error) { + txtarHeader := regexp.MustCompile(`(?m)^-- .* --$`) + + ar := new(txtar.Archive) + for _, p := range paths { + root := filepath.Clean(expand(p)) + prefix := root + string(filepath.Separator) + err := filepath.Walk(root, func(fileName string, info os.FileInfo, err error) error { + if err != nil || info.IsDir() { + return err + } + + suffix := "" + if fileName != root { + suffix = strings.TrimPrefix(fileName, prefix) + } + name := filepath.ToSlash(filepath.Join(p, suffix)) + + data, err := ioutil.ReadFile(fileName) + if err != nil { + return err + } + if txtarHeader.Match(data) { + return fmt.Errorf("cannot archive %s: file contains a txtar header", name) + } + + ar.Files = append(ar.Files, txtar.File{Name: name, Data: data}) + return nil + }) + if err != nil { + return err + } + } + + // After we have read all of the source files, read the comment from stdin. + // + // Wait until the read has been blocked for a while before prompting the user + // to enter it: if they are piping the comment in from some other file, the + // read should complete very quickly and there is no need for a prompt. + // (200ms is typically long enough to read a reasonable comment from the local + // machine, but short enough that humans don't notice it.) + // + // Don't prompt until we have successfully read the other files: + // if we encountered an error, we don't need to ask for a comment. + timer := time.AfterFunc(200*time.Millisecond, func() { + fmt.Fprintln(os.Stderr, "Enter comment:") + }) + comment, err := ioutil.ReadAll(os.Stdin) + timer.Stop() + if err != nil { + return fmt.Errorf("reading comment from %s: %v", os.Stdin.Name(), err) + } + ar.Comment = bytes.TrimSpace(comment) + + _, err = os.Stdout.Write(txtar.Format(ar)) + return err +} + +// expand is like os.ExpandEnv, but preserves unescaped variables (instead +// of escaping them to the empty string) if the variable is not set. +func expand(p string) string { + return os.Expand(p, func(key string) string { + v, ok := os.LookupEnv(key) + if !ok { + return "$" + key + } + return v + }) +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/txtar/txtar_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/txtar/txtar_test.go new file mode 100644 index 0000000..ea9f2bf --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/cmd/txtar/txtar_test.go @@ -0,0 +1,178 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main_test + +import ( + "fmt" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" + "sync" + "testing" +) + +const comment = "This is a txtar archive.\n" + +const testdata = `This is a txtar archive. +-- one.txt -- +one +-- dir/two.txt -- +two +-- $SPECIAL_LOCATION/three.txt -- +three +` + +func TestMain(m *testing.M) { + code := m.Run() + txtarBin.once.Do(func() {}) + if txtarBin.name != "" { + os.Remove(txtarBin.name) + } + os.Exit(code) +} + +func TestRoundTrip(t *testing.T) { + os.Setenv("SPECIAL_LOCATION", "special") + defer os.Unsetenv("SPECIAL_LOCATION") + + // Expand the testdata archive into a temporary directory. + parentDir, err := ioutil.TempDir("", "txtar") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(parentDir) + dir := filepath.Join(parentDir, "dir") + if err := os.Mkdir(dir, 0755); err != nil { + t.Fatal(err) + } + if out, err := txtar(t, dir, testdata, "--extract"); err != nil { + t.Fatal(err) + } else if out != comment { + t.Fatalf("txtar --extract: stdout:\n%s\nwant:\n%s", out, comment) + } + + // Now, re-archive its contents explicitly and ensure that the result matches + // the original. + args := []string{"one.txt", "dir", "$SPECIAL_LOCATION"} + if out, err := txtar(t, dir, comment, args...); err != nil { + t.Fatal(err) + } else if out != testdata { + t.Fatalf("txtar %s: archive:\n%s\n\nwant:\n%s", strings.Join(args, " "), out, testdata) + } +} + +func TestUnsafePaths(t *testing.T) { + // Set up temporary directories for test archives. + parentDir, err := ioutil.TempDir("", "txtar") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(parentDir) + dir := filepath.Join(parentDir, "dir") + if err := os.Mkdir(dir, 0755); err != nil { + t.Fatal(err) + } + + // Test --unsafe option for both absolute and relative paths + testcases := []struct{ name, path string }{ + {"Absolute", filepath.Join(parentDir, "dirSpecial")}, + {"Relative", "../special"}, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + // Set SPECIAL_LOCATION outside the current directory + t.Setenv("SPECIAL_LOCATION", tc.path) + + // Expand the testdata archive into a temporary directory. + + // Should fail without the --unsafe flag + if _, err := txtar(t, dir, testdata, "--extract"); err == nil { + t.Fatalf("txtar --extract: extracts to unsafe paths") + } + + // Should allow paths outside the current dir with the --unsafe flags + out, err := txtar(t, dir, testdata, "--extract", "--unsafe") + if err != nil { + t.Fatal(err) + } + if out != comment { + t.Fatalf("txtar --extract --unsafe: stdout:\n%s\nwant:\n%s", out, comment) + } + + // Now, re-archive its contents explicitly and ensure that the result matches + // the original. + args := []string{"one.txt", "dir", "$SPECIAL_LOCATION"} + out, err = txtar(t, dir, comment, args...) + if err != nil { + t.Fatal(err) + } + if out != testdata { + t.Fatalf("txtar %s: archive:\n%s\n\nwant:\n%s", strings.Join(args, " "), out, testdata) + } + }) + } +} + +// txtar runs the txtar command in the given directory with the given input and +// arguments. +func txtar(t *testing.T, dir, input string, args ...string) (string, error) { + t.Helper() + cmd := exec.Command(txtarName(t), args...) + cmd.Dir = dir + cmd.Env = append(os.Environ(), "PWD="+dir) + cmd.Stdin = strings.NewReader(input) + stderr := new(strings.Builder) + cmd.Stderr = stderr + out, err := cmd.Output() + if err != nil { + return "", fmt.Errorf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, stderr) + } + if stderr.String() != "" { + t.Logf("OK: %s\n%s", strings.Join(cmd.Args, " "), stderr) + } + return string(out), nil +} + +var txtarBin struct { + once sync.Once + name string + err error +} + +// txtarName returns the name of the txtar executable, building it if needed. +func txtarName(t *testing.T) string { + t.Helper() + if _, err := exec.LookPath("go"); err != nil { + t.Skipf("cannot build txtar binary: %v", err) + } + + txtarBin.once.Do(func() { + exe, err := ioutil.TempFile("", "txtar-*.exe") + if err != nil { + txtarBin.err = err + return + } + exe.Close() + txtarBin.name = exe.Name() + + cmd := exec.Command("go", "build", "-o", txtarBin.name, ".") + out, err := cmd.CombinedOutput() + if err != nil { + txtarBin.err = fmt.Errorf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, out) + } + }) + + if txtarBin.err != nil { + if runtime.GOOS == "android" { + t.Skipf("skipping test after failing to build txtar binary: go_android_exec may have failed to copy needed dependencies (see https://golang.org/issue/37088)") + } + t.Fatal(txtarBin.err) + } + return txtarBin.name +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/codereview.cfg b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/codereview.cfg new file mode 100644 index 0000000..3f8b14b --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/codereview.cfg @@ -0,0 +1 @@ +issuerepo: golang/go diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/constraints/constraints.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/constraints/constraints.go new file mode 100644 index 0000000..2c033df --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/constraints/constraints.go @@ -0,0 +1,50 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package constraints defines a set of useful constraints to be used +// with type parameters. +package constraints + +// Signed is a constraint that permits any signed integer type. +// If future releases of Go add new predeclared signed integer types, +// this constraint will be modified to include them. +type Signed interface { + ~int | ~int8 | ~int16 | ~int32 | ~int64 +} + +// Unsigned is a constraint that permits any unsigned integer type. +// If future releases of Go add new predeclared unsigned integer types, +// this constraint will be modified to include them. +type Unsigned interface { + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr +} + +// Integer is a constraint that permits any integer type. +// If future releases of Go add new predeclared integer types, +// this constraint will be modified to include them. +type Integer interface { + Signed | Unsigned +} + +// Float is a constraint that permits any floating-point type. +// If future releases of Go add new predeclared floating-point types, +// this constraint will be modified to include them. +type Float interface { + ~float32 | ~float64 +} + +// Complex is a constraint that permits any complex numeric type. +// If future releases of Go add new predeclared complex numeric types, +// this constraint will be modified to include them. +type Complex interface { + ~complex64 | ~complex128 +} + +// Ordered is a constraint that permits any ordered type: any type +// that supports the operators < <= >= >. +// If future releases of Go add new ordered types, +// this constraint will be modified to include them. +type Ordered interface { + Integer | Float | ~string +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/constraints/constraints_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/constraints/constraints_test.go new file mode 100644 index 0000000..5bc43a9 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/constraints/constraints_test.go @@ -0,0 +1,160 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package constraints + +import ( + "bytes" + "fmt" + "os" + "os/exec" + "path/filepath" + "runtime" + "testing" +) + +type ( + testSigned[T Signed] struct{ f T } + testUnsigned[T Unsigned] struct{ f T } + testInteger[T Integer] struct{ f T } + testFloat[T Float] struct{ f T } + testComplex[T Complex] struct{ f T } + testOrdered[T Ordered] struct{ f T } +) + +// TestTypes passes if it compiles. +type TestTypes struct { + _ testSigned[int] + _ testSigned[int64] + _ testUnsigned[uint] + _ testUnsigned[uintptr] + _ testInteger[int8] + _ testInteger[uint8] + _ testInteger[uintptr] + _ testFloat[float32] + _ testComplex[complex64] + _ testOrdered[int] + _ testOrdered[float64] + _ testOrdered[string] +} + +var prolog = []byte(` +package constrainttest + +import "golang.org/x/exp/constraints" + +type ( + testSigned[T constraints.Signed] struct{ f T } + testUnsigned[T constraints.Unsigned] struct{ f T } + testInteger[T constraints.Integer] struct{ f T } + testFloat[T constraints.Float] struct{ f T } + testComplex[T constraints.Complex] struct{ f T } + testOrdered[T constraints.Ordered] struct{ f T } +) +`) + +func TestFailure(t *testing.T) { + switch runtime.GOOS { + case "android", "js", "ios": + t.Skipf("can't run go tool on %s", runtime.GOOS) + } + + var exeSuffix string + if runtime.GOOS == "windows" { + exeSuffix = ".exe" + } + gocmd := filepath.Join(runtime.GOROOT(), "bin", "go"+exeSuffix) + if _, err := os.Stat(gocmd); err != nil { + t.Skipf("skipping because can't stat %s: %v", gocmd, err) + } + + tmpdir := t.TempDir() + + cwd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + // This package is golang.org/x/exp/constraints, so the root of the x/exp + // module is the parent directory of the directory in which this test runs. + expModDir := filepath.Dir(cwd) + + modFile := fmt.Sprintf(`module constraintest + +go 1.18 + +replace golang.org/x/exp => %s +`, expModDir) + if err := os.WriteFile(filepath.Join(tmpdir, "go.mod"), []byte(modFile), 0666); err != nil { + t.Fatal(err) + } + + // Write the prolog as its own file so that 'go mod tidy' has something to inspect. + // This will ensure that the go.mod and go.sum files include any dependencies + // needed by the constraints package (which should just be some version of + // x/exp itself). + if err := os.WriteFile(filepath.Join(tmpdir, "prolog.go"), []byte(prolog), 0666); err != nil { + t.Fatal(err) + } + + tidyCmd := exec.Command(gocmd, "mod", "tidy") + tidyCmd.Dir = tmpdir + tidyCmd.Env = append(os.Environ(), "PWD="+tmpdir) + if out, err := tidyCmd.CombinedOutput(); err != nil { + t.Fatalf("%v: %v\n%s", tidyCmd, err, out) + } else { + t.Logf("%v:\n%s", tidyCmd, out) + } + + // Test for types that should not satisfy a constraint. + // For each pair of constraint and type, write a Go file + // var V constraint[type] + // For example, + // var V testSigned[uint] + // This should not compile, as testSigned (above) uses + // constraints.Signed, and uint does not satisfy that constraint. + // Therefore, the build of that code should fail. + for i, test := range []struct { + constraint, typ string + }{ + {"testSigned", "uint"}, + {"testUnsigned", "int"}, + {"testInteger", "float32"}, + {"testFloat", "int8"}, + {"testComplex", "float64"}, + {"testOrdered", "bool"}, + } { + i := i + test := test + t.Run(fmt.Sprintf("%s %d", test.constraint, i), func(t *testing.T) { + t.Parallel() + name := fmt.Sprintf("go%d.go", i) + f, err := os.Create(filepath.Join(tmpdir, name)) + if err != nil { + t.Fatal(err) + } + if _, err := f.Write(prolog); err != nil { + t.Fatal(err) + } + if _, err := fmt.Fprintf(f, "var V %s[%s]\n", test.constraint, test.typ); err != nil { + t.Fatal(err) + } + if err := f.Close(); err != nil { + t.Fatal(err) + } + cmd := exec.Command(gocmd, "build", name) + cmd.Dir = tmpdir + if out, err := cmd.CombinedOutput(); err == nil { + t.Error("build succeeded, but expected to fail") + } else if len(out) > 0 { + t.Logf("%s", out) + const want = "does not implement" + if !bytes.Contains(out, []byte(want)) { + t.Errorf("output does not include %q", want) + } + } else { + t.Error("no error output, expected something") + } + }) + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/devtools/checklib.sh b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/devtools/checklib.sh new file mode 100644 index 0000000..0b6095e --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/devtools/checklib.sh @@ -0,0 +1,73 @@ +# Copyright 2021 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +# Library of useful bash functions and variables for presubmit checks. + +RED=; GREEN=; YELLOW=; NORMAL=; +MAXWIDTH=0 + +if tput setaf 1 >& /dev/null; then + RED=`tput setaf 1` + GREEN=`tput setaf 2` + YELLOW=`tput setaf 3` + NORMAL=`tput sgr0` + MAXWIDTH=$(( $(tput cols) - 2 )) +fi + +EXIT_CODE=0 + +info() { echo -e "${GREEN}$@${NORMAL}" 1>&2; } +warn() { echo -e "${YELLOW}$@${NORMAL}" 1>&2; } +err() { echo -e "${RED}$@${NORMAL}" 1>&2; EXIT_CODE=1; } + +die() { + err $@ + exit 1 +} + +dryrun=false + +# runcmd prints an info log describing the command that is about to be run, and +# then runs it. It sets EXIT_CODE to non-zero if the command fails, but does not exit +# the script. +runcmd() { + msg="$@" + if $dryrun; then + echo -e "${YELLOW}dryrun${GREEN}\$ $msg${NORMAL}" + return 0 + fi + # Truncate command logging for narrow terminals. + # Account for the 2 characters of '$ '. + if [[ $MAXWIDTH -gt 0 && ${#msg} -gt $MAXWIDTH ]]; then + msg="${msg::$(( MAXWIDTH - 3 ))}..." + fi + + echo -e "$@\n" 1>&2; + $@ || err "command failed" +} + +# check_header checks that all given files contain the standard header for Go +# projects. +check_header() { + if [[ "$@" != "" ]]; then + for FILE in $@ + do + line="$(head -4 $FILE)" + if [[ ! $line == *"The Go Authors. All rights reserved."* ]] && + [[ ! $line == "// DO NOT EDIT. This file was copied from" ]]; then + err "missing license header: $FILE" + fi + done + fi +} + +# ensure_go_binary verifies that a binary exists in $PATH corresponding to the +# given go-gettable URI. If no such binary exists, it is fetched via `go install`. +ensure_go_binary() { + local binary=$(basename $1) + if ! [ -x "$(command -v $binary)" ]; then + info "Installing: $1" + go install $1 + fi +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/ebnf/ebnf.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/ebnf/ebnf.go new file mode 100644 index 0000000..a4e20f0 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/ebnf/ebnf.go @@ -0,0 +1,267 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package ebnf is a library for EBNF grammars. The input is text ([]byte) +// satisfying the following grammar (represented itself in EBNF): +// +// Production = name "=" [ Expression ] "." . +// Expression = Alternative { "|" Alternative } . +// Alternative = Term { Term } . +// Term = name | token [ "…" token ] | Group | Option | Repetition . +// Group = "(" Expression ")" . +// Option = "[" Expression "]" . +// Repetition = "{" Expression "}" . +// +// A name is a Go identifier, a token is a Go string, and comments +// and white space follow the same rules as for the Go language. +// Production names starting with an uppercase Unicode letter denote +// non-terminal productions (i.e., productions which allow white-space +// and comments between tokens); all other production names denote +// lexical productions. +package ebnf // import "golang.org/x/exp/ebnf" + +import ( + "errors" + "fmt" + "text/scanner" + "unicode" + "unicode/utf8" +) + +// ---------------------------------------------------------------------------- +// Error handling + +type errorList []error + +func (list errorList) Err() error { + if len(list) == 0 { + return nil + } + return list +} + +func (list errorList) Error() string { + switch len(list) { + case 0: + return "no errors" + case 1: + return list[0].Error() + } + return fmt.Sprintf("%s (and %d more errors)", list[0], len(list)-1) +} + +func newError(pos scanner.Position, msg string) error { + return errors.New(fmt.Sprintf("%s: %s", pos, msg)) +} + +// ---------------------------------------------------------------------------- +// Internal representation + +type ( + // An Expression node represents a production expression. + Expression interface { + // Pos is the position of the first character of the syntactic construct + Pos() scanner.Position + } + + // An Alternative node represents a non-empty list of alternative expressions. + Alternative []Expression // x | y | z + + // A Sequence node represents a non-empty list of sequential expressions. + Sequence []Expression // x y z + + // A Name node represents a production name. + Name struct { + StringPos scanner.Position + String string + } + + // A Token node represents a literal. + Token struct { + StringPos scanner.Position + String string + } + + // A List node represents a range of characters. + Range struct { + Begin, End *Token // begin ... end + } + + // A Group node represents a grouped expression. + Group struct { + Lparen scanner.Position + Body Expression // (body) + } + + // An Option node represents an optional expression. + Option struct { + Lbrack scanner.Position + Body Expression // [body] + } + + // A Repetition node represents a repeated expression. + Repetition struct { + Lbrace scanner.Position + Body Expression // {body} + } + + // A Production node represents an EBNF production. + Production struct { + Name *Name + Expr Expression + } + + // A Bad node stands for pieces of source code that lead to a parse error. + Bad struct { + TokPos scanner.Position + Error string // parser error message + } + + // A Grammar is a set of EBNF productions. The map + // is indexed by production name. + // + Grammar map[string]*Production +) + +func (x Alternative) Pos() scanner.Position { return x[0].Pos() } // the parser always generates non-empty Alternative +func (x Sequence) Pos() scanner.Position { return x[0].Pos() } // the parser always generates non-empty Sequences +func (x *Name) Pos() scanner.Position { return x.StringPos } +func (x *Token) Pos() scanner.Position { return x.StringPos } +func (x *Range) Pos() scanner.Position { return x.Begin.Pos() } +func (x *Group) Pos() scanner.Position { return x.Lparen } +func (x *Option) Pos() scanner.Position { return x.Lbrack } +func (x *Repetition) Pos() scanner.Position { return x.Lbrace } +func (x *Production) Pos() scanner.Position { return x.Name.Pos() } +func (x *Bad) Pos() scanner.Position { return x.TokPos } + +// ---------------------------------------------------------------------------- +// Grammar verification + +func isLexical(name string) bool { + ch, _ := utf8.DecodeRuneInString(name) + return !unicode.IsUpper(ch) +} + +type verifier struct { + errors errorList + worklist []*Production + reached Grammar // set of productions reached from (and including) the root production + grammar Grammar +} + +func (v *verifier) error(pos scanner.Position, msg string) { + v.errors = append(v.errors, newError(pos, msg)) +} + +func (v *verifier) push(prod *Production) { + name := prod.Name.String + if _, found := v.reached[name]; !found { + v.worklist = append(v.worklist, prod) + v.reached[name] = prod + } +} + +func (v *verifier) verifyChar(x *Token) rune { + s := x.String + if utf8.RuneCountInString(s) != 1 { + v.error(x.Pos(), "single char expected, found "+s) + return 0 + } + ch, _ := utf8.DecodeRuneInString(s) + return ch +} + +func (v *verifier) verifyExpr(expr Expression, lexical bool) { + switch x := expr.(type) { + case nil: + // empty expression + case Alternative: + for _, e := range x { + v.verifyExpr(e, lexical) + } + case Sequence: + for _, e := range x { + v.verifyExpr(e, lexical) + } + case *Name: + // a production with this name must exist; + // add it to the worklist if not yet processed + if prod, found := v.grammar[x.String]; found { + v.push(prod) + } else { + v.error(x.Pos(), "missing production "+x.String) + } + // within a lexical production references + // to non-lexical productions are invalid + if lexical && !isLexical(x.String) { + v.error(x.Pos(), "reference to non-lexical production "+x.String) + } + case *Token: + // nothing to do for now + case *Range: + i := v.verifyChar(x.Begin) + j := v.verifyChar(x.End) + if i >= j { + v.error(x.Pos(), "decreasing character range") + } + case *Group: + v.verifyExpr(x.Body, lexical) + case *Option: + v.verifyExpr(x.Body, lexical) + case *Repetition: + v.verifyExpr(x.Body, lexical) + case *Bad: + v.error(x.Pos(), x.Error) + default: + panic(fmt.Sprintf("internal error: unexpected type %T", expr)) + } +} + +func (v *verifier) verify(grammar Grammar, start string) { + // find root production + root, found := grammar[start] + if !found { + var noPos scanner.Position + v.error(noPos, "no start production "+start) + return + } + + // initialize verifier + v.worklist = v.worklist[0:0] + v.reached = make(Grammar) + v.grammar = grammar + + // work through the worklist + v.push(root) + for { + n := len(v.worklist) - 1 + if n < 0 { + break + } + prod := v.worklist[n] + v.worklist = v.worklist[0:n] + v.verifyExpr(prod.Expr, isLexical(prod.Name.String)) + } + + // check if all productions were reached + if len(v.reached) < len(v.grammar) { + for name, prod := range v.grammar { + if _, found := v.reached[name]; !found { + v.error(prod.Pos(), name+" is unreachable") + } + } + } +} + +// Verify checks that: +// - all productions used are defined +// - all productions defined are used when beginning at start +// - lexical productions refer only to other lexical productions +// +// Position information is interpreted relative to the file set fset. +func Verify(grammar Grammar, start string) error { + var v verifier + v.verify(grammar, start) + return v.errors.Err() +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/ebnf/ebnf_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/ebnf/ebnf_test.go new file mode 100644 index 0000000..8219986 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/ebnf/ebnf_test.go @@ -0,0 +1,73 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ebnf + +import ( + "bytes" + "testing" +) + +var goodGrammars = []string{ + `Program = .`, + + `Program = foo . + foo = "foo" .`, + + `Program = "a" | "b" "c" .`, + + `Program = "a" … "z" .`, + + `Program = Song . + Song = { Note } . + Note = Do | (Re | Mi | Fa | So | La) | Ti . + Do = "c" . + Re = "d" . + Mi = "e" . + Fa = "f" . + So = "g" . + La = "a" . + Ti = ti . + ti = "b" .`, + + "Program = `\"` .", +} + +var badGrammars = []string{ + `Program = | .`, + `Program = | b .`, + `Program = a … b .`, + `Program = "a" … .`, + `Program = … "b" .`, + `Program = () .`, + `Program = [] .`, + `Program = {} .`, +} + +func checkGood(t *testing.T, src string) { + grammar, err := Parse("", bytes.NewBuffer([]byte(src))) + if err != nil { + t.Errorf("Parse(%s) failed: %v", src, err) + return + } + if err = Verify(grammar, "Program"); err != nil { + t.Errorf("Verify(%s) failed: %v", src, err) + } +} + +func checkBad(t *testing.T, src string) { + _, err := Parse("", bytes.NewBuffer([]byte(src))) + if err == nil { + t.Errorf("Parse(%s) should have failed", src) + } +} + +func TestGrammars(t *testing.T) { + for _, src := range goodGrammars { + checkGood(t, src) + } + for _, src := range badGrammars { + checkBad(t, src) + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/ebnf/parser.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/ebnf/parser.go new file mode 100644 index 0000000..7aa7a70 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/ebnf/parser.go @@ -0,0 +1,189 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ebnf + +import ( + "io" + "strconv" + "text/scanner" +) + +type parser struct { + errors errorList + scanner scanner.Scanner + pos scanner.Position // token position + tok rune // one token look-ahead + lit string // token literal +} + +func (p *parser) next() { + p.tok = p.scanner.Scan() + p.pos = p.scanner.Position + p.lit = p.scanner.TokenText() +} + +func (p *parser) error(pos scanner.Position, msg string) { + p.errors = append(p.errors, newError(pos, msg)) +} + +func (p *parser) errorExpected(pos scanner.Position, msg string) { + msg = `expected "` + msg + `"` + if pos.Offset == p.pos.Offset { + // the error happened at the current position; + // make the error message more specific + msg += ", found " + scanner.TokenString(p.tok) + if p.tok < 0 { + msg += " " + p.lit + } + } + p.error(pos, msg) +} + +func (p *parser) expect(tok rune) scanner.Position { + pos := p.pos + if p.tok != tok { + p.errorExpected(pos, scanner.TokenString(tok)) + } + p.next() // make progress in any case + return pos +} + +func (p *parser) parseIdentifier() *Name { + pos := p.pos + name := p.lit + p.expect(scanner.Ident) + return &Name{pos, name} +} + +func (p *parser) parseToken() *Token { + pos := p.pos + value := "" + if p.tok == scanner.String || p.tok == scanner.RawString { + value, _ = strconv.Unquote(p.lit) + // Unquote may fail with an error, but only if the scanner found + // an illegal string in the first place. In this case the error + // has already been reported. + p.next() + } else { + p.expect(scanner.String) + } + return &Token{pos, value} +} + +// ParseTerm returns nil if no term was found. +func (p *parser) parseTerm() (x Expression) { + pos := p.pos + + switch p.tok { + case scanner.Ident: + x = p.parseIdentifier() + + case scanner.String, scanner.RawString: + tok := p.parseToken() + x = tok + const ellipsis = '…' // U+2026, the horizontal ellipsis character + if p.tok == ellipsis { + p.next() + x = &Range{tok, p.parseToken()} + } + + case '(': + p.next() + x = &Group{pos, p.parseExpression()} + p.expect(')') + + case '[': + p.next() + x = &Option{pos, p.parseExpression()} + p.expect(']') + + case '{': + p.next() + x = &Repetition{pos, p.parseExpression()} + p.expect('}') + } + + return x +} + +func (p *parser) parseSequence() Expression { + var list Sequence + + for x := p.parseTerm(); x != nil; x = p.parseTerm() { + list = append(list, x) + } + + // no need for a sequence if list.Len() < 2 + switch len(list) { + case 0: + p.errorExpected(p.pos, "term") + return &Bad{p.pos, "term expected"} + case 1: + return list[0] + } + + return list +} + +func (p *parser) parseExpression() Expression { + var list Alternative + + for { + list = append(list, p.parseSequence()) + if p.tok != '|' { + break + } + p.next() + } + // len(list) > 0 + + // no need for an Alternative node if list.Len() < 2 + if len(list) == 1 { + return list[0] + } + + return list +} + +func (p *parser) parseProduction() *Production { + name := p.parseIdentifier() + p.expect('=') + var expr Expression + if p.tok != '.' { + expr = p.parseExpression() + } + p.expect('.') + return &Production{name, expr} +} + +func (p *parser) parse(filename string, src io.Reader) Grammar { + p.scanner.Init(src) + p.scanner.Filename = filename + p.next() // initializes pos, tok, lit + + grammar := make(Grammar) + for p.tok != scanner.EOF { + prod := p.parseProduction() + name := prod.Name.String + if _, found := grammar[name]; !found { + grammar[name] = prod + } else { + p.error(prod.Pos(), name+" declared already") + } + } + + return grammar +} + +// Parse parses a set of EBNF productions from source src. +// It returns a set of productions. Errors are reported +// for incorrect syntax and if a production is declared +// more than once; the filename is used only for error +// positions. +func Parse(filename string, src io.Reader) (Grammar, error) { + var p parser + grammar := p.parse(filename, src) + return grammar, p.errors.Err() +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/ebnflint/doc.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/ebnflint/doc.go new file mode 100644 index 0000000..79d3a66 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/ebnflint/doc.go @@ -0,0 +1,21 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Ebnflint verifies that EBNF productions are consistent and grammatically correct. +It reads them from an HTML document such as the Go specification. + +Grammar productions are grouped in boxes demarcated by the HTML elements + + <pre class="ebnf"> + </pre> + +Usage: + + go tool ebnflint [--start production] [file] + +The --start flag specifies the name of the start production for +the grammar; it defaults to "Start". +*/ +package main // import "golang.org/x/exp/ebnflint" diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/ebnflint/ebnflint.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/ebnflint/ebnflint.go new file mode 100644 index 0000000..bf8ad54 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/ebnflint/ebnflint.go @@ -0,0 +1,123 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "bytes" + "flag" + "fmt" + "go/scanner" + "go/token" + "io" + "io/ioutil" + "os" + "path/filepath" + + "golang.org/x/exp/ebnf" +) + +var fset = token.NewFileSet() +var start = flag.String("start", "Start", "name of start production") + +func usage() { + fmt.Fprintf(os.Stderr, "usage: go tool ebnflint [flags] [filename]\n") + flag.PrintDefaults() + os.Exit(1) +} + +// Markers around EBNF sections in .html files +var ( + open = []byte(`<pre class="ebnf">`) + close = []byte(`</pre>`) +) + +func report(err error) { + scanner.PrintError(os.Stderr, err) + os.Exit(1) +} + +func extractEBNF(src []byte) []byte { + var buf bytes.Buffer + + for { + // i = beginning of EBNF text + i := bytes.Index(src, open) + if i < 0 { + break // no EBNF found - we are done + } + i += len(open) + + // write as many newlines as found in the excluded text + // to maintain correct line numbers in error messages + for _, ch := range src[0:i] { + if ch == '\n' { + buf.WriteByte('\n') + } + } + + // j = end of EBNF text (or end of source) + j := bytes.Index(src[i:], close) // close marker + if j < 0 { + j = len(src) - i + } + j += i + + // copy EBNF text + buf.Write(src[i:j]) + + // advance + src = src[j:] + } + + return buf.Bytes() +} + +func main() { + flag.Parse() + + var ( + name string + r io.Reader + ) + switch flag.NArg() { + case 0: + name, r = "<stdin>", os.Stdin + case 1: + name = flag.Arg(0) + default: + usage() + } + + if err := verify(name, *start, r); err != nil { + report(err) + } +} + +func verify(name, start string, r io.Reader) error { + if r == nil { + f, err := os.Open(name) + if err != nil { + return err + } + defer f.Close() + r = f + } + + src, err := ioutil.ReadAll(r) + if err != nil { + return err + } + + if filepath.Ext(name) == ".html" || bytes.Index(src, open) >= 0 { + src = extractEBNF(src) + } + + grammar, err := ebnf.Parse(name, bytes.NewBuffer(src)) + if err != nil { + return err + } + + return ebnf.Verify(grammar, start) +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/ebnflint/ebnflint_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/ebnflint/ebnflint_test.go new file mode 100644 index 0000000..91fb363 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/ebnflint/ebnflint_test.go @@ -0,0 +1,22 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "os" + "runtime" + "testing" +) + +func TestSpec(t *testing.T) { + if err := verify(runtime.GOROOT()+"/doc/go_spec.html", "SourceFile", nil); err != nil { + if os.IsNotExist(err) { + // Couldn't find/open the file - skip test rather than + // complain since not all builders copy the spec. + t.Skip("spec file not found") + } + t.Fatal(err) + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/go.mod b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/go.mod new file mode 100644 index 0000000..c64f300 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/go.mod @@ -0,0 +1,14 @@ +module golang.org/x/exp + +go 1.18 + +require ( + golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 + golang.org/x/tools v0.1.10 +) + +require ( + github.com/google/go-cmp v0.5.8 // indirect + golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect +) diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/go.sum b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/go.sum new file mode 100644 index 0000000..d6c4d58 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/go.sum @@ -0,0 +1,14 @@ +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57 h1:LQmS1nU0twXLA96Kt7U9qtHJEbBk3z6Q0V4UXjZkpr4= +golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 h1:id054HUawV2/6IGm2IV8KZQjqtwAOo2CYlOToYqa0d0= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023 h1:0c3L82FDQ5rt1bjTBlchS8t6RQ6299/+5bWMnRLh+uI= +golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/inotify/README.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/inotify/README.txt new file mode 100644 index 0000000..2ba49f6 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/inotify/README.txt @@ -0,0 +1,3 @@ +Please use gopkg.in/fsnotify.v0 instead. + +For updates, see: https://fsnotify.org/ diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/i2c/devfs.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/i2c/devfs.go new file mode 100644 index 0000000..3c7704f --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/i2c/devfs.go @@ -0,0 +1,80 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux +// +build linux + +package i2c + +import ( + "fmt" + "io" + "os" + "syscall" + + "golang.org/x/exp/io/i2c/driver" +) + +// Devfs is an I2C driver that works against the devfs. +// You need to load the "i2c-dev" kernel module to use this driver. +type Devfs struct { + // Dev is the I2C bus device, e.g. /dev/i2c-1. Required. + Dev string +} + +const ( + i2c_SLAVE = 0x0703 // TODO(jbd): Allow users to use I2C_SLAVE_FORCE? + i2c_TENBIT = 0x0704 +) + +// TODO(jbd): Support I2C_RETRIES and I2C_TIMEOUT at the driver and implementation level. + +func (d *Devfs) Open(addr int, tenbit bool) (driver.Conn, error) { + f, err := os.OpenFile(d.Dev, os.O_RDWR, os.ModeDevice) + if err != nil { + return nil, err + } + conn := &devfsConn{f: f} + if tenbit { + if err := conn.ioctl(i2c_TENBIT, uintptr(1)); err != nil { + conn.Close() + return nil, fmt.Errorf("cannot enable the 10-bit address mode on bus %v: %v", d.Dev, err) + } + } + if err := conn.ioctl(i2c_SLAVE, uintptr(addr)); err != nil { + conn.Close() + return nil, fmt.Errorf("error opening the address (%v) on the bus (%v): %v", addr, d.Dev, err) + } + return conn, nil +} + +type devfsConn struct { + f *os.File +} + +func (c *devfsConn) Tx(w, r []byte) error { + if w != nil { + if _, err := c.f.Write(w); err != nil { + return err + } + c.f.Sync() + } + if r != nil { + if _, err := io.ReadFull(c.f, r); err != nil { + return err + } + } + return nil +} + +func (c *devfsConn) Close() error { + return c.f.Close() +} + +func (c *devfsConn) ioctl(arg1, arg2 uintptr) error { + if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, c.f.Fd(), arg1, arg2); errno != 0 { + return syscall.Errno(errno) + } + return nil +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/i2c/devfs_nonlinux.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/i2c/devfs_nonlinux.go new file mode 100644 index 0000000..619fb9f --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/i2c/devfs_nonlinux.go @@ -0,0 +1,25 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !linux +// +build !linux + +package i2c + +import ( + "errors" + + "golang.org/x/exp/io/i2c/driver" +) + +// Devfs is no-implementation so developers using cross compilation +// can rely on local tools even though the real implementation isn't +// available on their platform. +type Devfs struct { + Dev string +} + +func (d *Devfs) Open(addr int, tenbit bool) (driver.Conn, error) { + return nil, errors.New("not implemented on this platform") +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/i2c/driver/driver.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/i2c/driver/driver.go new file mode 100644 index 0000000..3fe51a4 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/i2c/driver/driver.go @@ -0,0 +1,24 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package driver contains interfaces to be implemented by various I2C implementations. +package driver // import "golang.org/x/exp/io/i2c/driver" + +// Opener opens a connection to an I2C device to communicate with +// the I2C address given. If the address is an 10-bit I2C address, +// tenbit is true. +type Opener interface { + Open(addr int, tenbit bool) (Conn, error) +} + +// Conn represents an active connection to an I2C device. +type Conn interface { + // Tx first writes w (if not nil), then reads len(r) + // bytes from device into r (if not nil) in a single + // I2C transaction. + Tx(w, r []byte) error + + // Close closes the connection. + Close() error +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/i2c/example/displayip/main.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/i2c/example/displayip/main.go new file mode 100644 index 0000000..58fe694 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/i2c/example/displayip/main.go @@ -0,0 +1,89 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package main contains a program that displays the IPv4 address +// of the machine on an a Grove-LCD RGB backlight. +package main + +import ( + "fmt" + "net" + + "golang.org/x/exp/io/i2c" +) + +const ( + DISPLAY_RGB_ADDR = 0x62 + DISPLAY_TEXT_ADDR = 0x3e +) + +func main() { + d, err := i2c.Open(&i2c.Devfs{Dev: "/dev/i2c-1"}, DISPLAY_RGB_ADDR) + if err != nil { + panic(err) + } + + td, err := i2c.Open(&i2c.Devfs{Dev: "/dev/i2c-1"}, DISPLAY_TEXT_ADDR) + if err != nil { + panic(err) + } + + // Set the backlight color to 100,100,100. + write(d, []byte{0, 0}) + write(d, []byte{1, 0}) + write(d, []byte{0x08, 0xaa}) + write(d, []byte{4, 100}) // R value + write(d, []byte{3, 100}) // G value + write(d, []byte{2, 100}) // B value + + ip, err := resolveIP() + if err != nil { + panic(err) + } + + fmt.Printf("host machine IP is %v\n", ip) + + write(td, []byte{0x80, 0x02}) // return home + write(td, []byte{0x80, 0x01}) // clean the display + write(td, []byte{0x80, 0x08 | 0x04}) // no cursor + write(td, []byte{0x80, 0x28}) // two lines + + for _, s := range ip { + write(td, []byte{0x40, byte(s)}) + } +} + +func write(d *i2c.Device, buf []byte) { + err := d.Write(buf) + if err != nil { + panic(err) + } +} + +func resolveIP() (string, error) { + var ip net.IP + ifaces, err := net.Interfaces() + if err != nil { + panic(err) + } + for _, i := range ifaces { + addrs, err := i.Addrs() + if err != nil { + panic(err) + } + for _, addr := range addrs { + switch v := addr.(type) { + case *net.IPNet: + ip = v.IP + case *net.IPAddr: + ip = v.IP + } + ip = ip.To4() + if ip != nil && ip.String() != "127.0.0.1" { + return ip.String(), nil + } + } + } + return "", fmt.Errorf("cannot resolve the IP") +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/i2c/example_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/i2c/example_test.go new file mode 100644 index 0000000..aeedaeb --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/i2c/example_test.go @@ -0,0 +1,24 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package i2c_test + +import ( + "golang.org/x/exp/io/i2c" +) + +func ExampleOpen() { + d, err := i2c.Open(&i2c.Devfs{Dev: "/dev/i2c-1"}, 0x39) + if err != nil { + panic(err) + } + + // opens a 10-bit address + d, err = i2c.Open(&i2c.Devfs{Dev: "/dev/i2c-1"}, i2c.TenBit(0x78)) + if err != nil { + panic(err) + } + + _ = d +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/i2c/i2c.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/i2c/i2c.go new file mode 100644 index 0000000..192ad3d --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/i2c/i2c.go @@ -0,0 +1,75 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package i2c allows users to read from and write to a slave I2C device. +// +// # Deprecated +// +// This package is not maintained anymore. An actively supported cross-platform +// alternative is https://periph.io/. +package i2c // import "golang.org/x/exp/io/i2c" + +import ( + "golang.org/x/exp/io/i2c/driver" +) + +const tenbitMask = 1 << 12 + +// Device represents an I2C device. Devices must be closed once +// they are no longer in use. +type Device struct { + conn driver.Conn +} + +// TenBit marks an I2C address as a 10-bit address. +func TenBit(addr int) int { + return addr | tenbitMask +} + +// Read reads len(buf) bytes from the device. +func (d *Device) Read(buf []byte) error { + return d.conn.Tx(nil, buf) +} + +// ReadReg is similar to Read but it reads from a register. +func (d *Device) ReadReg(reg byte, buf []byte) error { + return d.conn.Tx([]byte{reg}, buf) +} + +// Write writes the buffer to the device. If it is required to write to a +// specific register, the register should be passed as the first byte in the +// given buffer. +func (d *Device) Write(buf []byte) (err error) { + return d.conn.Tx(buf, nil) +} + +// WriteReg is similar to Write but writes to a register. +func (d *Device) WriteReg(reg byte, buf []byte) (err error) { + // TODO(jbd): Do not allocate, not optimal. + return d.conn.Tx(append([]byte{reg}, buf...), nil) +} + +// Close closes the device and releases the underlying sources. +func (d *Device) Close() error { + return d.conn.Close() +} + +// Open opens a connection to an I2C device. +// All devices must be closed once they are no longer in use. +// For devices that use 10-bit I2C addresses, addr can be marked +// as a 10-bit address with TenBit. +func Open(o driver.Opener, addr int) (*Device, error) { + unmasked, tenbit := resolveAddr(addr) + conn, err := o.Open(unmasked, tenbit) + if err != nil { + return nil, err + } + return &Device{conn: conn}, nil +} + +// resolveAddr returns whether the addr is 10-bit masked or not. +// It also returns the unmasked address. +func resolveAddr(addr int) (unmasked int, tenbit bool) { + return addr & (tenbitMask - 1), addr&tenbitMask == tenbitMask +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/i2c/i2c_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/i2c/i2c_test.go new file mode 100644 index 0000000..8765e3e --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/i2c/i2c_test.go @@ -0,0 +1,31 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package i2c + +import ( + "testing" +) + +func TestTenBit(t *testing.T) { + tc := []struct { + masked int + addrWant int + tenbitWant bool + }{ + {TenBit(0x5), 0x5, true}, + {0x5, 0x5, false}, + {TenBit(0x200), 0x200, true}, + } + + for _, tt := range tc { + unmasked, tenbit := resolveAddr(tt.masked) + if want, got := tt.tenbitWant, tenbit; got != want { + t.Errorf("want address %x as 10-bit; got non 10-bit", tt.masked) + } + if want, got := tt.addrWant, unmasked; got != want { + t.Errorf("want address %v; got %v", want, got) + } + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/spi/devfs.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/spi/devfs.go new file mode 100644 index 0000000..a5f1bca --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/spi/devfs.go @@ -0,0 +1,177 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux +// +build linux + +package spi + +import ( + "fmt" + "os" + "syscall" + "unsafe" + + "golang.org/x/exp/io/spi/driver" +) + +const ( + devfs_MAGIC = 107 + + devfs_NRBITS = 8 + devfs_TYPEBITS = 8 + devfs_SIZEBITS = 13 + devfs_DIRBITS = 3 + + devfs_NRSHIFT = 0 + devfs_TYPESHIFT = devfs_NRSHIFT + devfs_NRBITS + devfs_SIZESHIFT = devfs_TYPESHIFT + devfs_TYPEBITS + devfs_DIRSHIFT = devfs_SIZESHIFT + devfs_SIZEBITS + + devfs_READ = 2 + devfs_WRITE = 4 +) + +type payload struct { + tx uint64 + rx uint64 + length uint32 + speed uint32 + delay uint16 + bits uint8 + csChange uint8 + txNBits uint8 + rxNBits uint8 + pad uint16 +} + +// Devfs is an SPI driver that works against the devfs. +// You need to have loaded the "spidev" Linux module to use this driver. +type Devfs struct { + // Dev is the device to be opened. + // Device name is usually in the /dev/spidev<bus>.<chip> format. + // Required. + Dev string + + // Mode is the SPI mode. SPI mode is a combination of polarity and phases. + // CPOL is the high order bit, CPHA is the low order. Pre-computed mode + // values are Mode0, Mode1, Mode2 and Mode3. The value of the mode argument + // can be overridden by the device's driver. + // Required. + Mode Mode + + // MaxSpeed is the max clock speed (Hz) and can be overridden by the device's driver. + // Required. + MaxSpeed int64 +} + +// Open opens the provided device with the specified options +// and returns a connection. +func (d *Devfs) Open() (driver.Conn, error) { + f, err := os.OpenFile(d.Dev, os.O_RDWR, os.ModeDevice) + if err != nil { + return nil, err + } + conn := &devfsConn{f: f} + if err := conn.Configure(driver.Mode, int(d.Mode)); err != nil { + conn.Close() + return nil, err + } + if err := conn.Configure(driver.MaxSpeed, int(d.MaxSpeed)); err != nil { + conn.Close() + return nil, err + } + return conn, nil +} + +type devfsConn struct { + f *os.File + mode uint8 + speed uint32 + bits uint8 + delay uint16 + csChange uint8 +} + +func (c *devfsConn) Configure(k, v int) error { + switch k { + case driver.Mode: + m := uint8(v) + if err := c.ioctl(requestCode(devfs_WRITE, devfs_MAGIC, 1, 1), uintptr(unsafe.Pointer(&m))); err != nil { + return fmt.Errorf("error setting mode to %v: %v", m, err) + } + c.mode = m + case driver.Bits: + b := uint8(v) + if err := c.ioctl(requestCode(devfs_WRITE, devfs_MAGIC, 3, 1), uintptr(unsafe.Pointer(&b))); err != nil { + return fmt.Errorf("error setting bits per word to %v: %v", b, err) + } + c.bits = b + case driver.MaxSpeed: + s := uint32(v) + if err := c.ioctl(requestCode(devfs_WRITE, devfs_MAGIC, 4, 4), uintptr(unsafe.Pointer(&s))); err != nil { + return fmt.Errorf("error setting speed to %v: %v", s, err) + } + c.speed = s + case driver.Order: + o := uint8(v) + if err := c.ioctl(requestCode(devfs_WRITE, devfs_MAGIC, 2, 1), uintptr(unsafe.Pointer(&o))); err != nil { + return fmt.Errorf("error setting bit order to %v: %v", o, err) + } + case driver.Delay: + c.delay = uint16(v) + case driver.CSChange: + c.csChange = uint8(v) + default: + return fmt.Errorf("unknown key: %v", k) + } + return nil +} + +func (c *devfsConn) Tx(w, r []byte) error { + if r == nil { + r = make([]byte, len(w)) + } + // TODO(jbd): len(w) == len(r)? + // TODO(jbd): Allow nil w. + p := payload{ + tx: uint64(uintptr(unsafe.Pointer(&w[0]))), + rx: uint64(uintptr(unsafe.Pointer(&r[0]))), + length: uint32(len(w)), + speed: c.speed, + delay: c.delay, + bits: c.bits, + csChange: c.csChange, + } + // TODO(jbd): Read from the device and fill rx. + return c.ioctl(msgRequestCode(1), uintptr(unsafe.Pointer(&p))) +} + +func (c *devfsConn) Close() error { + return c.f.Close() +} + +// requestCode returns the device specific request code for the specified direction, +// type, number and size to be used in the ioctl call. +func requestCode(dir, typ, nr, size uintptr) uintptr { + return (dir << devfs_DIRSHIFT) | (typ << devfs_TYPESHIFT) | (nr << devfs_NRSHIFT) | (size << devfs_SIZESHIFT) +} + +// msgRequestCode returns the device specific value for the SPI +// message payload to be used in the ioctl call. +// n represents the number of messages. +func msgRequestCode(n uint32) uintptr { + return uintptr(0x40006B00 + (n * 0x200000)) +} + +// ioctl makes an IOCTL on the open device file descriptor. +func (c *devfsConn) ioctl(a1, a2 uintptr) error { + _, _, errno := syscall.Syscall( + syscall.SYS_IOCTL, c.f.Fd(), a1, a2, + ) + if errno != 0 { + return syscall.Errno(errno) + } + return nil +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/spi/devfs_nonlinux.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/spi/devfs_nonlinux.go new file mode 100644 index 0000000..499d69d --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/spi/devfs_nonlinux.go @@ -0,0 +1,40 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !linux +// +build !linux + +package spi + +import ( + "errors" + + "golang.org/x/exp/io/spi/driver" +) + +// Devfs is a no-implementation of an SPI driver that works against the devfs. +// You need to have loaded the Linux "spidev" module to use this driver. +type Devfs struct { + // Dev is the device to be opened. + // Device name is usually in the /dev/spidev<bus>.<chip> format. + // Required. + Dev string + + // Mode is the SPI mode. SPI mode is a combination of polarity and phases. + // CPOL is the high order bit, CPHA is the low order. Pre-computed mode + // values are Mode0, Mode1, Mode2 and Mode3. The value of the mode argument + // can be overridden by the device's driver. + // Required. + Mode Mode + + // MaxSpeed is the max clock speed (Hz) and can be overridden by the device's driver. + // Required. + MaxSpeed int64 +} + +// Open opens the provided device with the speicifed options +// and returns a connection. +func (d *Devfs) Open() (driver.Conn, error) { + return nil, errors.New("not implemented on this platform") +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/spi/driver/driver.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/spi/driver/driver.go new file mode 100644 index 0000000..7634440 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/spi/driver/driver.go @@ -0,0 +1,50 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package driver contains interfaces to be implemented by various SPI implementations. +package driver // import "golang.org/x/exp/io/spi/driver" + +const ( + Mode = iota + Bits + MaxSpeed + Order + Delay + CSChange +) + +// Opener is an interface to be implemented by the SPI driver to open +// a connection to an SPI device. +type Opener interface { + Open() (Conn, error) +} + +// Conn is a connection to an SPI device. +// TODO(jbd): Extend the interface to query configuration values. +type Conn interface { + // Configure configures the SPI device. + // + // Available configuration keys are: + // - Mode, the SPI mode (valid values are 0, 1, 2 and 3). + // - Bits, bits per word (default is 8-bit per word). + // - Speed, the max clock speed (in Hz). + // - Order, bit order to be used in transfers. Zero value represents + // the MSB-first, non-zero values represent LSB-first encoding. + // - Delay, the pause time between frames (in usecs). + // Some SPI devices require a minimum amount of wait time after + // each frame write. If set, Delay amount of usecs are inserted after + // each write. + // - CSChange, whether to leave the device's chipselect active after a Tx. + // + // SPI devices can override these values. + Configure(k, v int) error + + // Tx performs a SPI transaction: w is written if not nil, the result is + // put into r if not nil. len(w) must be equal to len(r), otherwise the + // driver should return an error. + Tx(w, r []byte) error + + // Close frees the underlying resources and closes the connection. + Close() error +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/spi/example_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/spi/example_test.go new file mode 100644 index 0000000..e75ec37 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/spi/example_test.go @@ -0,0 +1,38 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package spi_test + +import "golang.org/x/exp/io/spi" + +// Example illustrates a program that drives an APA-102 LED strip. +func Example() { + dev, err := spi.Open(&spi.Devfs{ + Dev: "/dev/spidev0.1", + Mode: spi.Mode3, + MaxSpeed: 500000, + }) + if err != nil { + panic(err) + } + defer dev.Close() + + if err := dev.Tx([]byte{ + 0, 0, 0, 0, + 0xff, 200, 0, 200, + 0xff, 200, 0, 200, + 0xe0, 200, 0, 200, + 0xff, 200, 0, 200, + 0xff, 8, 50, 0, + 0xff, 200, 0, 0, + 0xff, 0, 0, 0, + 0xff, 200, 0, 200, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + }, nil); err != nil { + panic(err) + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/spi/spi.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/spi/spi.go new file mode 100644 index 0000000..a675bd1 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/io/spi/spi.go @@ -0,0 +1,107 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package spi allows users to read from and write to an SPI device. +// +// # Deprecated +// +// This package is not maintained anymore. An actively supported cross-platform +// alternative is https://periph.io/. +package spi // import "golang.org/x/exp/io/spi" + +import ( + "time" + + "golang.org/x/exp/io/spi/driver" +) + +// Mode represents the SPI mode number where clock parity (CPOL) +// is the high order and clock edge (CPHA) is the low order bit. +type Mode int + +const ( + Mode0 = Mode(0) + Mode1 = Mode(1) + Mode2 = Mode(2) + Mode3 = Mode(3) +) + +// Order is the bit justification to be used while transferring +// words to the SPI device. MSB-first encoding is more popular +// than LSB-first. +type Order int + +const ( + MSBFirst = Order(0) + LSBFirst = Order(1) +) + +type Device struct { + conn driver.Conn +} + +// SetMode sets the SPI mode. SPI mode is a combination of polarity and phases. +// CPOL is the high order bit, CPHA is the low order. Pre-computed mode +// values are Mode0, Mode1, Mode2 and Mode3. +// The value can be changed by SPI device's driver. +func (d *Device) SetMode(mode Mode) error { + return d.conn.Configure(driver.Mode, int(mode)) +} + +// SetMaxSpeed sets the maximum clock speed in Hz. +// The value can be overridden by SPI device's driver. +func (d *Device) SetMaxSpeed(speed int) error { + return d.conn.Configure(driver.MaxSpeed, speed) +} + +// SetBitsPerWord sets how many bits it takes to represent a word, e.g. 8 represents 8-bit words. +// The default is 8 bits per word. +func (d *Device) SetBitsPerWord(bits int) error { + return d.conn.Configure(driver.Bits, bits) +} + +// SetBitOrder sets the bit justification used to transfer SPI words. +// Valid values are MSBFirst and LSBFirst. +func (d *Device) SetBitOrder(o Order) error { + return d.conn.Configure(driver.Order, int(o)) +} + +// SetDelay sets the amount of pause will be added after each frame write. +func (d *Device) SetDelay(t time.Duration) error { + return d.conn.Configure(driver.Delay, int(t.Nanoseconds()/1000)) +} + +// SetCSChange sets whether to leave the chipselect enabled after a Tx. +func (d *Device) SetCSChange(leaveEnabled bool) error { + v := 0 + if leaveEnabled { + v = 1 + } + return d.conn.Configure(driver.CSChange, v) +} + +// Tx performs a duplex transmission to write w to the SPI device +// and read len(r) bytes to r. +// User should not mutate the w and r until this call returns. +func (d *Device) Tx(w, r []byte) error { + // TODO(jbd): Allow nil w. + return d.conn.Tx(w, r) +} + +// Open opens a device with the specified bus and chip select +// by using the given driver. If a nil driver is provided, +// the default driver (devfs) is used. + +func Open(o driver.Opener) (*Device, error) { + conn, err := o.Open() + if err != nil { + return nil, err + } + return &Device{conn: conn}, nil +} + +// Close closes the SPI device and releases the related resources. +func (d *Device) Close() error { + return d.conn.Close() +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/maps/maps.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/maps/maps.go new file mode 100644 index 0000000..fc27cd1 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/maps/maps.go @@ -0,0 +1,90 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package maps defines various functions useful with maps of any type. +package maps + +// Keys returns the keys of the map m. +// The keys will be in an indeterminate order. +func Keys[M ~map[K]V, K comparable, V any](m M) []K { + r := make([]K, 0, len(m)) + for k := range m { + r = append(r, k) + } + return r +} + +// Values returns the values of the map m. +// The values will be in an indeterminate order. +func Values[M ~map[K]V, K comparable, V any](m M) []V { + r := make([]V, 0, len(m)) + for _, v := range m { + r = append(r, v) + } + return r +} + +// Equal reports whether two maps contain the same key/value pairs. +// Values are compared using ==. +func Equal[M1, M2 ~map[K]V, K, V comparable](m1 M1, m2 M2) bool { + if len(m1) != len(m2) { + return false + } + for k, v1 := range m1 { + if v2, ok := m2[k]; !ok || v1 != v2 { + return false + } + } + return true +} + +// EqualFunc is like Equal, but compares values using eq. +// Keys are still compared with ==. +func EqualFunc[M1 ~map[K]V1, M2 ~map[K]V2, K comparable, V1, V2 any](m1 M1, m2 M2, eq func(V1, V2) bool) bool { + if len(m1) != len(m2) { + return false + } + for k, v1 := range m1 { + if v2, ok := m2[k]; !ok || !eq(v1, v2) { + return false + } + } + return true +} + +// Clear removes all entries from m, leaving it empty. +func Clear[M ~map[K]V, K comparable, V any](m M) { + for k := range m { + delete(m, k) + } +} + +// Clone returns a copy of m. This is a shallow clone: +// the new keys and values are set using ordinary assignment. +func Clone[M ~map[K]V, K comparable, V any](m M) M { + r := make(M, len(m)) + for k, v := range m { + r[k] = v + } + return r +} + +// Copy copies all key/value pairs in src adding them to dst. +// When a key in src is already present in dst, +// the value in dst will be overwritten by the value associated +// with the key in src. +func Copy[M ~map[K]V, K comparable, V any](dst, src M) { + for k, v := range src { + dst[k] = v + } +} + +// DeleteFunc deletes any key/value pairs from m for which del returns true. +func DeleteFunc[M ~map[K]V, K comparable, V any](m M, del func(K, V) bool) { + for k, v := range m { + if del(k, v) { + delete(m, k) + } + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/maps/maps_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/maps/maps_test.go new file mode 100644 index 0000000..6dc6292 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/maps/maps_test.go @@ -0,0 +1,169 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package maps + +import ( + "math" + "sort" + "strconv" + "testing" + + "golang.org/x/exp/slices" +) + +var m1 = map[int]int{1: 2, 2: 4, 4: 8, 8: 16} +var m2 = map[int]string{1: "2", 2: "4", 4: "8", 8: "16"} + +func TestKeys(t *testing.T) { + want := []int{1, 2, 4, 8} + + got1 := Keys(m1) + sort.Ints(got1) + if !slices.Equal(got1, want) { + t.Errorf("Keys(%v) = %v, want %v", m1, got1, want) + } + + got2 := Keys(m2) + sort.Ints(got2) + if !slices.Equal(got2, want) { + t.Errorf("Keys(%v) = %v, want %v", m2, got2, want) + } +} + +func TestValues(t *testing.T) { + got1 := Values(m1) + want1 := []int{2, 4, 8, 16} + sort.Ints(got1) + if !slices.Equal(got1, want1) { + t.Errorf("Values(%v) = %v, want %v", m1, got1, want1) + } + + got2 := Values(m2) + want2 := []string{"16", "2", "4", "8"} + sort.Strings(got2) + if !slices.Equal(got2, want2) { + t.Errorf("Values(%v) = %v, want %v", m2, got2, want2) + } +} + +func TestEqual(t *testing.T) { + if !Equal(m1, m1) { + t.Errorf("Equal(%v, %v) = false, want true", m1, m1) + } + if Equal(m1, (map[int]int)(nil)) { + t.Errorf("Equal(%v, nil) = true, want false", m1) + } + if Equal((map[int]int)(nil), m1) { + t.Errorf("Equal(nil, %v) = true, want false", m1) + } + if !Equal[map[int]int, map[int]int](nil, nil) { + t.Error("Equal(nil, nil) = false, want true") + } + if ms := map[int]int{1: 2}; Equal(m1, ms) { + t.Errorf("Equal(%v, %v) = true, want false", m1, ms) + } + + // Comparing NaN for equality is expected to fail. + mf := map[int]float64{1: 0, 2: math.NaN()} + if Equal(mf, mf) { + t.Errorf("Equal(%v, %v) = true, want false", mf, mf) + } +} + +// equal is simply ==. +func equal[T comparable](v1, v2 T) bool { + return v1 == v2 +} + +// equalNaN is like == except that all NaNs are equal. +func equalNaN[T comparable](v1, v2 T) bool { + isNaN := func(f T) bool { return f != f } + return v1 == v2 || (isNaN(v1) && isNaN(v2)) +} + +// equalStr compares ints and strings. +func equalIntStr(v1 int, v2 string) bool { + return strconv.Itoa(v1) == v2 +} + +func TestEqualFunc(t *testing.T) { + if !EqualFunc(m1, m1, equal[int]) { + t.Errorf("EqualFunc(%v, %v, equal) = false, want true", m1, m1) + } + if EqualFunc(m1, (map[int]int)(nil), equal[int]) { + t.Errorf("EqualFunc(%v, nil, equal) = true, want false", m1) + } + if EqualFunc((map[int]int)(nil), m1, equal[int]) { + t.Errorf("EqualFunc(nil, %v, equal) = true, want false", m1) + } + if !EqualFunc[map[int]int, map[int]int](nil, nil, equal[int]) { + t.Error("EqualFunc(nil, nil, equal) = false, want true") + } + if ms := map[int]int{1: 2}; EqualFunc(m1, ms, equal[int]) { + t.Errorf("EqualFunc(%v, %v, equal) = true, want false", m1, ms) + } + + // Comparing NaN for equality is expected to fail. + mf := map[int]float64{1: 0, 2: math.NaN()} + if EqualFunc(mf, mf, equal[float64]) { + t.Errorf("EqualFunc(%v, %v, equal) = true, want false", mf, mf) + } + // But it should succeed using equalNaN. + if !EqualFunc(mf, mf, equalNaN[float64]) { + t.Errorf("EqualFunc(%v, %v, equalNaN) = false, want true", mf, mf) + } + + if !EqualFunc(m1, m2, equalIntStr) { + t.Errorf("EqualFunc(%v, %v, equalIntStr) = false, want true", m1, m2) + } +} + +func TestClear(t *testing.T) { + ml := map[int]int{1: 1, 2: 2, 3: 3} + Clear(ml) + if got := len(ml); got != 0 { + t.Errorf("len(%v) = %d after Clear, want 0", ml, got) + } + if !Equal(ml, (map[int]int)(nil)) { + t.Errorf("Equal(%v, nil) = false, want true", ml) + } +} + +func TestClone(t *testing.T) { + mc := Clone(m1) + if !Equal(mc, m1) { + t.Errorf("Clone(%v) = %v, want %v", m1, mc, m1) + } + mc[16] = 32 + if Equal(mc, m1) { + t.Errorf("Equal(%v, %v) = true, want false", mc, m1) + } +} + +func TestCopy(t *testing.T) { + mc := Clone(m1) + Copy(mc, mc) + if !Equal(mc, m1) { + t.Errorf("Copy(%v, %v) = %v, want %v", m1, m1, mc, m1) + } + Copy(mc, map[int]int{16: 32}) + want := map[int]int{1: 2, 2: 4, 4: 8, 8: 16, 16: 32} + if !Equal(mc, want) { + t.Errorf("Copy result = %v, want %v", mc, want) + } +} + +func TestDeleteFunc(t *testing.T) { + mc := Clone(m1) + DeleteFunc(mc, func(int, int) bool { return false }) + if !Equal(mc, m1) { + t.Errorf("DeleteFunc(%v, true) = %v, want %v", m1, mc, m1) + } + DeleteFunc(mc, func(k, v int) bool { return k > 3 }) + want := map[int]int{1: 2, 2: 4} + if !Equal(mc, want) { + t.Errorf("DeleteFunc result = %v, want %v", mc, want) + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/mmap/manual_test_program.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/mmap/manual_test_program.go new file mode 100644 index 0000000..a1ab17b --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/mmap/manual_test_program.go @@ -0,0 +1,56 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ignore +// +build ignore + +// +// This build tag means that "go build" does not build this file. Use "go run +// manual_test_program.go" to run it. +// +// You will also need to change "debug = false" to "debug = true" in mmap_*.go. + +package main + +import ( + "log" + "math/rand" + "time" + + "golang.org/x/exp/mmap" +) + +var garbage []byte + +func main() { + const filename = "manual_test_program.go" + + for _, explicitClose := range []bool{false, true} { + r, err := mmap.Open(filename) + if err != nil { + log.Fatalf("Open: %v", err) + } + if explicitClose { + r.Close() + } else { + // Leak the *mmap.ReaderAt returned by mmap.Open. The finalizer + // should pick it up, if finalizers run at all. + } + } + + println("Finished all explicit Close calls.") + println("Creating and collecting garbage.") + println("Look for two munmap log messages.") + println("Hit Ctrl-C to exit.") + + rng := rand.New(rand.NewSource(1)) + now := time.Now() + for { + garbage = make([]byte, rng.Intn(1<<20)) + if time.Since(now) > 1*time.Second { + now = time.Now() + print(".") + } + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/mmap/mmap_other.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/mmap/mmap_other.go new file mode 100644 index 0000000..1e7b948 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/mmap/mmap_other.go @@ -0,0 +1,76 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !linux && !windows && !darwin +// +build !linux,!windows,!darwin + +// Package mmap provides a way to memory-map a file. +package mmap + +import ( + "fmt" + "os" +) + +// ReaderAt reads a memory-mapped file. +// +// Like any io.ReaderAt, clients can execute parallel ReadAt calls, but it is +// not safe to call Close and reading methods concurrently. +type ReaderAt struct { + f *os.File + len int +} + +// Close closes the reader. +func (r *ReaderAt) Close() error { + return r.f.Close() +} + +// Len returns the length of the underlying memory-mapped file. +func (r *ReaderAt) Len() int { + return r.len +} + +// At returns the byte at index i. +func (r *ReaderAt) At(i int) byte { + if i < 0 || r.len <= i { + panic("index out of range") + } + var b [1]byte + r.ReadAt(b[:], int64(i)) + return b[0] +} + +// ReadAt implements the io.ReaderAt interface. +func (r *ReaderAt) ReadAt(p []byte, off int64) (int, error) { + return r.f.ReadAt(p, off) +} + +// Open memory-maps the named file for reading. +func Open(filename string) (*ReaderAt, error) { + f, err := os.Open(filename) + if err != nil { + return nil, err + } + fi, err := f.Stat() + if err != nil { + f.Close() + return nil, err + } + + size := fi.Size() + if size < 0 { + f.Close() + return nil, fmt.Errorf("mmap: file %q has negative size", filename) + } + if size != int64(int(size)) { + f.Close() + return nil, fmt.Errorf("mmap: file %q is too large", filename) + } + + return &ReaderAt{ + f: f, + len: int(fi.Size()), + }, nil +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/mmap/mmap_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/mmap/mmap_test.go new file mode 100644 index 0000000..797fc5f --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/mmap/mmap_test.go @@ -0,0 +1,34 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mmap + +import ( + "bytes" + "io" + "io/ioutil" + "testing" +) + +func TestOpen(t *testing.T) { + const filename = "mmap_test.go" + r, err := Open(filename) + if err != nil { + t.Fatalf("Open: %v", err) + } + got := make([]byte, r.Len()) + if _, err := r.ReadAt(got, 0); err != nil && err != io.EOF { + t.Fatalf("ReadAt: %v", err) + } + want, err := ioutil.ReadFile(filename) + if err != nil { + t.Fatalf("ioutil.ReadFile: %v", err) + } + if len(got) != len(want) { + t.Fatalf("got %d bytes, want %d", len(got), len(want)) + } + if !bytes.Equal(got, want) { + t.Fatalf("\ngot %q\nwant %q", string(got), string(want)) + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/mmap/mmap_unix.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/mmap/mmap_unix.go new file mode 100644 index 0000000..ae12499 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/mmap/mmap_unix.go @@ -0,0 +1,117 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux || darwin +// +build linux darwin + +// Package mmap provides a way to memory-map a file. +package mmap + +import ( + "errors" + "fmt" + "io" + "os" + "runtime" + "syscall" +) + +// debug is whether to print debugging messages for manual testing. +// +// The runtime.SetFinalizer documentation says that, "The finalizer for x is +// scheduled to run at some arbitrary time after x becomes unreachable. There +// is no guarantee that finalizers will run before a program exits", so we +// cannot automatically test that the finalizer runs. Instead, set this to true +// when running the manual test. +const debug = false + +// ReaderAt reads a memory-mapped file. +// +// Like any io.ReaderAt, clients can execute parallel ReadAt calls, but it is +// not safe to call Close and reading methods concurrently. +type ReaderAt struct { + data []byte +} + +// Close closes the reader. +func (r *ReaderAt) Close() error { + if r.data == nil { + return nil + } + data := r.data + r.data = nil + if debug { + var p *byte + if len(data) != 0 { + p = &data[0] + } + println("munmap", r, p) + } + runtime.SetFinalizer(r, nil) + return syscall.Munmap(data) +} + +// Len returns the length of the underlying memory-mapped file. +func (r *ReaderAt) Len() int { + return len(r.data) +} + +// At returns the byte at index i. +func (r *ReaderAt) At(i int) byte { + return r.data[i] +} + +// ReadAt implements the io.ReaderAt interface. +func (r *ReaderAt) ReadAt(p []byte, off int64) (int, error) { + if r.data == nil { + return 0, errors.New("mmap: closed") + } + if off < 0 || int64(len(r.data)) < off { + return 0, fmt.Errorf("mmap: invalid ReadAt offset %d", off) + } + n := copy(p, r.data[off:]) + if n < len(p) { + return n, io.EOF + } + return n, nil +} + +// Open memory-maps the named file for reading. +func Open(filename string) (*ReaderAt, error) { + f, err := os.Open(filename) + if err != nil { + return nil, err + } + defer f.Close() + fi, err := f.Stat() + if err != nil { + return nil, err + } + + size := fi.Size() + if size == 0 { + return &ReaderAt{}, nil + } + if size < 0 { + return nil, fmt.Errorf("mmap: file %q has negative size", filename) + } + if size != int64(int(size)) { + return nil, fmt.Errorf("mmap: file %q is too large", filename) + } + + data, err := syscall.Mmap(int(f.Fd()), 0, int(size), syscall.PROT_READ, syscall.MAP_SHARED) + if err != nil { + return nil, err + } + r := &ReaderAt{data} + if debug { + var p *byte + if len(data) != 0 { + p = &data[0] + } + println("mmap", r, p) + } + runtime.SetFinalizer(r, (*ReaderAt).Close) + return r, nil +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/mmap/mmap_windows.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/mmap/mmap_windows.go new file mode 100644 index 0000000..d898828 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/mmap/mmap_windows.go @@ -0,0 +1,123 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package mmap provides a way to memory-map a file. +package mmap + +import ( + "errors" + "fmt" + "io" + "os" + "runtime" + "syscall" + "unsafe" +) + +// debug is whether to print debugging messages for manual testing. +// +// The runtime.SetFinalizer documentation says that, "The finalizer for x is +// scheduled to run at some arbitrary time after x becomes unreachable. There +// is no guarantee that finalizers will run before a program exits", so we +// cannot automatically test that the finalizer runs. Instead, set this to true +// when running the manual test. +const debug = false + +// ReaderAt reads a memory-mapped file. +// +// Like any io.ReaderAt, clients can execute parallel ReadAt calls, but it is +// not safe to call Close and reading methods concurrently. +type ReaderAt struct { + data []byte +} + +// Close closes the reader. +func (r *ReaderAt) Close() error { + if r.data == nil { + return nil + } + data := r.data + r.data = nil + if debug { + var p *byte + if len(data) != 0 { + p = &data[0] + } + println("munmap", r, p) + } + runtime.SetFinalizer(r, nil) + return syscall.UnmapViewOfFile(uintptr(unsafe.Pointer(&data[0]))) +} + +// Len returns the length of the underlying memory-mapped file. +func (r *ReaderAt) Len() int { + return len(r.data) +} + +// At returns the byte at index i. +func (r *ReaderAt) At(i int) byte { + return r.data[i] +} + +// ReadAt implements the io.ReaderAt interface. +func (r *ReaderAt) ReadAt(p []byte, off int64) (int, error) { + if r.data == nil { + return 0, errors.New("mmap: closed") + } + if off < 0 || int64(len(r.data)) < off { + return 0, fmt.Errorf("mmap: invalid ReadAt offset %d", off) + } + n := copy(p, r.data[off:]) + if n < len(p) { + return n, io.EOF + } + return n, nil +} + +// Open memory-maps the named file for reading. +func Open(filename string) (*ReaderAt, error) { + f, err := os.Open(filename) + if err != nil { + return nil, err + } + defer f.Close() + fi, err := f.Stat() + if err != nil { + return nil, err + } + + size := fi.Size() + if size == 0 { + return &ReaderAt{}, nil + } + if size < 0 { + return nil, fmt.Errorf("mmap: file %q has negative size", filename) + } + if size != int64(int(size)) { + return nil, fmt.Errorf("mmap: file %q is too large", filename) + } + + low, high := uint32(size), uint32(size>>32) + fmap, err := syscall.CreateFileMapping(syscall.Handle(f.Fd()), nil, syscall.PAGE_READONLY, high, low, nil) + if err != nil { + return nil, err + } + defer syscall.CloseHandle(fmap) + ptr, err := syscall.MapViewOfFile(fmap, syscall.FILE_MAP_READ, 0, 0, uintptr(size)) + if err != nil { + return nil, err + } + data := unsafe.Slice((*byte)(unsafe.Pointer(ptr)), size) + + r := &ReaderAt{data: data} + if debug { + var p *byte + if len(data) != 0 { + p = &data[0] + } + println("mmap", r, p) + } + runtime.SetFinalizer(r, (*ReaderAt).Close) + return r, nil +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/arith128_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/arith128_test.go new file mode 100644 index 0000000..eed655b --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/arith128_test.go @@ -0,0 +1,126 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand + +import ( + "math/big" + "math/rand" + "testing" +) + +var bigMaxUint64 = big.NewInt(0).SetUint64(maxUint64) + +func bigInt(xHi, xLo uint64) *big.Int { + b := big.NewInt(0).SetUint64(xHi) + b.Lsh(b, 64) + b.Or(b, big.NewInt(0).SetUint64(xLo)) + return b +} + +func splitBigInt(b *big.Int) (outHi, outLo uint64) { + outHi = big.NewInt(0).Rsh(b, 64).Uint64() + outLo = big.NewInt(0).And(b, bigMaxUint64).Uint64() + return +} + +func bigMulMod128bits(xHi, xLo, yHi, yLo uint64) (outHi, outLo uint64) { + bigX := bigInt(xHi, xLo) + bigY := bigInt(yHi, yLo) + return splitBigInt(bigX.Mul(bigX, bigY)) +} + +func bigAddMod128bits(xHi, xLo, yHi, yLo uint64) (outHi, outLo uint64) { + bigX := bigInt(xHi, xLo) + bigY := bigInt(yHi, yLo) + return splitBigInt(bigX.Add(bigX, bigY)) +} + +type arithTest struct { + xHi, xLo uint64 +} + +const ( + iLo = increment & maxUint64 + iHi = (increment >> 64) & maxUint64 +) + +var arithTests = []arithTest{ + {0, 0}, + {0, 1}, + {1, 0}, + {0, maxUint64}, + {maxUint64, 0}, + {maxUint64, maxUint64}, + // Randomly generated 64-bit integers. + {3757956613005209672, 17983933746665545631}, + {511324141977587414, 5626651684620191081}, + {1534313104606153588, 2415006486399353367}, + {6873586429837825902, 13854394671140464137}, + {6617134480561088940, 18421520694158684312}, +} + +func TestPCGAdd(t *testing.T) { + for i, test := range arithTests { + p := &PCGSource{ + low: test.xLo, + high: test.xHi, + } + p.add() + expectHi, expectLo := bigAddMod128bits(test.xHi, test.xLo, iHi, iLo) + if p.low != expectLo || p.high != expectHi { + t.Errorf("%d: got hi=%d lo=%d; expect hi=%d lo=%d", i, p.high, p.low, expectHi, expectLo) + } + } +} + +const ( + mLo = multiplier & maxUint64 + mHi = (multiplier >> 64) & maxUint64 +) + +func TestPCGMultiply(t *testing.T) { + for i, test := range arithTests { + p := &PCGSource{ + low: test.xLo, + high: test.xHi, + } + p.multiply() + expectHi, expectLo := bigMulMod128bits(test.xHi, test.xLo, mHi, mLo) + if p.low != expectLo || p.high != expectHi { + t.Errorf("%d: got hi=%d lo=%d; expect hi=%d lo=%d", i, p.high, p.low, expectHi, expectLo) + } + } +} + +func TestPCGMultiplyLong(t *testing.T) { + if testing.Short() { + return + } + for i := 0; i < 1e6; i++ { + low := rand.Uint64() + high := rand.Uint64() + p := &PCGSource{ + low: low, + high: high, + } + p.multiply() + expectHi, expectLo := bigMulMod128bits(high, low, mHi, mLo) + if p.low != expectLo || p.high != expectHi { + t.Fatalf("%d: (%d,%d): got hi=%d lo=%d; expect hi=%d lo=%d", i, high, low, p.high, p.low, expectHi, expectLo) + } + } +} + +func BenchmarkPCGMultiply(b *testing.B) { + low := rand.Uint64() + high := rand.Uint64() + p := &PCGSource{ + low: low, + high: high, + } + for i := 0; i < b.N; i++ { + p.multiply() + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/example_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/example_test.go new file mode 100644 index 0000000..8faad51 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/example_test.go @@ -0,0 +1,163 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand_test + +import ( + "fmt" + "os" + "strings" + "text/tabwriter" + + "golang.org/x/exp/rand" +) + +// These tests serve as an example but also make sure we don't change +// the output of the random number generator when given a fixed seed. + +func Example() { + rand.Seed(42) // Try changing this number! + answers := []string{ + "It is certain", + "It is decidedly so", + "Without a doubt", + "Yes definitely", + "You may rely on it", + "As I see it yes", + "Most likely", + "Outlook good", + "Yes", + "Signs point to yes", + "Reply hazy try again", + "Ask again later", + "Better not tell you now", + "Cannot predict now", + "Concentrate and ask again", + "Don't count on it", + "My reply is no", + "My sources say no", + "Outlook not so good", + "Very doubtful", + } + fmt.Println("Magic 8-Ball says:", answers[rand.Intn(len(answers))]) + // Output: Magic 8-Ball says: Most likely +} + +// This example shows the use of each of the methods on a *Rand. +// The use of the global functions is the same, without the receiver. +func Example_rand() { + // Create and seed the generator. + // Typically a non-fixed seed should be used, such as time.Now().UnixNano(). + // Using a fixed seed will produce the same output on every run. + r := rand.New(rand.NewSource(1234)) + + // The tabwriter here helps us generate aligned output. + w := tabwriter.NewWriter(os.Stdout, 1, 1, 1, ' ', 0) + defer w.Flush() + show := func(name string, v1, v2, v3 interface{}) { + fmt.Fprintf(w, "%s\t%v\t%v\t%v\n", name, v1, v2, v3) + } + + // Float32 and Float64 values are in [0, 1). + show("Float32", r.Float32(), r.Float32(), r.Float32()) + show("Float64", r.Float64(), r.Float64(), r.Float64()) + + // ExpFloat64 values have an average of 1 but decay exponentially. + show("ExpFloat64", r.ExpFloat64(), r.ExpFloat64(), r.ExpFloat64()) + + // NormFloat64 values have an average of 0 and a standard deviation of 1. + show("NormFloat64", r.NormFloat64(), r.NormFloat64(), r.NormFloat64()) + + // Int31, Int63, and Uint32 generate values of the given width. + // The Int method (not shown) is like either Int31 or Int63 + // depending on the size of 'int'. + show("Int31", r.Int31(), r.Int31(), r.Int31()) + show("Int63", r.Int63(), r.Int63(), r.Int63()) + show("Uint32", r.Uint32(), r.Uint32(), r.Uint32()) + show("Uint64", r.Uint64(), r.Uint64(), r.Uint64()) + + // Intn, Int31n, Int63n and Uint64n limit their output to be < n. + // They do so more carefully than using r.Int()%n. + show("Intn(10)", r.Intn(10), r.Intn(10), r.Intn(10)) + show("Int31n(10)", r.Int31n(10), r.Int31n(10), r.Int31n(10)) + show("Int63n(10)", r.Int63n(10), r.Int63n(10), r.Int63n(10)) + show("Uint64n(10)", r.Uint64n(10), r.Uint64n(10), r.Uint64n(10)) + + // Perm generates a random permutation of the numbers [0, n). + show("Perm", r.Perm(5), r.Perm(5), r.Perm(5)) + // Output: + // Float32 0.030719291 0.47512934 0.031019364 + // Float64 0.6906635660087743 0.9898818576905045 0.2683634639782333 + // ExpFloat64 1.24979080914592 0.3451975160045876 0.5456817760595064 + // NormFloat64 0.879221333732727 -0.01508980368383761 -1.962250558270421 + // Int31 2043816560 1870670250 1334960143 + // Int63 7860766611810691572 1466711535823962239 3836585920276818709 + // Uint32 2051241581 751073909 1353986074 + // Uint64 10802154207635843641 14398820303406316826 11052107950969057042 + // Intn(10) 3 0 1 + // Int31n(10) 3 8 1 + // Int63n(10) 4 6 0 + // Uint64n(10) 2 9 4 + // Perm [1 3 4 0 2] [2 4 0 3 1] [3 2 0 4 1] +} + +func ExampleShuffle() { + words := strings.Fields("ink runs from the corners of my mouth") + rand.Shuffle(len(words), func(i, j int) { + words[i], words[j] = words[j], words[i] + }) + fmt.Println(words) + + // Output: + // [ink corners of from mouth runs the my] +} + +func ExampleShuffle_slicesInUnison() { + numbers := []byte("12345") + letters := []byte("ABCDE") + // Shuffle numbers, swapping corresponding entries in letters at the same time. + rand.Shuffle(len(numbers), func(i, j int) { + numbers[i], numbers[j] = numbers[j], numbers[i] + letters[i], letters[j] = letters[j], letters[i] + }) + for i := range numbers { + fmt.Printf("%c: %c\n", letters[i], numbers[i]) + } + + // Output: + // D: 4 + // A: 1 + // E: 5 + // B: 2 + // C: 3 +} + +func ExampleLockedSource() { + r := rand.New(new(rand.LockedSource)) + r.Seed(42) // Try changing this number! + answers := []string{ + "It is certain", + "It is decidedly so", + "Without a doubt", + "Yes definitely", + "You may rely on it", + "As I see it yes", + "Most likely", + "Outlook good", + "Yes", + "Signs point to yes", + "Reply hazy try again", + "Ask again later", + "Better not tell you now", + "Cannot predict now", + "Concentrate and ask again", + "Don't count on it", + "My reply is no", + "My sources say no", + "Outlook not so good", + "Very doubtful", + } + fmt.Println("Magic 8-Ball says:", answers[r.Intn(len(answers))]) + // Output: Magic 8-Ball says: Most likely +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/exp.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/exp.go new file mode 100644 index 0000000..0838672 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/exp.go @@ -0,0 +1,221 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand + +import ( + "math" +) + +/* + * Exponential distribution + * + * See "The Ziggurat Method for Generating Random Variables" + * (Marsaglia & Tsang, 2000) + * http://www.jstatsoft.org/v05/i08/paper [pdf] + */ + +const ( + re = 7.69711747013104972 +) + +// ExpFloat64 returns an exponentially distributed float64 in the range +// (0, +math.MaxFloat64] with an exponential distribution whose rate parameter +// (lambda) is 1 and whose mean is 1/lambda (1). +// To produce a distribution with a different rate parameter, +// callers can adjust the output using: +// +// sample = ExpFloat64() / desiredRateParameter +func (r *Rand) ExpFloat64() float64 { + for { + j := r.Uint32() + i := j & 0xFF + x := float64(j) * float64(we[i]) + if j < ke[i] { + return x + } + if i == 0 { + return re - math.Log(r.Float64()) + } + if fe[i]+float32(r.Float64())*(fe[i-1]-fe[i]) < float32(math.Exp(-x)) { + return x + } + } +} + +var ke = [256]uint32{ + 0xe290a139, 0x0, 0x9beadebc, 0xc377ac71, 0xd4ddb990, + 0xde893fb8, 0xe4a8e87c, 0xe8dff16a, 0xebf2deab, 0xee49a6e8, + 0xf0204efd, 0xf19bdb8e, 0xf2d458bb, 0xf3da104b, 0xf4b86d78, + 0xf577ad8a, 0xf61de83d, 0xf6afb784, 0xf730a573, 0xf7a37651, + 0xf80a5bb6, 0xf867189d, 0xf8bb1b4f, 0xf9079062, 0xf94d70ca, + 0xf98d8c7d, 0xf9c8928a, 0xf9ff175b, 0xfa319996, 0xfa6085f8, + 0xfa8c3a62, 0xfab5084e, 0xfadb36c8, 0xfaff0410, 0xfb20a6ea, + 0xfb404fb4, 0xfb5e2951, 0xfb7a59e9, 0xfb95038c, 0xfbae44ba, + 0xfbc638d8, 0xfbdcf892, 0xfbf29a30, 0xfc0731df, 0xfc1ad1ed, + 0xfc2d8b02, 0xfc3f6c4d, 0xfc5083ac, 0xfc60ddd1, 0xfc708662, + 0xfc7f8810, 0xfc8decb4, 0xfc9bbd62, 0xfca9027c, 0xfcb5c3c3, + 0xfcc20864, 0xfccdd70a, 0xfcd935e3, 0xfce42ab0, 0xfceebace, + 0xfcf8eb3b, 0xfd02c0a0, 0xfd0c3f59, 0xfd156b7b, 0xfd1e48d6, + 0xfd26daff, 0xfd2f2552, 0xfd372af7, 0xfd3eeee5, 0xfd4673e7, + 0xfd4dbc9e, 0xfd54cb85, 0xfd5ba2f2, 0xfd62451b, 0xfd68b415, + 0xfd6ef1da, 0xfd750047, 0xfd7ae120, 0xfd809612, 0xfd8620b4, + 0xfd8b8285, 0xfd90bcf5, 0xfd95d15e, 0xfd9ac10b, 0xfd9f8d36, + 0xfda43708, 0xfda8bf9e, 0xfdad2806, 0xfdb17141, 0xfdb59c46, + 0xfdb9a9fd, 0xfdbd9b46, 0xfdc170f6, 0xfdc52bd8, 0xfdc8ccac, + 0xfdcc542d, 0xfdcfc30b, 0xfdd319ef, 0xfdd6597a, 0xfdd98245, + 0xfddc94e5, 0xfddf91e6, 0xfde279ce, 0xfde54d1f, 0xfde80c52, + 0xfdeab7de, 0xfded5034, 0xfdefd5be, 0xfdf248e3, 0xfdf4aa06, + 0xfdf6f984, 0xfdf937b6, 0xfdfb64f4, 0xfdfd818d, 0xfdff8dd0, + 0xfe018a08, 0xfe03767a, 0xfe05536c, 0xfe07211c, 0xfe08dfc9, + 0xfe0a8fab, 0xfe0c30fb, 0xfe0dc3ec, 0xfe0f48b1, 0xfe10bf76, + 0xfe122869, 0xfe1383b4, 0xfe14d17c, 0xfe1611e7, 0xfe174516, + 0xfe186b2a, 0xfe19843e, 0xfe1a9070, 0xfe1b8fd6, 0xfe1c8289, + 0xfe1d689b, 0xfe1e4220, 0xfe1f0f26, 0xfe1fcfbc, 0xfe2083ed, + 0xfe212bc3, 0xfe21c745, 0xfe225678, 0xfe22d95f, 0xfe234ffb, + 0xfe23ba4a, 0xfe241849, 0xfe2469f2, 0xfe24af3c, 0xfe24e81e, + 0xfe25148b, 0xfe253474, 0xfe2547c7, 0xfe254e70, 0xfe25485a, + 0xfe25356a, 0xfe251586, 0xfe24e88f, 0xfe24ae64, 0xfe2466e1, + 0xfe2411df, 0xfe23af34, 0xfe233eb4, 0xfe22c02c, 0xfe22336b, + 0xfe219838, 0xfe20ee58, 0xfe20358c, 0xfe1f6d92, 0xfe1e9621, + 0xfe1daef0, 0xfe1cb7ac, 0xfe1bb002, 0xfe1a9798, 0xfe196e0d, + 0xfe1832fd, 0xfe16e5fe, 0xfe15869d, 0xfe141464, 0xfe128ed3, + 0xfe10f565, 0xfe0f478c, 0xfe0d84b1, 0xfe0bac36, 0xfe09bd73, + 0xfe07b7b5, 0xfe059a40, 0xfe03644c, 0xfe011504, 0xfdfeab88, + 0xfdfc26e9, 0xfdf98629, 0xfdf6c83b, 0xfdf3ec01, 0xfdf0f04a, + 0xfdedd3d1, 0xfdea953d, 0xfde7331e, 0xfde3abe9, 0xfddffdfb, + 0xfddc2791, 0xfdd826cd, 0xfdd3f9a8, 0xfdcf9dfc, 0xfdcb1176, + 0xfdc65198, 0xfdc15bb3, 0xfdbc2ce2, 0xfdb6c206, 0xfdb117be, + 0xfdab2a63, 0xfda4f5fd, 0xfd9e7640, 0xfd97a67a, 0xfd908192, + 0xfd8901f2, 0xfd812182, 0xfd78d98e, 0xfd7022bb, 0xfd66f4ed, + 0xfd5d4732, 0xfd530f9c, 0xfd48432b, 0xfd3cd59a, 0xfd30b936, + 0xfd23dea4, 0xfd16349e, 0xfd07a7a3, 0xfcf8219b, 0xfce7895b, + 0xfcd5c220, 0xfcc2aadb, 0xfcae1d5e, 0xfc97ed4e, 0xfc7fe6d4, + 0xfc65ccf3, 0xfc495762, 0xfc2a2fc8, 0xfc07ee19, 0xfbe213c1, + 0xfbb8051a, 0xfb890078, 0xfb5411a5, 0xfb180005, 0xfad33482, + 0xfa839276, 0xfa263b32, 0xf9b72d1c, 0xf930a1a2, 0xf889f023, + 0xf7b577d2, 0xf69c650c, 0xf51530f0, 0xf2cb0e3c, 0xeeefb15d, + 0xe6da6ecf, +} +var we = [256]float32{ + 2.0249555e-09, 1.486674e-11, 2.4409617e-11, 3.1968806e-11, + 3.844677e-11, 4.4228204e-11, 4.9516443e-11, 5.443359e-11, + 5.905944e-11, 6.344942e-11, 6.7643814e-11, 7.1672945e-11, + 7.556032e-11, 7.932458e-11, 8.298079e-11, 8.654132e-11, + 9.0016515e-11, 9.3415074e-11, 9.674443e-11, 1.0001099e-10, + 1.03220314e-10, 1.06377254e-10, 1.09486115e-10, 1.1255068e-10, + 1.1557435e-10, 1.1856015e-10, 1.2151083e-10, 1.2442886e-10, + 1.2731648e-10, 1.3017575e-10, 1.3300853e-10, 1.3581657e-10, + 1.3860142e-10, 1.4136457e-10, 1.4410738e-10, 1.4683108e-10, + 1.4953687e-10, 1.5222583e-10, 1.54899e-10, 1.5755733e-10, + 1.6020171e-10, 1.6283301e-10, 1.6545203e-10, 1.6805951e-10, + 1.7065617e-10, 1.732427e-10, 1.7581973e-10, 1.7838787e-10, + 1.8094774e-10, 1.8349985e-10, 1.8604476e-10, 1.8858298e-10, + 1.9111498e-10, 1.9364126e-10, 1.9616223e-10, 1.9867835e-10, + 2.0119004e-10, 2.0369768e-10, 2.0620168e-10, 2.087024e-10, + 2.1120022e-10, 2.136955e-10, 2.1618855e-10, 2.1867974e-10, + 2.2116936e-10, 2.2365775e-10, 2.261452e-10, 2.2863202e-10, + 2.311185e-10, 2.3360494e-10, 2.360916e-10, 2.3857874e-10, + 2.4106667e-10, 2.4355562e-10, 2.4604588e-10, 2.485377e-10, + 2.5103128e-10, 2.5352695e-10, 2.560249e-10, 2.585254e-10, + 2.6102867e-10, 2.6353494e-10, 2.6604446e-10, 2.6855745e-10, + 2.7107416e-10, 2.7359479e-10, 2.761196e-10, 2.7864877e-10, + 2.8118255e-10, 2.8372119e-10, 2.8626485e-10, 2.888138e-10, + 2.9136826e-10, 2.939284e-10, 2.9649452e-10, 2.9906677e-10, + 3.016454e-10, 3.0423064e-10, 3.0682268e-10, 3.0942177e-10, + 3.1202813e-10, 3.1464195e-10, 3.1726352e-10, 3.19893e-10, + 3.2253064e-10, 3.251767e-10, 3.2783135e-10, 3.3049485e-10, + 3.3316744e-10, 3.3584938e-10, 3.3854083e-10, 3.4124212e-10, + 3.4395342e-10, 3.46675e-10, 3.4940711e-10, 3.5215003e-10, + 3.5490397e-10, 3.5766917e-10, 3.6044595e-10, 3.6323455e-10, + 3.660352e-10, 3.6884823e-10, 3.7167386e-10, 3.745124e-10, + 3.773641e-10, 3.802293e-10, 3.8310827e-10, 3.860013e-10, + 3.8890866e-10, 3.918307e-10, 3.9476775e-10, 3.9772008e-10, + 4.0068804e-10, 4.0367196e-10, 4.0667217e-10, 4.09689e-10, + 4.1272286e-10, 4.1577405e-10, 4.1884296e-10, 4.2192994e-10, + 4.250354e-10, 4.281597e-10, 4.313033e-10, 4.3446652e-10, + 4.3764986e-10, 4.408537e-10, 4.4407847e-10, 4.4732465e-10, + 4.5059267e-10, 4.5388301e-10, 4.571962e-10, 4.6053267e-10, + 4.6389292e-10, 4.6727755e-10, 4.70687e-10, 4.741219e-10, + 4.7758275e-10, 4.810702e-10, 4.845848e-10, 4.8812715e-10, + 4.9169796e-10, 4.9529775e-10, 4.989273e-10, 5.0258725e-10, + 5.0627835e-10, 5.100013e-10, 5.1375687e-10, 5.1754584e-10, + 5.21369e-10, 5.2522725e-10, 5.2912136e-10, 5.330522e-10, + 5.370208e-10, 5.4102806e-10, 5.45075e-10, 5.491625e-10, + 5.532918e-10, 5.5746385e-10, 5.616799e-10, 5.6594107e-10, + 5.7024857e-10, 5.746037e-10, 5.7900773e-10, 5.834621e-10, + 5.8796823e-10, 5.925276e-10, 5.971417e-10, 6.018122e-10, + 6.065408e-10, 6.113292e-10, 6.1617933e-10, 6.2109295e-10, + 6.260722e-10, 6.3111916e-10, 6.3623595e-10, 6.4142497e-10, + 6.4668854e-10, 6.5202926e-10, 6.5744976e-10, 6.6295286e-10, + 6.6854156e-10, 6.742188e-10, 6.79988e-10, 6.858526e-10, + 6.9181616e-10, 6.978826e-10, 7.04056e-10, 7.103407e-10, + 7.167412e-10, 7.2326256e-10, 7.2990985e-10, 7.366886e-10, + 7.4360473e-10, 7.5066453e-10, 7.5787476e-10, 7.6524265e-10, + 7.7277595e-10, 7.80483e-10, 7.883728e-10, 7.9645507e-10, + 8.047402e-10, 8.1323964e-10, 8.219657e-10, 8.309319e-10, + 8.401528e-10, 8.496445e-10, 8.594247e-10, 8.6951274e-10, + 8.799301e-10, 8.9070046e-10, 9.018503e-10, 9.134092e-10, + 9.254101e-10, 9.378904e-10, 9.508923e-10, 9.644638e-10, + 9.786603e-10, 9.935448e-10, 1.0091913e-09, 1.025686e-09, + 1.0431306e-09, 1.0616465e-09, 1.08138e-09, 1.1025096e-09, + 1.1252564e-09, 1.1498986e-09, 1.1767932e-09, 1.206409e-09, + 1.2393786e-09, 1.276585e-09, 1.3193139e-09, 1.3695435e-09, + 1.4305498e-09, 1.508365e-09, 1.6160854e-09, 1.7921248e-09, +} +var fe = [256]float32{ + 1, 0.9381437, 0.90046996, 0.87170434, 0.8477855, 0.8269933, + 0.8084217, 0.7915276, 0.77595687, 0.7614634, 0.7478686, + 0.7350381, 0.72286767, 0.71127474, 0.70019263, 0.6895665, + 0.67935055, 0.6695063, 0.66000086, 0.65080583, 0.6418967, + 0.63325197, 0.6248527, 0.6166822, 0.60872537, 0.60096896, + 0.5934009, 0.58601034, 0.5787874, 0.57172304, 0.5648092, + 0.5580383, 0.5514034, 0.5448982, 0.5385169, 0.53225386, + 0.5261042, 0.52006316, 0.5141264, 0.50828975, 0.5025495, + 0.496902, 0.49134386, 0.485872, 0.48048335, 0.4751752, + 0.46994483, 0.46478975, 0.45970762, 0.45469615, 0.44975325, + 0.44487688, 0.44006512, 0.43531612, 0.43062815, 0.42599955, + 0.42142874, 0.4169142, 0.41245446, 0.40804818, 0.403694, + 0.3993907, 0.39513698, 0.39093173, 0.38677382, 0.38266218, + 0.37859577, 0.37457356, 0.37059465, 0.3666581, 0.362763, + 0.35890847, 0.35509375, 0.351318, 0.3475805, 0.34388044, + 0.34021714, 0.3365899, 0.33299807, 0.32944095, 0.32591796, + 0.3224285, 0.3189719, 0.31554767, 0.31215525, 0.30879408, + 0.3054636, 0.3021634, 0.29889292, 0.2956517, 0.29243928, + 0.28925523, 0.28609908, 0.28297043, 0.27986884, 0.27679393, + 0.2737453, 0.2707226, 0.2677254, 0.26475343, 0.26180625, + 0.25888354, 0.25598502, 0.2531103, 0.25025907, 0.24743107, + 0.24462597, 0.24184346, 0.23908329, 0.23634516, 0.23362878, + 0.23093392, 0.2282603, 0.22560766, 0.22297576, 0.22036438, + 0.21777324, 0.21520215, 0.21265087, 0.21011916, 0.20760682, + 0.20511365, 0.20263945, 0.20018397, 0.19774707, 0.19532852, + 0.19292815, 0.19054577, 0.1881812, 0.18583426, 0.18350479, + 0.1811926, 0.17889754, 0.17661946, 0.17435817, 0.17211354, + 0.1698854, 0.16767362, 0.16547804, 0.16329853, 0.16113494, + 0.15898713, 0.15685499, 0.15473837, 0.15263714, 0.15055119, + 0.14848037, 0.14642459, 0.14438373, 0.14235765, 0.14034624, + 0.13834943, 0.13636707, 0.13439907, 0.13244532, 0.13050574, + 0.1285802, 0.12666863, 0.12477092, 0.12288698, 0.12101672, + 0.119160056, 0.1173169, 0.115487166, 0.11367077, 0.11186763, + 0.11007768, 0.10830083, 0.10653701, 0.10478614, 0.10304816, + 0.101323, 0.09961058, 0.09791085, 0.09622374, 0.09454919, + 0.09288713, 0.091237515, 0.08960028, 0.087975375, 0.08636274, + 0.08476233, 0.083174095, 0.081597984, 0.08003395, 0.07848195, + 0.076941945, 0.07541389, 0.07389775, 0.072393484, 0.07090106, + 0.069420435, 0.06795159, 0.066494495, 0.06504912, 0.063615434, + 0.062193416, 0.060783047, 0.059384305, 0.057997175, + 0.05662164, 0.05525769, 0.053905312, 0.052564494, 0.051235236, + 0.049917534, 0.048611384, 0.047316793, 0.046033762, 0.0447623, + 0.043502413, 0.042254124, 0.041017443, 0.039792392, + 0.038578995, 0.037377283, 0.036187284, 0.035009038, + 0.033842582, 0.032687962, 0.031545233, 0.030414443, 0.02929566, + 0.02818895, 0.027094385, 0.026012046, 0.024942026, 0.023884421, + 0.022839336, 0.021806888, 0.020787204, 0.019780423, 0.0187867, + 0.0178062, 0.016839107, 0.015885621, 0.014945968, 0.014020392, + 0.013109165, 0.012212592, 0.011331013, 0.01046481, 0.009614414, + 0.008780315, 0.007963077, 0.0071633533, 0.006381906, + 0.0056196423, 0.0048776558, 0.004157295, 0.0034602648, + 0.0027887989, 0.0021459677, 0.0015362998, 0.0009672693, + 0.00045413437, +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/modulo_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/modulo_test.go new file mode 100644 index 0000000..da963c7 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/modulo_test.go @@ -0,0 +1,50 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file validates that the calculation in Uint64n corrects for +// possible bias. + +package rand + +import ( + "testing" +) + +// modSource is used to probe the upper region of uint64 space. It +// generates values sequentially in [maxUint64-15,maxUint64]. With +// modEdge == 15 and maxUint64 == 1<<64-1 == 18446744073709551615, +// this means that Uint64n(10) will repeatedly probe the top range. +// We thus expect a bias to result unless the calculation in Uint64n +// gets the edge condition right. We test this by calling Uint64n 100 +// times; the results should be perfectly evenly distributed across +// [0,10). +type modSource uint64 + +const modEdge = 15 + +func (m *modSource) Seed(uint64) {} + +// Uint64 returns a non-pseudo-random 64-bit unsigned integer as a uint64. +func (m *modSource) Uint64() uint64 { + if *m > modEdge { + *m = 0 + } + r := maxUint64 - *m + *m++ + return uint64(r) +} + +func TestUint64Modulo(t *testing.T) { + var src modSource + rng := New(&src) + var result [10]uint64 + for i := 0; i < 100; i++ { + result[rng.Uint64n(10)]++ + } + for _, r := range result { + if r != 10 { + t.Fatal(result) + } + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/normal.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/normal.go new file mode 100644 index 0000000..b66da3a --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/normal.go @@ -0,0 +1,156 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand + +import ( + "math" +) + +/* + * Normal distribution + * + * See "The Ziggurat Method for Generating Random Variables" + * (Marsaglia & Tsang, 2000) + * http://www.jstatsoft.org/v05/i08/paper [pdf] + */ + +const ( + rn = 3.442619855899 +) + +func absInt32(i int32) uint32 { + if i < 0 { + return uint32(-i) + } + return uint32(i) +} + +// NormFloat64 returns a normally distributed float64 in the range +// [-math.MaxFloat64, +math.MaxFloat64] with +// standard normal distribution (mean = 0, stddev = 1). +// To produce a different normal distribution, callers can +// adjust the output using: +// +// sample = NormFloat64() * desiredStdDev + desiredMean +func (r *Rand) NormFloat64() float64 { + for { + j := int32(r.Uint32()) // Possibly negative + i := j & 0x7F + x := float64(j) * float64(wn[i]) + if absInt32(j) < kn[i] { + // This case should be hit better than 99% of the time. + return x + } + + if i == 0 { + // This extra work is only required for the base strip. + for { + x = -math.Log(r.Float64()) * (1.0 / rn) + y := -math.Log(r.Float64()) + if y+y >= x*x { + break + } + } + if j > 0 { + return rn + x + } + return -rn - x + } + if fn[i]+float32(r.Float64())*(fn[i-1]-fn[i]) < float32(math.Exp(-.5*x*x)) { + return x + } + } +} + +var kn = [128]uint32{ + 0x76ad2212, 0x0, 0x600f1b53, 0x6ce447a6, 0x725b46a2, + 0x7560051d, 0x774921eb, 0x789a25bd, 0x799045c3, 0x7a4bce5d, + 0x7adf629f, 0x7b5682a6, 0x7bb8a8c6, 0x7c0ae722, 0x7c50cce7, + 0x7c8cec5b, 0x7cc12cd6, 0x7ceefed2, 0x7d177e0b, 0x7d3b8883, + 0x7d5bce6c, 0x7d78dd64, 0x7d932886, 0x7dab0e57, 0x7dc0dd30, + 0x7dd4d688, 0x7de73185, 0x7df81cea, 0x7e07c0a3, 0x7e163efa, + 0x7e23b587, 0x7e303dfd, 0x7e3beec2, 0x7e46db77, 0x7e51155d, + 0x7e5aabb3, 0x7e63abf7, 0x7e6c222c, 0x7e741906, 0x7e7b9a18, + 0x7e82adfa, 0x7e895c63, 0x7e8fac4b, 0x7e95a3fb, 0x7e9b4924, + 0x7ea0a0ef, 0x7ea5b00d, 0x7eaa7ac3, 0x7eaf04f3, 0x7eb3522a, + 0x7eb765a5, 0x7ebb4259, 0x7ebeeafd, 0x7ec2620a, 0x7ec5a9c4, + 0x7ec8c441, 0x7ecbb365, 0x7ece78ed, 0x7ed11671, 0x7ed38d62, + 0x7ed5df12, 0x7ed80cb4, 0x7eda175c, 0x7edc0005, 0x7eddc78e, + 0x7edf6ebf, 0x7ee0f647, 0x7ee25ebe, 0x7ee3a8a9, 0x7ee4d473, + 0x7ee5e276, 0x7ee6d2f5, 0x7ee7a620, 0x7ee85c10, 0x7ee8f4cd, + 0x7ee97047, 0x7ee9ce59, 0x7eea0eca, 0x7eea3147, 0x7eea3568, + 0x7eea1aab, 0x7ee9e071, 0x7ee98602, 0x7ee90a88, 0x7ee86d08, + 0x7ee7ac6a, 0x7ee6c769, 0x7ee5bc9c, 0x7ee48a67, 0x7ee32efc, + 0x7ee1a857, 0x7edff42f, 0x7ede0ffa, 0x7edbf8d9, 0x7ed9ab94, + 0x7ed7248d, 0x7ed45fae, 0x7ed1585c, 0x7ece095f, 0x7eca6ccb, + 0x7ec67be2, 0x7ec22eee, 0x7ebd7d1a, 0x7eb85c35, 0x7eb2c075, + 0x7eac9c20, 0x7ea5df27, 0x7e9e769f, 0x7e964c16, 0x7e8d44ba, + 0x7e834033, 0x7e781728, 0x7e6b9933, 0x7e5d8a1a, 0x7e4d9ded, + 0x7e3b737a, 0x7e268c2f, 0x7e0e3ff5, 0x7df1aa5d, 0x7dcf8c72, + 0x7da61a1e, 0x7d72a0fb, 0x7d30e097, 0x7cd9b4ab, 0x7c600f1a, + 0x7ba90bdc, 0x7a722176, 0x77d664e5, +} +var wn = [128]float32{ + 1.7290405e-09, 1.2680929e-10, 1.6897518e-10, 1.9862688e-10, + 2.2232431e-10, 2.4244937e-10, 2.601613e-10, 2.7611988e-10, + 2.9073963e-10, 3.042997e-10, 3.1699796e-10, 3.289802e-10, + 3.4035738e-10, 3.5121603e-10, 3.616251e-10, 3.7164058e-10, + 3.8130857e-10, 3.9066758e-10, 3.9975012e-10, 4.08584e-10, + 4.1719309e-10, 4.2559822e-10, 4.338176e-10, 4.418672e-10, + 4.497613e-10, 4.5751258e-10, 4.651324e-10, 4.7263105e-10, + 4.8001775e-10, 4.87301e-10, 4.944885e-10, 5.015873e-10, + 5.0860405e-10, 5.155446e-10, 5.2241467e-10, 5.2921934e-10, + 5.359635e-10, 5.426517e-10, 5.4928817e-10, 5.5587696e-10, + 5.624219e-10, 5.6892646e-10, 5.753941e-10, 5.818282e-10, + 5.882317e-10, 5.946077e-10, 6.00959e-10, 6.072884e-10, + 6.135985e-10, 6.19892e-10, 6.2617134e-10, 6.3243905e-10, + 6.386974e-10, 6.449488e-10, 6.511956e-10, 6.5744005e-10, + 6.6368433e-10, 6.699307e-10, 6.7618144e-10, 6.824387e-10, + 6.8870465e-10, 6.949815e-10, 7.012715e-10, 7.075768e-10, + 7.1389966e-10, 7.202424e-10, 7.266073e-10, 7.329966e-10, + 7.394128e-10, 7.4585826e-10, 7.5233547e-10, 7.58847e-10, + 7.653954e-10, 7.719835e-10, 7.7861395e-10, 7.852897e-10, + 7.920138e-10, 7.987892e-10, 8.0561924e-10, 8.125073e-10, + 8.194569e-10, 8.2647167e-10, 8.3355556e-10, 8.407127e-10, + 8.479473e-10, 8.55264e-10, 8.6266755e-10, 8.7016316e-10, + 8.777562e-10, 8.8545243e-10, 8.932582e-10, 9.0117996e-10, + 9.09225e-10, 9.174008e-10, 9.2571584e-10, 9.341788e-10, + 9.427997e-10, 9.515889e-10, 9.605579e-10, 9.697193e-10, + 9.790869e-10, 9.88676e-10, 9.985036e-10, 1.0085882e-09, + 1.0189509e-09, 1.0296151e-09, 1.0406069e-09, 1.0519566e-09, + 1.063698e-09, 1.0758702e-09, 1.0885183e-09, 1.1016947e-09, + 1.1154611e-09, 1.1298902e-09, 1.1450696e-09, 1.1611052e-09, + 1.1781276e-09, 1.1962995e-09, 1.2158287e-09, 1.2369856e-09, + 1.2601323e-09, 1.2857697e-09, 1.3146202e-09, 1.347784e-09, + 1.3870636e-09, 1.4357403e-09, 1.5008659e-09, 1.6030948e-09, +} +var fn = [128]float32{ + 1, 0.9635997, 0.9362827, 0.9130436, 0.89228165, 0.87324303, + 0.8555006, 0.8387836, 0.8229072, 0.8077383, 0.793177, + 0.7791461, 0.7655842, 0.7524416, 0.73967725, 0.7272569, + 0.7151515, 0.7033361, 0.69178915, 0.68049186, 0.6694277, + 0.658582, 0.6479418, 0.63749546, 0.6272325, 0.6171434, + 0.6072195, 0.5974532, 0.58783704, 0.5783647, 0.56903, + 0.5598274, 0.5507518, 0.54179835, 0.5329627, 0.52424055, + 0.5156282, 0.50712204, 0.49871865, 0.49041483, 0.48220766, + 0.4740943, 0.46607214, 0.4581387, 0.45029163, 0.44252872, + 0.43484783, 0.427247, 0.41972435, 0.41227803, 0.40490642, + 0.39760786, 0.3903808, 0.3832238, 0.37613547, 0.36911446, + 0.3621595, 0.35526937, 0.34844297, 0.34167916, 0.33497685, + 0.3283351, 0.3217529, 0.3152294, 0.30876362, 0.30235484, + 0.29600215, 0.28970486, 0.2834622, 0.2772735, 0.27113807, + 0.2650553, 0.25902456, 0.2530453, 0.24711695, 0.241239, + 0.23541094, 0.22963232, 0.2239027, 0.21822165, 0.21258877, + 0.20700371, 0.20146611, 0.19597565, 0.19053204, 0.18513499, + 0.17978427, 0.17447963, 0.1692209, 0.16400786, 0.15884037, + 0.15371831, 0.14864157, 0.14361008, 0.13862377, 0.13368265, + 0.12878671, 0.12393598, 0.119130544, 0.11437051, 0.10965602, + 0.104987256, 0.10036444, 0.095787846, 0.0912578, 0.08677467, + 0.0823389, 0.077950984, 0.073611505, 0.06932112, 0.06508058, + 0.06089077, 0.056752663, 0.0526674, 0.048636295, 0.044660863, + 0.040742867, 0.03688439, 0.033087887, 0.029356318, + 0.025693292, 0.022103304, 0.018592102, 0.015167298, + 0.011839478, 0.008624485, 0.005548995, 0.0026696292, +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/race_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/race_test.go new file mode 100644 index 0000000..376224f --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/race_test.go @@ -0,0 +1,48 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand + +import ( + "sync" + "testing" +) + +// TestConcurrent exercises the rand API concurrently, triggering situations +// where the race detector is likely to detect issues. +func TestConcurrent(t *testing.T) { + const ( + numRoutines = 10 + numCycles = 10 + ) + var wg sync.WaitGroup + defer wg.Wait() + wg.Add(numRoutines) + for i := 0; i < numRoutines; i++ { + go func(i int) { + defer wg.Done() + buf := make([]byte, 997) + for j := 0; j < numCycles; j++ { + var seed uint64 + seed += uint64(ExpFloat64()) + seed += uint64(Float32()) + seed += uint64(Float64()) + seed += uint64(Intn(Int())) + seed += uint64(Int31n(Int31())) + seed += uint64(Int63n(Int63())) + seed += uint64(NormFloat64()) + seed += uint64(Uint32()) + seed += uint64(Uint64()) + for _, p := range Perm(10) { + seed += uint64(p) + } + Read(buf) + for _, b := range buf { + seed += uint64(b) + } + Seed(uint64(i*j) * seed) + } + }(i) + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/rand.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/rand.go new file mode 100644 index 0000000..ee6161b --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/rand.go @@ -0,0 +1,372 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package rand implements pseudo-random number generators. +// +// Random numbers are generated by a Source. Top-level functions, such as +// Float64 and Int, use a default shared Source that produces a deterministic +// sequence of values each time a program is run. Use the Seed function to +// initialize the default Source if different behavior is required for each run. +// The default Source, a LockedSource, is safe for concurrent use by multiple +// goroutines, but Sources created by NewSource are not. However, Sources are small +// and it is reasonable to have a separate Source for each goroutine, seeded +// differently, to avoid locking. +// +// For random numbers suitable for security-sensitive work, see the crypto/rand +// package. +package rand + +import "sync" + +// A Source represents a source of uniformly-distributed +// pseudo-random int64 values in the range [0, 1<<64). +type Source interface { + Uint64() uint64 + Seed(seed uint64) +} + +// NewSource returns a new pseudo-random Source seeded with the given value. +func NewSource(seed uint64) Source { + var rng PCGSource + rng.Seed(seed) + return &rng +} + +// A Rand is a source of random numbers. +type Rand struct { + src Source + + // readVal contains remainder of 64-bit integer used for bytes + // generation during most recent Read call. + // It is saved so next Read call can start where the previous + // one finished. + readVal uint64 + // readPos indicates the number of low-order bytes of readVal + // that are still valid. + readPos int8 +} + +// New returns a new Rand that uses random values from src +// to generate other random values. +func New(src Source) *Rand { + return &Rand{src: src} +} + +// Seed uses the provided seed value to initialize the generator to a deterministic state. +// Seed should not be called concurrently with any other Rand method. +func (r *Rand) Seed(seed uint64) { + if lk, ok := r.src.(*LockedSource); ok { + lk.seedPos(seed, &r.readPos) + return + } + + r.src.Seed(seed) + r.readPos = 0 +} + +// Uint64 returns a pseudo-random 64-bit integer as a uint64. +func (r *Rand) Uint64() uint64 { return r.src.Uint64() } + +// Int63 returns a non-negative pseudo-random 63-bit integer as an int64. +func (r *Rand) Int63() int64 { return int64(r.src.Uint64() &^ (1 << 63)) } + +// Uint32 returns a pseudo-random 32-bit value as a uint32. +func (r *Rand) Uint32() uint32 { return uint32(r.Uint64() >> 32) } + +// Int31 returns a non-negative pseudo-random 31-bit integer as an int32. +func (r *Rand) Int31() int32 { return int32(r.Uint64() >> 33) } + +// Int returns a non-negative pseudo-random int. +func (r *Rand) Int() int { + u := uint(r.Uint64()) + return int(u << 1 >> 1) // clear sign bit. +} + +const maxUint64 = (1 << 64) - 1 + +// Uint64n returns, as a uint64, a pseudo-random number in [0,n). +// It is guaranteed more uniform than taking a Source value mod n +// for any n that is not a power of 2. +func (r *Rand) Uint64n(n uint64) uint64 { + if n&(n-1) == 0 { // n is power of two, can mask + if n == 0 { + panic("invalid argument to Uint64n") + } + return r.Uint64() & (n - 1) + } + // If n does not divide v, to avoid bias we must not use + // a v that is within maxUint64%n of the top of the range. + v := r.Uint64() + if v > maxUint64-n { // Fast check. + ceiling := maxUint64 - maxUint64%n + for v >= ceiling { + v = r.Uint64() + } + } + + return v % n +} + +// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n). +// It panics if n <= 0. +func (r *Rand) Int63n(n int64) int64 { + if n <= 0 { + panic("invalid argument to Int63n") + } + return int64(r.Uint64n(uint64(n))) +} + +// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n). +// It panics if n <= 0. +func (r *Rand) Int31n(n int32) int32 { + if n <= 0 { + panic("invalid argument to Int31n") + } + // TODO: Avoid some 64-bit ops to make it more efficient on 32-bit machines. + return int32(r.Uint64n(uint64(n))) +} + +// Intn returns, as an int, a non-negative pseudo-random number in [0,n). +// It panics if n <= 0. +func (r *Rand) Intn(n int) int { + if n <= 0 { + panic("invalid argument to Intn") + } + // TODO: Avoid some 64-bit ops to make it more efficient on 32-bit machines. + return int(r.Uint64n(uint64(n))) +} + +// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0). +func (r *Rand) Float64() float64 { + // There is one bug in the value stream: r.Int63() may be so close + // to 1<<63 that the division rounds up to 1.0, and we've guaranteed + // that the result is always less than 1.0. + // + // We tried to fix this by mapping 1.0 back to 0.0, but since float64 + // values near 0 are much denser than near 1, mapping 1 to 0 caused + // a theoretically significant overshoot in the probability of returning 0. + // Instead of that, if we round up to 1, just try again. + // Getting 1 only happens 1/2⁵³ of the time, so most clients + // will not observe it anyway. +again: + f := float64(r.Uint64n(1<<53)) / (1 << 53) + if f == 1.0 { + goto again // resample; this branch is taken O(never) + } + return f +} + +// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0). +func (r *Rand) Float32() float32 { + // We do not want to return 1.0. + // This only happens 1/2²⁴ of the time (plus the 1/2⁵³ of the time in Float64). +again: + f := float32(r.Float64()) + if f == 1 { + goto again // resample; this branch is taken O(very rarely) + } + return f +} + +// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n). +func (r *Rand) Perm(n int) []int { + m := make([]int, n) + // In the following loop, the iteration when i=0 always swaps m[0] with m[0]. + // A change to remove this useless iteration is to assign 1 to i in the init + // statement. But Perm also effects r. Making this change will affect + // the final state of r. So this change can't be made for compatibility + // reasons for Go 1. + for i := 0; i < n; i++ { + j := r.Intn(i + 1) + m[i] = m[j] + m[j] = i + } + return m +} + +// Shuffle pseudo-randomizes the order of elements. +// n is the number of elements. Shuffle panics if n < 0. +// swap swaps the elements with indexes i and j. +func (r *Rand) Shuffle(n int, swap func(i, j int)) { + if n < 0 { + panic("invalid argument to Shuffle") + } + + // Fisher-Yates shuffle: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle + // Shuffle really ought not be called with n that doesn't fit in 32 bits. + // Not only will it take a very long time, but with 2³¹! possible permutations, + // there's no way that any PRNG can have a big enough internal state to + // generate even a minuscule percentage of the possible permutations. + // Nevertheless, the right API signature accepts an int n, so handle it as best we can. + i := n - 1 + for ; i > 1<<31-1-1; i-- { + j := int(r.Int63n(int64(i + 1))) + swap(i, j) + } + for ; i > 0; i-- { + j := int(r.Int31n(int32(i + 1))) + swap(i, j) + } +} + +// Read generates len(p) random bytes and writes them into p. It +// always returns len(p) and a nil error. +// Read should not be called concurrently with any other Rand method unless +// the underlying source is a LockedSource. +func (r *Rand) Read(p []byte) (n int, err error) { + if lk, ok := r.src.(*LockedSource); ok { + return lk.Read(p, &r.readVal, &r.readPos) + } + return read(p, r.src, &r.readVal, &r.readPos) +} + +func read(p []byte, src Source, readVal *uint64, readPos *int8) (n int, err error) { + pos := *readPos + val := *readVal + rng, _ := src.(*PCGSource) + for n = 0; n < len(p); n++ { + if pos == 0 { + if rng != nil { + val = rng.Uint64() + } else { + val = src.Uint64() + } + pos = 8 + } + p[n] = byte(val) + val >>= 8 + pos-- + } + *readPos = pos + *readVal = val + return +} + +/* + * Top-level convenience functions + */ + +var globalRand = New(&LockedSource{src: *NewSource(1).(*PCGSource)}) + +// Type assert that globalRand's source is a LockedSource whose src is a PCGSource. +var _ PCGSource = globalRand.src.(*LockedSource).src + +// Seed uses the provided seed value to initialize the default Source to a +// deterministic state. If Seed is not called, the generator behaves as +// if seeded by Seed(1). +// Seed, unlike the Rand.Seed method, is safe for concurrent use. +func Seed(seed uint64) { globalRand.Seed(seed) } + +// Int63 returns a non-negative pseudo-random 63-bit integer as an int64 +// from the default Source. +func Int63() int64 { return globalRand.Int63() } + +// Uint32 returns a pseudo-random 32-bit value as a uint32 +// from the default Source. +func Uint32() uint32 { return globalRand.Uint32() } + +// Uint64 returns a pseudo-random 64-bit value as a uint64 +// from the default Source. +func Uint64() uint64 { return globalRand.Uint64() } + +// Int31 returns a non-negative pseudo-random 31-bit integer as an int32 +// from the default Source. +func Int31() int32 { return globalRand.Int31() } + +// Int returns a non-negative pseudo-random int from the default Source. +func Int() int { return globalRand.Int() } + +// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n) +// from the default Source. +// It panics if n <= 0. +func Int63n(n int64) int64 { return globalRand.Int63n(n) } + +// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n) +// from the default Source. +// It panics if n <= 0. +func Int31n(n int32) int32 { return globalRand.Int31n(n) } + +// Intn returns, as an int, a non-negative pseudo-random number in [0,n) +// from the default Source. +// It panics if n <= 0. +func Intn(n int) int { return globalRand.Intn(n) } + +// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0) +// from the default Source. +func Float64() float64 { return globalRand.Float64() } + +// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0) +// from the default Source. +func Float32() float32 { return globalRand.Float32() } + +// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n) +// from the default Source. +func Perm(n int) []int { return globalRand.Perm(n) } + +// Shuffle pseudo-randomizes the order of elements using the default Source. +// n is the number of elements. Shuffle panics if n < 0. +// swap swaps the elements with indexes i and j. +func Shuffle(n int, swap func(i, j int)) { globalRand.Shuffle(n, swap) } + +// Read generates len(p) random bytes from the default Source and +// writes them into p. It always returns len(p) and a nil error. +// Read, unlike the Rand.Read method, is safe for concurrent use. +func Read(p []byte) (n int, err error) { return globalRand.Read(p) } + +// NormFloat64 returns a normally distributed float64 in the range +// [-math.MaxFloat64, +math.MaxFloat64] with +// standard normal distribution (mean = 0, stddev = 1) +// from the default Source. +// To produce a different normal distribution, callers can +// adjust the output using: +// +// sample = NormFloat64() * desiredStdDev + desiredMean +func NormFloat64() float64 { return globalRand.NormFloat64() } + +// ExpFloat64 returns an exponentially distributed float64 in the range +// (0, +math.MaxFloat64] with an exponential distribution whose rate parameter +// (lambda) is 1 and whose mean is 1/lambda (1) from the default Source. +// To produce a distribution with a different rate parameter, +// callers can adjust the output using: +// +// sample = ExpFloat64() / desiredRateParameter +func ExpFloat64() float64 { return globalRand.ExpFloat64() } + +// LockedSource is an implementation of Source that is concurrency-safe. +// A Rand using a LockedSource is safe for concurrent use. +// +// The zero value of LockedSource is valid, but should be seeded before use. +type LockedSource struct { + lk sync.Mutex + src PCGSource +} + +func (s *LockedSource) Uint64() (n uint64) { + s.lk.Lock() + n = s.src.Uint64() + s.lk.Unlock() + return +} + +func (s *LockedSource) Seed(seed uint64) { + s.lk.Lock() + s.src.Seed(seed) + s.lk.Unlock() +} + +// seedPos implements Seed for a LockedSource without a race condiiton. +func (s *LockedSource) seedPos(seed uint64, readPos *int8) { + s.lk.Lock() + s.src.Seed(seed) + *readPos = 0 + s.lk.Unlock() +} + +// Read implements Read for a LockedSource. +func (s *LockedSource) Read(p []byte, readVal *uint64, readPos *int8) (n int, err error) { + s.lk.Lock() + n, err = read(p, &s.src, readVal, readPos) + s.lk.Unlock() + return +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/rand_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/rand_test.go new file mode 100644 index 0000000..4383e4f --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/rand_test.go @@ -0,0 +1,617 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand + +import ( + "bytes" + "errors" + "fmt" + "io" + "math" + "os" + "runtime" + "testing" + "testing/iotest" + "time" +) + +const ( + numTestSamples = 10000 +) + +type statsResults struct { + mean float64 + stddev float64 + closeEnough float64 + maxError float64 +} + +func max(a, b float64) float64 { + if a > b { + return a + } + return b +} + +func nearEqual(a, b, closeEnough, maxError float64) bool { + absDiff := math.Abs(a - b) + if absDiff < closeEnough { // Necessary when one value is zero and one value is close to zero. + return true + } + return absDiff/max(math.Abs(a), math.Abs(b)) < maxError +} + +var testSeeds = []uint64{1, 1754801282, 1698661970, 1550503961} + +// checkSimilarDistribution returns success if the mean and stddev of the +// two statsResults are similar. +func (this *statsResults) checkSimilarDistribution(expected *statsResults) error { + if !nearEqual(this.mean, expected.mean, expected.closeEnough, expected.maxError) { + s := fmt.Sprintf("mean %v != %v (allowed error %v, %v)", this.mean, expected.mean, expected.closeEnough, expected.maxError) + fmt.Println(s) + return errors.New(s) + } + if !nearEqual(this.stddev, expected.stddev, 0, expected.maxError) { + s := fmt.Sprintf("stddev %v != %v (allowed error %v, %v)", this.stddev, expected.stddev, expected.closeEnough, expected.maxError) + fmt.Println(s) + return errors.New(s) + } + return nil +} + +func getStatsResults(samples []float64) *statsResults { + res := new(statsResults) + var sum, squaresum float64 + for _, s := range samples { + sum += s + squaresum += s * s + } + res.mean = sum / float64(len(samples)) + res.stddev = math.Sqrt(squaresum/float64(len(samples)) - res.mean*res.mean) + return res +} + +func checkSampleDistribution(t *testing.T, samples []float64, expected *statsResults) { + t.Helper() + actual := getStatsResults(samples) + err := actual.checkSimilarDistribution(expected) + if err != nil { + t.Errorf(err.Error()) + } +} + +func checkSampleSliceDistributions(t *testing.T, samples []float64, nslices int, expected *statsResults) { + t.Helper() + chunk := len(samples) / nslices + for i := 0; i < nslices; i++ { + low := i * chunk + var high int + if i == nslices-1 { + high = len(samples) - 1 + } else { + high = (i + 1) * chunk + } + checkSampleDistribution(t, samples[low:high], expected) + } +} + +// +// Normal distribution tests +// + +func generateNormalSamples(nsamples int, mean, stddev float64, seed uint64) []float64 { + r := New(NewSource(seed)) + samples := make([]float64, nsamples) + for i := range samples { + samples[i] = r.NormFloat64()*stddev + mean + } + return samples +} + +func testNormalDistribution(t *testing.T, nsamples int, mean, stddev float64, seed uint64) { + //fmt.Printf("testing nsamples=%v mean=%v stddev=%v seed=%v\n", nsamples, mean, stddev, seed); + + samples := generateNormalSamples(nsamples, mean, stddev, seed) + errorScale := max(1.0, stddev) // Error scales with stddev + expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.08 * errorScale} + + // Make sure that the entire set matches the expected distribution. + checkSampleDistribution(t, samples, expected) + + // Make sure that each half of the set matches the expected distribution. + checkSampleSliceDistributions(t, samples, 2, expected) + + // Make sure that each 7th of the set matches the expected distribution. + checkSampleSliceDistributions(t, samples, 7, expected) +} + +// Actual tests + +func TestStandardNormalValues(t *testing.T) { + for _, seed := range testSeeds { + testNormalDistribution(t, numTestSamples, 0, 1, seed) + } +} + +func TestNonStandardNormalValues(t *testing.T) { + sdmax := 1000.0 + mmax := 1000.0 + if testing.Short() { + sdmax = 5 + mmax = 5 + } + for sd := 0.5; sd < sdmax; sd *= 2 { + for m := 0.5; m < mmax; m *= 2 { + for _, seed := range testSeeds { + testNormalDistribution(t, numTestSamples, m, sd, seed) + if testing.Short() { + break + } + } + } + } +} + +// +// Exponential distribution tests +// + +func generateExponentialSamples(nsamples int, rate float64, seed uint64) []float64 { + r := New(NewSource(seed)) + samples := make([]float64, nsamples) + for i := range samples { + samples[i] = r.ExpFloat64() / rate + } + return samples +} + +func testExponentialDistribution(t *testing.T, nsamples int, rate float64, seed uint64) { + //fmt.Printf("testing nsamples=%v rate=%v seed=%v\n", nsamples, rate, seed) + + mean := 1 / rate + stddev := mean + + samples := generateExponentialSamples(nsamples, rate, seed) + errorScale := max(1.0, 1/rate) // Error scales with the inverse of the rate + expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.20 * errorScale} + + // Make sure that the entire set matches the expected distribution. + checkSampleDistribution(t, samples, expected) + + // Make sure that each half of the set matches the expected distribution. + checkSampleSliceDistributions(t, samples, 2, expected) + + // Make sure that each 7th of the set matches the expected distribution. + checkSampleSliceDistributions(t, samples, 7, expected) +} + +// Actual tests + +func TestStandardExponentialValues(t *testing.T) { + for _, seed := range testSeeds { + testExponentialDistribution(t, numTestSamples, 1, seed) + } +} + +func TestNonStandardExponentialValues(t *testing.T) { + for rate := 0.05; rate < 10; rate *= 2 { + for _, seed := range testSeeds { + testExponentialDistribution(t, numTestSamples, rate, seed) + if testing.Short() { + break + } + } + } +} + +// +// Table generation tests +// + +func initNorm() (testKn []uint32, testWn, testFn []float32) { + const m1 = 1 << 31 + var ( + dn float64 = rn + tn = dn + vn float64 = 9.91256303526217e-3 + ) + + testKn = make([]uint32, 128) + testWn = make([]float32, 128) + testFn = make([]float32, 128) + + q := vn / math.Exp(-0.5*dn*dn) + testKn[0] = uint32((dn / q) * m1) + testKn[1] = 0 + testWn[0] = float32(q / m1) + testWn[127] = float32(dn / m1) + testFn[0] = 1.0 + testFn[127] = float32(math.Exp(-0.5 * dn * dn)) + for i := 126; i >= 1; i-- { + dn = math.Sqrt(-2.0 * math.Log(vn/dn+math.Exp(-0.5*dn*dn))) + testKn[i+1] = uint32((dn / tn) * m1) + tn = dn + testFn[i] = float32(math.Exp(-0.5 * dn * dn)) + testWn[i] = float32(dn / m1) + } + return +} + +func initExp() (testKe []uint32, testWe, testFe []float32) { + const m2 = 1 << 32 + var ( + de float64 = re + te = de + ve float64 = 3.9496598225815571993e-3 + ) + + testKe = make([]uint32, 256) + testWe = make([]float32, 256) + testFe = make([]float32, 256) + + q := ve / math.Exp(-de) + testKe[0] = uint32((de / q) * m2) + testKe[1] = 0 + testWe[0] = float32(q / m2) + testWe[255] = float32(de / m2) + testFe[0] = 1.0 + testFe[255] = float32(math.Exp(-de)) + for i := 254; i >= 1; i-- { + de = -math.Log(ve/de + math.Exp(-de)) + testKe[i+1] = uint32((de / te) * m2) + te = de + testFe[i] = float32(math.Exp(-de)) + testWe[i] = float32(de / m2) + } + return +} + +// compareUint32Slices returns the first index where the two slices +// disagree, or <0 if the lengths are the same and all elements +// are identical. +func compareUint32Slices(s1, s2 []uint32) int { + if len(s1) != len(s2) { + if len(s1) > len(s2) { + return len(s2) + 1 + } + return len(s1) + 1 + } + for i := range s1 { + if s1[i] != s2[i] { + return i + } + } + return -1 +} + +// compareFloat32Slices returns the first index where the two slices +// disagree, or <0 if the lengths are the same and all elements +// are identical. +func compareFloat32Slices(s1, s2 []float32) int { + if len(s1) != len(s2) { + if len(s1) > len(s2) { + return len(s2) + 1 + } + return len(s1) + 1 + } + for i := range s1 { + if !nearEqual(float64(s1[i]), float64(s2[i]), 0, 1e-7) { + return i + } + } + return -1 +} + +func TestNormTables(t *testing.T) { + testKn, testWn, testFn := initNorm() + if i := compareUint32Slices(kn[0:], testKn); i >= 0 { + t.Errorf("kn disagrees at index %v; %v != %v", i, kn[i], testKn[i]) + } + if i := compareFloat32Slices(wn[0:], testWn); i >= 0 { + t.Errorf("wn disagrees at index %v; %v != %v", i, wn[i], testWn[i]) + } + if i := compareFloat32Slices(fn[0:], testFn); i >= 0 { + t.Errorf("fn disagrees at index %v; %v != %v", i, fn[i], testFn[i]) + } +} + +func TestExpTables(t *testing.T) { + testKe, testWe, testFe := initExp() + if i := compareUint32Slices(ke[0:], testKe); i >= 0 { + t.Errorf("ke disagrees at index %v; %v != %v", i, ke[i], testKe[i]) + } + if i := compareFloat32Slices(we[0:], testWe); i >= 0 { + t.Errorf("we disagrees at index %v; %v != %v", i, we[i], testWe[i]) + } + if i := compareFloat32Slices(fe[0:], testFe); i >= 0 { + t.Errorf("fe disagrees at index %v; %v != %v", i, fe[i], testFe[i]) + } +} + +func hasSlowFloatingPoint() bool { + switch runtime.GOARCH { + case "arm": + return os.Getenv("GOARM") == "5" + case "mips", "mipsle", "mips64", "mips64le": + // Be conservative and assume that all mips boards + // have emulated floating point. + // TODO: detect what it actually has. + return true + } + return false +} + +func TestFloat32(t *testing.T) { + // For issue 6721, the problem came after 7533753 calls, so check 10e6. + num := int(10e6) + // But do the full amount only on builders (not locally). + // But ARM5 floating point emulation is slow (Issue 10749), so + // do less for that builder: + if testing.Short() && hasSlowFloatingPoint() { // TODO: (testenv.Builder() == "" || hasSlowFloatingPoint()) + num /= 100 // 1.72 seconds instead of 172 seconds + } + + r := New(NewSource(1)) + for ct := 0; ct < num; ct++ { + f := r.Float32() + if f >= 1 { + t.Fatal("Float32() should be in range [0,1). ct:", ct, "f:", f) + } + } +} + +func testReadUniformity(t *testing.T, n int, seed uint64) { + r := New(NewSource(seed)) + buf := make([]byte, n) + nRead, err := r.Read(buf) + if err != nil { + t.Errorf("Read err %v", err) + } + if nRead != n { + t.Errorf("Read returned unexpected n; %d != %d", nRead, n) + } + + // Expect a uniform distribution of byte values, which lie in [0, 255]. + var ( + mean = 255.0 / 2 + stddev = 256.0 / math.Sqrt(12.0) + errorScale = stddev / math.Sqrt(float64(n)) + ) + + expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.08 * errorScale} + + // Cast bytes as floats to use the common distribution-validity checks. + samples := make([]float64, n) + for i, val := range buf { + samples[i] = float64(val) + } + // Make sure that the entire set matches the expected distribution. + checkSampleDistribution(t, samples, expected) +} + +func TestReadUniformity(t *testing.T) { + testBufferSizes := []int{ + 2, 4, 7, 64, 1024, 1 << 16, 1 << 20, + } + for _, seed := range testSeeds { + for _, n := range testBufferSizes { + testReadUniformity(t, n, seed) + } + } +} + +func TestReadEmpty(t *testing.T) { + r := New(NewSource(1)) + buf := make([]byte, 0) + n, err := r.Read(buf) + if err != nil { + t.Errorf("Read err into empty buffer; %v", err) + } + if n != 0 { + t.Errorf("Read into empty buffer returned unexpected n of %d", n) + } +} + +func TestReadByOneByte(t *testing.T) { + r := New(NewSource(1)) + b1 := make([]byte, 100) + _, err := io.ReadFull(iotest.OneByteReader(r), b1) + if err != nil { + t.Errorf("read by one byte: %v", err) + } + r = New(NewSource(1)) + b2 := make([]byte, 100) + _, err = r.Read(b2) + if err != nil { + t.Errorf("read: %v", err) + } + if !bytes.Equal(b1, b2) { + t.Errorf("read by one byte vs single read:\n%x\n%x", b1, b2) + } +} + +func TestReadSeedReset(t *testing.T) { + r := New(NewSource(42)) + b1 := make([]byte, 128) + _, err := r.Read(b1) + if err != nil { + t.Errorf("read: %v", err) + } + r.Seed(42) + b2 := make([]byte, 128) + _, err = r.Read(b2) + if err != nil { + t.Errorf("read: %v", err) + } + if !bytes.Equal(b1, b2) { + t.Errorf("mismatch after re-seed:\n%x\n%x", b1, b2) + } +} + +func TestShuffleSmall(t *testing.T) { + // Check that Shuffle allows n=0 and n=1, but that swap is never called for them. + r := New(NewSource(1)) + for n := 0; n <= 1; n++ { + r.Shuffle(n, func(i, j int) { t.Fatalf("swap called, n=%d i=%d j=%d", n, i, j) }) + } +} + +func TestPCGSourceRoundTrip(t *testing.T) { + var src PCGSource + src.Seed(uint64(time.Now().Unix())) + + src.Uint64() // Step PRNG once to makes sure high and low are different. + + buf, err := src.MarshalBinary() + if err != nil { + t.Errorf("unexpected error marshaling state: %v", err) + } + + var dst PCGSource + // Get dst into a non-zero state. + dst.Seed(1) + for i := 0; i < 10; i++ { + dst.Uint64() + } + + err = dst.UnmarshalBinary(buf) + if err != nil { + t.Errorf("unexpected error unmarshaling state: %v", err) + } + + if dst != src { + t.Errorf("mismatch between generator states: got:%+v want:%+v", dst, src) + } +} + +// Benchmarks + +func BenchmarkSource(b *testing.B) { + rng := NewSource(0) + for n := b.N; n > 0; n-- { + rng.Uint64() + } +} + +func BenchmarkInt63Threadsafe(b *testing.B) { + for n := b.N; n > 0; n-- { + Int63() + } +} + +func BenchmarkInt63ThreadsafeParallel(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + Int63() + } + }) +} + +func BenchmarkInt63Unthreadsafe(b *testing.B) { + r := New(NewSource(1)) + for n := b.N; n > 0; n-- { + r.Int63() + } +} + +func BenchmarkIntn1000(b *testing.B) { + r := New(NewSource(1)) + for n := b.N; n > 0; n-- { + r.Intn(1000) + } +} + +func BenchmarkInt63n1000(b *testing.B) { + r := New(NewSource(1)) + for n := b.N; n > 0; n-- { + r.Int63n(1000) + } +} + +func BenchmarkInt31n1000(b *testing.B) { + r := New(NewSource(1)) + for n := b.N; n > 0; n-- { + r.Int31n(1000) + } +} + +func BenchmarkFloat32(b *testing.B) { + r := New(NewSource(1)) + for n := b.N; n > 0; n-- { + r.Float32() + } +} + +func BenchmarkFloat64(b *testing.B) { + r := New(NewSource(1)) + for n := b.N; n > 0; n-- { + r.Float64() + } +} + +func BenchmarkPerm3(b *testing.B) { + r := New(NewSource(1)) + for n := b.N; n > 0; n-- { + r.Perm(3) + } +} + +func BenchmarkPerm30(b *testing.B) { + r := New(NewSource(1)) + for n := b.N; n > 0; n-- { + r.Perm(30) + } +} + +func BenchmarkPerm30ViaShuffle(b *testing.B) { + r := New(NewSource(1)) + for n := b.N; n > 0; n-- { + p := make([]int, 30) + for i := range p { + p[i] = i + } + r.Shuffle(30, func(i, j int) { p[i], p[j] = p[j], p[i] }) + } +} + +// BenchmarkShuffleOverhead uses a minimal swap function +// to measure just the shuffling overhead. +func BenchmarkShuffleOverhead(b *testing.B) { + r := New(NewSource(1)) + for n := b.N; n > 0; n-- { + r.Shuffle(52, func(i, j int) { + if i < 0 || i >= 52 || j < 0 || j >= 52 { + b.Fatalf("bad swap(%d, %d)", i, j) + } + }) + } +} + +func BenchmarkRead3(b *testing.B) { + r := New(NewSource(1)) + buf := make([]byte, 3) + b.ResetTimer() + for n := b.N; n > 0; n-- { + r.Read(buf) + } +} + +func BenchmarkRead64(b *testing.B) { + r := New(NewSource(1)) + buf := make([]byte, 64) + b.ResetTimer() + for n := b.N; n > 0; n-- { + r.Read(buf) + } +} + +func BenchmarkRead1000(b *testing.B) { + r := New(NewSource(1)) + buf := make([]byte, 1000) + b.ResetTimer() + for n := b.N; n > 0; n-- { + r.Read(buf) + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/regress_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/regress_test.go new file mode 100644 index 0000000..e3a8f6e --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/regress_test.go @@ -0,0 +1,490 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test that random number sequences generated by a specific seed +// do not change from version to version. +// +// If the generator changes, the golden outputs need updating, and +// client programs may break. Although the desire for compatibility +// is not as stringent as in the original math/rand package, +// when possible avoid changing the generator. + +package rand_test + +import ( + "flag" + "fmt" + "reflect" + "testing" + + . "golang.org/x/exp/rand" +) + +var printgolden = flag.Bool("printgolden", false, "print golden results for regression test") + +// TestSource verifies that the output of the default Source is locked down. +func TestSourceRegress(t *testing.T) { + src := NewSource(1) + var got [20]uint64 + for i := range got { + got[i] = src.Uint64() + } + want := [20]uint64{ + 0x34e936394905d167, + 0x817c0ef62fe4c731, + 0x937987e6e24f5a40, + 0x0c0a8307fe226199, + 0xf96363568d8bab56, + 0xbaef3af36bd02620, + 0x8f18e416eb6b936b, + 0x05a43fc149f3a67a, + 0xdab012eb3ce01697, + 0xf76c495a133c6aa9, + 0x304b24c5040ce457, + 0x47d77e0abb413159, + 0x52a810fa9e452f04, + 0x2d24b66380cf4780, + 0x5ec7691b92018ef5, + 0x5076dfa749261ea0, + 0xac8f11ad3941d213, + 0x13fa8d67de91db25, + 0xb50883a9893274eb, + 0xeb8f59263f9109ac, + } + if got != want { + t.Errorf("got:\n\t%#016x\nwant:\n\t%#016x", got, want) + if *printgolden { + for _, x := range got { + fmt.Printf("\t\t%#016x,\n", x) + } + } + } +} + +// TestRegress validates that the output stream is locked down, for instance so +// optimizations do not change the output. It iterates over methods of the +// Rand type to find functions to evaluate and checks the first 20 results +// against the golden results. +func TestRegress(t *testing.T) { + var int32s = []int32{1, 10, 32, 1 << 20, 1<<20 + 1, 1000000000, 1 << 30, 1<<31 - 2, 1<<31 - 1} + var int64s = []int64{1, 10, 32, 1 << 20, 1<<20 + 1, 1000000000, 1 << 30, 1<<31 - 2, 1<<31 - 1, 1000000000000000000, 1 << 60, 1<<63 - 2, 1<<63 - 1} + var uint64s = []uint64{1, 10, 32, 1 << 20, 1<<20 + 1, 1000000000, 1 << 30, 1<<31 - 2, 1<<31 - 1, 1000000000000000000, 1 << 60, 1<<64 - 2, 1<<64 - 1} + var permSizes = []int{0, 1, 5, 8, 9, 10, 16} + var readBufferSizes = []int{1, 7, 8, 9, 10} + r := New(NewSource(0)) + + rv := reflect.ValueOf(r) + n := rv.NumMethod() + p := 0 + if *printgolden { + fmt.Printf("var regressGolden = []interface{}{\n") + } + for i := 0; i < n; i++ { + m := rv.Type().Method(i) + mv := rv.Method(i) + mt := mv.Type() + if mt.NumOut() == 0 { + continue + } + r.Seed(0) + if *printgolden && i > 0 { + fmt.Println() + } + for repeat := 0; repeat < 20; repeat++ { + var args []reflect.Value + var argstr string + if mt.NumIn() == 1 { + var x interface{} + switch mt.In(0).Kind() { + default: + t.Fatalf("unexpected argument type for r.%s", m.Name) + + case reflect.Int: + if m.Name == "Perm" { + x = permSizes[repeat%len(permSizes)] + break + } + big := int64s[repeat%len(int64s)] + if int64(int(big)) != big { + r.Int63n(big) // what would happen on 64-bit machine, to keep stream in sync + if *printgolden { + fmt.Printf("\tskipped, // must run printgolden on 64-bit machine\n") + } + p++ + continue + } + x = int(big) + + case reflect.Int32: + x = int32s[repeat%len(int32s)] + + case reflect.Int64: + x = int64s[repeat%len(int64s)] + + case reflect.Uint64: + x = uint64s[repeat%len(uint64s)] + + case reflect.Slice: + if m.Name == "Read" { + n := readBufferSizes[repeat%len(readBufferSizes)] + x = make([]byte, n) + } + } + argstr = fmt.Sprint(x) + args = append(args, reflect.ValueOf(x)) + } + + var out interface{} + out = mv.Call(args)[0].Interface() + if m.Name == "Int" || m.Name == "Intn" { + out = int64(out.(int)) + } + if m.Name == "Read" { + out = args[0].Interface().([]byte) + } + if *printgolden { + var val string + big := int64(1 << 60) + if int64(int(big)) != big && (m.Name == "Int" || m.Name == "Intn") { + // 32-bit machine cannot print 64-bit results + val = "truncated" + } else if reflect.TypeOf(out).Kind() == reflect.Slice { + val = fmt.Sprintf("%#v", out) + } else { + val = fmt.Sprintf("%T(%v)", out, out) + } + fmt.Printf("\t%s, // %s(%s)\n", val, m.Name, argstr) + } else { + want := regressGolden[p] + if m.Name == "Int" { + want = int64(int(uint(want.(int64)) << 1 >> 1)) + } + if !reflect.DeepEqual(out, want) { + t.Errorf("r.%s(%s) = %v, want %v", m.Name, argstr, out, want) + } + } + p++ + } + } + if *printgolden { + fmt.Printf("}\n") + } +} + +var regressGolden = []interface{}{ + float64(0.6279600685109523), // ExpFloat64() + float64(0.16198826513357806), // ExpFloat64() + float64(0.007880404652650552), // ExpFloat64() + float64(0.41649788761745654), // ExpFloat64() + float64(1.6958707787276301), // ExpFloat64() + float64(2.7227327706138036), // ExpFloat64() + float64(2.4235600263079657), // ExpFloat64() + float64(1.277967771105418), // ExpFloat64() + float64(0.7111660437031769), // ExpFloat64() + float64(0.23090401427981888), // ExpFloat64() + float64(1.4746763588379928), // ExpFloat64() + float64(1.4868726779832278), // ExpFloat64() + float64(0.1686257242078103), // ExpFloat64() + float64(0.2732721816228957), // ExpFloat64() + float64(0.4644536065869748), // ExpFloat64() + float64(0.01319850986379164), // ExpFloat64() + float64(0.7184492551742854), // ExpFloat64() + float64(0.1913536422195827), // ExpFloat64() + float64(0.16034475958495667), // ExpFloat64() + float64(0.40599859014785644), // ExpFloat64() + + float32(0.7979972), // Float32() + float32(0.7725961), // Float32() + float32(0.21894403), // Float32() + float32(0.96194494), // Float32() + float32(0.2915732), // Float32() + float32(0.59569645), // Float32() + float32(0.99596655), // Float32() + float32(0.4979039), // Float32() + float32(0.98148686), // Float32() + float32(0.01380035), // Float32() + float32(0.086487144), // Float32() + float32(0.6114401), // Float32() + float32(0.71081316), // Float32() + float32(0.6342346), // Float32() + float32(0.008082573), // Float32() + float32(0.33020085), // Float32() + float32(0.032625034), // Float32() + float32(0.9278005), // Float32() + float32(0.34497985), // Float32() + float32(0.66506875), // Float32() + + float64(0.797997151016231), // Float64() + float64(0.7725961454373316), // Float64() + float64(0.21894402538580782), // Float64() + float64(0.9619449481780457), // Float64() + float64(0.2915731877602916), // Float64() + float64(0.5956964580775652), // Float64() + float64(0.9959665347028619), // Float64() + float64(0.49790390966591147), // Float64() + float64(0.9814868602566785), // Float64() + float64(0.013800350332924483), // Float64() + float64(0.08648714463652596), // Float64() + float64(0.6114401479210267), // Float64() + float64(0.7108131531183706), // Float64() + float64(0.6342346133706837), // Float64() + float64(0.008082572853887138), // Float64() + float64(0.3302008651926287), // Float64() + float64(0.03262503454637655), // Float64() + float64(0.9278004634858956), // Float64() + float64(0.3449798628384906), // Float64() + float64(0.665068719316529), // Float64() + + int64(5474557666971700975), // Int() + int64(5591422465364813936), // Int() + int64(74029666500212977), // Int() + int64(8088122161323000979), // Int() + int64(7298457654139700474), // Int() + int64(1590632625527662686), // Int() + int64(9052198920789078554), // Int() + int64(7381380909356947872), // Int() + int64(1738222704626512495), // Int() + int64(3278744831230954970), // Int() + int64(7062423222661652521), // Int() + int64(6715870808026712034), // Int() + int64(528819992478005418), // Int() + int64(2284534088986354339), // Int() + int64(945828723091990082), // Int() + int64(3813019469742317492), // Int() + int64(1369388146907482806), // Int() + int64(7367238674766648970), // Int() + int64(8217673022687244206), // Int() + int64(3185531743396549562), // Int() + + int32(1711064216), // Int31() + int32(650927245), // Int31() + int32(8618187), // Int31() + int32(941581344), // Int31() + int32(1923394120), // Int31() + int32(1258915833), // Int31() + int32(1053814650), // Int31() + int32(859305834), // Int31() + int32(1276097579), // Int31() + int32(1455437958), // Int31() + int32(1895916096), // Int31() + int32(781830261), // Int31() + int32(61562749), // Int31() + int32(265954771), // Int31() + int32(1183850779), // Int31() + int32(443893888), // Int31() + int32(1233159585), // Int31() + int32(857659461), // Int31() + int32(956663049), // Int31() + int32(370844703), // Int31() + + int32(0), // Int31n(1) + int32(6), // Int31n(10) + int32(17), // Int31n(32) + int32(1000595), // Int31n(1048576) + int32(424333), // Int31n(1048577) + int32(382438494), // Int31n(1000000000) + int32(902738458), // Int31n(1073741824) + int32(1204933878), // Int31n(2147483646) + int32(1376191263), // Int31n(2147483647) + int32(0), // Int31n(1) + int32(9), // Int31n(10) + int32(2), // Int31n(32) + int32(440490), // Int31n(1048576) + int32(176312), // Int31n(1048577) + int32(946765890), // Int31n(1000000000) + int32(665034676), // Int31n(1073741824) + int32(1947285452), // Int31n(2147483646) + int32(1702344608), // Int31n(2147483647) + int32(0), // Int31n(1) + int32(2), // Int31n(10) + + int64(5474557666971700975), // Int63() + int64(5591422465364813936), // Int63() + int64(74029666500212977), // Int63() + int64(8088122161323000979), // Int63() + int64(7298457654139700474), // Int63() + int64(1590632625527662686), // Int63() + int64(9052198920789078554), // Int63() + int64(7381380909356947872), // Int63() + int64(1738222704626512495), // Int63() + int64(3278744831230954970), // Int63() + int64(7062423222661652521), // Int63() + int64(6715870808026712034), // Int63() + int64(528819992478005418), // Int63() + int64(2284534088986354339), // Int63() + int64(945828723091990082), // Int63() + int64(3813019469742317492), // Int63() + int64(1369388146907482806), // Int63() + int64(7367238674766648970), // Int63() + int64(8217673022687244206), // Int63() + int64(3185531743396549562), // Int63() + + int64(0), // Int63n(1) + int64(6), // Int63n(10) + int64(17), // Int63n(32) + int64(1000595), // Int63n(1048576) + int64(424333), // Int63n(1048577) + int64(382438494), // Int63n(1000000000) + int64(902738458), // Int63n(1073741824) + int64(1204933878), // Int63n(2147483646) + int64(1376191263), // Int63n(2147483647) + int64(502116868085730778), // Int63n(1000000000000000000) + int64(144894195020570665), // Int63n(1152921504606846976) + int64(6715870808026712034), // Int63n(9223372036854775806) + int64(528819992478005418), // Int63n(9223372036854775807) + int64(0), // Int63n(1) + int64(0), // Int63n(10) + int64(20), // Int63n(32) + int64(854710), // Int63n(1048576) + int64(649893), // Int63n(1048577) + int64(687244206), // Int63n(1000000000) + int64(836883386), // Int63n(1073741824) + + int64(0), // Intn(1) + int64(6), // Intn(10) + int64(17), // Intn(32) + int64(1000595), // Intn(1048576) + int64(424333), // Intn(1048577) + int64(382438494), // Intn(1000000000) + int64(902738458), // Intn(1073741824) + int64(1204933878), // Intn(2147483646) + int64(1376191263), // Intn(2147483647) + int64(502116868085730778), // Intn(1000000000000000000) + int64(144894195020570665), // Intn(1152921504606846976) + int64(6715870808026712034), // Intn(9223372036854775806) + int64(528819992478005418), // Intn(9223372036854775807) + int64(0), // Intn(1) + int64(0), // Intn(10) + int64(20), // Intn(32) + int64(854710), // Intn(1048576) + int64(649893), // Intn(1048577) + int64(687244206), // Intn(1000000000) + int64(836883386), // Intn(1073741824) + + float64(-0.5410658516792047), // NormFloat64() + float64(0.615296849055287), // NormFloat64() + float64(0.007477442280032887), // NormFloat64() + float64(1.3443892057169684), // NormFloat64() + float64(-0.17508902754863512), // NormFloat64() + float64(-2.03494397556937), // NormFloat64() + float64(2.5213558871972306), // NormFloat64() + float64(1.4572921639613627), // NormFloat64() + float64(-1.5164961164210644), // NormFloat64() + float64(-0.4861150771891445), // NormFloat64() + float64(-0.8699409548614199), // NormFloat64() + float64(1.6271559815452794), // NormFloat64() + float64(0.1659465769926195), // NormFloat64() + float64(0.2921716191987018), // NormFloat64() + float64(-1.2550269636927838), // NormFloat64() + float64(0.11257973349467548), // NormFloat64() + float64(0.5437525915836436), // NormFloat64() + float64(0.781754430770282), // NormFloat64() + float64(0.5201256313962235), // NormFloat64() + float64(1.3826174159276245), // NormFloat64() + + []int{}, // Perm(0) + []int{0}, // Perm(1) + []int{0, 2, 3, 1, 4}, // Perm(5) + []int{5, 6, 3, 7, 4, 2, 0, 1}, // Perm(8) + []int{8, 4, 5, 2, 7, 3, 0, 6, 1}, // Perm(9) + []int{6, 1, 5, 3, 2, 9, 7, 0, 8, 4}, // Perm(10) + []int{12, 5, 1, 9, 15, 7, 13, 6, 10, 11, 8, 0, 4, 2, 14, 3}, // Perm(16) + []int{}, // Perm(0) + []int{0}, // Perm(1) + []int{0, 2, 3, 4, 1}, // Perm(5) + []int{3, 2, 7, 4, 0, 6, 5, 1}, // Perm(8) + []int{0, 6, 2, 1, 3, 7, 5, 8, 4}, // Perm(9) + []int{2, 5, 6, 4, 7, 3, 0, 8, 1, 9}, // Perm(10) + []int{3, 6, 5, 4, 9, 15, 13, 7, 1, 11, 10, 8, 12, 0, 2, 14}, // Perm(16) + []int{}, // Perm(0) + []int{0}, // Perm(1) + []int{2, 4, 3, 1, 0}, // Perm(5) + []int{1, 6, 7, 5, 4, 3, 2, 0}, // Perm(8) + []int{7, 6, 8, 2, 0, 1, 3, 4, 5}, // Perm(9) + []int{2, 9, 7, 1, 5, 4, 0, 6, 8, 3}, // Perm(10) + + []byte{0xef}, // Read([0]) + []byte{0x4e, 0x3d, 0x52, 0x31, 0x89, 0xf9, 0xcb}, // Read([0 0 0 0 0 0 0]) + []byte{0x70, 0x68, 0x35, 0x8d, 0x1b, 0xb9, 0x98, 0x4d}, // Read([0 0 0 0 0 0 0 0]) + []byte{0xf1, 0xf8, 0x95, 0xe6, 0x96, 0x1, 0x7, 0x1, 0x93}, // Read([0 0 0 0 0 0 0 0 0]) + []byte{0x44, 0x9f, 0xc5, 0x40, 0xc8, 0x3e, 0x70, 0xfa, 0x44, 0x3a}, // Read([0 0 0 0 0 0 0 0 0 0]) + []byte{0x4b}, // Read([0]) + []byte{0x91, 0x54, 0x49, 0xe5, 0x5e, 0x28, 0xb9}, // Read([0 0 0 0 0 0 0]) + []byte{0x4, 0xf2, 0xf, 0x13, 0x96, 0x1a, 0xb2, 0xce}, // Read([0 0 0 0 0 0 0 0]) + []byte{0x35, 0xf5, 0xde, 0x9f, 0x7d, 0xa0, 0x19, 0x12, 0x2e}, // Read([0 0 0 0 0 0 0 0 0]) + []byte{0xd4, 0xee, 0x6f, 0x66, 0x6f, 0x32, 0xc8, 0x21, 0x57, 0x68}, // Read([0 0 0 0 0 0 0 0 0 0]) + []byte{0x1f}, // Read([0]) + []byte{0x98, 0xda, 0x4d, 0xab, 0x6e, 0xd, 0x71}, // Read([0 0 0 0 0 0 0]) + []byte{0x80, 0xad, 0x29, 0xa0, 0x37, 0xb0, 0x80, 0xc4}, // Read([0 0 0 0 0 0 0 0]) + []byte{0x2, 0xe2, 0xe2, 0x7, 0xd9, 0xed, 0xea, 0x90, 0x33}, // Read([0 0 0 0 0 0 0 0 0]) + []byte{0x5d, 0xaa, 0xb8, 0xc6, 0x39, 0xfb, 0xbe, 0x56, 0x7, 0xa3}, // Read([0 0 0 0 0 0 0 0 0 0]) + []byte{0x62}, // Read([0]) + []byte{0x4d, 0x63, 0xa6, 0x4b, 0xb4, 0x1f, 0x42}, // Read([0 0 0 0 0 0 0]) + []byte{0x66, 0x42, 0x62, 0x36, 0x42, 0x20, 0x8d, 0xb4}, // Read([0 0 0 0 0 0 0 0]) + []byte{0x9f, 0xa3, 0x67, 0x1, 0x91, 0xea, 0x34, 0xb6, 0xa}, // Read([0 0 0 0 0 0 0 0 0]) + []byte{0xd, 0xa8, 0x43, 0xb, 0x1, 0x93, 0x8a, 0x56, 0xfc, 0x98}, // Read([0 0 0 0 0 0 0 0 0 0]) + + uint32(3422128433), // Uint32() + uint32(1301854491), // Uint32() + uint32(17236374), // Uint32() + uint32(1883162688), // Uint32() + uint32(3846788241), // Uint32() + uint32(2517831666), // Uint32() + uint32(2107629301), // Uint32() + uint32(1718611668), // Uint32() + uint32(2552195159), // Uint32() + uint32(2910875917), // Uint32() + uint32(3791832192), // Uint32() + uint32(1563660522), // Uint32() + uint32(123125499), // Uint32() + uint32(531909542), // Uint32() + uint32(2367701558), // Uint32() + uint32(887787777), // Uint32() + uint32(2466319171), // Uint32() + uint32(1715318922), // Uint32() + uint32(1913326099), // Uint32() + uint32(741689406), // Uint32() + + uint64(14697929703826476783), // Uint64() + uint64(5591422465364813936), // Uint64() + uint64(74029666500212977), // Uint64() + uint64(8088122161323000979), // Uint64() + uint64(16521829690994476282), // Uint64() + uint64(10814004662382438494), // Uint64() + uint64(9052198920789078554), // Uint64() + uint64(7381380909356947872), // Uint64() + uint64(10961594741481288303), // Uint64() + uint64(12502116868085730778), // Uint64() + uint64(16285795259516428329), // Uint64() + uint64(6715870808026712034), // Uint64() + uint64(528819992478005418), // Uint64() + uint64(2284534088986354339), // Uint64() + uint64(10169200759946765890), // Uint64() + uint64(3813019469742317492), // Uint64() + uint64(10592760183762258614), // Uint64() + uint64(7367238674766648970), // Uint64() + uint64(8217673022687244206), // Uint64() + uint64(3185531743396549562), // Uint64() + + uint64(0), // Uint64n(1) + uint64(6), // Uint64n(10) + uint64(17), // Uint64n(32) + uint64(1000595), // Uint64n(1048576) + uint64(424333), // Uint64n(1048577) + uint64(382438494), // Uint64n(1000000000) + uint64(902738458), // Uint64n(1073741824) + uint64(1204933878), // Uint64n(2147483646) + uint64(1376191263), // Uint64n(2147483647) + uint64(502116868085730778), // Uint64n(1000000000000000000) + uint64(144894195020570665), // Uint64n(1152921504606846976) + uint64(6715870808026712034), // Uint64n(18446744073709551614) + uint64(528819992478005418), // Uint64n(18446744073709551615) + uint64(0), // Uint64n(1) + uint64(0), // Uint64n(10) + uint64(20), // Uint64n(32) + uint64(854710), // Uint64n(1048576) + uint64(649893), // Uint64n(1048577) + uint64(687244206), // Uint64n(1000000000) + uint64(836883386), // Uint64n(1073741824) +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/rng.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/rng.go new file mode 100644 index 0000000..9b79108 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/rng.go @@ -0,0 +1,91 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package rand + +import ( + "encoding/binary" + "io" + "math/bits" +) + +// PCGSource is an implementation of a 64-bit permuted congruential +// generator as defined in +// +// PCG: A Family of Simple Fast Space-Efficient Statistically Good +// Algorithms for Random Number Generation +// Melissa E. O’Neill, Harvey Mudd College +// http://www.pcg-random.org/pdf/toms-oneill-pcg-family-v1.02.pdf +// +// The generator here is the congruential generator PCG XSL RR 128/64 (LCG) +// as found in the software available at http://www.pcg-random.org/. +// It has period 2^128 with 128 bits of state, producing 64-bit values. +// Is state is represented by two uint64 words. +type PCGSource struct { + low uint64 + high uint64 +} + +const ( + maxUint32 = (1 << 32) - 1 + + multiplier = 47026247687942121848144207491837523525 + mulHigh = multiplier >> 64 + mulLow = multiplier & maxUint64 + + increment = 117397592171526113268558934119004209487 + incHigh = increment >> 64 + incLow = increment & maxUint64 + + // TODO: Use these? + initializer = 245720598905631564143578724636268694099 + initHigh = initializer >> 64 + initLow = initializer & maxUint64 +) + +// Seed uses the provided seed value to initialize the generator to a deterministic state. +func (pcg *PCGSource) Seed(seed uint64) { + pcg.low = seed + pcg.high = seed // TODO: What is right? +} + +// Uint64 returns a pseudo-random 64-bit unsigned integer as a uint64. +func (pcg *PCGSource) Uint64() uint64 { + pcg.multiply() + pcg.add() + // XOR high and low 64 bits together and rotate right by high 6 bits of state. + return bits.RotateLeft64(pcg.high^pcg.low, -int(pcg.high>>58)) +} + +func (pcg *PCGSource) add() { + var carry uint64 + pcg.low, carry = bits.Add64(pcg.low, incLow, 0) + pcg.high, _ = bits.Add64(pcg.high, incHigh, carry) +} + +func (pcg *PCGSource) multiply() { + hi, lo := bits.Mul64(pcg.low, mulLow) + hi += pcg.high * mulLow + hi += pcg.low * mulHigh + pcg.low = lo + pcg.high = hi +} + +// MarshalBinary returns the binary representation of the current state of the generator. +func (pcg *PCGSource) MarshalBinary() ([]byte, error) { + var buf [16]byte + binary.BigEndian.PutUint64(buf[:8], pcg.high) + binary.BigEndian.PutUint64(buf[8:], pcg.low) + return buf[:], nil +} + +// UnmarshalBinary sets the state of the generator to the state represented in data. +func (pcg *PCGSource) UnmarshalBinary(data []byte) error { + if len(data) < 16 { + return io.ErrUnexpectedEOF + } + pcg.low = binary.BigEndian.Uint64(data[8:]) + pcg.high = binary.BigEndian.Uint64(data[:8]) + return nil +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/zipf.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/zipf.go new file mode 100644 index 0000000..f04c814 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/rand/zipf.go @@ -0,0 +1,77 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// W.Hormann, G.Derflinger: +// "Rejection-Inversion to Generate Variates +// from Monotone Discrete Distributions" +// http://eeyore.wu-wien.ac.at/papers/96-04-04.wh-der.ps.gz + +package rand + +import "math" + +// A Zipf generates Zipf distributed variates. +type Zipf struct { + r *Rand + imax float64 + v float64 + q float64 + s float64 + oneminusQ float64 + oneminusQinv float64 + hxm float64 + hx0minusHxm float64 +} + +func (z *Zipf) h(x float64) float64 { + return math.Exp(z.oneminusQ*math.Log(z.v+x)) * z.oneminusQinv +} + +func (z *Zipf) hinv(x float64) float64 { + return math.Exp(z.oneminusQinv*math.Log(z.oneminusQ*x)) - z.v +} + +// NewZipf returns a Zipf variate generator. +// The generator generates values k ∈ [0, imax] +// such that P(k) is proportional to (v + k) ** (-s). +// Requirements: s > 1 and v >= 1. +func NewZipf(r *Rand, s float64, v float64, imax uint64) *Zipf { + z := new(Zipf) + if s <= 1.0 || v < 1 { + return nil + } + z.r = r + z.imax = float64(imax) + z.v = v + z.q = s + z.oneminusQ = 1.0 - z.q + z.oneminusQinv = 1.0 / z.oneminusQ + z.hxm = z.h(z.imax + 0.5) + z.hx0minusHxm = z.h(0.5) - math.Exp(math.Log(z.v)*(-z.q)) - z.hxm + z.s = 1 - z.hinv(z.h(1.5)-math.Exp(-z.q*math.Log(z.v+1.0))) + return z +} + +// Uint64 returns a value drawn from the Zipf distribution described +// by the Zipf object. +func (z *Zipf) Uint64() uint64 { + if z == nil { + panic("rand: nil Zipf") + } + k := 0.0 + + for { + r := z.r.Float64() // r on [0,1] + ur := z.hxm + r*z.hx0minusHxm + x := z.hinv(ur) + k = math.Floor(x + 0.5) + if k-x <= z.s { + break + } + if ur >= z.h(k+0.5)-math.Exp(-math.Log(k+z.v)*z.q) { + break + } + } + return uint64(k) +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/README b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/README new file mode 100644 index 0000000..18ad8fd --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/README @@ -0,0 +1,4 @@ +This directory holds programs from +"The Computer Language Benchmarks Game". +They used to be in the main Go distribution in test/bench/shootout +but are now only of historical value. diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/binary-tree-freelist.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/binary-tree-freelist.go new file mode 100644 index 0000000..e4c3e8a --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/binary-tree-freelist.go @@ -0,0 +1,132 @@ +//go:build ignore +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* The Computer Language Benchmarks Game + * http://shootout.alioth.debian.org/ + * + * contributed by The Go Authors. + * based on C program by Kevin Carson + */ + +package main + +import ( + "flag" + "fmt" +) + +var n = flag.Int("n", 15, "depth") + +type Node struct { + item int + left, right *Node +} + +type Arena struct { + head *Node +} + +var arena Arena + +func (n *Node) free() { + if n.left != nil { + n.left.free() + } + if n.right != nil { + n.right.free() + } + n.left = arena.head + arena.head = n +} + +func (a *Arena) New(item int, left, right *Node) *Node { + if a.head == nil { + nodes := make([]Node, 3<<uint(*n)) + for i := 0; i < len(nodes)-1; i++ { + nodes[i].left = &nodes[i+1] + } + a.head = &nodes[0] + } + n := a.head + a.head = a.head.left + n.item = item + n.left = left + n.right = right + return n +} + +func bottomUpTree(item, depth int) *Node { + if depth <= 0 { + return arena.New(item, nil, nil) + } + return arena.New(item, bottomUpTree(2*item-1, depth-1), bottomUpTree(2*item, depth-1)) +} + +func (n *Node) itemCheck() int { + if n.left == nil { + return n.item + } + return n.item + n.left.itemCheck() - n.right.itemCheck() +} + +const minDepth = 4 + +func main() { + flag.Parse() + + maxDepth := *n + if minDepth+2 > *n { + maxDepth = minDepth + 2 + } + stretchDepth := maxDepth + 1 + + check := bottomUpTree(0, stretchDepth).itemCheck() + fmt.Printf("stretch tree of depth %d\t check: %d\n", stretchDepth, check) + + longLivedTree := bottomUpTree(0, maxDepth) + + for depth := minDepth; depth <= maxDepth; depth += 2 { + iterations := 1 << uint(maxDepth-depth+minDepth) + check = 0 + + for i := 1; i <= iterations; i++ { + t := bottomUpTree(i, depth) + check += t.itemCheck() + t.free() + t = bottomUpTree(-i, depth) + check += t.itemCheck() + t.free() + } + fmt.Printf("%d\t trees of depth %d\t check: %d\n", iterations*2, depth, check) + } + fmt.Printf("long lived tree of depth %d\t check: %d\n", maxDepth, longLivedTree.itemCheck()) +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/binary-tree-freelist.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/binary-tree-freelist.txt new file mode 100644 index 0000000..f8286dd --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/binary-tree-freelist.txt @@ -0,0 +1,8 @@ +stretch tree of depth 16 check: -1 +65536 trees of depth 4 check: -65536 +16384 trees of depth 6 check: -16384 +4096 trees of depth 8 check: -4096 +1024 trees of depth 10 check: -1024 +256 trees of depth 12 check: -256 +64 trees of depth 14 check: -64 +long lived tree of depth 15 check: -1 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/binary-tree.c b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/binary-tree.c new file mode 100644 index 0000000..a909246 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/binary-tree.c @@ -0,0 +1,166 @@ +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* The Computer Language Shootout Benchmarks + http://shootout.alioth.debian.org/ + + contributed by Kevin Carson + compilation: + gcc -O3 -fomit-frame-pointer -funroll-loops -static binary-trees.c -lm + icc -O3 -ip -unroll -static binary-trees.c -lm +*/ + +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + + +typedef struct tn { + struct tn* left; + struct tn* right; + long item; +} treeNode; + + +treeNode* NewTreeNode(treeNode* left, treeNode* right, long item) +{ + treeNode* new; + + new = (treeNode*)malloc(sizeof(treeNode)); + + new->left = left; + new->right = right; + new->item = item; + + return new; +} /* NewTreeNode() */ + + +long ItemCheck(treeNode* tree) +{ + if (tree->left == NULL) + return tree->item; + else + return tree->item + ItemCheck(tree->left) - ItemCheck(tree->right); +} /* ItemCheck() */ + + +treeNode* BottomUpTree(long item, unsigned depth) +{ + if (depth > 0) + return NewTreeNode + ( + BottomUpTree(2 * item - 1, depth - 1), + BottomUpTree(2 * item, depth - 1), + item + ); + else + return NewTreeNode(NULL, NULL, item); +} /* BottomUpTree() */ + + +void DeleteTree(treeNode* tree) +{ + if (tree->left != NULL) + { + DeleteTree(tree->left); + DeleteTree(tree->right); + } + + free(tree); +} /* DeleteTree() */ + + +int main(int argc, char* argv[]) +{ + unsigned N, depth, minDepth, maxDepth, stretchDepth; + treeNode *stretchTree, *longLivedTree, *tempTree; + + N = atol(argv[1]); + + minDepth = 4; + + if ((minDepth + 2) > N) + maxDepth = minDepth + 2; + else + maxDepth = N; + + stretchDepth = maxDepth + 1; + + stretchTree = BottomUpTree(0, stretchDepth); + printf + ( + "stretch tree of depth %u\t check: %li\n", + stretchDepth, + ItemCheck(stretchTree) + ); + + DeleteTree(stretchTree); + + longLivedTree = BottomUpTree(0, maxDepth); + + for (depth = minDepth; depth <= maxDepth; depth += 2) + { + long i, iterations, check; + + iterations = pow(2, maxDepth - depth + minDepth); + + check = 0; + + for (i = 1; i <= iterations; i++) + { + tempTree = BottomUpTree(i, depth); + check += ItemCheck(tempTree); + DeleteTree(tempTree); + + tempTree = BottomUpTree(-i, depth); + check += ItemCheck(tempTree); + DeleteTree(tempTree); + } /* for(i = 1...) */ + + printf + ( + "%li\t trees of depth %u\t check: %li\n", + iterations * 2, + depth, + check + ); + } /* for(depth = minDepth...) */ + + printf + ( + "long lived tree of depth %u\t check: %li\n", + maxDepth, + ItemCheck(longLivedTree) + ); + + return 0; +} /* main() */ diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/binary-tree.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/binary-tree.go new file mode 100644 index 0000000..5f6cb34 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/binary-tree.go @@ -0,0 +1,95 @@ +//go:build ignore +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* The Computer Language Benchmarks Game + * http://shootout.alioth.debian.org/ + * + * contributed by The Go Authors. + * based on C program by Kevin Carson + */ + +package main + +import ( + "flag" + "fmt" +) + +var n = flag.Int("n", 15, "depth") + +type Node struct { + item int + left, right *Node +} + +func bottomUpTree(item, depth int) *Node { + if depth <= 0 { + return &Node{item: item} + } + return &Node{item, bottomUpTree(2*item-1, depth-1), bottomUpTree(2*item, depth-1)} +} + +func (n *Node) itemCheck() int { + if n.left == nil { + return n.item + } + return n.item + n.left.itemCheck() - n.right.itemCheck() +} + +const minDepth = 4 + +func main() { + flag.Parse() + + maxDepth := *n + if minDepth+2 > *n { + maxDepth = minDepth + 2 + } + stretchDepth := maxDepth + 1 + + check := bottomUpTree(0, stretchDepth).itemCheck() + fmt.Printf("stretch tree of depth %d\t check: %d\n", stretchDepth, check) + + longLivedTree := bottomUpTree(0, maxDepth) + + for depth := minDepth; depth <= maxDepth; depth += 2 { + iterations := 1 << uint(maxDepth-depth+minDepth) + check = 0 + + for i := 1; i <= iterations; i++ { + check += bottomUpTree(i, depth).itemCheck() + check += bottomUpTree(-i, depth).itemCheck() + } + fmt.Printf("%d\t trees of depth %d\t check: %d\n", iterations*2, depth, check) + } + fmt.Printf("long lived tree of depth %d\t check: %d\n", maxDepth, longLivedTree.itemCheck()) +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/binary-tree.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/binary-tree.txt new file mode 100644 index 0000000..f8286dd --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/binary-tree.txt @@ -0,0 +1,8 @@ +stretch tree of depth 16 check: -1 +65536 trees of depth 4 check: -65536 +16384 trees of depth 6 check: -16384 +4096 trees of depth 8 check: -4096 +1024 trees of depth 10 check: -1024 +256 trees of depth 12 check: -256 +64 trees of depth 14 check: -64 +long lived tree of depth 15 check: -1 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/chameneosredux.c b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/chameneosredux.c new file mode 100644 index 0000000..cb7d94d --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/chameneosredux.c @@ -0,0 +1,332 @@ +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* The Computer Language Benchmarks Game + http://shootout.alioth.debian.org/ + + contributed by Michael Barker + based on a Java contribution by Luzius Meisser + + convert to C by dualamd +*/ + +#include <stdlib.h> +#include <stdio.h> +#include <pthread.h> + + +enum Colour +{ + blue = 0, + red = 1, + yellow = 2, + Invalid = 3 +}; + +const char* ColourName[] = {"blue", "red", "yellow"}; +const int STACK_SIZE = 32*1024; + +typedef unsigned int BOOL; +const BOOL TRUE = 1; +const BOOL FALSE = 0; + +int CreatureID = 0; + + +enum Colour doCompliment(enum Colour c1, enum Colour c2) +{ + switch (c1) + { + case blue: + switch (c2) + { + case blue: + return blue; + case red: + return yellow; + case yellow: + return red; + default: + goto errlb; + } + case red: + switch (c2) + { + case blue: + return yellow; + case red: + return red; + case yellow: + return blue; + default: + goto errlb; + } + case yellow: + switch (c2) + { + case blue: + return red; + case red: + return blue; + case yellow: + return yellow; + default: + goto errlb; + } + default: + break; + } + +errlb: + printf("Invalid colour\n"); + exit( 1 ); +} + +/* convert integer to number string: 1234 -> "one two three four" */ +char* formatNumber(int n, char* outbuf) +{ + int ochar = 0, ichar = 0; + int i; + char tmp[64]; + + const char* NUMBERS[] = + { + "zero", "one", "two", "three", "four", "five", + "six", "seven", "eight", "nine" + }; + + ichar = sprintf(tmp, "%d", n); + + for (i = 0; i < ichar; i++) + ochar += sprintf( outbuf + ochar, " %s", NUMBERS[ tmp[i] - '0' ] ); + + return outbuf; +} + + +struct MeetingPlace +{ + pthread_mutex_t mutex; + int meetingsLeft; + struct Creature* firstCreature; +}; + +struct Creature +{ + pthread_t ht; + pthread_attr_t stack_att; + + struct MeetingPlace* place; + int count; + int sameCount; + + enum Colour colour; + int id; + + BOOL two_met; + BOOL sameid; +}; + + +void MeetingPlace_Init(struct MeetingPlace* m, int meetings ) +{ + pthread_mutex_init( &m->mutex, 0 ); + m->meetingsLeft = meetings; + m->firstCreature = 0; +} + + +BOOL Meet( struct Creature* cr) +{ + BOOL retval = TRUE; + + struct MeetingPlace* mp = cr->place; + pthread_mutex_lock( &(mp->mutex) ); + + if ( mp->meetingsLeft > 0 ) + { + if ( mp->firstCreature == 0 ) + { + cr->two_met = FALSE; + mp->firstCreature = cr; + } + else + { + struct Creature* first; + enum Colour newColour; + + first = mp->firstCreature; + newColour = doCompliment( cr->colour, first->colour ); + + cr->sameid = cr->id == first->id; + cr->colour = newColour; + cr->two_met = TRUE; + + first->sameid = cr->sameid; + first->colour = newColour; + first->two_met = TRUE; + + mp->firstCreature = 0; + mp->meetingsLeft--; + } + } + else + retval = FALSE; + + pthread_mutex_unlock( &(mp->mutex) ); + return retval; +} + + +void* CreatureThreadRun(void* param) +{ + struct Creature* cr = (struct Creature*)param; + + while (TRUE) + { + if ( Meet(cr) ) + { + while (cr->two_met == FALSE) + sched_yield(); + + if (cr->sameid) + cr->sameCount++; + cr->count++; + } + else + break; + } + + return 0; +} + +void Creature_Init( struct Creature *cr, struct MeetingPlace* place, enum Colour colour ) +{ + cr->place = place; + cr->count = cr->sameCount = 0; + + cr->id = ++CreatureID; + cr->colour = colour; + cr->two_met = FALSE; + + pthread_attr_init( &cr->stack_att ); + pthread_attr_setstacksize( &cr->stack_att, STACK_SIZE ); + pthread_create( &cr->ht, &cr->stack_att, &CreatureThreadRun, (void*)(cr) ); +} + +/* format meeting times of each creature to string */ +char* Creature_getResult(struct Creature* cr, char* str) +{ + char numstr[256]; + formatNumber(cr->sameCount, numstr); + + sprintf( str, "%u%s", cr->count, numstr ); + return str; +} + + +void runGame( int n_meeting, int ncolor, const enum Colour* colours ) +{ + int i; + int total = 0; + char str[256]; + + struct MeetingPlace place; + struct Creature *creatures = (struct Creature*) calloc( ncolor, sizeof(struct Creature) ); + + MeetingPlace_Init( &place, n_meeting ); + + /* print initial color of each creature */ + for (i = 0; i < ncolor; i++) + { + printf( "%s ", ColourName[ colours[i] ] ); + Creature_Init( &(creatures[i]), &place, colours[i] ); + } + printf("\n"); + + /* wait for them to meet */ + for (i = 0; i < ncolor; i++) + pthread_join( creatures[i].ht, 0 ); + + /* print meeting times of each creature */ + for (i = 0; i < ncolor; i++) + { + printf( "%s\n", Creature_getResult(&(creatures[i]), str) ); + total += creatures[i].count; + } + + /* print total meeting times, should equal n_meeting */ + printf( "%s\n\n", formatNumber(total, str) ); + + /* cleaup & quit */ + pthread_mutex_destroy( &place.mutex ); + free( creatures ); +} + + +void printColours( enum Colour c1, enum Colour c2 ) +{ + printf( "%s + %s -> %s\n", + ColourName[c1], + ColourName[c2], + ColourName[doCompliment(c1, c2)] ); +} + +void printColoursTable(void) +{ + printColours(blue, blue); + printColours(blue, red); + printColours(blue, yellow); + printColours(red, blue); + printColours(red, red); + printColours(red, yellow); + printColours(yellow, blue); + printColours(yellow, red); + printColours(yellow, yellow); +} + +int main(int argc, char** argv) +{ + int n = (argc == 2) ? atoi(argv[1]) : 600; + + printColoursTable(); + printf("\n"); + + const enum Colour r1[] = { blue, red, yellow }; + const enum Colour r2[] = { blue, red, yellow, + red, yellow, blue, + red, yellow, red, blue }; + + runGame( n, sizeof(r1) / sizeof(r1[0]), r1 ); + runGame( n, sizeof(r2) / sizeof(r2[0]), r2 ); + + return 0; +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/chameneosredux.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/chameneosredux.go new file mode 100644 index 0000000..80bea32 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/chameneosredux.go @@ -0,0 +1,183 @@ +//go:build ignore +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* The Computer Language Benchmarks Game + * http://shootout.alioth.debian.org/ + * + * contributed by The Go Authors. + */ + +package main + +import ( + "flag" + "fmt" + "strconv" +) + +const ( + blue = iota + red + yellow + ncol +) + +var complement = [...]int{ + red | red<<2: red, + red | yellow<<2: blue, + red | blue<<2: yellow, + yellow | red<<2: blue, + yellow | yellow<<2: yellow, + yellow | blue<<2: red, + blue | red<<2: yellow, + blue | yellow<<2: red, + blue | blue<<2: blue, +} + +var colname = [...]string{ + blue: "blue", + red: "red", + yellow: "yellow", +} + +// information about the current state of a creature. +type info struct { + colour int // creature's current colour. + name int // creature's name. +} + +// exclusive access data-structure kept inside meetingplace. +// if mate is nil, it indicates there's no creature currently waiting; +// otherwise the creature's info is stored in info, and +// it is waiting to receive its mate's information on the mate channel. +type rendez struct { + n int // current number of encounters. + mate chan<- info // creature waiting when non-nil. + info info // info about creature waiting. +} + +// result sent by each creature at the end of processing. +type result struct { + met int + same int +} + +var n = 600 + +func main() { + flag.Parse() + if flag.NArg() > 0 { + n, _ = strconv.Atoi(flag.Arg(0)) + } + + for c0 := 0; c0 < ncol; c0++ { + for c1 := 0; c1 < ncol; c1++ { + fmt.Printf("%s + %s -> %s\n", colname[c0], colname[c1], colname[complement[c0|c1<<2]]) + } + } + fmt.Print("\n") + + pallmall([]int{blue, red, yellow}) + pallmall([]int{blue, red, yellow, red, yellow, blue, red, yellow, red, blue}) +} + +func pallmall(cols []int) { + + // invariant: meetingplace always contains a value unless a creature + // is currently dealing with it (whereupon it must put it back). + meetingplace := make(chan rendez, 1) + meetingplace <- rendez{n: 0} + + ended := make(chan result) + msg := "" + for i, col := range cols { + go creature(info{col, i}, meetingplace, ended) + msg += " " + colname[col] + } + fmt.Println(msg) + tot := 0 + // wait for all results + for range cols { + result := <-ended + tot += result.met + fmt.Printf("%v%v\n", result.met, spell(result.same, true)) + } + fmt.Printf("%v\n\n", spell(tot, true)) +} + +// in this function, variables ending in 0 refer to the local creature, +// variables ending in 1 to the creature we've met. +func creature(info0 info, meetingplace chan rendez, ended chan result) { + c0 := make(chan info) + met := 0 + same := 0 + for { + var othername int + // get access to rendez data and decide what to do. + switch r := <-meetingplace; { + case r.n >= n: + // if no more meetings left, then send our result data and exit. + meetingplace <- rendez{n: r.n} + ended <- result{met, same} + return + case r.mate == nil: + // no creature waiting; wait for someone to meet us, + // get their info and send our info in reply. + meetingplace <- rendez{n: r.n, info: info0, mate: c0} + info1 := <-c0 + othername = info1.name + info0.colour = complement[info0.colour|info1.colour<<2] + default: + // another creature is waiting for us with its info; + // increment meeting count, + // send them our info in reply. + r.n++ + meetingplace <- rendez{n: r.n, mate: nil} + r.mate <- info0 + othername = r.info.name + info0.colour = complement[info0.colour|r.info.colour<<2] + } + if othername == info0.name { + same++ + } + met++ + } +} + +var digits = [...]string{"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"} + +func spell(n int, required bool) string { + if n == 0 && !required { + return "" + } + return spell(n/10, false) + " " + digits[n%10] +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/chameneosredux.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/chameneosredux.txt new file mode 100644 index 0000000..6016d59 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/chameneosredux.txt @@ -0,0 +1,29 @@ +blue + blue -> blue +blue + red -> yellow +blue + yellow -> red +red + blue -> yellow +red + red -> red +red + yellow -> blue +yellow + blue -> red +yellow + red -> blue +yellow + yellow -> yellow + + blue red yellow +400 zero +400 zero +400 zero + one two zero zero + + blue red yellow red yellow blue red yellow red blue +120 zero +120 zero +120 zero +120 zero +120 zero +120 zero +120 zero +120 zero +120 zero +120 zero + one two zero zero + diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fannkuch-parallel.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fannkuch-parallel.go new file mode 100644 index 0000000..a69b09c --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fannkuch-parallel.go @@ -0,0 +1,227 @@ +//go:build ignore +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * The Computer Language Benchmarks Game + * http://shootout.alioth.debian.org/ + * + * contributed by The Go Authors. + * Based on fannkuch.scala by Rex Kerr + */ + +package main + +import ( + "flag" + "fmt" + "runtime" +) + +var n = flag.Int("n", 7, "count") +var nCPU = flag.Int("ncpu", 4, "number of cpus") + +type Job struct { + start []int + n int +} + +type Found struct { + who *Kucher + k int +} + +type Kucher struct { + perm []int + temp []int + flip []int + in chan Job +} + +func NewKucher(length int) *Kucher { + return &Kucher{ + perm: make([]int, length), + temp: make([]int, length), + flip: make([]int, length), + in: make(chan Job), + } +} + +func (k *Kucher) permute(n int) bool { + i := 0 + for ; i < n-1 && k.flip[i] == 0; i++ { + t := k.perm[0] + j := 0 + for ; j <= i; j++ { + k.perm[j] = k.perm[j+1] + } + k.perm[j] = t + } + k.flip[i]-- + for i > 0 { + i-- + k.flip[i] = i + } + return k.flip[n-1] >= 0 +} + +func (k *Kucher) count() int { + K := 0 + copy(k.temp, k.perm) + for k.temp[0] != 0 { + m := k.temp[0] + for i := 0; i < m; i++ { + k.temp[i], k.temp[m] = k.temp[m], k.temp[i] + m-- + } + K++ + } + return K +} + +func (k *Kucher) Run(foreman chan<- Found) { + for job := range k.in { + verbose := 30 + copy(k.perm, job.start) + for i, v := range k.perm { + if v != i { + verbose = 0 + } + k.flip[i] = i + } + K := 0 + for { + if verbose > 0 { + for _, p := range k.perm { + fmt.Print(p + 1) + } + fmt.Println() + verbose-- + } + count := k.count() + if count > K { + K = count + } + if !k.permute(job.n) { + break + } + } + foreman <- Found{k, K} + } +} + +type Fanner struct { + jobind int + jobsdone int + k int + jobs []Job + workers []*Kucher + in chan Found + result chan int +} + +func NewFanner(jobs []Job, workers []*Kucher) *Fanner { + return &Fanner{ + jobs: jobs, workers: workers, + in: make(chan Found), + result: make(chan int), + } +} + +func (f *Fanner) Run(N int) { + for msg := range f.in { + if msg.k > f.k { + f.k = msg.k + } + if msg.k >= 0 { + f.jobsdone++ + } + if f.jobind < len(f.jobs) { + msg.who.in <- f.jobs[f.jobind] + f.jobind++ + } else if f.jobsdone == len(f.jobs) { + f.result <- f.k + return + } + } +} + +func swapped(a []int, i, j int) []int { + b := make([]int, len(a)) + copy(b, a) + b[i], b[j] = a[j], a[i] + return b +} + +func main() { + flag.Parse() + runtime.GOMAXPROCS(*nCPU) + N := *n + base := make([]int, N) + for i := range base { + base[i] = i + } + + njobs := 1 + if N > 8 { + njobs += (N*(N-1))/2 - 28 // njobs = 1 + sum(8..N-1) = 1 + sum(1..N-1) - sum(1..7) + } + jobs := make([]Job, njobs) + jobsind := 0 + + firstN := N + if firstN > 8 { + firstN = 8 + } + jobs[jobsind] = Job{base, firstN} + jobsind++ + for i := N - 1; i >= 8; i-- { + for j := 0; j < i; j++ { + jobs[jobsind] = Job{swapped(base, i, j), i} + jobsind++ + } + } + + nworkers := *nCPU + if njobs < nworkers { + nworkers = njobs + } + workers := make([]*Kucher, nworkers) + foreman := NewFanner(jobs, workers) + go foreman.Run(N) + for i := range workers { + k := NewKucher(N) + workers[i] = k + go k.Run(foreman.in) + foreman.in <- Found{k, -1} + } + fmt.Printf("Pfannkuchen(%d) = %d\n", N, <-foreman.result) +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fannkuch-parallel.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fannkuch-parallel.txt new file mode 100644 index 0000000..e66f779 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fannkuch-parallel.txt @@ -0,0 +1,31 @@ +1234567 +2134567 +2314567 +3214567 +3124567 +1324567 +2341567 +3241567 +3421567 +4321567 +4231567 +2431567 +3412567 +4312567 +4132567 +1432567 +1342567 +3142567 +4123567 +1423567 +1243567 +2143567 +2413567 +4213567 +2345167 +3245167 +3425167 +4325167 +4235167 +2435167 +Pfannkuchen(7) = 16 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fannkuch.c b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fannkuch.c new file mode 100644 index 0000000..a12d8bd --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fannkuch.c @@ -0,0 +1,136 @@ +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * The Computer Language Shootout + * http://shootout.alioth.debian.org/ + * Contributed by Heiner Marxen + * + * "fannkuch" for C gcc + * + * $Id: fannkuch.1.gcc.code,v 1.15 2009-04-28 15:39:31 igouy-guest Exp $ + */ + +#include <stdio.h> +#include <stdlib.h> + +#define Int int +#define Aint int + + static long +fannkuch( int n ) +{ + Aint* perm; + Aint* perm1; + Aint* count; + long flips; + long flipsMax; + Int r; + Int i; + Int k; + Int didpr; + const Int n1 = n - 1; + + if( n < 1 ) return 0; + + perm = calloc(n, sizeof(*perm )); + perm1 = calloc(n, sizeof(*perm1)); + count = calloc(n, sizeof(*count)); + + for( i=0 ; i<n ; ++i ) perm1[i] = i; /* initial (trivial) permu */ + + r = n; didpr = 0; flipsMax = 0; + for(;;) { + if( didpr < 30 ) { + for( i=0 ; i<n ; ++i ) printf("%d", (int)(1+perm1[i])); + printf("\n"); + ++didpr; + } + for( ; r!=1 ; --r ) { + count[r-1] = r; + } + +#define XCH(x,y) { Aint t_mp; t_mp=(x); (x)=(y); (y)=t_mp; } + + if( ! (perm1[0]==0 || perm1[n1]==n1) ) { + flips = 0; + for( i=1 ; i<n ; ++i ) { /* perm = perm1 */ + perm[i] = perm1[i]; + } + k = perm1[0]; /* cache perm[0] in k */ + do { /* k!=0 ==> k>0 */ + Int j; + for( i=1, j=k-1 ; i<j ; ++i, --j ) { + XCH(perm[i], perm[j]) + } + ++flips; + /* + * Now exchange k (caching perm[0]) and perm[k]... with care! + * XCH(k, perm[k]) does NOT work! + */ + j=perm[k]; perm[k]=k ; k=j; + }while( k ); + if( flipsMax < flips ) { + flipsMax = flips; + } + } + + for(;;) { + if( r == n ) { + return flipsMax; + } + /* rotate down perm[0..r] by one */ + { + Int perm0 = perm1[0]; + i = 0; + while( i < r ) { + k = i+1; + perm1[i] = perm1[k]; + i = k; + } + perm1[r] = perm0; + } + if( (count[r] -= 1) > 0 ) { + break; + } + ++r; + } + } +} + + int +main( int argc, char* argv[] ) +{ + int n = (argc>1) ? atoi(argv[1]) : 0; + + printf("Pfannkuchen(%d) = %ld\n", n, fannkuch(n)); + return 0; +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fannkuch.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fannkuch.go new file mode 100644 index 0000000..4f07dff --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fannkuch.go @@ -0,0 +1,125 @@ +//go:build ignore +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * The Computer Language Benchmarks Game + * http://shootout.alioth.debian.org/ + * + * contributed by The Go Authors. + * Based on fannkuch.c by Heiner Marxen + */ + +package main + +import ( + "flag" + "fmt" +) + +var n = flag.Int("n", 7, "count") + +func fannkuch(n int) int { + if n < 1 { + return 0 + } + + n1 := n - 1 + perm := make([]int, n) + perm1 := make([]int, n) + count := make([]int, n) + + for i := 0; i < n; i++ { + perm1[i] = i // initial (trivial) permutation + } + + r := n + didpr := 0 + flipsMax := 0 + for { + if didpr < 30 { + for i := 0; i < n; i++ { + fmt.Printf("%d", 1+perm1[i]) + } + fmt.Printf("\n") + didpr++ + } + for ; r != 1; r-- { + count[r-1] = r + } + + if perm1[0] != 0 && perm1[n1] != n1 { + flips := 0 + for i := 1; i < n; i++ { // perm = perm1 + perm[i] = perm1[i] + } + k := perm1[0] // cache perm[0] in k + for { // k!=0 ==> k>0 + for i, j := 1, k-1; i < j; i, j = i+1, j-1 { + perm[i], perm[j] = perm[j], perm[i] + } + flips++ + // Now exchange k (caching perm[0]) and perm[k]... with care! + j := perm[k] + perm[k] = k + k = j + if k == 0 { + break + } + } + if flipsMax < flips { + flipsMax = flips + } + } + + for ; r < n; r++ { + // rotate down perm[0..r] by one + perm0 := perm1[0] + for i := 0; i < r; i++ { + perm1[i] = perm1[i+1] + } + perm1[r] = perm0 + count[r]-- + if count[r] > 0 { + break + } + } + if r == n { + return flipsMax + } + } + return 0 +} + +func main() { + flag.Parse() + fmt.Printf("Pfannkuchen(%d) = %d\n", *n, fannkuch(*n)) +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fannkuch.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fannkuch.txt new file mode 100644 index 0000000..e66f779 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fannkuch.txt @@ -0,0 +1,31 @@ +1234567 +2134567 +2314567 +3214567 +3124567 +1324567 +2341567 +3241567 +3421567 +4321567 +4231567 +2431567 +3412567 +4312567 +4132567 +1432567 +1342567 +3142567 +4123567 +1423567 +1243567 +2143567 +2413567 +4213567 +2345167 +3245167 +3425167 +4325167 +4235167 +2435167 +Pfannkuchen(7) = 16 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fasta-1000.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fasta-1000.txt new file mode 100644 index 0000000..f1caba0 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fasta-1000.txt @@ -0,0 +1,171 @@ +>ONE Homo sapiens alu +GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGA +TCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACT +AAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAG +GCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCG +CCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGT +GGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCA +GGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAA +TTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAG +AATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCA +GCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGT +AATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACC +AGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTG +GTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACC +CGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAG +AGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTT +TGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACA +TGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCT +GTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGG +TTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGT +CTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGG +CGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCG +TCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTA +CTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCG +AGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCG +GGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACC +TGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAA +TACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGA +GGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACT +GCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTC +ACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGT +TCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGC +CGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCG +CTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTG +GGCGACAGAGCGAGACTCCG +>TWO IUB ambiguity codes +cttBtatcatatgctaKggNcataaaSatgtaaaDcDRtBggDtctttataattcBgtcg +tactDtDagcctatttSVHtHttKtgtHMaSattgWaHKHttttagacatWatgtRgaaa +NtactMcSMtYtcMgRtacttctWBacgaaatatagScDtttgaagacacatagtVgYgt +cattHWtMMWcStgttaggKtSgaYaaccWStcgBttgcgaMttBYatcWtgacaYcaga +gtaBDtRacttttcWatMttDBcatWtatcttactaBgaYtcttgttttttttYaaScYa +HgtgttNtSatcMtcVaaaStccRcctDaataataStcYtRDSaMtDttgttSagtRRca +tttHatSttMtWgtcgtatSSagactYaaattcaMtWatttaSgYttaRgKaRtccactt +tattRggaMcDaWaWagttttgacatgttctacaaaRaatataataaMttcgDacgaSSt +acaStYRctVaNMtMgtaggcKatcttttattaaaaagVWaHKYagtttttatttaacct +tacgtVtcVaattVMBcttaMtttaStgacttagattWWacVtgWYagWVRctDattBYt +gtttaagaagattattgacVatMaacattVctgtBSgaVtgWWggaKHaatKWcBScSWa +accRVacacaaactaccScattRatatKVtactatatttHttaagtttSKtRtacaaagt +RDttcaaaaWgcacatWaDgtDKacgaacaattacaRNWaatHtttStgttattaaMtgt +tgDcgtMgcatBtgcttcgcgaDWgagctgcgaggggVtaaScNatttacttaatgacag +cccccacatYScaMgtaggtYaNgttctgaMaacNaMRaacaaacaKctacatagYWctg +ttWaaataaaataRattagHacacaagcgKatacBttRttaagtatttccgatctHSaat +actcNttMaagtattMtgRtgaMgcataatHcMtaBSaRattagttgatHtMttaaKagg +YtaaBataSaVatactWtataVWgKgttaaaacagtgcgRatatacatVtHRtVYataSa +KtWaStVcNKHKttactatccctcatgWHatWaRcttactaggatctataDtDHBttata +aaaHgtacVtagaYttYaKcctattcttcttaataNDaaggaaaDYgcggctaaWSctBa +aNtgctggMBaKctaMVKagBaactaWaDaMaccYVtNtaHtVWtKgRtcaaNtYaNacg +gtttNattgVtttctgtBaWgtaattcaagtcaVWtactNggattctttaYtaaagccgc +tcttagHVggaYtgtNcDaVagctctctKgacgtatagYcctRYHDtgBattDaaDgccK +tcHaaStttMcctagtattgcRgWBaVatHaaaataYtgtttagMDMRtaataaggatMt +ttctWgtNtgtgaaaaMaatatRtttMtDgHHtgtcattttcWattRSHcVagaagtacg +ggtaKVattKYagactNaatgtttgKMMgYNtcccgSKttctaStatatNVataYHgtNa +BKRgNacaactgatttcctttaNcgatttctctataScaHtataRagtcRVttacDSDtt +aRtSatacHgtSKacYagttMHtWataggatgactNtatSaNctataVtttRNKtgRacc +tttYtatgttactttttcctttaaacatacaHactMacacggtWataMtBVacRaSaatc +cgtaBVttccagccBcttaRKtgtgcctttttRtgtcagcRttKtaaacKtaaatctcac +aattgcaNtSBaaccgggttattaaBcKatDagttactcttcattVtttHaaggctKKga +tacatcBggScagtVcacattttgaHaDSgHatRMaHWggtatatRgccDttcgtatcga +aacaHtaagttaRatgaVacttagattVKtaaYttaaatcaNatccRttRRaMScNaaaD +gttVHWgtcHaaHgacVaWtgttScactaagSgttatcttagggDtaccagWattWtRtg +ttHWHacgattBtgVcaYatcggttgagKcWtKKcaVtgaYgWctgYggVctgtHgaNcV +taBtWaaYatcDRaaRtSctgaHaYRttagatMatgcatttNattaDttaattgttctaa +ccctcccctagaWBtttHtBccttagaVaatMcBHagaVcWcagBVttcBtaYMccagat +gaaaaHctctaacgttagNWRtcggattNatcRaNHttcagtKttttgWatWttcSaNgg +gaWtactKKMaacatKatacNattgctWtatctaVgagctatgtRaHtYcWcttagccaa +tYttWttaWSSttaHcaaaaagVacVgtaVaRMgattaVcDactttcHHggHRtgNcctt +tYatcatKgctcctctatVcaaaaKaaaagtatatctgMtWtaaaacaStttMtcgactt +taSatcgDataaactaaacaagtaaVctaggaSccaatMVtaaSKNVattttgHccatca +cBVctgcaVatVttRtactgtVcaattHgtaaattaaattttYtatattaaRSgYtgBag +aHSBDgtagcacRHtYcBgtcacttacactaYcgctWtattgSHtSatcataaatataHt +cgtYaaMNgBaatttaRgaMaatatttBtttaaaHHKaatctgatWatYaacttMctctt +ttVctagctDaaagtaVaKaKRtaacBgtatccaaccactHHaagaagaaggaNaaatBW +attccgStaMSaMatBttgcatgRSacgttVVtaaDMtcSgVatWcaSatcttttVatag +ttactttacgatcaccNtaDVgSRcgVcgtgaacgaNtaNatatagtHtMgtHcMtagaa +attBgtataRaaaacaYKgtRccYtatgaagtaataKgtaaMttgaaRVatgcagaKStc +tHNaaatctBBtcttaYaBWHgtVtgacagcaRcataWctcaBcYacYgatDgtDHccta +>THREE Homo sapiens frequency +aacacttcaccaggtatcgtgaaggctcaagattacccagagaacctttgcaatataaga +atatgtatgcagcattaccctaagtaattatattctttttctgactcaaagtgacaagcc +ctagtgtatattaaatcggtatatttgggaaattcctcaaactatcctaatcaggtagcc +atgaaagtgatcaaaaaagttcgtacttataccatacatgaattctggccaagtaaaaaa +tagattgcgcaaaattcgtaccttaagtctctcgccaagatattaggatcctattactca +tatcgtgtttttctttattgccgccatccccggagtatctcacccatccttctcttaaag +gcctaatattacctatgcaaataaacatatattgttgaaaattgagaacctgatcgtgat +tcttatgtgtaccatatgtatagtaatcacgcgactatatagtgctttagtatcgcccgt +gggtgagtgaatattctgggctagcgtgagatagtttcttgtcctaatatttttcagatc +gaatagcttctatttttgtgtttattgacatatgtcgaaactccttactcagtgaaagtc +atgaccagatccacgaacaatcttcggaatcagtctcgttttacggcggaatcttgagtc +taacttatatcccgtcgcttactttctaacaccccttatgtatttttaaaattacgttta +ttcgaacgtacttggcggaagcgttattttttgaagtaagttacattgggcagactcttg +acattttcgatacgactttctttcatccatcacaggactcgttcgtattgatatcagaag +ctcgtgatgattagttgtcttctttaccaatactttgaggcctattctgcgaaatttttg +ttgccctgcgaacttcacataccaaggaacacctcgcaacatgccttcatatccatcgtt +cattgtaattcttacacaatgaatcctaagtaattacatccctgcgtaaaagatggtagg +ggcactgaggatatattaccaagcatttagttatgagtaatcagcaatgtttcttgtatt +aagttctctaaaatagttacatcgtaatgttatctcgggttccgcgaataaacgagatag +attcattatatatggccctaagcaaaaacctcctcgtattctgttggtaattagaatcac +acaatacgggttgagatattaattatttgtagtacgaagagatataaaaagatgaacaat +tactcaagtcaagatgtatacgggatttataataaaaatcgggtagagatctgctttgca +attcagacgtgccactaaatcgtaatatgtcgcgttacatcagaaagggtaactattatt +aattaataaagggcttaatcactacatattagatcttatccgatagtcttatctattcgt +tgtatttttaagcggttctaattcagtcattatatcagtgctccgagttctttattattg +ttttaaggatgacaaaatgcctcttgttataacgctgggagaagcagactaagagtcgga +gcagttggtagaatgaggctgcaaaagacggtctcgacgaatggacagactttactaaac +caatgaaagacagaagtagagcaaagtctgaagtggtatcagcttaattatgacaaccct +taatacttccctttcgccgaatactggcgtggaaaggttttaaaagtcgaagtagttaga +ggcatctctcgctcataaataggtagactactcgcaatccaatgtgactatgtaatactg +ggaacatcagtccgcgatgcagcgtgtttatcaaccgtccccactcgcctggggagacat +gagaccacccccgtggggattattagtccgcagtaatcgactcttgacaatccttttcga +ttatgtcatagcaatttacgacagttcagcgaagtgactactcggcgaaatggtattact +aaagcattcgaacccacatgaatgtgattcttggcaatttctaatccactaaagcttttc +cgttgaatctggttgtagatatttatataagttcactaattaagatcacggtagtatatt +gatagtgatgtctttgcaagaggttggccgaggaatttacggattctctattgatacaat +ttgtctggcttataactcttaaggctgaaccaggcgtttttagacgacttgatcagctgt +tagaatggtttggactccctctttcatgtcagtaacatttcagccgttattgttacgata +tgcttgaacaatattgatctaccacacacccatagtatattttataggtcatgctgttac +ctacgagcatggtattccacttcccattcaatgagtattcaacatcactagcctcagaga +tgatgacccacctctaataacgtcacgttgcggccatgtgaaacctgaacttgagtagac +gatatcaagcgctttaaattgcatataacatttgagggtaaagctaagcggatgctttat +ataatcaatactcaataataagatttgattgcattttagagttatgacacgacatagttc +actaacgagttactattcccagatctagactgaagtactgatcgagacgatccttacgtc +gatgatcgttagttatcgacttaggtcgggtctctagcggtattggtacttaaccggaca +ctatactaataacccatgatcaaagcataacagaatacagacgataatttcgccaacata +tatgtacagaccccaagcatgagaagctcattgaaagctatcattgaagtcccgctcaca +atgtgtcttttccagacggtttaactggttcccgggagtcctggagtttcgacttacata +aatggaaacaatgtattttgctaatttatctatagcgtcatttggaccaatacagaatat +tatgttgcctagtaatccactataacccgcaagtgctgatagaaaatttttagacgattt +ataaatgccccaagtatccctcccgtgaatcctccgttatactaattagtattcgttcat +acgtataccgcgcatatatgaacatttggcgataaggcgcgtgaattgttacgtgacaga +gatagcagtttcttgtgatatggttaacagacgtacatgaagggaaactttatatctata +gtgatgcttccgtagaaataccgccactggtctgccaatgatgaagtatgtagctttagg +tttgtactatgaggctttcgtttgtttgcagagtataacagttgcgagtgaaaaaccgac +gaatttatactaatacgctttcactattggctacaaaatagggaagagtttcaatcatga +gagggagtatatggatgctttgtagctaaaggtagaacgtatgtatatgctgccgttcat +tcttgaaagatacataagcgataagttacgacaattataagcaacatccctaccttcgta +acgatttcactgttactgcgcttgaaatacactatggggctattggcggagagaagcaga +tcgcgccgagcatatacgagacctataatgttgatgatagagaaggcgtctgaattgata +catcgaagtacactttctttcgtagtatctctcgtcctctttctatctccggacacaaga +attaagttatatatatagagtcttaccaatcatgttgaatcctgattctcagagttcttt +ggcgggccttgtgatgactgagaaacaatgcaatattgctccaaatttcctaagcaaatt +ctcggttatgttatgttatcagcaaagcgttacgttatgttatttaaatctggaatgacg +gagcgaagttcttatgtcggtgtgggaataattcttttgaagacagcactccttaaataa +tatcgctccgtgtttgtatttatcgaatgggtctgtaaccttgcacaagcaaatcggtgg +tgtatatatcggataacaattaatacgatgttcatagtgacagtatactgatcgagtcct +ctaaagtcaattacctcacttaacaatctcattgatgttgtgtcattcccggtatcgccc +gtagtatgtgctctgattgaccgagtgtgaaccaaggaacatctactaatgcctttgtta +ggtaagatctctctgaattccttcgtgccaacttaaaacattatcaaaatttcttctact +tggattaactacttttacgagcatggcaaattcccctgtggaagacggttcattattatc +ggaaaccttatagaaattgcgtgttgactgaaattagatttttattgtaagagttgcatc +tttgcgattcctctggtctagcttccaatgaacagtcctcccttctattcgacatcgggt +ccttcgtacatgtctttgcgatgtaataattaggttcggagtgtggccttaatgggtgca +actaggaatacaacgcaaatttgctgacatgatagcaaatcggtatgccggcaccaaaac +gtgctccttgcttagcttgtgaatgagactcagtagttaaataaatccatatctgcaatc +gattccacaggtattgtccactatctttgaactactctaagagatacaagcttagctgag +accgaggtgtatatgactacgctgatatctgtaaggtaccaatgcaggcaaagtatgcga +gaagctaataccggctgtttccagctttataagattaaaatttggctgtcctggcggcct +cagaattgttctatcgtaatcagttggttcattaattagctaagtacgaggtacaactta +tctgtcccagaacagctccacaagtttttttacagccgaaacccctgtgtgaatcttaat +atccaagcgcgttatctgattagagtttacaactcagtattttatcagtacgttttgttt +ccaacattacccggtatgacaaaatgacgccacgtgtcgaataatggtctgaccaatgta +ggaagtgaaaagataaatat diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fasta.c b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fasta.c new file mode 100644 index 0000000..cf0f2a7 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fasta.c @@ -0,0 +1,221 @@ +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * http://shootout.alioth.debian.org/u32/program.php?test=fasta&lang=gcc&id=3 + */ + +/* The Computer Language Benchmarks Game + * http://shootout.alioth.debian.org/ + * + * contributed by Petr Prokhorenkov + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifndef fwrite_unlocked +// not available on OS X +#define fwrite_unlocked fwrite +#define fputc_unlocked fputc +#define fputs_unlocked fputs +#endif + +#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) +#define unlikely(x) __builtin_expect((x), 0) + +#define IM 139968 +#define IA 3877 +#define IC 29573 + +#define LINE_LEN 60 +#define LOOKUP_SIZE 4096 +#define LOOKUP_SCALE ((float)(LOOKUP_SIZE - 1)) + +typedef unsigned random_t; + +void +random_init(random_t *random) { + *random = 42; +} + +// Special version with result rescaled to LOOKUP_SCALE. +static inline +float +random_next_lookup(random_t *random) { + *random = (*random*IA + IC)%IM; + + return (*random)*(LOOKUP_SCALE/IM); +} + +struct amino_acid { + char sym; + float prob; + float cprob_lookup; +}; + +void +repeat(const char *alu, const char *title, int n) { + int len = strlen(alu); + char buffer[len + LINE_LEN]; + int pos = 0; + + memcpy(buffer, alu, len); + memcpy(buffer + len, alu, LINE_LEN); + + fputs_unlocked(title, stdout); + while (n > 0) { + int bytes = n > LINE_LEN ? LINE_LEN : n; + + fwrite_unlocked(buffer + pos, bytes, 1, stdout); + pos += bytes; + if (pos > len) { + pos -= len; + } + fputc_unlocked('\n', stdout); + n -= bytes; + } +} + +/* + * Lookup table contains mapping from real values to cumulative + * probabilities. Careful selection of table size allows lookup + * virtually in constant time. + * + * All cumulative probabilities are rescaled to LOOKUP_SCALE, + * this allows to save one multiplication operation on each iteration + * in randomize(). + */ + +void * +fill_lookup(struct amino_acid **lookup, struct amino_acid *amino_acid, int amino_acid_size) { + float p = 0; + int i, j; + + for (i = 0; i < amino_acid_size; i++) { + p += amino_acid[i].prob; + amino_acid[i].cprob_lookup = p*LOOKUP_SCALE; + } + + // Prevent rounding error. + amino_acid[amino_acid_size - 1].cprob_lookup = LOOKUP_SIZE - 1; + + for (i = 0, j = 0; i < LOOKUP_SIZE; i++) { + while (amino_acid[j].cprob_lookup < i) { + j++; + } + lookup[i] = &amino_acid[j]; + } + + return 0; +} + +void +randomize(struct amino_acid *amino_acid, int amino_acid_size, + const char *title, int n, random_t *rand) { + struct amino_acid *lookup[LOOKUP_SIZE]; + char line_buffer[LINE_LEN + 1]; + int i, j; + + line_buffer[LINE_LEN] = '\n'; + + fill_lookup(lookup, amino_acid, amino_acid_size); + + fputs_unlocked(title, stdout); + + for (i = 0, j = 0; i < n; i++, j++) { + if (j == LINE_LEN) { + fwrite_unlocked(line_buffer, LINE_LEN + 1, 1, stdout); + j = 0; + } + + float r = random_next_lookup(rand); + struct amino_acid *u = lookup[(short)r]; + while (unlikely(u->cprob_lookup < r)) { + ++u; + } + line_buffer[j] = u->sym; + } + line_buffer[j] = '\n'; + fwrite_unlocked(line_buffer, j + 1, 1, stdout); +} + +struct amino_acid amino_acid[] = { + { 'a', 0.27 }, + { 'c', 0.12 }, + { 'g', 0.12 }, + { 't', 0.27 }, + + { 'B', 0.02 }, + { 'D', 0.02 }, + { 'H', 0.02 }, + { 'K', 0.02 }, + { 'M', 0.02 }, + { 'N', 0.02 }, + { 'R', 0.02 }, + { 'S', 0.02 }, + { 'V', 0.02 }, + { 'W', 0.02 }, + { 'Y', 0.02 }, +}; + +struct amino_acid homo_sapiens[] = { + { 'a', 0.3029549426680 }, + { 'c', 0.1979883004921 }, + { 'g', 0.1975473066391 }, + { 't', 0.3015094502008 }, +}; + +static const char alu[] = + "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTG" + "GGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGA" + "GACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAA" + "AATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAAT" + "CCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAAC" + "CCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTG" + "CACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"; + +int +main(int argc, const char **argv) { + int n = argc > 1 ? atoi( argv[1] ) : 512; + random_t rand; + + random_init(&rand); + + repeat(alu, ">ONE Homo sapiens alu\n", n*2); + randomize(amino_acid, ARRAY_SIZE(amino_acid), + ">TWO IUB ambiguity codes\n", n*3, &rand); + randomize(homo_sapiens, ARRAY_SIZE(homo_sapiens), + ">THREE Homo sapiens frequency\n", n*5, &rand); + + return 0; +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fasta.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fasta.go new file mode 100644 index 0000000..3890113 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fasta.go @@ -0,0 +1,208 @@ +//go:build ignore +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* The Computer Language Benchmarks Game + * http://shootout.alioth.debian.org/ + * + * contributed by The Go Authors. + * Based on C program by by Petr Prokhorenkov. + */ + +package main + +import ( + "flag" + "os" +) + +var out = make(buffer, 0, 32768) + +var n = flag.Int("n", 1000, "length of result") + +const Line = 60 + +func Repeat(alu []byte, n int) { + buf := append(alu, alu...) + off := 0 + for n > 0 { + m := n + if m > Line { + m = Line + } + buf1 := out.NextWrite(m + 1) + copy(buf1, buf[off:]) + buf1[m] = '\n' + if off += m; off >= len(alu) { + off -= len(alu) + } + n -= m + } +} + +const ( + IM = 139968 + IA = 3877 + IC = 29573 + + LookupSize = 4096 + LookupScale float64 = LookupSize - 1 +) + +var rand uint32 = 42 + +type Acid struct { + sym byte + prob float64 + cprob float64 + next *Acid +} + +func computeLookup(acid []Acid) *[LookupSize]*Acid { + var lookup [LookupSize]*Acid + var p float64 + for i := range acid { + p += acid[i].prob + acid[i].cprob = p * LookupScale + if i > 0 { + acid[i-1].next = &acid[i] + } + } + acid[len(acid)-1].cprob = 1.0 * LookupScale + + j := 0 + for i := range lookup { + for acid[j].cprob < float64(i) { + j++ + } + lookup[i] = &acid[j] + } + + return &lookup +} + +func Random(acid []Acid, n int) { + lookup := computeLookup(acid) + for n > 0 { + m := n + if m > Line { + m = Line + } + buf := out.NextWrite(m + 1) + f := LookupScale / IM + myrand := rand + for i := 0; i < m; i++ { + myrand = (myrand*IA + IC) % IM + r := float64(int(myrand)) * f + a := lookup[int(r)] + for a.cprob < r { + a = a.next + } + buf[i] = a.sym + } + rand = myrand + buf[m] = '\n' + n -= m + } +} + +func main() { + defer out.Flush() + + flag.Parse() + + iub := []Acid{ + {prob: 0.27, sym: 'a'}, + {prob: 0.12, sym: 'c'}, + {prob: 0.12, sym: 'g'}, + {prob: 0.27, sym: 't'}, + {prob: 0.02, sym: 'B'}, + {prob: 0.02, sym: 'D'}, + {prob: 0.02, sym: 'H'}, + {prob: 0.02, sym: 'K'}, + {prob: 0.02, sym: 'M'}, + {prob: 0.02, sym: 'N'}, + {prob: 0.02, sym: 'R'}, + {prob: 0.02, sym: 'S'}, + {prob: 0.02, sym: 'V'}, + {prob: 0.02, sym: 'W'}, + {prob: 0.02, sym: 'Y'}, + } + + homosapiens := []Acid{ + {prob: 0.3029549426680, sym: 'a'}, + {prob: 0.1979883004921, sym: 'c'}, + {prob: 0.1975473066391, sym: 'g'}, + {prob: 0.3015094502008, sym: 't'}, + } + + alu := []byte( + "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" + + "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" + + "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" + + "ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" + + "GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" + + "AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" + + "AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA") + + out.WriteString(">ONE Homo sapiens alu\n") + Repeat(alu, 2**n) + out.WriteString(">TWO IUB ambiguity codes\n") + Random(iub, 3**n) + out.WriteString(">THREE Homo sapiens frequency\n") + Random(homosapiens, 5**n) +} + +type buffer []byte + +func (b *buffer) Flush() { + p := *b + if len(p) > 0 { + os.Stdout.Write(p) + } + *b = p[0:0] +} + +func (b *buffer) WriteString(s string) { + p := b.NextWrite(len(s)) + copy(p, s) +} + +func (b *buffer) NextWrite(n int) []byte { + p := *b + if len(p)+n > cap(p) { + b.Flush() + p = *b + } + out := p[len(p) : len(p)+n] + *b = p[:len(p)+n] + return out +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fasta.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fasta.txt new file mode 100644 index 0000000..f1caba0 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/fasta.txt @@ -0,0 +1,171 @@ +>ONE Homo sapiens alu +GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGA +TCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACT +AAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAG +GCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCG +CCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGT +GGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCA +GGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAA +TTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAG +AATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCA +GCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGT +AATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACC +AGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTG +GTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACC +CGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAG +AGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTT +TGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACA +TGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCT +GTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGG +TTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGT +CTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGG +CGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCG +TCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTA +CTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCG +AGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCG +GGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACC +TGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAA +TACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGA +GGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACT +GCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTC +ACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGT +TCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGC +CGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCG +CTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTG +GGCGACAGAGCGAGACTCCG +>TWO IUB ambiguity codes +cttBtatcatatgctaKggNcataaaSatgtaaaDcDRtBggDtctttataattcBgtcg +tactDtDagcctatttSVHtHttKtgtHMaSattgWaHKHttttagacatWatgtRgaaa +NtactMcSMtYtcMgRtacttctWBacgaaatatagScDtttgaagacacatagtVgYgt +cattHWtMMWcStgttaggKtSgaYaaccWStcgBttgcgaMttBYatcWtgacaYcaga +gtaBDtRacttttcWatMttDBcatWtatcttactaBgaYtcttgttttttttYaaScYa +HgtgttNtSatcMtcVaaaStccRcctDaataataStcYtRDSaMtDttgttSagtRRca +tttHatSttMtWgtcgtatSSagactYaaattcaMtWatttaSgYttaRgKaRtccactt +tattRggaMcDaWaWagttttgacatgttctacaaaRaatataataaMttcgDacgaSSt +acaStYRctVaNMtMgtaggcKatcttttattaaaaagVWaHKYagtttttatttaacct +tacgtVtcVaattVMBcttaMtttaStgacttagattWWacVtgWYagWVRctDattBYt +gtttaagaagattattgacVatMaacattVctgtBSgaVtgWWggaKHaatKWcBScSWa +accRVacacaaactaccScattRatatKVtactatatttHttaagtttSKtRtacaaagt +RDttcaaaaWgcacatWaDgtDKacgaacaattacaRNWaatHtttStgttattaaMtgt +tgDcgtMgcatBtgcttcgcgaDWgagctgcgaggggVtaaScNatttacttaatgacag +cccccacatYScaMgtaggtYaNgttctgaMaacNaMRaacaaacaKctacatagYWctg +ttWaaataaaataRattagHacacaagcgKatacBttRttaagtatttccgatctHSaat +actcNttMaagtattMtgRtgaMgcataatHcMtaBSaRattagttgatHtMttaaKagg +YtaaBataSaVatactWtataVWgKgttaaaacagtgcgRatatacatVtHRtVYataSa +KtWaStVcNKHKttactatccctcatgWHatWaRcttactaggatctataDtDHBttata +aaaHgtacVtagaYttYaKcctattcttcttaataNDaaggaaaDYgcggctaaWSctBa +aNtgctggMBaKctaMVKagBaactaWaDaMaccYVtNtaHtVWtKgRtcaaNtYaNacg +gtttNattgVtttctgtBaWgtaattcaagtcaVWtactNggattctttaYtaaagccgc +tcttagHVggaYtgtNcDaVagctctctKgacgtatagYcctRYHDtgBattDaaDgccK +tcHaaStttMcctagtattgcRgWBaVatHaaaataYtgtttagMDMRtaataaggatMt +ttctWgtNtgtgaaaaMaatatRtttMtDgHHtgtcattttcWattRSHcVagaagtacg +ggtaKVattKYagactNaatgtttgKMMgYNtcccgSKttctaStatatNVataYHgtNa +BKRgNacaactgatttcctttaNcgatttctctataScaHtataRagtcRVttacDSDtt +aRtSatacHgtSKacYagttMHtWataggatgactNtatSaNctataVtttRNKtgRacc +tttYtatgttactttttcctttaaacatacaHactMacacggtWataMtBVacRaSaatc +cgtaBVttccagccBcttaRKtgtgcctttttRtgtcagcRttKtaaacKtaaatctcac +aattgcaNtSBaaccgggttattaaBcKatDagttactcttcattVtttHaaggctKKga +tacatcBggScagtVcacattttgaHaDSgHatRMaHWggtatatRgccDttcgtatcga +aacaHtaagttaRatgaVacttagattVKtaaYttaaatcaNatccRttRRaMScNaaaD +gttVHWgtcHaaHgacVaWtgttScactaagSgttatcttagggDtaccagWattWtRtg +ttHWHacgattBtgVcaYatcggttgagKcWtKKcaVtgaYgWctgYggVctgtHgaNcV +taBtWaaYatcDRaaRtSctgaHaYRttagatMatgcatttNattaDttaattgttctaa +ccctcccctagaWBtttHtBccttagaVaatMcBHagaVcWcagBVttcBtaYMccagat +gaaaaHctctaacgttagNWRtcggattNatcRaNHttcagtKttttgWatWttcSaNgg +gaWtactKKMaacatKatacNattgctWtatctaVgagctatgtRaHtYcWcttagccaa +tYttWttaWSSttaHcaaaaagVacVgtaVaRMgattaVcDactttcHHggHRtgNcctt +tYatcatKgctcctctatVcaaaaKaaaagtatatctgMtWtaaaacaStttMtcgactt +taSatcgDataaactaaacaagtaaVctaggaSccaatMVtaaSKNVattttgHccatca +cBVctgcaVatVttRtactgtVcaattHgtaaattaaattttYtatattaaRSgYtgBag +aHSBDgtagcacRHtYcBgtcacttacactaYcgctWtattgSHtSatcataaatataHt +cgtYaaMNgBaatttaRgaMaatatttBtttaaaHHKaatctgatWatYaacttMctctt +ttVctagctDaaagtaVaKaKRtaacBgtatccaaccactHHaagaagaaggaNaaatBW +attccgStaMSaMatBttgcatgRSacgttVVtaaDMtcSgVatWcaSatcttttVatag +ttactttacgatcaccNtaDVgSRcgVcgtgaacgaNtaNatatagtHtMgtHcMtagaa +attBgtataRaaaacaYKgtRccYtatgaagtaataKgtaaMttgaaRVatgcagaKStc +tHNaaatctBBtcttaYaBWHgtVtgacagcaRcataWctcaBcYacYgatDgtDHccta +>THREE Homo sapiens frequency +aacacttcaccaggtatcgtgaaggctcaagattacccagagaacctttgcaatataaga +atatgtatgcagcattaccctaagtaattatattctttttctgactcaaagtgacaagcc +ctagtgtatattaaatcggtatatttgggaaattcctcaaactatcctaatcaggtagcc +atgaaagtgatcaaaaaagttcgtacttataccatacatgaattctggccaagtaaaaaa +tagattgcgcaaaattcgtaccttaagtctctcgccaagatattaggatcctattactca +tatcgtgtttttctttattgccgccatccccggagtatctcacccatccttctcttaaag +gcctaatattacctatgcaaataaacatatattgttgaaaattgagaacctgatcgtgat +tcttatgtgtaccatatgtatagtaatcacgcgactatatagtgctttagtatcgcccgt +gggtgagtgaatattctgggctagcgtgagatagtttcttgtcctaatatttttcagatc +gaatagcttctatttttgtgtttattgacatatgtcgaaactccttactcagtgaaagtc +atgaccagatccacgaacaatcttcggaatcagtctcgttttacggcggaatcttgagtc +taacttatatcccgtcgcttactttctaacaccccttatgtatttttaaaattacgttta +ttcgaacgtacttggcggaagcgttattttttgaagtaagttacattgggcagactcttg +acattttcgatacgactttctttcatccatcacaggactcgttcgtattgatatcagaag +ctcgtgatgattagttgtcttctttaccaatactttgaggcctattctgcgaaatttttg +ttgccctgcgaacttcacataccaaggaacacctcgcaacatgccttcatatccatcgtt +cattgtaattcttacacaatgaatcctaagtaattacatccctgcgtaaaagatggtagg +ggcactgaggatatattaccaagcatttagttatgagtaatcagcaatgtttcttgtatt +aagttctctaaaatagttacatcgtaatgttatctcgggttccgcgaataaacgagatag +attcattatatatggccctaagcaaaaacctcctcgtattctgttggtaattagaatcac +acaatacgggttgagatattaattatttgtagtacgaagagatataaaaagatgaacaat +tactcaagtcaagatgtatacgggatttataataaaaatcgggtagagatctgctttgca +attcagacgtgccactaaatcgtaatatgtcgcgttacatcagaaagggtaactattatt +aattaataaagggcttaatcactacatattagatcttatccgatagtcttatctattcgt +tgtatttttaagcggttctaattcagtcattatatcagtgctccgagttctttattattg +ttttaaggatgacaaaatgcctcttgttataacgctgggagaagcagactaagagtcgga +gcagttggtagaatgaggctgcaaaagacggtctcgacgaatggacagactttactaaac +caatgaaagacagaagtagagcaaagtctgaagtggtatcagcttaattatgacaaccct +taatacttccctttcgccgaatactggcgtggaaaggttttaaaagtcgaagtagttaga +ggcatctctcgctcataaataggtagactactcgcaatccaatgtgactatgtaatactg +ggaacatcagtccgcgatgcagcgtgtttatcaaccgtccccactcgcctggggagacat +gagaccacccccgtggggattattagtccgcagtaatcgactcttgacaatccttttcga +ttatgtcatagcaatttacgacagttcagcgaagtgactactcggcgaaatggtattact +aaagcattcgaacccacatgaatgtgattcttggcaatttctaatccactaaagcttttc +cgttgaatctggttgtagatatttatataagttcactaattaagatcacggtagtatatt +gatagtgatgtctttgcaagaggttggccgaggaatttacggattctctattgatacaat +ttgtctggcttataactcttaaggctgaaccaggcgtttttagacgacttgatcagctgt +tagaatggtttggactccctctttcatgtcagtaacatttcagccgttattgttacgata +tgcttgaacaatattgatctaccacacacccatagtatattttataggtcatgctgttac +ctacgagcatggtattccacttcccattcaatgagtattcaacatcactagcctcagaga +tgatgacccacctctaataacgtcacgttgcggccatgtgaaacctgaacttgagtagac +gatatcaagcgctttaaattgcatataacatttgagggtaaagctaagcggatgctttat +ataatcaatactcaataataagatttgattgcattttagagttatgacacgacatagttc +actaacgagttactattcccagatctagactgaagtactgatcgagacgatccttacgtc +gatgatcgttagttatcgacttaggtcgggtctctagcggtattggtacttaaccggaca +ctatactaataacccatgatcaaagcataacagaatacagacgataatttcgccaacata +tatgtacagaccccaagcatgagaagctcattgaaagctatcattgaagtcccgctcaca +atgtgtcttttccagacggtttaactggttcccgggagtcctggagtttcgacttacata +aatggaaacaatgtattttgctaatttatctatagcgtcatttggaccaatacagaatat +tatgttgcctagtaatccactataacccgcaagtgctgatagaaaatttttagacgattt +ataaatgccccaagtatccctcccgtgaatcctccgttatactaattagtattcgttcat +acgtataccgcgcatatatgaacatttggcgataaggcgcgtgaattgttacgtgacaga +gatagcagtttcttgtgatatggttaacagacgtacatgaagggaaactttatatctata +gtgatgcttccgtagaaataccgccactggtctgccaatgatgaagtatgtagctttagg +tttgtactatgaggctttcgtttgtttgcagagtataacagttgcgagtgaaaaaccgac +gaatttatactaatacgctttcactattggctacaaaatagggaagagtttcaatcatga +gagggagtatatggatgctttgtagctaaaggtagaacgtatgtatatgctgccgttcat +tcttgaaagatacataagcgataagttacgacaattataagcaacatccctaccttcgta +acgatttcactgttactgcgcttgaaatacactatggggctattggcggagagaagcaga +tcgcgccgagcatatacgagacctataatgttgatgatagagaaggcgtctgaattgata +catcgaagtacactttctttcgtagtatctctcgtcctctttctatctccggacacaaga +attaagttatatatatagagtcttaccaatcatgttgaatcctgattctcagagttcttt +ggcgggccttgtgatgactgagaaacaatgcaatattgctccaaatttcctaagcaaatt +ctcggttatgttatgttatcagcaaagcgttacgttatgttatttaaatctggaatgacg +gagcgaagttcttatgtcggtgtgggaataattcttttgaagacagcactccttaaataa +tatcgctccgtgtttgtatttatcgaatgggtctgtaaccttgcacaagcaaatcggtgg +tgtatatatcggataacaattaatacgatgttcatagtgacagtatactgatcgagtcct +ctaaagtcaattacctcacttaacaatctcattgatgttgtgtcattcccggtatcgccc +gtagtatgtgctctgattgaccgagtgtgaaccaaggaacatctactaatgcctttgtta +ggtaagatctctctgaattccttcgtgccaacttaaaacattatcaaaatttcttctact +tggattaactacttttacgagcatggcaaattcccctgtggaagacggttcattattatc +ggaaaccttatagaaattgcgtgttgactgaaattagatttttattgtaagagttgcatc +tttgcgattcctctggtctagcttccaatgaacagtcctcccttctattcgacatcgggt +ccttcgtacatgtctttgcgatgtaataattaggttcggagtgtggccttaatgggtgca +actaggaatacaacgcaaatttgctgacatgatagcaaatcggtatgccggcaccaaaac +gtgctccttgcttagcttgtgaatgagactcagtagttaaataaatccatatctgcaatc +gattccacaggtattgtccactatctttgaactactctaagagatacaagcttagctgag +accgaggtgtatatgactacgctgatatctgtaaggtaccaatgcaggcaaagtatgcga +gaagctaataccggctgtttccagctttataagattaaaatttggctgtcctggcggcct +cagaattgttctatcgtaatcagttggttcattaattagctaagtacgaggtacaactta +tctgtcccagaacagctccacaagtttttttacagccgaaacccctgtgtgaatcttaat +atccaagcgcgttatctgattagagtttacaactcagtattttatcagtacgttttgttt +ccaacattacccggtatgacaaaatgacgccacgtgtcgaataatggtctgaccaatgta +ggaagtgaaaagataaatat diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/k-nucleotide-parallel.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/k-nucleotide-parallel.go new file mode 100644 index 0000000..8b25419 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/k-nucleotide-parallel.go @@ -0,0 +1,160 @@ +//go:build ignore +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* The Computer Language Benchmarks Game + * http://shootout.alioth.debian.org/ + * + * contributed by The Go Authors. + */ + +package main + +import ( + "bufio" + "bytes" + "fmt" + "io/ioutil" + "os" + "runtime" + "sort" +) + +func count(data string, n int) map[string]int { + counts := make(map[string]int) + top := len(data) - n + for i := 0; i <= top; i++ { + s := data[i : i+n] + counts[s]++ + } + return counts +} + +func countOne(data string, s string) int { + return count(data, len(s))[s] +} + +type kNuc struct { + name string + count int +} + +type kNucArray []kNuc + +func (kn kNucArray) Len() int { return len(kn) } +func (kn kNucArray) Swap(i, j int) { kn[i], kn[j] = kn[j], kn[i] } +func (kn kNucArray) Less(i, j int) bool { + if kn[i].count == kn[j].count { + return kn[i].name > kn[j].name // sort down + } + return kn[i].count > kn[j].count +} + +func sortedArray(m map[string]int) kNucArray { + kn := make(kNucArray, len(m)) + i := 0 + for k, v := range m { + kn[i] = kNuc{k, v} + i++ + } + sort.Sort(kn) + return kn +} + +func printKnucs(a kNucArray) { + sum := 0 + for _, kn := range a { + sum += kn.count + } + for _, kn := range a { + fmt.Printf("%s %.3f\n", kn.name, 100*float64(kn.count)/float64(sum)) + } + fmt.Print("\n") +} + +func main() { + runtime.GOMAXPROCS(4) + in := bufio.NewReader(os.Stdin) + three := []byte(">THREE ") + for { + line, err := in.ReadSlice('\n') + if err != nil { + fmt.Fprintln(os.Stderr, "ReadLine err:", err) + os.Exit(2) + } + if line[0] == '>' && bytes.Equal(line[0:len(three)], three) { + break + } + } + data, err := ioutil.ReadAll(in) + if err != nil { + fmt.Fprintln(os.Stderr, "ReadAll err:", err) + os.Exit(2) + } + // delete the newlines and convert to upper case + j := 0 + for i := 0; i < len(data); i++ { + if data[i] != '\n' { + data[j] = data[i] &^ ' ' // upper case + j++ + } + } + str := string(data[0:j]) + + var arr1, arr2 kNucArray + countsdone := make(chan bool) + go func() { + arr1 = sortedArray(count(str, 1)) + countsdone <- true + }() + go func() { + arr2 = sortedArray(count(str, 2)) + countsdone <- true + }() + + interests := []string{"GGT", "GGTA", "GGTATT", "GGTATTTTAATT", "GGTATTTTAATTTATAGT"} + results := make([]chan string, len(interests)) + for i, s := range interests { + ch := make(chan string) + results[i] = ch + go func(result chan string, ss string) { + result <- fmt.Sprintf("%d %s\n", countOne(str, ss), ss) + }(ch, s) + } + <-countsdone + <-countsdone + printKnucs(arr1) + printKnucs(arr2) + for _, rc := range results { + fmt.Print(<-rc) + } + +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/k-nucleotide-parallel.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/k-nucleotide-parallel.txt new file mode 100644 index 0000000..84169b8 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/k-nucleotide-parallel.txt @@ -0,0 +1,27 @@ +T 31.520 +A 29.600 +C 19.480 +G 19.400 + +AT 9.922 +TT 9.602 +TA 9.402 +AA 8.402 +GA 6.321 +TC 6.301 +TG 6.201 +GT 6.041 +CT 5.961 +AG 5.841 +CA 5.461 +AC 5.441 +CC 4.041 +CG 4.021 +GC 3.701 +GG 3.341 + +54 GGT +24 GGTA +4 GGTATT +0 GGTATTTTAATT +0 GGTATTTTAATTTATAGT diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/k-nucleotide.c b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/k-nucleotide.c new file mode 100644 index 0000000..6f54dce --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/k-nucleotide.c @@ -0,0 +1,230 @@ +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <stdlib.h> +#include <glib.h> + +typedef struct stat_s stat_t; +struct stat_s +{ + const gchar *key; + long stat; +}; + +#define MAX_ELM (8192 / sizeof (stat_t)) + +static int +generate_frequencies (int fl, char *buffer, long buflen, + GHashTable *ht, GTrashStack **ts, GPtrArray *roots, GStringChunk *sc) +{ + gchar *key; + long i; + + if (fl > buflen) return 0; + if (fl == 0) return 0; + + for (i = 0; i < buflen - fl + 1; ++i) + { + char nulled; + stat_t *stat; + + nulled = buffer[i + fl]; + buffer[i + fl] = '\0'; + + key = g_string_chunk_insert_const(sc, buffer + i); + + stat = g_hash_table_lookup(ht, key); + if (!stat) + { + stat = g_trash_stack_pop(ts); + if (!stat) + { + int j; + + stat = malloc(sizeof (stat_t) * MAX_ELM); + g_ptr_array_add(roots, stat); + + for (j = 1; j < MAX_ELM; ++j) + g_trash_stack_push(ts, stat + j); + } + stat->stat = 1; + stat->key = key; + + g_hash_table_insert(ht, key, stat); + } + else + stat->stat++; + + buffer[i + fl] = nulled; + } + + return buflen - fl + 1; +} + +static int +cmp_func(gconstpointer a, gconstpointer b) +{ + const stat_t *left = a; + const stat_t *right = b; + + return right->stat - left->stat; +} + +static void +sorted_list(gpointer key, gpointer value, gpointer user_data) +{ + stat_t *data = value; + GList **lst = user_data; + + *lst = g_list_insert_sorted(*lst, data, cmp_func); +} + +static void +display_stat(gpointer data, gpointer user_data) +{ + long *total = user_data; + stat_t *st = data; + + printf("%s %.3f\n", st->key, 100 * (float) st->stat / *total); +} + +void +write_frequencies (int fl, char *buffer, long buflen, GTrashStack **ts, GPtrArray *roots) +{ + GStringChunk *sc; + GHashTable *ht; + GList *lst; + long total; + + ht = g_hash_table_new_full(g_str_hash, g_str_equal, NULL /* free key */, NULL /* free value */); + sc = g_string_chunk_new(buflen); + lst = NULL; + + total = generate_frequencies (fl, buffer, buflen, ht, ts, roots, sc); + + if (!total) goto on_error; + + g_hash_table_foreach(ht, sorted_list, &lst); + g_list_foreach(lst, display_stat, &total); + g_list_free(lst); + + on_error: + g_hash_table_destroy(ht); + g_string_chunk_free(sc); +} + +void +write_count (char *searchFor, char *buffer, long buflen, GTrashStack **ts, GPtrArray *roots) +{ + GStringChunk *sc; + GHashTable *ht; + stat_t *result; + GList *lst; + long total; + long fl; + + fl = strlen(searchFor); + + ht = g_hash_table_new_full(g_str_hash, g_str_equal, NULL /* free key */, NULL /* free value */); + sc = g_string_chunk_new(buflen); + lst = NULL; + result = NULL; + + total = generate_frequencies (fl, buffer, buflen, ht, ts, roots, sc); + + if (!total) goto on_error; + + result = g_hash_table_lookup(ht, searchFor); + + on_error: + printf("%ld\t%s\n", result ? result->stat : 0, searchFor); + + g_hash_table_destroy(ht); + g_string_chunk_free(sc); +} + +int +main () +{ + char buffer[4096]; + GTrashStack *ts; + GPtrArray *roots; + GString *stuff; + gchar *s; + int len; + + roots = g_ptr_array_new(); + ts = NULL; + + while (fgets(buffer, sizeof (buffer), stdin)) + if (strncmp(buffer, ">THREE", 6) == 0) + break; + + stuff = g_string_new(NULL); + + while (fgets(buffer, sizeof (buffer), stdin)) + { + size_t sz; + + if (buffer[0] == '>') + break; + + sz = strlen(buffer); + if (buffer[sz - 1] == '\n') + --sz; + + stuff = g_string_append_len(stuff, buffer, sz); + } + + stuff = g_string_ascii_up(stuff); + len = stuff->len; + s = g_string_free(stuff, FALSE); + + write_frequencies(1, s, len, &ts, roots); + printf("\n"); + write_frequencies(2, s, len, &ts, roots); + printf("\n"); + write_count("GGT", s, len, &ts, roots); + write_count("GGTA", s, len, &ts, roots); + write_count("GGTATT", s, len, &ts, roots); + write_count("GGTATTTTAATT", s, len, &ts, roots); + write_count("GGTATTTTAATTTATAGT", s, len, &ts, roots); + + free(s); + + g_ptr_array_foreach(roots, (GFunc)free, NULL); + g_ptr_array_free(roots, TRUE); + + return 0; +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/k-nucleotide.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/k-nucleotide.go new file mode 100644 index 0000000..efc8d95 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/k-nucleotide.go @@ -0,0 +1,143 @@ +//go:build ignore +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* The Computer Language Benchmarks Game + * http://shootout.alioth.debian.org/ + * + * contributed by The Go Authors. + */ + +package main + +import ( + "bufio" + "bytes" + "fmt" + "io/ioutil" + "os" + "sort" +) + +var in *bufio.Reader + +func count(data string, n int) map[string]int { + counts := make(map[string]int) + top := len(data) - n + for i := 0; i <= top; i++ { + s := data[i : i+n] + counts[s]++ + } + return counts +} + +func countOne(data string, s string) int { + return count(data, len(s))[s] +} + +type kNuc struct { + name string + count int +} + +type kNucArray []kNuc + +func (kn kNucArray) Len() int { return len(kn) } +func (kn kNucArray) Swap(i, j int) { kn[i], kn[j] = kn[j], kn[i] } +func (kn kNucArray) Less(i, j int) bool { + if kn[i].count == kn[j].count { + return kn[i].name > kn[j].name // sort down + } + return kn[i].count > kn[j].count +} + +func sortedArray(m map[string]int) kNucArray { + kn := make(kNucArray, len(m)) + i := 0 + for k, v := range m { + kn[i].name = k + kn[i].count = v + i++ + } + sort.Sort(kn) + return kn +} + +func print(m map[string]int) { + a := sortedArray(m) + sum := 0 + for _, kn := range a { + sum += kn.count + } + for _, kn := range a { + fmt.Printf("%s %.3f\n", kn.name, 100*float64(kn.count)/float64(sum)) + } +} + +func main() { + in = bufio.NewReader(os.Stdin) + three := []byte(">THREE ") + for { + line, err := in.ReadSlice('\n') + if err != nil { + fmt.Fprintln(os.Stderr, "ReadLine err:", err) + os.Exit(2) + } + if line[0] == '>' && bytes.Equal(line[0:len(three)], three) { + break + } + } + data, err := ioutil.ReadAll(in) + if err != nil { + fmt.Fprintln(os.Stderr, "ReadAll err:", err) + os.Exit(2) + } + // delete the newlines and convert to upper case + j := 0 + for i := 0; i < len(data); i++ { + if data[i] != '\n' { + data[j] = data[i] &^ ' ' // upper case + j++ + } + } + str := string(data[0:j]) + + print(count(str, 1)) + fmt.Print("\n") + + print(count(str, 2)) + fmt.Print("\n") + + interests := []string{"GGT", "GGTA", "GGTATT", "GGTATTTTAATT", "GGTATTTTAATTTATAGT"} + for _, s := range interests { + fmt.Printf("%d %s\n", countOne(str, s), s) + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/k-nucleotide.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/k-nucleotide.txt new file mode 100644 index 0000000..84169b8 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/k-nucleotide.txt @@ -0,0 +1,27 @@ +T 31.520 +A 29.600 +C 19.480 +G 19.400 + +AT 9.922 +TT 9.602 +TA 9.402 +AA 8.402 +GA 6.321 +TC 6.301 +TG 6.201 +GT 6.041 +CT 5.961 +AG 5.841 +CA 5.461 +AC 5.441 +CC 4.041 +CG 4.021 +GC 3.701 +GG 3.341 + +54 GGT +24 GGTA +4 GGTATT +0 GGTATTTTAATT +0 GGTATTTTAATTTATAGT diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/mandelbrot.c b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/mandelbrot.c new file mode 100644 index 0000000..9fac37a --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/mandelbrot.c @@ -0,0 +1,93 @@ +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* The Computer Language Shootout + http://shootout.alioth.debian.org/ + + contributed by Greg Buchholz + + for the debian (AMD) machine... + compile flags: -O3 -ffast-math -march=athlon-xp -funroll-loops + + for the gp4 (Intel) machine... + compile flags: -O3 -ffast-math -march=pentium4 -funroll-loops +*/ + +#include<stdio.h> + +int main (int argc, char **argv) +{ + int w, h, bit_num = 0; + char byte_acc = 0; + int i, iter = 50; + double x, y, limit = 2.0; + double Zr, Zi, Cr, Ci, Tr, Ti; + + w = h = atoi(argv[1]); + + printf("P4\n%d %d\n",w,h); + + for(y=0;y<h;++y) + { + for(x=0;x<w;++x) + { + Zr = Zi = Tr = Ti = 0.0; + Cr = (2.0*x/w - 1.5); Ci=(2.0*y/h - 1.0); + + for (i=0;i<iter && (Tr+Ti <= limit*limit);++i) + { + Zi = 2.0*Zr*Zi + Ci; + Zr = Tr - Ti + Cr; + Tr = Zr * Zr; + Ti = Zi * Zi; + } + + byte_acc <<= 1; + if(Tr+Ti <= limit*limit) byte_acc |= 0x01; + + ++bit_num; + + if(bit_num == 8) + { + putc(byte_acc,stdout); + byte_acc = 0; + bit_num = 0; + } + else if(x == w-1) + { + byte_acc <<= (8-w%8); + putc(byte_acc,stdout); + byte_acc = 0; + bit_num = 0; + } + } + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/mandelbrot.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/mandelbrot.go new file mode 100644 index 0000000..2b82a2f --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/mandelbrot.go @@ -0,0 +1,98 @@ +//go:build ignore +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* The Computer Language Benchmarks Game + * http://shootout.alioth.debian.org/ + * + * contributed by The Go Authors. + * Based on mandelbrot.c contributed by Greg Buchholz + */ + +package main + +import ( + "bufio" + "flag" + "fmt" + "os" +) + +var n = flag.Int("n", 200, "size") + +func main() { + flag.Parse() + out := bufio.NewWriter(os.Stdout) + defer out.Flush() + + w := float64(*n) + h := float64(*n) + bit_num := 0 + byte_acc := byte(0) + const Iter = 50 + const Zero float64 = 0 + const Limit = 2.0 + + fmt.Fprintf(out, "P4\n%d %d\n", *n, *n) + + for y := 0.0; y < h; y++ { + for x := 0.0; x < w; x++ { + Zr, Zi, Tr, Ti := Zero, Zero, Zero, Zero + Cr := (2*x/w - 1.5) + Ci := (2*y/h - 1.0) + + for i := 0; i < Iter && (Tr+Ti <= Limit*Limit); i++ { + Zi = 2*Zr*Zi + Ci + Zr = Tr - Ti + Cr + Tr = Zr * Zr + Ti = Zi * Zi + } + + byte_acc <<= 1 + if Tr+Ti <= Limit*Limit { + byte_acc |= 0x01 + } + + bit_num++ + + if bit_num == 8 { + out.WriteByte(byte_acc) + byte_acc = 0 + bit_num = 0 + } else if x == w-1 { + byte_acc <<= uint(8 - uint(*n)%8) + out.WriteByte(byte_acc) + byte_acc = 0 + bit_num = 0 + } + } + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/mandelbrot.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/mandelbrot.txt Binary files differnew file mode 100644 index 0000000..2f7bbbc --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/mandelbrot.txt diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/meteor-contest.c b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/meteor-contest.c new file mode 100644 index 0000000..dda181b --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/meteor-contest.c @@ -0,0 +1,628 @@ +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* The Computer Language Benchmarks Game + * http://shootout.alioth.debian.org/ + * + * contributed by Christian Vosteen + */ + +#include <stdlib.h> +#include <stdio.h> +#define TRUE 1 +#define FALSE 0 + +/* The board is a 50 cell hexagonal pattern. For . . . . . + * maximum speed the board will be implemented as . . . . . + * 50 bits, which will fit into a 64 bit long long . . . . . + * int. . . . . . + * . . . . . + * I will represent 0's as empty cells and 1's . . . . . + * as full cells. . . . . . + * . . . . . + * . . . . . + * . . . . . + */ + +unsigned long long board = 0xFFFC000000000000ULL; + +/* The puzzle pieces must be specified by the path followed + * from one end to the other along 12 hexagonal directions. + * + * Piece 0 Piece 1 Piece 2 Piece 3 Piece 4 + * + * O O O O O O O O O O O O O O O + * O O O O O O O + * O O O + * + * Piece 5 Piece 6 Piece 7 Piece 8 Piece 9 + * + * O O O O O O O O O O O O O + * O O O O O O O O O + * O O O + * + * I had to make it 12 directions because I wanted all of the + * piece definitions to fit into the same size arrays. It is + * not possible to define piece 4 in terms of the 6 cardinal + * directions in 4 moves. + */ + +#define E 0 +#define ESE 1 +#define SE 2 +#define S 3 +#define SW 4 +#define WSW 5 +#define W 6 +#define WNW 7 +#define NW 8 +#define N 9 +#define NE 10 +#define ENE 11 +#define PIVOT 12 + +char piece_def[10][4] = { + { E, E, E, SE}, + { SE, E, NE, E}, + { E, E, SE, SW}, + { E, E, SW, SE}, + { SE, E, NE, S}, + { E, E, SW, E}, + { E, SE, SE, NE}, + { E, SE, SE, W}, + { E, SE, E, E}, + { E, E, E, SW} +}; + + +/* To minimize the amount of work done in the recursive solve function below, + * I'm going to allocate enough space for all legal rotations of each piece + * at each position on the board. That's 10 pieces x 50 board positions x + * 12 rotations. However, not all 12 rotations will fit on every cell, so + * I'll have to keep count of the actual number that do. + * The pieces are going to be unsigned long long ints just like the board so + * they can be bitwise-anded with the board to determine if they fit. + * I'm also going to record the next possible open cell for each piece and + * location to reduce the burden on the solve function. + */ +unsigned long long pieces[10][50][12]; +int piece_counts[10][50]; +char next_cell[10][50][12]; + +/* Returns the direction rotated 60 degrees clockwise */ +char rotate(char dir) { + return (dir + 2) % PIVOT; +} + +/* Returns the direction flipped on the horizontal axis */ +char flip(char dir) { + return (PIVOT - dir) % PIVOT; +} + + +/* Returns the new cell index from the specified cell in the + * specified direction. The index is only valid if the + * starting cell and direction have been checked by the + * out_of_bounds function first. + */ +char shift(char cell, char dir) { + switch(dir) { + case E: + return cell + 1; + case ESE: + if((cell / 5) % 2) + return cell + 7; + else + return cell + 6; + case SE: + if((cell / 5) % 2) + return cell + 6; + else + return cell + 5; + case S: + return cell + 10; + case SW: + if((cell / 5) % 2) + return cell + 5; + else + return cell + 4; + case WSW: + if((cell / 5) % 2) + return cell + 4; + else + return cell + 3; + case W: + return cell - 1; + case WNW: + if((cell / 5) % 2) + return cell - 6; + else + return cell - 7; + case NW: + if((cell / 5) % 2) + return cell - 5; + else + return cell - 6; + case N: + return cell - 10; + case NE: + if((cell / 5) % 2) + return cell - 4; + else + return cell - 5; + case ENE: + if((cell / 5) % 2) + return cell - 3; + else + return cell - 4; + default: + return cell; + } +} + +/* Returns wether the specified cell and direction will land outside + * of the board. Used to determine if a piece is at a legal board + * location or not. + */ +char out_of_bounds(char cell, char dir) { + char i; + switch(dir) { + case E: + return cell % 5 == 4; + case ESE: + i = cell % 10; + return i == 4 || i == 8 || i == 9 || cell >= 45; + case SE: + return cell % 10 == 9 || cell >= 45; + case S: + return cell >= 40; + case SW: + return cell % 10 == 0 || cell >= 45; + case WSW: + i = cell % 10; + return i == 0 || i == 1 || i == 5 || cell >= 45; + case W: + return cell % 5 == 0; + case WNW: + i = cell % 10; + return i == 0 || i == 1 || i == 5 || cell < 5; + case NW: + return cell % 10 == 0 || cell < 5; + case N: + return cell < 10; + case NE: + return cell % 10 == 9 || cell < 5; + case ENE: + i = cell % 10; + return i == 4 || i == 8 || i == 9 || cell < 5; + default: + return FALSE; + } +} + +/* Rotate a piece 60 degrees clockwise */ +void rotate_piece(int piece) { + int i; + for(i = 0; i < 4; i++) + piece_def[piece][i] = rotate(piece_def[piece][i]); +} + +/* Flip a piece along the horizontal axis */ +void flip_piece(int piece) { + int i; + for(i = 0; i < 4; i++) + piece_def[piece][i] = flip(piece_def[piece][i]); +} + +/* Convenience function to quickly calculate all of the indices for a piece */ +void calc_cell_indices(char *cell, int piece, char index) { + cell[0] = index; + cell[1] = shift(cell[0], piece_def[piece][0]); + cell[2] = shift(cell[1], piece_def[piece][1]); + cell[3] = shift(cell[2], piece_def[piece][2]); + cell[4] = shift(cell[3], piece_def[piece][3]); +} + +/* Convenience function to quickly calculate if a piece fits on the board */ +int cells_fit_on_board(char *cell, int piece) { + return (!out_of_bounds(cell[0], piece_def[piece][0]) && + !out_of_bounds(cell[1], piece_def[piece][1]) && + !out_of_bounds(cell[2], piece_def[piece][2]) && + !out_of_bounds(cell[3], piece_def[piece][3])); +} + +/* Returns the lowest index of the cells of a piece. + * I use the lowest index that a piece occupies as the index for looking up + * the piece in the solve function. + */ +char minimum_of_cells(char *cell) { + char minimum = cell[0]; + minimum = cell[1] < minimum ? cell[1] : minimum; + minimum = cell[2] < minimum ? cell[2] : minimum; + minimum = cell[3] < minimum ? cell[3] : minimum; + minimum = cell[4] < minimum ? cell[4] : minimum; + return minimum; +} + +/* Calculate the lowest possible open cell if the piece is placed on the board. + * Used to later reduce the amount of time searching for open cells in the + * solve function. + */ +char first_empty_cell(char *cell, char minimum) { + char first_empty = minimum; + while(first_empty == cell[0] || first_empty == cell[1] || + first_empty == cell[2] || first_empty == cell[3] || + first_empty == cell[4]) + first_empty++; + return first_empty; +} + +/* Generate the unsigned long long int that will later be anded with the + * board to determine if it fits. + */ +unsigned long long bitmask_from_cells(char *cell) { + unsigned long long piece_mask = 0ULL; + int i; + for(i = 0; i < 5; i++) + piece_mask |= 1ULL << cell[i]; + return piece_mask; +} + +/* Record the piece and other important information in arrays that will + * later be used by the solve function. + */ +void record_piece(int piece, int minimum, char first_empty, + unsigned long long piece_mask) { + pieces[piece][minimum][piece_counts[piece][minimum]] = piece_mask; + next_cell[piece][minimum][piece_counts[piece][minimum]] = first_empty; + piece_counts[piece][minimum]++; +} + + +/* Fill the entire board going cell by cell. If any cells are "trapped" + * they will be left alone. + */ +void fill_contiguous_space(char *board, int index) { + if(board[index] == 1) + return; + board[index] = 1; + if(!out_of_bounds(index, E)) + fill_contiguous_space(board, shift(index, E)); + if(!out_of_bounds(index, SE)) + fill_contiguous_space(board, shift(index, SE)); + if(!out_of_bounds(index, SW)) + fill_contiguous_space(board, shift(index, SW)); + if(!out_of_bounds(index, W)) + fill_contiguous_space(board, shift(index, W)); + if(!out_of_bounds(index, NW)) + fill_contiguous_space(board, shift(index, NW)); + if(!out_of_bounds(index, NE)) + fill_contiguous_space(board, shift(index, NE)); +} + + +/* To thin the number of pieces, I calculate if any of them trap any empty + * cells at the edges. There are only a handful of exceptions where the + * the board can be solved with the trapped cells. For example: piece 8 can + * trap 5 cells in the corner, but piece 3 can fit in those cells, or piece 0 + * can split the board in half where both halves are viable. + */ +int has_island(char *cell, int piece) { + char temp_board[50]; + char c; + int i; + for(i = 0; i < 50; i++) + temp_board[i] = 0; + for(i = 0; i < 5; i++) + temp_board[((int)cell[i])] = 1; + i = 49; + while(temp_board[i] == 1) + i--; + fill_contiguous_space(temp_board, i); + c = 0; + for(i = 0; i < 50; i++) + if(temp_board[i] == 0) + c++; + if(c == 0 || (c == 5 && piece == 8) || (c == 40 && piece == 8) || + (c % 5 == 0 && piece == 0)) + return FALSE; + else + return TRUE; +} + + +/* Calculate all six rotations of the specified piece at the specified index. + * We calculate only half of piece 3's rotations. This is because any solution + * found has an identical solution rotated 180 degrees. Thus we can reduce the + * number of attempted pieces in the solve algorithm by not including the 180- + * degree-rotated pieces of ONE of the pieces. I chose piece 3 because it gave + * me the best time ;) + */ + void calc_six_rotations(char piece, char index) { + char rotation, cell[5]; + char minimum, first_empty; + unsigned long long piece_mask; + + for(rotation = 0; rotation < 6; rotation++) { + if(piece != 3 || rotation < 3) { + calc_cell_indices(cell, piece, index); + if(cells_fit_on_board(cell, piece) && !has_island(cell, piece)) { + minimum = minimum_of_cells(cell); + first_empty = first_empty_cell(cell, minimum); + piece_mask = bitmask_from_cells(cell); + record_piece(piece, minimum, first_empty, piece_mask); + } + } + rotate_piece(piece); + } +} + +/* Calculate every legal rotation for each piece at each board location. */ +void calc_pieces(void) { + char piece, index; + + for(piece = 0; piece < 10; piece++) { + for(index = 0; index < 50; index++) { + calc_six_rotations(piece, index); + flip_piece(piece); + calc_six_rotations(piece, index); + } + } +} + + + +/* Calculate all 32 possible states for a 5-bit row and all rows that will + * create islands that follow any of the 32 possible rows. These pre- + * calculated 5-bit rows will be used to find islands in a partially solved + * board in the solve function. + */ +#define ROW_MASK 0x1F +#define TRIPLE_MASK 0x7FFF +char all_rows[32] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; +int bad_even_rows[32][32]; +int bad_odd_rows[32][32]; +int bad_even_triple[32768]; +int bad_odd_triple[32768]; + +int rows_bad(char row1, char row2, int even) { + /* even is referring to row1 */ + int i, in_zeroes, group_okay; + char block, row2_shift; + /* Test for blockages at same index and shifted index */ + if(even) + row2_shift = ((row2 << 1) & ROW_MASK) | 0x01; + else + row2_shift = (row2 >> 1) | 0x10; + block = ((row1 ^ row2) & row2) & ((row1 ^ row2_shift) & row2_shift); + /* Test for groups of 0's */ + in_zeroes = FALSE; + group_okay = FALSE; + for(i = 0; i < 5; i++) { + if(row1 & (1 << i)) { + if(in_zeroes) { + if(!group_okay) + return TRUE; + in_zeroes = FALSE; + group_okay = FALSE; + } + } else { + if(!in_zeroes) + in_zeroes = TRUE; + if(!(block & (1 << i))) + group_okay = TRUE; + } + } + if(in_zeroes) + return !group_okay; + else + return FALSE; +} + +/* Check for cases where three rows checked sequentially cause a false + * positive. One scenario is when 5 cells may be surrounded where piece 5 + * or 7 can fit. The other scenario is when piece 2 creates a hook shape. + */ +int triple_is_okay(char row1, char row2, char row3, int even) { + if(even) { + /* There are four cases: + * row1: 00011 00001 11001 10101 + * row2: 01011 00101 10001 10001 + * row3: 011?? 00110 ????? ????? + */ + return ((row1 == 0x03) && (row2 == 0x0B) && ((row3 & 0x1C) == 0x0C)) || + ((row1 == 0x01) && (row2 == 0x05) && (row3 == 0x06)) || + ((row1 == 0x19) && (row2 == 0x11)) || + ((row1 == 0x15) && (row2 == 0x11)); + } else { + /* There are two cases: + * row1: 10011 10101 + * row2: 10001 10001 + * row3: ????? ????? + */ + return ((row1 == 0x13) && (row2 == 0x11)) || + ((row1 == 0x15) && (row2 == 0x11)); + } +} + + +void calc_rows(void) { + int row1, row2, row3; + int result1, result2; + for(row1 = 0; row1 < 32; row1++) { + for(row2 = 0; row2 < 32; row2++) { + bad_even_rows[row1][row2] = rows_bad(row1, row2, TRUE); + bad_odd_rows[row1][row2] = rows_bad(row1, row2, FALSE); + } + } + for(row1 = 0; row1 < 32; row1++) { + for(row2 = 0; row2 < 32; row2++) { + for(row3 = 0; row3 < 32; row3++) { + result1 = bad_even_rows[row1][row2]; + result2 = bad_odd_rows[row2][row3]; + if(result1 == FALSE && result2 == TRUE + && triple_is_okay(row1, row2, row3, TRUE)) + bad_even_triple[row1+(row2*32)+(row3*1024)] = FALSE; + else + bad_even_triple[row1+(row2*32)+(row3*1024)] = result1 || result2; + + result1 = bad_odd_rows[row1][row2]; + result2 = bad_even_rows[row2][row3]; + if(result1 == FALSE && result2 == TRUE + && triple_is_okay(row1, row2, row3, FALSE)) + bad_odd_triple[row1+(row2*32)+(row3*1024)] = FALSE; + else + bad_odd_triple[row1+(row2*32)+(row3*1024)] = result1 || result2; + } + } + } +} + + + +/* Calculate islands while solving the board. + */ +int boardHasIslands(char cell) { + /* Too low on board, don't bother checking */ + if(cell >= 40) + return FALSE; + int current_triple = (board >> ((cell / 5) * 5)) & TRIPLE_MASK; + if((cell / 5) % 2) + return bad_odd_triple[current_triple]; + else + return bad_even_triple[current_triple]; +} + + +/* The recursive solve algorithm. Try to place each permutation in the upper- + * leftmost empty cell. Mark off available pieces as it goes along. + * Because the board is a bit mask, the piece number and bit mask must be saved + * at each successful piece placement. This data is used to create a 50 char + * array if a solution is found. + */ +short avail = 0x03FF; +char sol_nums[10]; +unsigned long long sol_masks[10]; +signed char solutions[2100][50]; +int solution_count = 0; +int max_solutions = 2100; + +void record_solution(void) { + int sol_no, index; + unsigned long long sol_mask; + for(sol_no = 0; sol_no < 10; sol_no++) { + sol_mask = sol_masks[sol_no]; + for(index = 0; index < 50; index++) { + if(sol_mask & 1ULL) { + solutions[solution_count][index] = sol_nums[sol_no]; + /* Board rotated 180 degrees is a solution too! */ + solutions[solution_count+1][49-index] = sol_nums[sol_no]; + } + sol_mask = sol_mask >> 1; + } + } + solution_count += 2; +} + +void solve(int depth, int cell) { + int piece, rotation, max_rots; + unsigned long long *piece_mask; + short piece_no_mask; + + if(solution_count >= max_solutions) + return; + + while(board & (1ULL << cell)) + cell++; + + for(piece = 0; piece < 10; piece++) { + piece_no_mask = 1 << piece; + if(!(avail & piece_no_mask)) + continue; + avail ^= piece_no_mask; + max_rots = piece_counts[piece][cell]; + piece_mask = pieces[piece][cell]; + for(rotation = 0; rotation < max_rots; rotation++) { + if(!(board & *(piece_mask + rotation))) { + sol_nums[depth] = piece; + sol_masks[depth] = *(piece_mask + rotation); + if(depth == 9) { + /* Solution found!!!!!11!!ONE! */ + record_solution(); + avail ^= piece_no_mask; + return; + } + board |= *(piece_mask + rotation); + if(!boardHasIslands(next_cell[piece][cell][rotation])) + solve(depth + 1, next_cell[piece][cell][rotation]); + board ^= *(piece_mask + rotation); + } + } + avail ^= piece_no_mask; + } +} + + +/* qsort comparator - used to find first and last solutions */ +int solution_sort(const void *elem1, const void *elem2) { + signed char *char1 = (signed char *) elem1; + signed char *char2 = (signed char *) elem2; + int i = 0; + while(i < 50 && char1[i] == char2[i]) + i++; + return char1[i] - char2[i]; +} + + +/* pretty print a board in the specified hexagonal format */ +void pretty(signed char *b) { + int i; + for(i = 0; i < 50; i += 10) { + printf("%c %c %c %c %c \n %c %c %c %c %c \n", b[i]+'0', b[i+1]+'0', + b[i+2]+'0', b[i+3]+'0', b[i+4]+'0', b[i+5]+'0', b[i+6]+'0', + b[i+7]+'0', b[i+8]+'0', b[i+9]+'0'); + } + printf("\n"); +} + +int main(int argc, char **argv) { + if(argc > 1) + max_solutions = atoi(argv[1]); + calc_pieces(); + calc_rows(); + solve(0, 0); + printf("%d solutions found\n\n", solution_count); + qsort(solutions, solution_count, 50 * sizeof(signed char), solution_sort); + pretty(solutions[0]); + pretty(solutions[solution_count-1]); + return 0; +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/meteor-contest.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/meteor-contest.go new file mode 100644 index 0000000..cfe49ec --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/meteor-contest.go @@ -0,0 +1,659 @@ +//go:build ignore +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* The Computer Language Benchmarks Game + * http://shootout.alioth.debian.org/ + * + * contributed by The Go Authors. + * based on meteor-contest.c by Christian Vosteen + */ + +package main + +import ( + "flag" + "fmt" +) + +var max_solutions = flag.Int("n", 2100, "maximum number of solutions") + +func boolInt(b bool) int8 { + if b { + return 1 + } + return 0 +} + +/* The board is a 50 cell hexagonal pattern. For . . . . . + * maximum speed the board will be implemented as . . . . . + * 50 bits, which will fit into a 64 bit long long . . . . . + * int. . . . . . + * . . . . . + * I will represent 0's as empty cells and 1's . . . . . + * as full cells. . . . . . + * . . . . . + * . . . . . + * . . . . . + */ + +var board uint64 = 0xFFFC000000000000 + +/* The puzzle pieces must be specified by the path followed + * from one end to the other along 12 hexagonal directions. + * + * Piece 0 Piece 1 Piece 2 Piece 3 Piece 4 + * + * O O O O O O O O O O O O O O O + * O O O O O O O + * O O O + * + * Piece 5 Piece 6 Piece 7 Piece 8 Piece 9 + * + * O O O O O O O O O O O O O + * O O O O O O O O O + * O O O + * + * I had to make it 12 directions because I wanted all of the + * piece definitions to fit into the same size arrays. It is + * not possible to define piece 4 in terms of the 6 cardinal + * directions in 4 moves. + */ + +const ( + E = iota + ESE + SE + S + SW + WSW + W + WNW + NW + N + NE + ENE + PIVOT +) + +var piece_def = [10][4]int8{ + [4]int8{E, E, E, SE}, + [4]int8{SE, E, NE, E}, + [4]int8{E, E, SE, SW}, + [4]int8{E, E, SW, SE}, + [4]int8{SE, E, NE, S}, + [4]int8{E, E, SW, E}, + [4]int8{E, SE, SE, NE}, + [4]int8{E, SE, SE, W}, + [4]int8{E, SE, E, E}, + [4]int8{E, E, E, SW}, +} + +/* To minimize the amount of work done in the recursive solve function below, + * I'm going to allocate enough space for all legal rotations of each piece + * at each position on the board. That's 10 pieces x 50 board positions x + * 12 rotations. However, not all 12 rotations will fit on every cell, so + * I'll have to keep count of the actual number that do. + * The pieces are going to be unsigned long long ints just like the board so + * they can be bitwise-anded with the board to determine if they fit. + * I'm also going to record the next possible open cell for each piece and + * location to reduce the burden on the solve function. + */ +var ( + pieces [10][50][12]uint64 + piece_counts [10][50]int + next_cell [10][50][12]int8 +) + +/* Returns the direction rotated 60 degrees clockwise */ +func rotate(dir int8) int8 { return (dir + 2) % PIVOT } + +/* Returns the direction flipped on the horizontal axis */ +func flip(dir int8) int8 { return (PIVOT - dir) % PIVOT } + +/* Returns the new cell index from the specified cell in the + * specified direction. The index is only valid if the + * starting cell and direction have been checked by the + * out_of_bounds function first. + */ +func shift(cell, dir int8) int8 { + switch dir { + case E: + return cell + 1 + case ESE: + if ((cell / 5) % 2) != 0 { + return cell + 7 + } else { + return cell + 6 + } + case SE: + if ((cell / 5) % 2) != 0 { + return cell + 6 + } else { + return cell + 5 + } + case S: + return cell + 10 + case SW: + if ((cell / 5) % 2) != 0 { + return cell + 5 + } else { + return cell + 4 + } + case WSW: + if ((cell / 5) % 2) != 0 { + return cell + 4 + } else { + return cell + 3 + } + case W: + return cell - 1 + case WNW: + if ((cell / 5) % 2) != 0 { + return cell - 6 + } else { + return cell - 7 + } + case NW: + if ((cell / 5) % 2) != 0 { + return cell - 5 + } else { + return cell - 6 + } + case N: + return cell - 10 + case NE: + if ((cell / 5) % 2) != 0 { + return cell - 4 + } else { + return cell - 5 + } + case ENE: + if ((cell / 5) % 2) != 0 { + return cell - 3 + } else { + return cell - 4 + } + } + return cell +} + +/* Returns wether the specified cell and direction will land outside + * of the board. Used to determine if a piece is at a legal board + * location or not. + */ +func out_of_bounds(cell, dir int8) bool { + switch dir { + case E: + return cell%5 == 4 + case ESE: + i := cell % 10 + return i == 4 || i == 8 || i == 9 || cell >= 45 + case SE: + return cell%10 == 9 || cell >= 45 + case S: + return cell >= 40 + case SW: + return cell%10 == 0 || cell >= 45 + case WSW: + i := cell % 10 + return i == 0 || i == 1 || i == 5 || cell >= 45 + case W: + return cell%5 == 0 + case WNW: + i := cell % 10 + return i == 0 || i == 1 || i == 5 || cell < 5 + case NW: + return cell%10 == 0 || cell < 5 + case N: + return cell < 10 + case NE: + return cell%10 == 9 || cell < 5 + case ENE: + i := cell % 10 + return i == 4 || i == 8 || i == 9 || cell < 5 + } + return false +} + +/* Rotate a piece 60 degrees clockwise */ +func rotate_piece(piece int) { + for i := 0; i < 4; i++ { + piece_def[piece][i] = rotate(piece_def[piece][i]) + } +} + +/* Flip a piece along the horizontal axis */ +func flip_piece(piece int) { + for i := 0; i < 4; i++ { + piece_def[piece][i] = flip(piece_def[piece][i]) + } +} + +/* Convenience function to quickly calculate all of the indices for a piece */ +func calc_cell_indices(cell []int8, piece int, index int8) { + cell[0] = index + for i := 1; i < 5; i++ { + cell[i] = shift(cell[i-1], piece_def[piece][i-1]) + } +} + +/* Convenience function to quickly calculate if a piece fits on the board */ +func cells_fit_on_board(cell []int8, piece int) bool { + return !out_of_bounds(cell[0], piece_def[piece][0]) && + !out_of_bounds(cell[1], piece_def[piece][1]) && + !out_of_bounds(cell[2], piece_def[piece][2]) && + !out_of_bounds(cell[3], piece_def[piece][3]) +} + +/* Returns the lowest index of the cells of a piece. + * I use the lowest index that a piece occupies as the index for looking up + * the piece in the solve function. + */ +func minimum_of_cells(cell []int8) int8 { + minimum := cell[0] + for i := 1; i < 5; i++ { + if cell[i] < minimum { + minimum = cell[i] + } + } + return minimum +} + +/* Calculate the lowest possible open cell if the piece is placed on the board. + * Used to later reduce the amount of time searching for open cells in the + * solve function. + */ +func first_empty_cell(cell []int8, minimum int8) int8 { + first_empty := minimum + for first_empty == cell[0] || first_empty == cell[1] || + first_empty == cell[2] || first_empty == cell[3] || + first_empty == cell[4] { + first_empty++ + } + return first_empty +} + +/* Generate the unsigned long long int that will later be anded with the + * board to determine if it fits. + */ +func bitmask_from_cells(cell []int8) uint64 { + var piece_mask uint64 + for i := 0; i < 5; i++ { + piece_mask |= 1 << uint(cell[i]) + } + return piece_mask +} + +/* Record the piece and other important information in arrays that will + * later be used by the solve function. + */ +func record_piece(piece int, minimum int8, first_empty int8, piece_mask uint64) { + pieces[piece][minimum][piece_counts[piece][minimum]] = piece_mask + next_cell[piece][minimum][piece_counts[piece][minimum]] = first_empty + piece_counts[piece][minimum]++ +} + +/* Fill the entire board going cell by cell. If any cells are "trapped" + * they will be left alone. + */ +func fill_contiguous_space(board []int8, index int8) { + if board[index] == 1 { + return + } + board[index] = 1 + if !out_of_bounds(index, E) { + fill_contiguous_space(board, shift(index, E)) + } + if !out_of_bounds(index, SE) { + fill_contiguous_space(board, shift(index, SE)) + } + if !out_of_bounds(index, SW) { + fill_contiguous_space(board, shift(index, SW)) + } + if !out_of_bounds(index, W) { + fill_contiguous_space(board, shift(index, W)) + } + if !out_of_bounds(index, NW) { + fill_contiguous_space(board, shift(index, NW)) + } + if !out_of_bounds(index, NE) { + fill_contiguous_space(board, shift(index, NE)) + } +} + +/* To thin the number of pieces, I calculate if any of them trap any empty + * cells at the edges. There are only a handful of exceptions where the + * the board can be solved with the trapped cells. For example: piece 8 can + * trap 5 cells in the corner, but piece 3 can fit in those cells, or piece 0 + * can split the board in half where both halves are viable. + */ +func has_island(cell []int8, piece int) bool { + temp_board := make([]int8, 50) + var i int + for i = 0; i < 5; i++ { + temp_board[cell[i]] = 1 + } + i = 49 + for temp_board[i] == 1 { + i-- + } + fill_contiguous_space(temp_board, int8(i)) + c := 0 + for i = 0; i < 50; i++ { + if temp_board[i] == 0 { + c++ + } + } + if c == 0 || (c == 5 && piece == 8) || (c == 40 && piece == 8) || + (c%5 == 0 && piece == 0) { + return false + } + return true +} + +/* Calculate all six rotations of the specified piece at the specified index. + * We calculate only half of piece 3's rotations. This is because any solution + * found has an identical solution rotated 180 degrees. Thus we can reduce the + * number of attempted pieces in the solve algorithm by not including the 180- + * degree-rotated pieces of ONE of the pieces. I chose piece 3 because it gave + * me the best time ;) + */ +func calc_six_rotations(piece, index int) { + cell := make([]int8, 5) + for rotation := 0; rotation < 6; rotation++ { + if piece != 3 || rotation < 3 { + calc_cell_indices(cell, piece, int8(index)) + if cells_fit_on_board(cell, piece) && !has_island(cell, piece) { + minimum := minimum_of_cells(cell) + first_empty := first_empty_cell(cell, minimum) + piece_mask := bitmask_from_cells(cell) + record_piece(piece, minimum, first_empty, piece_mask) + } + } + rotate_piece(piece) + } +} + +/* Calculate every legal rotation for each piece at each board location. */ +func calc_pieces() { + for piece := 0; piece < 10; piece++ { + for index := 0; index < 50; index++ { + calc_six_rotations(piece, index) + flip_piece(piece) + calc_six_rotations(piece, index) + } + } +} + +/* Calculate all 32 possible states for a 5-bit row and all rows that will + * create islands that follow any of the 32 possible rows. These pre- + * calculated 5-bit rows will be used to find islands in a partially solved + * board in the solve function. + */ +const ( + ROW_MASK = 0x1F + TRIPLE_MASK = 0x7FFF +) + +var ( + all_rows = [32]int8{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + } + bad_even_rows [32][32]int8 + bad_odd_rows [32][32]int8 + bad_even_triple [32768]int8 + bad_odd_triple [32768]int8 +) + +func rows_bad(row1, row2 int8, even bool) int8 { + /* even is referring to row1 */ + var row2_shift int8 + /* Test for blockages at same index and shifted index */ + if even { + row2_shift = ((row2 << 1) & ROW_MASK) | 0x01 + } else { + row2_shift = (row2 >> 1) | 0x10 + } + block := ((row1 ^ row2) & row2) & ((row1 ^ row2_shift) & row2_shift) + /* Test for groups of 0's */ + in_zeroes := false + group_okay := false + for i := uint8(0); i < 5; i++ { + if row1&(1<<i) != 0 { + if in_zeroes { + if !group_okay { + return 1 + } + in_zeroes = false + group_okay = false + } + } else { + if !in_zeroes { + in_zeroes = true + } + if (block & (1 << i)) == 0 { + group_okay = true + } + } + } + if in_zeroes { + return boolInt(!group_okay) + } + return 0 +} + +/* Check for cases where three rows checked sequentially cause a false + * positive. One scenario is when 5 cells may be surrounded where piece 5 + * or 7 can fit. The other scenario is when piece 2 creates a hook shape. + */ +func triple_is_okay(row1, row2, row3 int, even bool) bool { + if even { + /* There are four cases: + * row1: 00011 00001 11001 10101 + * row2: 01011 00101 10001 10001 + * row3: 011?? 00110 ????? ????? + */ + return ((row1 == 0x03) && (row2 == 0x0B) && ((row3 & 0x1C) == 0x0C)) || + ((row1 == 0x01) && (row2 == 0x05) && (row3 == 0x06)) || + ((row1 == 0x19) && (row2 == 0x11)) || + ((row1 == 0x15) && (row2 == 0x11)) + } + /* There are two cases: + * row1: 10011 10101 + * row2: 10001 10001 + * row3: ????? ????? + */ + return ((row1 == 0x13) && (row2 == 0x11)) || + ((row1 == 0x15) && (row2 == 0x11)) +} + +func calc_rows() { + for row1 := int8(0); row1 < 32; row1++ { + for row2 := int8(0); row2 < 32; row2++ { + bad_even_rows[row1][row2] = rows_bad(row1, row2, true) + bad_odd_rows[row1][row2] = rows_bad(row1, row2, false) + } + } + for row1 := 0; row1 < 32; row1++ { + for row2 := 0; row2 < 32; row2++ { + for row3 := 0; row3 < 32; row3++ { + result1 := bad_even_rows[row1][row2] + result2 := bad_odd_rows[row2][row3] + if result1 == 0 && result2 != 0 && triple_is_okay(row1, row2, row3, true) { + bad_even_triple[row1+(row2*32)+(row3*1024)] = 0 + } else { + bad_even_triple[row1+(row2*32)+(row3*1024)] = boolInt(result1 != 0 || result2 != 0) + } + + result1 = bad_odd_rows[row1][row2] + result2 = bad_even_rows[row2][row3] + if result1 == 0 && result2 != 0 && triple_is_okay(row1, row2, row3, false) { + bad_odd_triple[row1+(row2*32)+(row3*1024)] = 0 + } else { + bad_odd_triple[row1+(row2*32)+(row3*1024)] = boolInt(result1 != 0 || result2 != 0) + } + } + } + } +} + +/* Calculate islands while solving the board. + */ +func boardHasIslands(cell int8) int8 { + /* Too low on board, don't bother checking */ + if cell >= 40 { + return 0 + } + current_triple := (board >> uint((cell/5)*5)) & TRIPLE_MASK + if (cell/5)%2 != 0 { + return bad_odd_triple[current_triple] + } + return bad_even_triple[current_triple] +} + +/* The recursive solve algorithm. Try to place each permutation in the upper- + * leftmost empty cell. Mark off available pieces as it goes along. + * Because the board is a bit mask, the piece number and bit mask must be saved + * at each successful piece placement. This data is used to create a 50 char + * array if a solution is found. + */ +var ( + avail uint16 = 0x03FF + sol_nums [10]int8 + sol_masks [10]uint64 + solutions [2100][50]int8 + solution_count = 0 +) + +func record_solution() { + for sol_no := 0; sol_no < 10; sol_no++ { + sol_mask := sol_masks[sol_no] + for index := 0; index < 50; index++ { + if sol_mask&1 == 1 { + solutions[solution_count][index] = sol_nums[sol_no] + /* Board rotated 180 degrees is a solution too! */ + solutions[solution_count+1][49-index] = sol_nums[sol_no] + } + sol_mask = sol_mask >> 1 + } + } + solution_count += 2 +} + +func solve(depth, cell int8) { + if solution_count >= *max_solutions { + return + } + + for board&(1<<uint(cell)) != 0 { + cell++ + } + + for piece := int8(0); piece < 10; piece++ { + var piece_no_mask uint16 = 1 << uint(piece) + if avail&piece_no_mask == 0 { + continue + } + avail ^= piece_no_mask + max_rots := piece_counts[piece][cell] + piece_mask := pieces[piece][cell] + for rotation := 0; rotation < max_rots; rotation++ { + if board&piece_mask[rotation] == 0 { + sol_nums[depth] = piece + sol_masks[depth] = piece_mask[rotation] + if depth == 9 { + /* Solution found!!!!!11!!ONE! */ + record_solution() + avail ^= piece_no_mask + return + } + board |= piece_mask[rotation] + if boardHasIslands(next_cell[piece][cell][rotation]) == 0 { + solve(depth+1, next_cell[piece][cell][rotation]) + } + board ^= piece_mask[rotation] + } + } + avail ^= piece_no_mask + } +} + +/* pretty print a board in the specified hexagonal format */ +func pretty(b *[50]int8) { + for i := 0; i < 50; i += 10 { + fmt.Printf("%c %c %c %c %c \n %c %c %c %c %c \n", b[i]+'0', b[i+1]+'0', + b[i+2]+'0', b[i+3]+'0', b[i+4]+'0', b[i+5]+'0', b[i+6]+'0', + b[i+7]+'0', b[i+8]+'0', b[i+9]+'0') + } + fmt.Printf("\n") +} + +/* Find smallest and largest solutions */ +func smallest_largest() (smallest, largest *[50]int8) { + smallest = &solutions[0] + largest = &solutions[0] + for i := 1; i < solution_count; i++ { + candidate := &solutions[i] + for j, s := range *smallest { + c := candidate[j] + if c == s { + continue + } + if c < s { + smallest = candidate + } + break + } + for j, s := range *largest { + c := candidate[j] + if c == s { + continue + } + if c > s { + largest = candidate + } + break + } + } + return +} + +func main() { + flag.Parse() + calc_pieces() + calc_rows() + solve(0, 0) + fmt.Printf("%d solutions found\n\n", solution_count) + smallest, largest := smallest_largest() + pretty(smallest) + pretty(largest) +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/meteor-contest.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/meteor-contest.txt new file mode 100644 index 0000000..38d9783 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/meteor-contest.txt @@ -0,0 +1,24 @@ +2098 solutions found + +0 0 0 0 1 + 2 2 2 0 1 +2 6 6 1 1 + 2 6 1 5 5 +8 6 5 5 5 + 8 6 3 3 3 +4 8 8 9 3 + 4 4 8 9 3 +4 7 4 7 9 + 7 7 7 9 9 + +9 9 9 9 8 + 9 6 6 8 5 +6 6 8 8 5 + 6 8 2 5 5 +7 7 7 2 5 + 7 4 7 2 0 +1 4 2 2 0 + 1 4 4 0 3 +1 4 0 0 3 + 1 1 3 3 3 + diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/nbody.c b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/nbody.c new file mode 100644 index 0000000..ea601aa --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/nbody.c @@ -0,0 +1,172 @@ +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * The Great Computer Language Shootout + * http://shootout.alioth.debian.org/ + * + * contributed by Christoph Bauer + * + */ + +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +#define pi 3.141592653589793 +#define solar_mass (4 * pi * pi) +#define days_per_year 365.24 + +struct planet { + double x, y, z; + double vx, vy, vz; + double mass; +}; + +void advance(int nbodies, struct planet * bodies, double dt) +{ + int i, j; + + for (i = 0; i < nbodies; i++) { + struct planet * b = &(bodies[i]); + for (j = i + 1; j < nbodies; j++) { + struct planet * b2 = &(bodies[j]); + double dx = b->x - b2->x; + double dy = b->y - b2->y; + double dz = b->z - b2->z; + double distance = sqrt(dx * dx + dy * dy + dz * dz); + double mag = dt / (distance * distance * distance); + b->vx -= dx * b2->mass * mag; + b->vy -= dy * b2->mass * mag; + b->vz -= dz * b2->mass * mag; + b2->vx += dx * b->mass * mag; + b2->vy += dy * b->mass * mag; + b2->vz += dz * b->mass * mag; + } + } + for (i = 0; i < nbodies; i++) { + struct planet * b = &(bodies[i]); + b->x += dt * b->vx; + b->y += dt * b->vy; + b->z += dt * b->vz; + } +} + +double energy(int nbodies, struct planet * bodies) +{ + double e; + int i, j; + + e = 0.0; + for (i = 0; i < nbodies; i++) { + struct planet * b = &(bodies[i]); + e += 0.5 * b->mass * (b->vx * b->vx + b->vy * b->vy + b->vz * b->vz); + for (j = i + 1; j < nbodies; j++) { + struct planet * b2 = &(bodies[j]); + double dx = b->x - b2->x; + double dy = b->y - b2->y; + double dz = b->z - b2->z; + double distance = sqrt(dx * dx + dy * dy + dz * dz); + e -= (b->mass * b2->mass) / distance; + } + } + return e; +} + +void offset_momentum(int nbodies, struct planet * bodies) +{ + double px = 0.0, py = 0.0, pz = 0.0; + int i; + for (i = 0; i < nbodies; i++) { + px += bodies[i].vx * bodies[i].mass; + py += bodies[i].vy * bodies[i].mass; + pz += bodies[i].vz * bodies[i].mass; + } + bodies[0].vx = - px / solar_mass; + bodies[0].vy = - py / solar_mass; + bodies[0].vz = - pz / solar_mass; +} + +#define NBODIES 5 +struct planet bodies[NBODIES] = { + { /* sun */ + 0, 0, 0, 0, 0, 0, solar_mass + }, + { /* jupiter */ + 4.84143144246472090e+00, + -1.16032004402742839e+00, + -1.03622044471123109e-01, + 1.66007664274403694e-03 * days_per_year, + 7.69901118419740425e-03 * days_per_year, + -6.90460016972063023e-05 * days_per_year, + 9.54791938424326609e-04 * solar_mass + }, + { /* saturn */ + 8.34336671824457987e+00, + 4.12479856412430479e+00, + -4.03523417114321381e-01, + -2.76742510726862411e-03 * days_per_year, + 4.99852801234917238e-03 * days_per_year, + 2.30417297573763929e-05 * days_per_year, + 2.85885980666130812e-04 * solar_mass + }, + { /* uranus */ + 1.28943695621391310e+01, + -1.51111514016986312e+01, + -2.23307578892655734e-01, + 2.96460137564761618e-03 * days_per_year, + 2.37847173959480950e-03 * days_per_year, + -2.96589568540237556e-05 * days_per_year, + 4.36624404335156298e-05 * solar_mass + }, + { /* neptune */ + 1.53796971148509165e+01, + -2.59193146099879641e+01, + 1.79258772950371181e-01, + 2.68067772490389322e-03 * days_per_year, + 1.62824170038242295e-03 * days_per_year, + -9.51592254519715870e-05 * days_per_year, + 5.15138902046611451e-05 * solar_mass + } +}; + +int main(int argc, char ** argv) +{ + int n = atoi(argv[1]); + int i; + + offset_momentum(NBODIES, bodies); + printf ("%.9f\n", energy(NBODIES, bodies)); + for (i = 1; i <= n; i++) + advance(NBODIES, bodies, 0.01); + printf ("%.9f\n", energy(NBODIES, bodies)); + return 0; +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/nbody.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/nbody.go new file mode 100644 index 0000000..4eeba44 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/nbody.go @@ -0,0 +1,180 @@ +//go:build ignore +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* The Computer Language Benchmarks Game + * http://shootout.alioth.debian.org/ + * + * contributed by The Go Authors. + * based on C program by Christoph Bauer + */ + +package main + +import ( + "flag" + "fmt" + "math" +) + +var n = flag.Int("n", 1000, "number of iterations") + +type Body struct { + x, y, z, vx, vy, vz, mass float64 +} + +const ( + solarMass = 4 * math.Pi * math.Pi + daysPerYear = 365.24 +) + +func (b *Body) offsetMomentum(px, py, pz float64) { + b.vx = -px / solarMass + b.vy = -py / solarMass + b.vz = -pz / solarMass +} + +type System []*Body + +func NewSystem(body []Body) System { + n := make(System, len(body)) + for i := 0; i < len(body); i++ { + n[i] = new(Body) // copy to avoid overwriting the inputs + *n[i] = body[i] + } + var px, py, pz float64 + for _, body := range n { + px += body.vx * body.mass + py += body.vy * body.mass + pz += body.vz * body.mass + } + n[0].offsetMomentum(px, py, pz) + return n +} + +func (sys System) energy() float64 { + var e float64 + for i, body := range sys { + e += 0.5 * body.mass * + (body.vx*body.vx + body.vy*body.vy + body.vz*body.vz) + for j := i + 1; j < len(sys); j++ { + body2 := sys[j] + dx := body.x - body2.x + dy := body.y - body2.y + dz := body.z - body2.z + distance := math.Sqrt(dx*dx + dy*dy + dz*dz) + e -= (body.mass * body2.mass) / distance + } + } + return e +} + +func (sys System) advance(dt float64) { + for i, body := range sys { + for j := i + 1; j < len(sys); j++ { + body2 := sys[j] + dx := body.x - body2.x + dy := body.y - body2.y + dz := body.z - body2.z + + dSquared := dx*dx + dy*dy + dz*dz + distance := math.Sqrt(dSquared) + mag := dt / (dSquared * distance) + + body.vx -= dx * body2.mass * mag + body.vy -= dy * body2.mass * mag + body.vz -= dz * body2.mass * mag + + body2.vx += dx * body.mass * mag + body2.vy += dy * body.mass * mag + body2.vz += dz * body.mass * mag + } + } + + for _, body := range sys { + body.x += dt * body.vx + body.y += dt * body.vy + body.z += dt * body.vz + } +} + +var ( + jupiter = Body{ + x: 4.84143144246472090e+00, + y: -1.16032004402742839e+00, + z: -1.03622044471123109e-01, + vx: 1.66007664274403694e-03 * daysPerYear, + vy: 7.69901118419740425e-03 * daysPerYear, + vz: -6.90460016972063023e-05 * daysPerYear, + mass: 9.54791938424326609e-04 * solarMass, + } + saturn = Body{ + x: 8.34336671824457987e+00, + y: 4.12479856412430479e+00, + z: -4.03523417114321381e-01, + vx: -2.76742510726862411e-03 * daysPerYear, + vy: 4.99852801234917238e-03 * daysPerYear, + vz: 2.30417297573763929e-05 * daysPerYear, + mass: 2.85885980666130812e-04 * solarMass, + } + uranus = Body{ + x: 1.28943695621391310e+01, + y: -1.51111514016986312e+01, + z: -2.23307578892655734e-01, + vx: 2.96460137564761618e-03 * daysPerYear, + vy: 2.37847173959480950e-03 * daysPerYear, + vz: -2.96589568540237556e-05 * daysPerYear, + mass: 4.36624404335156298e-05 * solarMass, + } + neptune = Body{ + x: 1.53796971148509165e+01, + y: -2.59193146099879641e+01, + z: 1.79258772950371181e-01, + vx: 2.68067772490389322e-03 * daysPerYear, + vy: 1.62824170038242295e-03 * daysPerYear, + vz: -9.51592254519715870e-05 * daysPerYear, + mass: 5.15138902046611451e-05 * solarMass, + } + sun = Body{ + mass: solarMass, + } +) + +func main() { + flag.Parse() + + system := NewSystem([]Body{sun, jupiter, saturn, uranus, neptune}) + fmt.Printf("%.9f\n", system.energy()) + for i := 0; i < *n; i++ { + system.advance(0.01) + } + fmt.Printf("%.9f\n", system.energy()) +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/nbody.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/nbody.txt new file mode 100644 index 0000000..1731557 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/nbody.txt @@ -0,0 +1,2 @@ +-0.169075164 +-0.169087605 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/pidigits.c b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/pidigits.c new file mode 100644 index 0000000..9cbcae4 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/pidigits.c @@ -0,0 +1,125 @@ +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* The Computer Language Benchmarks Game + http://shootout.alioth.debian.org/ + + contributed by Paolo Bonzini & Sean Bartlett + modified by Michael Mellor +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <gmp.h> + +static mpz_t numer, accum, denom, tmp1, tmp2; + +static int extract_digit() +{ + if (mpz_cmp(numer, accum) > 0) + return -1; + + /* Compute (numer * 3 + accum) / denom */ + mpz_mul_2exp(tmp1, numer, 1); + mpz_add(tmp1, tmp1, numer); + mpz_add(tmp1, tmp1, accum); + mpz_fdiv_qr(tmp1, tmp2, tmp1, denom); + + /* Now, if (numer * 4 + accum) % denom... */ + mpz_add(tmp2, tmp2, numer); + + /* ... is normalized, then the two divisions have the same result. */ + if (mpz_cmp(tmp2, denom) >= 0) + return -1; + + return mpz_get_ui(tmp1); +} + +static void next_term(unsigned int k) +{ + unsigned int y2 = k*2 + 1; + + mpz_mul_2exp(tmp1, numer, 1); + mpz_add(accum, accum, tmp1); + mpz_mul_ui(accum, accum, y2); + mpz_mul_ui(numer, numer, k); + mpz_mul_ui(denom, denom, y2); +} + +static void eliminate_digit(unsigned int d) +{ + mpz_submul_ui(accum, denom, d); + mpz_mul_ui(accum, accum, 10); + mpz_mul_ui(numer, numer, 10); +} + +static void pidigits(unsigned int n) +{ + int d; + unsigned int i = 0, k = 0, m; + mpz_init(tmp1); + mpz_init(tmp2); + mpz_init_set_ui(numer, 1); + mpz_init_set_ui(accum, 0); + mpz_init_set_ui(denom, 1); + + for(;;) + { + do { + k++; + next_term(k); + d = extract_digit(); + } while(d == -1); + + putchar(d + '0'); + + i++; + m = i%10; + if(m == 0) + printf("\t:%d\n", i); + if(i >= n) + break; + eliminate_digit(d); + } + + if(m) { + m = 10 - m; + while(m--) + putchar(' '); + printf("\t:%d\n", n); + } +} + +int main(int argc, char **argv) +{ + pidigits(argc > 1 ? atoi(argv[1]) : 27); + return 0; +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/pidigits.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/pidigits.go new file mode 100644 index 0000000..16f8f81 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/pidigits.go @@ -0,0 +1,138 @@ +//go:build ignore +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* The Computer Language Benchmarks Game + * http://shootout.alioth.debian.org/ + * + * contributed by The Go Authors. + * based on pidigits.c (by Paolo Bonzini & Sean Bartlett, + * modified by Michael Mellor) + */ + +package main + +import ( + "flag" + "fmt" + "math/big" +) + +var n = flag.Int("n", 27, "number of digits") +var silent = flag.Bool("s", false, "don't print result") + +var ( + tmp1 = big.NewInt(0) + tmp2 = big.NewInt(0) + tmp3 = big.NewInt(0) + y2 = big.NewInt(0) + bigk = big.NewInt(0) + numer = big.NewInt(1) + accum = big.NewInt(0) + denom = big.NewInt(1) + ten = big.NewInt(10) +) + +func extract_digit() int64 { + if numer.Cmp(accum) > 0 { + return -1 + } + + // Compute (numer * 3 + accum) / denom + tmp1.Lsh(numer, 1) + tmp1.Add(tmp1, numer) + tmp1.Add(tmp1, accum) + tmp1.DivMod(tmp1, denom, tmp2) + + // Now, if (numer * 4 + accum) % denom... + tmp2.Add(tmp2, numer) + + // ... is normalized, then the two divisions have the same result. + if tmp2.Cmp(denom) >= 0 { + return -1 + } + + return tmp1.Int64() +} + +func next_term(k int64) { + y2.SetInt64(k*2 + 1) + bigk.SetInt64(k) + + tmp1.Lsh(numer, 1) + accum.Add(accum, tmp1) + accum.Mul(accum, y2) + numer.Mul(numer, bigk) + denom.Mul(denom, y2) +} + +func eliminate_digit(d int64) { + tmp3.SetInt64(d) + accum.Sub(accum, tmp3.Mul(denom, tmp3)) + accum.Mul(accum, ten) + numer.Mul(numer, ten) +} + +func printf(s string, arg ...interface{}) { + if !*silent { + fmt.Printf(s, arg...) + } +} + +func main() { + flag.Parse() + + var m int // 0 <= m < 10 + for i, k := 0, int64(0); ; { + d := int64(-1) + for d < 0 { + k++ + next_term(k) + d = extract_digit() + } + + printf("%c", d+'0') + + i++ + m = i % 10 + if m == 0 { + printf("\t:%d\n", i) + } + if i >= *n { + break + } + eliminate_digit(d) + } + + if m > 0 { + printf("%s\t:%d\n", " "[m:10], *n) + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/pidigits.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/pidigits.txt new file mode 100644 index 0000000..ad946a9 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/pidigits.txt @@ -0,0 +1,3 @@ +3141592653 :10 +5897932384 :20 +6264338 :27 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/regex-dna-parallel.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/regex-dna-parallel.go new file mode 100644 index 0000000..68ccd76 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/regex-dna-parallel.go @@ -0,0 +1,127 @@ +//go:build ignore +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* The Computer Language Benchmarks Game + * http://shootout.alioth.debian.org/ + * + * contributed by The Go Authors. + */ + +package main + +import ( + "fmt" + "io/ioutil" + "os" + "regexp" + "runtime" +) + +var variants = []string{ + "agggtaaa|tttaccct", + "[cgt]gggtaaa|tttaccc[acg]", + "a[act]ggtaaa|tttacc[agt]t", + "ag[act]gtaaa|tttac[agt]ct", + "agg[act]taaa|ttta[agt]cct", + "aggg[acg]aaa|ttt[cgt]ccct", + "agggt[cgt]aa|tt[acg]accct", + "agggta[cgt]a|t[acg]taccct", + "agggtaa[cgt]|[acg]ttaccct", +} + +type Subst struct { + pat, repl string +} + +var substs = []Subst{ + Subst{"B", "(c|g|t)"}, + Subst{"D", "(a|g|t)"}, + Subst{"H", "(a|c|t)"}, + Subst{"K", "(g|t)"}, + Subst{"M", "(a|c)"}, + Subst{"N", "(a|c|g|t)"}, + Subst{"R", "(a|g)"}, + Subst{"S", "(c|g)"}, + Subst{"V", "(a|c|g)"}, + Subst{"W", "(a|t)"}, + Subst{"Y", "(c|t)"}, +} + +func countMatches(pat string, bytes []byte) int { + re := regexp.MustCompile(pat) + n := 0 + for { + e := re.FindIndex(bytes) + if e == nil { + break + } + n++ + bytes = bytes[e[1]:] + } + return n +} + +func main() { + runtime.GOMAXPROCS(4) + bytes, err := ioutil.ReadAll(os.Stdin) + if err != nil { + fmt.Fprintf(os.Stderr, "can't read input: %s\n", err) + os.Exit(2) + } + ilen := len(bytes) + // Delete the comment lines and newlines + bytes = regexp.MustCompile("(>[^\n]+)?\n").ReplaceAll(bytes, []byte{}) + clen := len(bytes) + + mresults := make([]chan int, len(variants)) + for i, s := range variants { + ch := make(chan int) + mresults[i] = ch + go func(ss string) { + ch <- countMatches(ss, bytes) + }(s) + } + + lenresult := make(chan int) + bb := bytes + go func() { + for _, sub := range substs { + bb = regexp.MustCompile(sub.pat).ReplaceAll(bb, []byte(sub.repl)) + } + lenresult <- len(bb) + }() + + for i, s := range variants { + fmt.Printf("%s %d\n", s, <-mresults[i]) + } + fmt.Printf("\n%d\n%d\n%d\n", ilen, clen, <-lenresult) +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/regex-dna-parallel.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/regex-dna-parallel.txt new file mode 100644 index 0000000..e23e71f --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/regex-dna-parallel.txt @@ -0,0 +1,13 @@ +agggtaaa|tttaccct 1 +[cgt]gggtaaa|tttaccc[acg] 0 +a[act]ggtaaa|tttacc[agt]t 0 +ag[act]gtaaa|tttac[agt]ct 0 +agg[act]taaa|ttta[agt]cct 1 +aggg[acg]aaa|ttt[cgt]ccct 0 +agggt[cgt]aa|tt[acg]accct 0 +agggta[cgt]a|t[acg]taccct 0 +agggtaa[cgt]|[acg]ttaccct 2 + +10245 +10000 +13348 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/regex-dna.c b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/regex-dna.c new file mode 100644 index 0000000..0c95bc7 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/regex-dna.c @@ -0,0 +1,156 @@ +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* +** The Computer Language Shootout +** http://shootout.alioth.debian.org/ +** contributed by Mike Pall +** +** regex-dna benchmark using PCRE +** +** compile with: +** gcc -O3 -fomit-frame-pointer -o regexdna regexdna.c -lpcre +*/ + +#define __USE_STRING_INLINES +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <pcre.h> + +typedef struct fbuf { + char *buf; + size_t size, len; +} fbuf_t; + +static void fb_init(fbuf_t *b) +{ + b->buf = NULL; + b->len = b->size = 0; +} + +static char *fb_need(fbuf_t *b, size_t need) +{ + need += b->len; + if (need > b->size) { + if (b->size == 0) b->size = need; + else while (need > b->size) b->size += b->size; + if (!(b->buf = realloc(b->buf, b->size))) exit(1); + } + return b->buf+b->len; +} + +#define FB_MINREAD (3<<16) + +/* Read all of a stdio stream into dst buffer. */ +static size_t fb_readall(fbuf_t *dst, FILE *fp) +{ + char *dp; + int n; + for (dp = fb_need(dst, FB_MINREAD); + (n = fread(dp, 1, dst->size-dst->len, fp)) > 0; + dp = fb_need(dst, FB_MINREAD)) dst->len += n; + if (ferror(fp)) exit(1); + return dst->len; +} + +/* Substitute pattern p with replacement r, copying from src to dst buffer. */ +static size_t fb_subst(fbuf_t *dst, fbuf_t *src, const char *p, const char *r) +{ + pcre *re; + pcre_extra *re_ex; + const char *re_e; + char *dp; + int re_eo, m[3], pos, rlen, clen; + if (!(re = pcre_compile(p, PCRE_CASELESS, &re_e, &re_eo, NULL))) exit(1); + re_ex = pcre_study(re, 0, &re_e); + for (dst->len = 0, rlen = strlen(r), pos = 0; + pcre_exec(re, re_ex, src->buf, src->len, pos, 0, m, 3) >= 0; + pos = m[1]) { + clen = m[0]-pos; + dp = fb_need(dst, clen+rlen); + dst->len += clen+rlen; + memcpy(dp, src->buf+pos, clen); + memcpy(dp+clen, r, rlen); + } + clen = src->len-pos; + dp = fb_need(dst, clen); + dst->len += clen; + memcpy(dp, src->buf+pos, clen); + return dst->len; +} + +/* Count all matches with pattern p in src buffer. */ +static int fb_countmatches(fbuf_t *src, const char *p) +{ + pcre *re; + pcre_extra *re_ex; + const char *re_e; + int re_eo, m[3], pos, count; + if (!(re = pcre_compile(p, PCRE_CASELESS, &re_e, &re_eo, NULL))) exit(1); + re_ex = pcre_study(re, 0, &re_e); + for (count = 0, pos = 0; + pcre_exec(re, re_ex, src->buf, src->len, pos, 0, m, 3) >= 0; + pos = m[1]) count++; + return count; +} + +static const char *variants[] = { + "agggtaaa|tttaccct", "[cgt]gggtaaa|tttaccc[acg]", + "a[act]ggtaaa|tttacc[agt]t", "ag[act]gtaaa|tttac[agt]ct", + "agg[act]taaa|ttta[agt]cct", "aggg[acg]aaa|ttt[cgt]ccct", + "agggt[cgt]aa|tt[acg]accct", "agggta[cgt]a|t[acg]taccct", + "agggtaa[cgt]|[acg]ttaccct", NULL +}; + +static const char *subst[] = { + "B", "(c|g|t)", "D", "(a|g|t)", "H", "(a|c|t)", "K", "(g|t)", + "M", "(a|c)", "N", "(a|c|g|t)", "R", "(a|g)", "S", "(c|g)", + "V", "(a|c|g)", "W", "(a|t)", "Y", "(c|t)", NULL +}; + +int main(int argc, char **argv) +{ + fbuf_t seq[2]; + const char **pp; + size_t ilen, clen, slen; + int flip; + fb_init(&seq[0]); + fb_init(&seq[1]); + ilen = fb_readall(&seq[0], stdin); + clen = fb_subst(&seq[1], &seq[0], ">.*|\n", ""); + for (pp = variants; *pp; pp++) + printf("%s %d\n", *pp, fb_countmatches(&seq[1], *pp)); + for (slen = 0, flip = 1, pp = subst; *pp; pp += 2, flip = 1-flip) + slen = fb_subst(&seq[1-flip], &seq[flip], *pp, pp[1]); + printf("\n%zu\n%zu\n%zu\n", ilen, clen, slen); + return 0; +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/regex-dna.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/regex-dna.go new file mode 100644 index 0000000..85e1939 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/regex-dna.go @@ -0,0 +1,109 @@ +//go:build ignore +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* The Computer Language Benchmarks Game + * http://shootout.alioth.debian.org/ + * + * contributed by The Go Authors. + */ + +package main + +import ( + "fmt" + "io/ioutil" + "os" + "regexp" +) + +var variants = []string{ + "agggtaaa|tttaccct", + "[cgt]gggtaaa|tttaccc[acg]", + "a[act]ggtaaa|tttacc[agt]t", + "ag[act]gtaaa|tttac[agt]ct", + "agg[act]taaa|ttta[agt]cct", + "aggg[acg]aaa|ttt[cgt]ccct", + "agggt[cgt]aa|tt[acg]accct", + "agggta[cgt]a|t[acg]taccct", + "agggtaa[cgt]|[acg]ttaccct", +} + +type Subst struct { + pat, repl string +} + +var substs = []Subst{ + Subst{"B", "(c|g|t)"}, + Subst{"D", "(a|g|t)"}, + Subst{"H", "(a|c|t)"}, + Subst{"K", "(g|t)"}, + Subst{"M", "(a|c)"}, + Subst{"N", "(a|c|g|t)"}, + Subst{"R", "(a|g)"}, + Subst{"S", "(c|g)"}, + Subst{"V", "(a|c|g)"}, + Subst{"W", "(a|t)"}, + Subst{"Y", "(c|t)"}, +} + +func countMatches(pat string, bytes []byte) int { + re := regexp.MustCompile(pat) + n := 0 + for { + e := re.FindIndex(bytes) + if len(e) == 0 { + break + } + n++ + bytes = bytes[e[1]:] + } + return n +} + +func main() { + bytes, err := ioutil.ReadAll(os.Stdin) + if err != nil { + fmt.Fprintf(os.Stderr, "can't read input: %s\n", err) + os.Exit(2) + } + ilen := len(bytes) + // Delete the comment lines and newlines + bytes = regexp.MustCompile("(>[^\n]+)?\n").ReplaceAll(bytes, []byte{}) + clen := len(bytes) + for _, s := range variants { + fmt.Printf("%s %d\n", s, countMatches(s, bytes)) + } + for _, sub := range substs { + bytes = regexp.MustCompile(sub.pat).ReplaceAll(bytes, []byte(sub.repl)) + } + fmt.Printf("\n%d\n%d\n%d\n", ilen, clen, len(bytes)) +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/regex-dna.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/regex-dna.txt new file mode 100644 index 0000000..e23e71f --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/regex-dna.txt @@ -0,0 +1,13 @@ +agggtaaa|tttaccct 1 +[cgt]gggtaaa|tttaccc[acg] 0 +a[act]ggtaaa|tttacc[agt]t 0 +ag[act]gtaaa|tttac[agt]ct 0 +agg[act]taaa|ttta[agt]cct 1 +aggg[acg]aaa|ttt[cgt]ccct 0 +agggt[cgt]aa|tt[acg]accct 0 +agggta[cgt]a|t[acg]taccct 0 +agggtaa[cgt]|[acg]ttaccct 2 + +10245 +10000 +13348 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/reverse-complement.c b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/reverse-complement.c new file mode 100644 index 0000000..ed2c982 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/reverse-complement.c @@ -0,0 +1,102 @@ +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * The Computer Language Benchmarks Game + * http://shootout.alioth.debian.org + * + * contributed by Bob W + */ + +#include <stdio.h> +#include <stdlib.h> + +#define JBFSIZE 82 // line input buffer size +#define QBFSIZE 5200 // output buffer initial size +#define Z16 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" +#define V32 "\0TVGH\0\0CD\0\0M\0KN\0\0\0YSA\0BW\0R\0\0\0\0\0\0" +#define VALL Z16 Z16 Z16 Z16 V32 V32 Z16 Z16 Z16 Z16 Z16 Z16 Z16 Z16 + +int errex(char *s, int n) { // error message+value, return 1 + fprintf(stderr,"\n*** Error: %s [%d]!\n", s, n); + return 1; +} + +int main () { // ***** main ***** + char *pj, *pq, *pr; // buffer pointers: inp,out,/out + char *jjj = malloc(JBFSIZE); // allocate input line buffer + char *qqq = malloc(QBFSIZE); // output buffer (dyn. size) + char *pqstop = qqq+QBFSIZE; // end-of-buffer pointer + char xtab[256] = VALL; // char conversion table + + if (!jjj || !qqq) + return errex("Buffer allocation", !jjj + !qqq); + pj = fgets(jjj,JBFSIZE,stdin); // fetch 1st line + if (!pj) + return errex("No input data",0); + if (*jjj != '>') + return errex("1st char not '>'", 0); + + while (pj) { // MAIN LOOP: process data + fputs(jjj, stdout); // output ID line + + for (pq=qqq+1, pr=pqstop; ; pq++) { // LOOP: fill output buffer + pj = fgets(jjj, JBFSIZE, stdin); // get line from stdin + if (!pj || (*jjj=='>')) break; // EOF or new ID line + if (pr <= (pq+61)) { // need to resize buffer + char *newstop = pqstop + 12777888; + char *newptr = realloc(qqq, newstop-qqq); + if (!newptr) + return errex("Out of memory", 0); + if (newptr != qqq) { // new base: adj. pointers + size_t x = newptr-qqq; // offset for pointer update + pq+=x; pr+=x; qqq+=x; + newstop+=x; pqstop+=x; + } + pr = __builtin_memmove(newstop-(pqstop-pr), pr, pqstop-pr); + pqstop = newstop; // buffer resize complete + } + while (*pj) { // LOOP: conv. & revert line + char c = xtab[(unsigned char)(*pj++)]; + if (c) // conversion valid + *(--pr) = c; + } + } + + for (pq = qqq; pr<pqstop; ) { // LOOP: format output + size_t x = (pqstop-pr)<60 ? pqstop-pr : 60; + __builtin_memmove(pq,pr,x); // move line to free space + pr+=x; pq+=x; *(pq++) = 0xA; // adjust pointers, add LF + } + fwrite(qqq, 1, pq-qqq, stdout); // output converted data + } + return 0; +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/reverse-complement.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/reverse-complement.go new file mode 100644 index 0000000..11b59d2 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/reverse-complement.go @@ -0,0 +1,108 @@ +//go:build ignore +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* The Computer Language Benchmarks Game + * http://shootout.alioth.debian.org/ + * + * contributed by The Go Authors. + */ + +package main + +import ( + "bufio" + "os" +) + +const lineSize = 60 + +var complement = [256]uint8{ + 'A': 'T', 'a': 'T', + 'C': 'G', 'c': 'G', + 'G': 'C', 'g': 'C', + 'T': 'A', 't': 'A', + 'U': 'A', 'u': 'A', + 'M': 'K', 'm': 'K', + 'R': 'Y', 'r': 'Y', + 'W': 'W', 'w': 'W', + 'S': 'S', 's': 'S', + 'Y': 'R', 'y': 'R', + 'K': 'M', 'k': 'M', + 'V': 'B', 'v': 'B', + 'H': 'D', 'h': 'D', + 'D': 'H', 'd': 'H', + 'B': 'V', 'b': 'V', + 'N': 'N', 'n': 'N', +} + +func main() { + in := bufio.NewReader(os.Stdin) + buf := make([]byte, 1024*1024) + line, err := in.ReadSlice('\n') + for err == nil { + os.Stdout.Write(line) + + // Accumulate reversed complement in buf[w:] + nchar := 0 + w := len(buf) + for { + line, err = in.ReadSlice('\n') + if err != nil || line[0] == '>' { + break + } + line = line[0 : len(line)-1] + nchar += len(line) + if len(line)+nchar/60+128 >= w { + nbuf := make([]byte, len(buf)*5) + copy(nbuf[len(nbuf)-len(buf):], buf) + w += len(nbuf) - len(buf) + buf = nbuf + } + + // This loop is the bottleneck. + for _, c := range line { + w-- + buf[w] = complement[c] + } + } + + // Copy down to beginning of buffer, inserting newlines. + // The loop left room for the newlines and 128 bytes of padding. + i := 0 + for j := w; j < len(buf); j += 60 { + n := copy(buf[i:i+60], buf[j:]) + buf[i+n] = '\n' + i += n + 1 + } + os.Stdout.Write(buf[0:i]) + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/reverse-complement.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/reverse-complement.txt new file mode 100644 index 0000000..14d792a --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/reverse-complement.txt @@ -0,0 +1,171 @@ +>ONE Homo sapiens alu +CGGAGTCTCGCTCTGTCGCCCAGGCTGGAGTGCAGTGGCGCGATCTCGGCTCACTGCAAC +CTCCGCCTCCCGGGTTCAAGCGATTCTCCTGCCTCAGCCTCCCGAGTAGCTGGGATTACA +GGCGCGCGCCACCACGCCCGGCTAATTTTTGTATTTTTAGTAGAGACGGGGTTTCACCAT +GTTGGCCAGGCTGGTCTCGAACTCCTGACCTCAGGTGATCCGCCCGCCTCGGCCTCCCAA +AGTGCTGGGATTACAGGCGTGAGCCACCGCGCCCGGCCTTTTTGAGACGGAGTCTCGCTC +TGTCGCCCAGGCTGGAGTGCAGTGGCGCGATCTCGGCTCACTGCAACCTCCGCCTCCCGG +GTTCAAGCGATTCTCCTGCCTCAGCCTCCCGAGTAGCTGGGATTACAGGCGCGCGCCACC +ACGCCCGGCTAATTTTTGTATTTTTAGTAGAGACGGGGTTTCACCATGTTGGCCAGGCTG +GTCTCGAACTCCTGACCTCAGGTGATCCGCCCGCCTCGGCCTCCCAAAGTGCTGGGATTA +CAGGCGTGAGCCACCGCGCCCGGCCTTTTTGAGACGGAGTCTCGCTCTGTCGCCCAGGCT +GGAGTGCAGTGGCGCGATCTCGGCTCACTGCAACCTCCGCCTCCCGGGTTCAAGCGATTC +TCCTGCCTCAGCCTCCCGAGTAGCTGGGATTACAGGCGCGCGCCACCACGCCCGGCTAAT +TTTTGTATTTTTAGTAGAGACGGGGTTTCACCATGTTGGCCAGGCTGGTCTCGAACTCCT +GACCTCAGGTGATCCGCCCGCCTCGGCCTCCCAAAGTGCTGGGATTACAGGCGTGAGCCA +CCGCGCCCGGCCTTTTTGAGACGGAGTCTCGCTCTGTCGCCCAGGCTGGAGTGCAGTGGC +GCGATCTCGGCTCACTGCAACCTCCGCCTCCCGGGTTCAAGCGATTCTCCTGCCTCAGCC +TCCCGAGTAGCTGGGATTACAGGCGCGCGCCACCACGCCCGGCTAATTTTTGTATTTTTA +GTAGAGACGGGGTTTCACCATGTTGGCCAGGCTGGTCTCGAACTCCTGACCTCAGGTGAT +CCGCCCGCCTCGGCCTCCCAAAGTGCTGGGATTACAGGCGTGAGCCACCGCGCCCGGCCT +TTTTGAGACGGAGTCTCGCTCTGTCGCCCAGGCTGGAGTGCAGTGGCGCGATCTCGGCTC +ACTGCAACCTCCGCCTCCCGGGTTCAAGCGATTCTCCTGCCTCAGCCTCCCGAGTAGCTG +GGATTACAGGCGCGCGCCACCACGCCCGGCTAATTTTTGTATTTTTAGTAGAGACGGGGT +TTCACCATGTTGGCCAGGCTGGTCTCGAACTCCTGACCTCAGGTGATCCGCCCGCCTCGG +CCTCCCAAAGTGCTGGGATTACAGGCGTGAGCCACCGCGCCCGGCCTTTTTGAGACGGAG +TCTCGCTCTGTCGCCCAGGCTGGAGTGCAGTGGCGCGATCTCGGCTCACTGCAACCTCCG +CCTCCCGGGTTCAAGCGATTCTCCTGCCTCAGCCTCCCGAGTAGCTGGGATTACAGGCGC +GCGCCACCACGCCCGGCTAATTTTTGTATTTTTAGTAGAGACGGGGTTTCACCATGTTGG +CCAGGCTGGTCTCGAACTCCTGACCTCAGGTGATCCGCCCGCCTCGGCCTCCCAAAGTGC +TGGGATTACAGGCGTGAGCCACCGCGCCCGGCCTTTTTGAGACGGAGTCTCGCTCTGTCG +CCCAGGCTGGAGTGCAGTGGCGCGATCTCGGCTCACTGCAACCTCCGCCTCCCGGGTTCA +AGCGATTCTCCTGCCTCAGCCTCCCGAGTAGCTGGGATTACAGGCGCGCGCCACCACGCC +CGGCTAATTTTTGTATTTTTAGTAGAGACGGGGTTTCACCATGTTGGCCAGGCTGGTCTC +GAACTCCTGACCTCAGGTGATCCGCCCGCCTCGGCCTCCCAAAGTGCTGGGATTACAGGC +GTGAGCCACCGCGCCCGGCC +>TWO IUB ambiguity codes +TAGGDHACHATCRGTRGVTGAGWTATGYTGCTGTCABACDWVTRTAAGAVVAGATTTNDA +GASMTCTGCATBYTTCAAKTTACMTATTACTTCATARGGYACMRTGTTTTYTATACVAAT +TTCTAKGDACKADACTATATNTANTCGTTCACGBCGYSCBHTANGGTGATCGTAAAGTAA +CTATBAAAAGATSTGWATBCSGAKHTTABBAACGTSYCATGCAAVATKTSKTASCGGAAT +WVATTTNTCCTTCTTCTTDDAGTGGTTGGATACVGTTAYMTMTBTACTTTHAGCTAGBAA +AAGAGKAAGTTRATWATCAGATTMDDTTTAAAVAAATATTKTCYTAAATTVCNKTTRACG +ADTATATTTATGATSADSCAATAWAGCGRTAGTGTAAGTGACVGRADYGTGCTACHVSDT +CTVCARCSYTTAATATARAAAATTTAATTTACDAATTGBACAGTAYAABATBTGCAGBVG +TGATGGDCAAAATBNMSTTABKATTGGSTCCTAGBTTACTTGTTTAGTTTATHCGATSTA +AAGTCGAKAAASTGTTTTAWAKCAGATATACTTTTMTTTTGBATAGAGGAGCMATGATRA +AAGGNCAYDCCDDGAAAGTHGBTAATCKYTBTACBGTBCTTTTTGDTAASSWTAAWAARA +TTGGCTAAGWGRADTYACATAGCTCBTAGATAWAGCAATNGTATMATGTTKMMAGTAWTC +CCNTSGAAWATWCAAAAMACTGAADNTYGATNAATCCGAYWNCTAACGTTAGAGDTTTTC +ATCTGGKRTAVGAABVCTGWGBTCTDVGKATTBTCTAAGGVADAAAVWTCTAGGGGAGGG +TTAGAACAATTAAHTAATNAAATGCATKATCTAAYRTDTCAGSAYTTYHGATRTTWAVTA +BGNTCDACAGBCCRCAGWCRTCABTGMMAWGMCTCAACCGATRTGBCAVAATCGTDWDAA +CAYAWAATWCTGGTAHCCCTAAGATAACSCTTAGTGSAACAWTBGTCDTTDGACWDBAAC +HTTTNGSKTYYAAYGGATNTGATTTAARTTAMBAATCTAAGTBTCATYTAACTTADTGTT +TCGATACGAAHGGCYATATACCWDTKYATDCSHTDTCAAAATGTGBACTGSCCVGATGTA +TCMMAGCCTTDAAABAATGAAGAGTAACTHATMGVTTAATAACCCGGTTVSANTGCAATT +GTGAGATTTAMGTTTAMAAYGCTGACAYAAAAAGGCACAMYTAAGVGGCTGGAABVTACG +GATTSTYGTBVAKTATWACCGTGTKAGTDTGTATGTTTAAAGGAAAAAGTAACATARAAA +GGTYCAMNYAAABTATAGNTSATANAGTCATCCTATWADKAACTRGTMSACDGTATSAYT +AAHSHGTAABYGACTYTATADTGSTATAGAGAAATCGNTAAAGGAAATCAGTTGTNCYMV +TNACDRTATBNATATASTAGAAMSCGGGANRCKKMCAAACATTNAGTCTRMAATBMTACC +CGTACTTCTBGDSYAATWGAAAATGACADDCHAKAAAYATATTKTTTTCACANACWAGAA +AKATCCTTATTAYKHKCTAAACARTATTTTDATBTVWCYGCAATACTAGGKAAASTTDGA +MGGCHTTHAATVCAHDRYAGGRCTATACGTCMAGAGAGCTBTHGNACARTCCBDCTAAGA +GCGGCTTTARTAAAGAATCCNAGTAWBTGACTTGAATTACWTVACAGAAABCAATNAAAC +CGTNTRANTTGAYCMAWBADTANABRGGTKTHTWTAGTTVCTMBKTAGMTVKCCAGCANT +TVAGSWTTAGCCGCRHTTTCCTTHNTATTAAGAAGAATAGGMTRAARTCTABGTACDTTT +TATAAVDHAHTATAGATCCTAGTAAGYTWATDWCATGAGGGATAGTAAMDMNGBASTWAM +TSTATRBAYDABATGTATATYCGCACTGTTTTAACMCWBTATAWAGTATBTSTATVTTAR +CCTMTTAAKADATCAACTAATYTSVTAKGDATTATGCKTCAYCAKAATACTTKAANGAGT +ATTSDAGATCGGAAATACTTAAYAAVGTATMCGCTTGTGTDCTAATYTATTTTATTTWAA +CAGWRCTATGTAGMTGTTTGTTYKTNGTTKTCAGAACNTRACCTACKTGSRATGTGGGGG +CTGTCATTAAGTAAATNGSTTABCCCCTCGCAGCTCWHTCGCGAAGCAVATGCKACGHCA +ACAKTTAATAACASAAADATTWNYTGTAATTGTTCGTMHACHTWATGTGCWTTTTGAAHY +ACTTTGTAYAMSAAACTTAADAAATATAGTABMATATYAATGSGGTAGTTTGTGTBYGGT +TWSGSVGWMATTDMTCCWWCABTCSVACAGBAATGTTKATBGTCAATAATCTTCTTAAAC +ARVAATHAGYBWCTRWCABGTWWAATCTAAGTCASTAAAKTAAGVKBAATTBGABACGTA +AGGTTAAATAAAAACTRMDTWBCTTTTTAATAAAAGATMGCCTACKAKNTBAGYRASTGT +ASSTCGTHCGAAKTTATTATATTYTTTGTAGAACATGTCAAAACTWTWTHGKTCCYAATA +AAGTGGAYTMCYTAARCSTAAATWAKTGAATTTRAGTCTSSATACGACWAKAASATDAAA +TGYYACTSAACAAHAKTSHYARGASTATTATTHAGGYGGASTTTBGAKGATSANAACACD +TRGSTTRAAAAAAAACAAGARTCVTAGTAAGATAWATGVHAAKATWGAAAAGTYAHVTAC +TCTGRTGTCAWGATRVAAKTCGCAAVCGASWGGTTRTCSAMCCTAACASGWKKAWDAATG +ACRCBACTATGTGTCTTCAAAHGSCTATATTTCGTVWAGAAGTAYCKGARAKSGKAGTAN +TTTCYACATWATGTCTAAAADMDTWCAATSTKDACAMAADADBSAAATAGGCTHAHAGTA +CGACVGAATTATAAAGAHCCVAYHGHTTTACATSTTTATGNCCMTAGCATATGATAVAAG +>THREE Homo sapiens frequency +ATATTTATCTTTTCACTTCCTACATTGGTCAGACCATTATTCGACACGTGGCGTCATTTT +GTCATACCGGGTAATGTTGGAAACAAAACGTACTGATAAAATACTGAGTTGTAAACTCTA +ATCAGATAACGCGCTTGGATATTAAGATTCACACAGGGGTTTCGGCTGTAAAAAAACTTG +TGGAGCTGTTCTGGGACAGATAAGTTGTACCTCGTACTTAGCTAATTAATGAACCAACTG +ATTACGATAGAACAATTCTGAGGCCGCCAGGACAGCCAAATTTTAATCTTATAAAGCTGG +AAACAGCCGGTATTAGCTTCTCGCATACTTTGCCTGCATTGGTACCTTACAGATATCAGC +GTAGTCATATACACCTCGGTCTCAGCTAAGCTTGTATCTCTTAGAGTAGTTCAAAGATAG +TGGACAATACCTGTGGAATCGATTGCAGATATGGATTTATTTAACTACTGAGTCTCATTC +ACAAGCTAAGCAAGGAGCACGTTTTGGTGCCGGCATACCGATTTGCTATCATGTCAGCAA +ATTTGCGTTGTATTCCTAGTTGCACCCATTAAGGCCACACTCCGAACCTAATTATTACAT +CGCAAAGACATGTACGAAGGACCCGATGTCGAATAGAAGGGAGGACTGTTCATTGGAAGC +TAGACCAGAGGAATCGCAAAGATGCAACTCTTACAATAAAAATCTAATTTCAGTCAACAC +GCAATTTCTATAAGGTTTCCGATAATAATGAACCGTCTTCCACAGGGGAATTTGCCATGC +TCGTAAAAGTAGTTAATCCAAGTAGAAGAAATTTTGATAATGTTTTAAGTTGGCACGAAG +GAATTCAGAGAGATCTTACCTAACAAAGGCATTAGTAGATGTTCCTTGGTTCACACTCGG +TCAATCAGAGCACATACTACGGGCGATACCGGGAATGACACAACATCAATGAGATTGTTA +AGTGAGGTAATTGACTTTAGAGGACTCGATCAGTATACTGTCACTATGAACATCGTATTA +ATTGTTATCCGATATATACACCACCGATTTGCTTGTGCAAGGTTACAGACCCATTCGATA +AATACAAACACGGAGCGATATTATTTAAGGAGTGCTGTCTTCAAAAGAATTATTCCCACA +CCGACATAAGAACTTCGCTCCGTCATTCCAGATTTAAATAACATAACGTAACGCTTTGCT +GATAACATAACATAACCGAGAATTTGCTTAGGAAATTTGGAGCAATATTGCATTGTTTCT +CAGTCATCACAAGGCCCGCCAAAGAACTCTGAGAATCAGGATTCAACATGATTGGTAAGA +CTCTATATATATAACTTAATTCTTGTGTCCGGAGATAGAAAGAGGACGAGAGATACTACG +AAAGAAAGTGTACTTCGATGTATCAATTCAGACGCCTTCTCTATCATCAACATTATAGGT +CTCGTATATGCTCGGCGCGATCTGCTTCTCTCCGCCAATAGCCCCATAGTGTATTTCAAG +CGCAGTAACAGTGAAATCGTTACGAAGGTAGGGATGTTGCTTATAATTGTCGTAACTTAT +CGCTTATGTATCTTTCAAGAATGAACGGCAGCATATACATACGTTCTACCTTTAGCTACA +AAGCATCCATATACTCCCTCTCATGATTGAAACTCTTCCCTATTTTGTAGCCAATAGTGA +AAGCGTATTAGTATAAATTCGTCGGTTTTTCACTCGCAACTGTTATACTCTGCAAACAAA +CGAAAGCCTCATAGTACAAACCTAAAGCTACATACTTCATCATTGGCAGACCAGTGGCGG +TATTTCTACGGAAGCATCACTATAGATATAAAGTTTCCCTTCATGTACGTCTGTTAACCA +TATCACAAGAAACTGCTATCTCTGTCACGTAACAATTCACGCGCCTTATCGCCAAATGTT +CATATATGCGCGGTATACGTATGAACGAATACTAATTAGTATAACGGAGGATTCACGGGA +GGGATACTTGGGGCATTTATAAATCGTCTAAAAATTTTCTATCAGCACTTGCGGGTTATA +GTGGATTACTAGGCAACATAATATTCTGTATTGGTCCAAATGACGCTATAGATAAATTAG +CAAAATACATTGTTTCCATTTATGTAAGTCGAAACTCCAGGACTCCCGGGAACCAGTTAA +ACCGTCTGGAAAAGACACATTGTGAGCGGGACTTCAATGATAGCTTTCAATGAGCTTCTC +ATGCTTGGGGTCTGTACATATATGTTGGCGAAATTATCGTCTGTATTCTGTTATGCTTTG +ATCATGGGTTATTAGTATAGTGTCCGGTTAAGTACCAATACCGCTAGAGACCCGACCTAA +GTCGATAACTAACGATCATCGACGTAAGGATCGTCTCGATCAGTACTTCAGTCTAGATCT +GGGAATAGTAACTCGTTAGTGAACTATGTCGTGTCATAACTCTAAAATGCAATCAAATCT +TATTATTGAGTATTGATTATATAAAGCATCCGCTTAGCTTTACCCTCAAATGTTATATGC +AATTTAAAGCGCTTGATATCGTCTACTCAAGTTCAGGTTTCACATGGCCGCAACGTGACG +TTATTAGAGGTGGGTCATCATCTCTGAGGCTAGTGATGTTGAATACTCATTGAATGGGAA +GTGGAATACCATGCTCGTAGGTAACAGCATGACCTATAAAATATACTATGGGTGTGTGGT +AGATCAATATTGTTCAAGCATATCGTAACAATAACGGCTGAAATGTTACTGACATGAAAG +AGGGAGTCCAAACCATTCTAACAGCTGATCAAGTCGTCTAAAAACGCCTGGTTCAGCCTT +AAGAGTTATAAGCCAGACAAATTGTATCAATAGAGAATCCGTAAATTCCTCGGCCAACCT +CTTGCAAAGACATCACTATCAATATACTACCGTGATCTTAATTAGTGAACTTATATAAAT +ATCTACAACCAGATTCAACGGAAAAGCTTTAGTGGATTAGAAATTGCCAAGAATCACATT +CATGTGGGTTCGAATGCTTTAGTAATACCATTTCGCCGAGTAGTCACTTCGCTGAACTGT +CGTAAATTGCTATGACATAATCGAAAAGGATTGTCAAGAGTCGATTACTGCGGACTAATA +ATCCCCACGGGGGTGGTCTCATGTCTCCCCAGGCGAGTGGGGACGGTTGATAAACACGCT +GCATCGCGGACTGATGTTCCCAGTATTACATAGTCACATTGGATTGCGAGTAGTCTACCT +ATTTATGAGCGAGAGATGCCTCTAACTACTTCGACTTTTAAAACCTTTCCACGCCAGTAT +TCGGCGAAAGGGAAGTATTAAGGGTTGTCATAATTAAGCTGATACCACTTCAGACTTTGC +TCTACTTCTGTCTTTCATTGGTTTAGTAAAGTCTGTCCATTCGTCGAGACCGTCTTTTGC +AGCCTCATTCTACCAACTGCTCCGACTCTTAGTCTGCTTCTCCCAGCGTTATAACAAGAG +GCATTTTGTCATCCTTAAAACAATAATAAAGAACTCGGAGCACTGATATAATGACTGAAT +TAGAACCGCTTAAAAATACAACGAATAGATAAGACTATCGGATAAGATCTAATATGTAGT +GATTAAGCCCTTTATTAATTAATAATAGTTACCCTTTCTGATGTAACGCGACATATTACG +ATTTAGTGGCACGTCTGAATTGCAAAGCAGATCTCTACCCGATTTTTATTATAAATCCCG +TATACATCTTGACTTGAGTAATTGTTCATCTTTTTATATCTCTTCGTACTACAAATAATT +AATATCTCAACCCGTATTGTGTGATTCTAATTACCAACAGAATACGAGGAGGTTTTTGCT +TAGGGCCATATATAATGAATCTATCTCGTTTATTCGCGGAACCCGAGATAACATTACGAT +GTAACTATTTTAGAGAACTTAATACAAGAAACATTGCTGATTACTCATAACTAAATGCTT +GGTAATATATCCTCAGTGCCCCTACCATCTTTTACGCAGGGATGTAATTACTTAGGATTC +ATTGTGTAAGAATTACAATGAACGATGGATATGAAGGCATGTTGCGAGGTGTTCCTTGGT +ATGTGAAGTTCGCAGGGCAACAAAAATTTCGCAGAATAGGCCTCAAAGTATTGGTAAAGA +AGACAACTAATCATCACGAGCTTCTGATATCAATACGAACGAGTCCTGTGATGGATGAAA +GAAAGTCGTATCGAAAATGTCAAGAGTCTGCCCAATGTAACTTACTTCAAAAAATAACGC +TTCCGCCAAGTACGTTCGAATAAACGTAATTTTAAAAATACATAAGGGGTGTTAGAAAGT +AAGCGACGGGATATAAGTTAGACTCAAGATTCCGCCGTAAAACGAGACTGATTCCGAAGA +TTGTTCGTGGATCTGGTCATGACTTTCACTGAGTAAGGAGTTTCGACATATGTCAATAAA +CACAAAAATAGAAGCTATTCGATCTGAAAAATATTAGGACAAGAAACTATCTCACGCTAG +CCCAGAATATTCACTCACCCACGGGCGATACTAAAGCACTATATAGTCGCGTGATTACTA +TACATATGGTACACATAAGAATCACGATCAGGTTCTCAATTTTCAACAATATATGTTTAT +TTGCATAGGTAATATTAGGCCTTTAAGAGAAGGATGGGTGAGATACTCCGGGGATGGCGG +CAATAAAGAAAAACACGATATGAGTAATAGGATCCTAATATCTTGGCGAGAGACTTAAGG +TACGAATTTTGCGCAATCTATTTTTTACTTGGCCAGAATTCATGTATGGTATAAGTACGA +ACTTTTTTGATCACTTTCATGGCTACCTGATTAGGATAGTTTGAGGAATTTCCCAAATAT +ACCGATTTAATATACACTAGGGCTTGTCACTTTGAGTCAGAAAAAGAATATAATTACTTA +GGGTAATGCTGCATACATATTCTTATATTGCAAAGGTTCTCTGGGTAATCTTGAGCCTTC +ACGATACCTGGTGAAGTGTT diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/spectral-norm-parallel.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/spectral-norm-parallel.go new file mode 100644 index 0000000..5ad4e20 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/spectral-norm-parallel.go @@ -0,0 +1,114 @@ +//go:build ignore +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* The Computer Language Benchmarks Game + * http://shootout.alioth.debian.org/ + * + * contributed by The Go Authors. + * Based on spectral-norm.c by Sebastien Loisel + */ + +package main + +import ( + "flag" + "fmt" + "math" + "runtime" +) + +var n = flag.Int("n", 2000, "count") +var nCPU = flag.Int("ncpu", 4, "number of cpus") + +func evalA(i, j int) float64 { return 1 / float64(((i+j)*(i+j+1)/2 + i + 1)) } + +type Vec []float64 + +func (v Vec) Times(i, n int, u Vec, c chan int) { + for ; i < n; i++ { + v[i] = 0 + for j := 0; j < len(u); j++ { + v[i] += evalA(i, j) * u[j] + } + } + c <- 1 +} + +func (v Vec) TimesTransp(i, n int, u Vec, c chan int) { + for ; i < n; i++ { + v[i] = 0 + for j := 0; j < len(u); j++ { + v[i] += evalA(j, i) * u[j] + } + } + c <- 1 +} + +func wait(c chan int) { + for i := 0; i < *nCPU; i++ { + <-c + } +} + +func (v Vec) ATimesTransp(u Vec) { + x := make(Vec, len(u)) + c := make(chan int, *nCPU) + for i := 0; i < *nCPU; i++ { + go x.Times(i*len(v) / *nCPU, (i+1)*len(v) / *nCPU, u, c) + } + wait(c) + for i := 0; i < *nCPU; i++ { + go v.TimesTransp(i*len(v) / *nCPU, (i+1)*len(v) / *nCPU, x, c) + } + wait(c) +} + +func main() { + flag.Parse() + runtime.GOMAXPROCS(*nCPU) + N := *n + u := make(Vec, N) + for i := 0; i < N; i++ { + u[i] = 1 + } + v := make(Vec, N) + for i := 0; i < 10; i++ { + v.ATimesTransp(u) + u.ATimesTransp(v) + } + var vBv, vv float64 + for i := 0; i < N; i++ { + vBv += u[i] * v[i] + vv += v[i] * v[i] + } + fmt.Printf("%0.9f\n", math.Sqrt(vBv/vv)) +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/spectral-norm.c b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/spectral-norm.c new file mode 100644 index 0000000..9247543 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/spectral-norm.c @@ -0,0 +1,84 @@ +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* -*- mode: c -*- + * + * The Great Computer Language Shootout + * http://shootout.alioth.debian.org/ + * + * Contributed by Sebastien Loisel + */ + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> + +double eval_A(int i, int j) { return 1.0/((i+j)*(i+j+1)/2+i+1); } + +void eval_A_times_u(int N, const double u[], double Au[]) +{ + int i,j; + for(i=0;i<N;i++) + { + Au[i]=0; + for(j=0;j<N;j++) Au[i]+=eval_A(i,j)*u[j]; + } +} + +void eval_At_times_u(int N, const double u[], double Au[]) +{ + int i,j; + for(i=0;i<N;i++) + { + Au[i]=0; + for(j=0;j<N;j++) Au[i]+=eval_A(j,i)*u[j]; + } +} + +void eval_AtA_times_u(int N, const double u[], double AtAu[]) +{ double v[N]; eval_A_times_u(N,u,v); eval_At_times_u(N,v,AtAu); } + +int main(int argc, char *argv[]) +{ + int i; + int N = ((argc == 2) ? atoi(argv[1]) : 2000); + double u[N],v[N],vBv,vv; + for(i=0;i<N;i++) u[i]=1; + for(i=0;i<10;i++) + { + eval_AtA_times_u(N,u,v); + eval_AtA_times_u(N,v,u); + } + vBv=vv=0; + for(i=0;i<N;i++) { vBv+=u[i]*v[i]; vv+=v[i]*v[i]; } + printf("%0.9f\n",sqrt(vBv/vv)); + return 0; +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/spectral-norm.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/spectral-norm.go new file mode 100644 index 0000000..fb41051 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/spectral-norm.go @@ -0,0 +1,96 @@ +//go:build ignore +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* The Computer Language Benchmarks Game + * http://shootout.alioth.debian.org/ + * + * contributed by The Go Authors. + * Based on spectral-norm.c by Sebastien Loisel + */ + +package main + +import ( + "flag" + "fmt" + "math" +) + +var n = flag.Int("n", 2000, "count") + +func evalA(i, j int) float64 { return 1 / float64(((i+j)*(i+j+1)/2 + i + 1)) } + +type Vec []float64 + +func (v Vec) Times(u Vec) { + for i := 0; i < len(v); i++ { + v[i] = 0 + for j := 0; j < len(u); j++ { + v[i] += evalA(i, j) * u[j] + } + } +} + +func (v Vec) TimesTransp(u Vec) { + for i := 0; i < len(v); i++ { + v[i] = 0 + for j := 0; j < len(u); j++ { + v[i] += evalA(j, i) * u[j] + } + } +} + +func (v Vec) ATimesTransp(u Vec) { + x := make(Vec, len(u)) + x.Times(u) + v.TimesTransp(x) +} + +func main() { + flag.Parse() + N := *n + u := make(Vec, N) + for i := 0; i < N; i++ { + u[i] = 1 + } + v := make(Vec, N) + for i := 0; i < 10; i++ { + v.ATimesTransp(u) + u.ATimesTransp(v) + } + var vBv, vv float64 + for i := 0; i < N; i++ { + vBv += u[i] * v[i] + vv += v[i] * v[i] + } + fmt.Printf("%0.9f\n", math.Sqrt(vBv/vv)) +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/spectral-norm.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/spectral-norm.txt new file mode 100644 index 0000000..b988598 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/spectral-norm.txt @@ -0,0 +1 @@ +1.274224152 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/threadring.c b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/threadring.c new file mode 100644 index 0000000..59bb59d --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/threadring.c @@ -0,0 +1,115 @@ +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* +* The Computer Language Benchmarks Game +* http://shootout.alioth.debian.org/ + +* contributed by Premysl Hruby +*/ + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <pthread.h> +#include <string.h> +#include <limits.h> + +// PTHREAD_STACK_MIN undeclared on mingw +#ifndef PTHREAD_STACK_MIN +#define PTHREAD_STACK_MIN 65535 +#endif + +#define THREADS (503) + +struct stack { + char x[PTHREAD_STACK_MIN]; +}; + + +/* staticaly initialize mutex[0] mutex */ +static pthread_mutex_t mutex[THREADS]; +static int data[THREADS]; +static struct stack stacks[THREADS]; +/* stacks must be defined staticaly, or my i386 box run of virtual memory for this + * process while creating thread +- #400 */ + +static void* thread(void *num) +{ + int l = (int)(uintptr_t)num; + int r = (l+1) % THREADS; + int token; + + while(1) { + pthread_mutex_lock(mutex + l); + token = data[l]; + if (token) { + data[r] = token - 1; + pthread_mutex_unlock(mutex + r); + } + else { + printf("%i\n", l+1); + exit(0); + } + } +} + + + +int main(int argc, char **argv) +{ + int i; + pthread_t cthread; + pthread_attr_t stack_attr; + + if (argc != 2) + exit(255); + data[0] = atoi(argv[1]); + + pthread_attr_init(&stack_attr); + + for (i = 0; i < THREADS; i++) { + pthread_mutex_init(mutex + i, NULL); + pthread_mutex_lock(mutex + i); + +#if defined(__MINGW32__) || defined(__MINGW64__) + pthread_attr_setstackaddr(&stack_attr, &stacks[i]); + pthread_attr_setstacksize(&stack_attr, sizeof(struct stack)); +#else + pthread_attr_setstack(&stack_attr, &stacks[i], sizeof(struct stack)); +#endif + + pthread_create(&cthread, &stack_attr, thread, (void*)(uintptr_t)i); + } + + pthread_mutex_unlock(mutex + 0); + pthread_join(cthread, NULL); +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/threadring.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/threadring.go new file mode 100644 index 0000000..035867f --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/threadring.go @@ -0,0 +1,74 @@ +//go:build ignore +// +build ignore + +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* The Computer Language Benchmarks Game + * http://shootout.alioth.debian.org/ + * + * contributed by The Go Authors. + */ + +package main + +import ( + "flag" + "fmt" + "os" +) + +var n = flag.Int("n", 1000, "how many passes") + +const Nthread = 503 + +func f(i int, in <-chan int, out chan<- int) { + for { + n := <-in + if n == 0 { + fmt.Printf("%d\n", i) + os.Exit(0) + } + out <- n - 1 + } +} + +func main() { + flag.Parse() + + one := make(chan int) // will be input to thread 1 + var in, out chan int = nil, one + for i := 1; i <= Nthread-1; i++ { + in, out = out, make(chan int) + go f(i, in, out) + } + go f(Nthread, out, one) + one <- *n + <-make(chan int) // hang until ring completes +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/threadring.txt b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/threadring.txt new file mode 100644 index 0000000..f9aaa4d --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/threadring.txt @@ -0,0 +1 @@ +498 diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/timing.log b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/timing.log new file mode 100644 index 0000000..4e7d17a --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/timing.log @@ -0,0 +1,1254 @@ +All tests on r45 or r70 + +Aug 3 2009 + +First version of fasta. Translation of fasta.c, fetched from + http://shootout.alioth.debian.org/u32q/benchmark.php?test=fasta&lang=gpp&id=4 + +fasta -n 25000000 + gcc -O2 fasta.c 5.98u 0.00s 6.01r + gccgo -O2 fasta.go 8.82u 0.02s 8.85r + 6g fasta.go 13.50u 0.02s 13.53r + 6g -B fata.go 12.99u 0.02s 13.02r + +Aug 4 2009 +[added timing.sh] + +# myrandom: +# hand-written optimization of integer division +# use int32->float conversion +fasta -n 25000000 + # probably I/O library inefficiencies + gcc -O2 fasta.c 5.99u 0.00s 6.00r + gccgo -O2 fasta.go 8.82u 0.02s 8.85r + gc fasta 10.70u 0.00s 10.77r + gc_B fasta 10.09u 0.03s 10.12r + +reverse-complement < output-of-fasta-25000000 + # we don't know - memory cache behavior? + gcc -O2 reverse-complement.c 2.04u 0.94s 10.54r + gccgo -O2 reverse-complement.go 6.54u 0.63s 7.17r + gc reverse-complement 6.55u 0.70s 7.26r + gc_B reverse-complement 6.32u 0.70s 7.10r + +nbody 50000000 + # math.Sqrt needs to be in assembly; inlining is probably the other 50% + gcc -O2 nbody.c 21.61u 0.01s 24.80r + gccgo -O2 nbody.go 118.55u 0.02s 120.32r + gc nbody 100.84u 0.00s 100.85r + gc_B nbody 103.33u 0.00s 103.39r +[ +hacked Sqrt in assembler + gc nbody 31.97u 0.00s 32.01r +] + +binary-tree 15 # too slow to use 20 + # memory allocation and garbage collection + gcc -O2 binary-tree.c -lm 0.86u 0.00s 0.87r + gccgo -O2 binary-tree.go 1.69u 0.46s 2.15r + gccgo -O2 binary-tree-freelist.go 8.48u 0.00s 8.48r + gc binary-tree 9.60u 0.01s 9.62r + gc binary-tree-freelist 0.48u 0.01s 0.50r + +August 5, 2009 + +fannkuch 12 + # bounds checking is half the difference + # rest might be registerization + gcc -O2 fannkuch.c 60.09u 0.01s 60.32r + gccgo -O2 fannkuch.go 64.89u 0.00s 64.92r + gc fannkuch 124.59u 0.00s 124.67r + gc_B fannkuch 91.14u 0.00s 91.16r + +regex-dna 100000 + # regexp code is slow on trivial regexp + gcc -O2 regex-dna.c -lpcre 0.92u 0.00s 0.99r + gc regexp-dna 26.94u 0.18s 28.75r + gc_B regexp-dna 26.51u 0.09s 26.75r + +spectral-norm 5500 + gcc -O2 spectral-norm.c -lm 11.54u 0.00s 11.55r + gccgo -O2 spectral-norm.go 12.20u 0.00s 12.23r + gc spectral-norm 50.23u 0.00s 50.36r + gc_B spectral-norm 49.69u 0.01s 49.83r + gc spectral-norm-parallel 24.47u 0.03s 11.05r # has shift >>1 not div /2 + [using >>1 instead of /2 : gc gives 24.33u 0.00s 24.33r] + +August 6, 2009 + +k-nucleotide 5000000 + # string maps are slower than glib string maps + gcc -O2 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include k-nucleotide.c -lglib-2.0 k-nucleotide.c: 10.72u 0.01s 10.74r + gccgo -O2 k-nucleotide.go 21.64u 0.83s 22.78r + gc k-nucleotide 16.08u 0.06s 16.50r + gc_B k-nucleotide 17.32u 0.02s 17.37r + +mandelbrot 5500 + # floating point code generator should use more registers + gcc -O2 mandelbrot.c 56.13u 0.02s 56.17r + gccgo -O2 mandelbrot.go 57.49u 0.01s 57.51r + gc mandelbrot 74.32u 0.00s 74.35r + gc_B mandelbrot 74.28u 0.01s 74.31r + +meteor 2100 + # we don't know + gcc -O2 meteor-contest.c 0.10u 0.00s 0.10r + gccgo -O2 meteor-contest.go 0.12u 0.00s 0.14r + gc meteor-contest 0.24u 0.00s 0.26r + gc_B meteor-contest 0.23u 0.00s 0.24r + +pidigits 10000 + # bignum is slower than gmp + gcc -O2 pidigits.c -lgmp 2.60u 0.00s 2.62r + gc pidigits 77.69u 0.14s 78.18r + gc_B pidigits 74.26u 0.18s 75.41r + gc_B pidigits 68.48u 0.20s 69.31r # special case: no bounds checking in bignum + +August 7 2009 + +# New gc does better division by powers of 2. Significant improvements: + +spectral-norm 5500 + # floating point code generator should use more registers; possibly inline evalA + gcc -O2 spectral-norm.c -lm 11.50u 0.00s 11.50r + gccgo -O2 spectral-norm.go 12.02u 0.00s 12.02r + gc spectral-norm 23.98u 0.00s 24.00r # new time is 0.48 times old time, 52% faster + gc_B spectral-norm 23.71u 0.01s 23.72r # ditto + gc spectral-norm-parallel 24.04u 0.00s 6.26r # /2 put back. note: 4x faster (on r70, idle) + +k-nucleotide 1000000 + # string maps are slower than glib string maps + gcc -O2 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include k-nucleotide.c -lglib-2.0 10.82u 0.04s 10.87r + gccgo -O2 k-nucleotide.go 22.73u 0.89s 23.63r + gc k-nucleotide 15.97u 0.03s 16.04r + gc_B k-nucleotide 15.86u 0.06s 15.93r # 8.5% faster, but probably due to weird cache effeccts in previous version + +pidigits 10000 + # bignum is slower than gmp + gcc -O2 pidigits.c -lgmp 2.58u 0.00s 2.58r + gc pidigits 71.24u 0.04s 71.28r # 8.5% faster + gc_B pidigits 71.25u 0.03s 71.29r # 4% faster + +threadring 50000000 + gcc -O2 threadring.c -lpthread 35.51u 160.21s 199.50r + gccgo -O2 threadring.go 90.33u 459.95s 448.03r + gc threadring 33.11u 0.00s 33.14r + GOMAXPROCS=4 gc threadring 114.48u 226.65s 371.59r + # change wait code to do <-make(chan int) instead of time.Sleep + gc threadring 28.41u 0.01s 29.35r + GOMAXPROCS=4 gc threadring 112.59u 232.83s 384.72r + +chameneos 6000000 + gcc -O2 chameneosredux.c -lpthread 18.14u 276.52s 76.93r + gc chameneosredux 20.19u 0.01s 20.23r + +Aug 10 2009 + +# new 6g with better fp registers, fast div and mod of integers +# complete set of timings listed. significant changes marked *** + +fasta -n 25000000 + # probably I/O library inefficiencies + gcc -O2 fasta.c 5.96u 0.00s 5.97r + gc fasta 10.59u 0.01s 10.61r + gc_B fasta 9.92u 0.02s 9.95r + +reverse-complement < output-of-fasta-25000000 + # we don't know - memory cache behavior? + gcc -O2 reverse-complement.c 1.96u 1.56s 16.23r + gccgo -O2 reverse-complement.go 6.41u 0.62s 7.05r + gc reverse-complement 6.46u 0.70s 7.17r + gc_B reverse-complement 6.22u 0.72s 6.95r + +nbody 50000000 + # math.Sqrt needs to be in assembly; inlining is probably the other 50% + gcc -O2 nbody.c 21.26u 0.01s 21.28r + gccgo -O2 nbody.go 116.68u 0.07s 116.80r + gc nbody 86.64u 0.01s 86.68r # -14% + gc_B nbody 85.72u 0.02s 85.77r # *** -17% + +binary-tree 15 # too slow to use 20 + # memory allocation and garbage collection + gcc -O2 binary-tree.c -lm 0.87u 0.00s 0.87r + gccgo -O2 binary-tree.go 1.61u 0.47s 2.09r + gccgo -O2 binary-tree-freelist.go 0.00u 0.00s 0.01r + gc binary-tree 9.11u 0.01s 9.13r # *** -5% + gc binary-tree-freelist 0.47u 0.01s 0.48r + +fannkuch 12 + # bounds checking is half the difference + # rest might be registerization + gcc -O2 fannkuch.c 59.92u 0.00s 59.94r + gccgo -O2 fannkuch.go 65.54u 0.00s 65.58r + gc fannkuch 123.98u 0.01s 124.04r + gc_B fannkuch 90.75u 0.00s 90.78r + +regex-dna 100000 + # regexp code is slow on trivial regexp + gcc -O2 regex-dna.c -lpcre 0.91u 0.00s 0.92r + gc regex-dna 27.25u 0.02s 27.28r + gc_B regex-dna 29.51u 0.03s 29.55r + +spectral-norm 5500 + # possibly inline evalA + gcc -O2 spectral-norm.c -lm 11.57u 0.00s 11.57r + gccgo -O2 spectral-norm.go 12.07u 0.01s 12.08r + gc spectral-norm 23.99u 0.00s 24.00r + gc_B spectral-norm 23.73u 0.00s 23.75r + +k-nucleotide 1000000 + # string maps are slower than glib string maps + gcc -O2 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include k-nucleotide.c -lglib-2.0 10.63u 0.02s 10.69r + gccgo -O2 k-nucleotide.go 23.19u 0.91s 24.12r + gc k-nucleotide 16.73u 0.04s 16.78r # *** +5% (but this one seems to vary by more than that) + gc_B k-nucleotide 16.46u 0.04s 16.51r # *** +5% + +mandelbrot 16000 + gcc -O2 mandelbrot.c 56.16u 0.00s 56.16r + gccgo -O2 mandelbrot.go 57.41u 0.01s 57.42r + gc mandelbrot 64.05u 0.02s 64.08r # *** -14% + gc_B mandelbrot 64.10u 0.02s 64.14r # *** -14% + +meteor 2100 + # we don't know + gcc -O2 meteor-contest.c 0.10u 0.00s 0.10r + gccgo -O2 meteor-contest.go 0.12u 0.00s 0.12r + gc meteor-contest 0.18u 0.00s 0.20r # *** -25% + gc_B meteor-contest 0.17u 0.00s 0.18r # *** -24% + +pidigits 10000 + # bignum is slower than gmp + gcc -O2 pidigits.c -lgmp 2.57u 0.00s 2.57r + gc pidigits 71.82u 0.04s 71.89r + gc_B pidigits 71.84u 0.08s 71.98r + +threadring 50000000 + gcc -O2 threadring.c -lpthread 30.91u 164.33s 204.57r + gccgo -O2 threadring.go 87.12u 460.04s 447.61r + gc threadring 38.55u 0.00s 38.56r # *** +16% + +chameneos 6000000 + gcc -O2 chameneosredux.c -lpthread 17.93u 323.65s 88.47r + gc chameneosredux 21.72u 0.00s 21.73r + +August 10 2009 + +# In-place versions for some bignum operations. +pidigits 10000 + gcc -O2 pidigits.c -lgmp 2.56u 0.00s 2.57r + gc pidigits 55.22u 0.04s 55.29r # *** -23% + gc_B pidigits 55.49u 0.02s 55.60r # *** -23% + +September 3 2009 + +# New 6g inlines slices, has a few other tweaks. +# Complete rerun. Significant changes marked. + +fasta -n 25000000 + # probably I/O library inefficiencies + gcc -O2 fasta.c 5.96u 0.00s 5.96r + gc fasta 10.63u 0.02s 10.66r + gc_B fasta 9.92u 0.01s 9.94r + +reverse-complement < output-of-fasta-25000000 + # we don't know - memory cache behavior? + gcc -O2 reverse-complement.c 1.92u 0.33s 2.93r + gccgo -O2 reverse-complement.go 6.76u 0.72s 7.58r # +5% + gc reverse-complement 6.59u 0.70s 7.29r # +2% + gc_B reverse-complement 5.57u 0.80s 6.37r # -10% + +nbody 50000000 + # math.Sqrt needs to be in assembly; inlining is probably the other 50% + # also loop alignment appears to be critical + gcc -O2 nbody.c 21.28u 0.00s 21.28r + gccgo -O2 nbody.go 119.21u 0.00s 119.22r # +2% + gc nbody 109.72u 0.00s 109.78r # + 28% ***** + gc_B nbody 85.90u 0.00s 85.91r + +binary-tree 15 # too slow to use 20 + # memory allocation and garbage collection + gcc -O2 binary-tree.c -lm 0.86u 0.00s 0.87r + gccgo -O2 binary-tree.go 1.88u 0.54s 2.42r # +17% + gccgo -O2 binary-tree-freelist.go 0.01u 0.01s 0.02r + gc binary-tree 8.94u 0.01s 8.96r # -2% + gc binary-tree-freelist 0.47u 0.01s 0.48r + +fannkuch 12 + # bounds checking is half the difference + # rest might be registerization + gcc -O2 fannkuch.c 60.12u 0.00s 60.12r + gccgo -O2 fannkuch.go 92.62u 0.00s 92.66r # +41% *** + gc fannkuch 123.90u 0.00s 123.92r + gc_B fannkuch 89.71u 0.00s 89.74r # -1% + +regex-dna 100000 + # regexp code is slow on trivial regexp + gcc -O2 regex-dna.c -lpcre 0.88u 0.00s 0.88r + gc regex-dna 25.77u 0.01s 25.79r # -5% + gc_B regex-dna 26.05u 0.02s 26.09r # -12% *** + +spectral-norm 5500 + # possibly inline evalA + gcc -O2 spectral-norm.c -lm 11.51u 0.00s 11.51r + gccgo -O2 spectral-norm.go 11.95u 0.00s 11.96r + gc spectral-norm 24.23u 0.00s 24.23r + gc_B spectral-norm 23.83u 0.00s 23.84r + +k-nucleotide 1000000 + # string maps are slower than glib string maps + gcc -O2 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include k-nucleotide.c -lglib-2.0 10.68u 0.04s 10.72r + gccgo -O2 k-nucleotide.go 23.03u 0.88s 23.92r + gc k-nucleotide 15.79u 0.05s 15.85r # -5% (but this one seems to vary by more than that) + gc_B k-nucleotide 17.88u 0.05s 17.95r # +8% (ditto) + +mandelbrot 16000 + gcc -O2 mandelbrot.c 56.17u 0.02s 56.20r + gccgo -O2 mandelbrot.go 56.74u 0.02s 56.79r # -1% + gc mandelbrot 63.31u 0.01s 63.35r # -1% + gc_B mandelbrot 63.29u 0.00s 63.31r # -1% + +meteor 2100 + # we don't know + gcc -O2 meteor-contest.c 0.10u 0.00s 0.10r + gccgo -O2 meteor-contest.go 0.11u 0.00s 0.12r + gc meteor-contest 0.18u 0.00s 0.19r + gc_B meteor-contest 0.17u 0.00s 0.18r + +pidigits 10000 + # bignum is slower than gmp + gcc -O2 pidigits.c -lgmp 2.56u 0.00s 2.57r + gc pidigits 55.87u 0.03s 55.91r + gc_B pidigits 55.93u 0.03s 55.99r + +# these tests are compared using real time, since they run multiple processors +# accuracy probably low +threadring 50000000 + gcc -O2 threadring.c -lpthread 26.31u 164.69s 199.92r # -2% + gccgo -O2 threadring.go 87.90u 487.26s 472.81r # +6% + gc threadring 28.89u 0.00s 28.90r # -25% *** + +chameneos 6000000 + gcc -O2 chameneosredux.c -lpthread 16.41u 296.91s 81.17r # -8% + gc chameneosredux 19.97u 0.00s 19.97r # -8% + +Sep 22, 2009 + +# 6g inlines sliceslice in most cases. + +fasta -n 25000000 + # probably I/O library inefficiencies + gc fasta 10.24u 0.00s 10.25r # -4% + gc_B fasta 9.68u 0.01s 9.69r # -3% + +reverse-complement < output-of-fasta-25000000 + # we don't know - memory cache behavior? + gc reverse-complement 6.67u 0.69s 7.37r # +1% + gc_B reverse-complement 6.00u 0.64s 6.65r # +7% + +nbody -n 50000000 + # math.Sqrt needs to be in assembly; inlining is probably the other 50% + # also loop alignment appears to be critical + gc nbody 86.27u 0.00s 86.29r # -21% + gc_B nbody 104.52u 0.00s 104.54r # +22% + +fannkuch 12 + # bounds checking is half the difference + # rest might be registerization + gc fannkuch 128.36u 0.00s 128.37r # +4% + gc_B fannkuch 89.32u 0.00s 89.34r + +regex-dna 100000 + # regexp code is slow on trivial regexp + gc regex-dna 24.82u 0.01s 24.86r # -4% + gc_B regex-dna 24.55u 0.01s 24.57r # -6% + +spectral-norm 5500 + # possibly inline evalA + gc spectral-norm 24.05u 0.00s 24.07r # -1% + gc_B spectral-norm 23.60u 0.00s 23.65r # -1% + +k-nucleotide 1000000 + # string maps are slower than glib string maps + gc k-nucleotide 17.84u 0.04s 17.89r # +13% but mysterious variation continues + gc_B k-nucleotide 15.56u 0.08s 15.65r # -13% (ditto) + +mandelbrot 16000 + gc mandelbrot 64.08u 0.01s 64.11r # +1% + gc_B mandelbrot 64.04u 0.00s 64.05r # +1% + +pidigits 10000 + # bignum is slower than gmp + gc pidigits 58.68u 0.02s 58.72r # +5% + gc_B pidigits 58.86u 0.05s 58.99r # +5% + +# these tests are compared using real time, since they run multiple processors +# accuracy probably low +threadring 50000000 + gc threadring 32.70u 0.02s 32.77r # +13% + +chameneos 6000000 + gc chameneosredux 26.62u 0.00s 26.63r # +13% + +Sep 24, 2009 + +# Sqrt now in assembler for 6g. +nbody -n 50000000 + # remember, at least for 6g, alignment of loops may be important + gcc -O2 nbody.c 21.24u 0.00s 21.25r + gccgo -O2 nbody.go 121.03u 0.00s 121.04r + gc nbody 30.26u 0.00s 30.27r # -65% *** + gc_B nbody 30.20u 0.02s 30.22r # -72% *** + +Nov 13 2009 + +# fix bug in regexp; take performance hit. good regexps will come in time. +regex-dna 100000 + gcc -O2 regex-dna.c -lpcre 0.92u 0.00s 0.94r + gc regex-dna 29.78u 0.03s 29.83r + gc_B regex-dna 32.63u 0.03s 32.74r + +Nov 24 2009 + +# Roger Peppe's rewrite of the benchmark +chameneos 6000000 + gcc -O2 chameneosredux.c -lpthread 18.00u 303.29s 83.64r + gc chameneosredux 12.10u 0.00s 12.10r # 2.22X faster + +Jan 6, 2010 + +# Long-overdue update. All numbers included in this complete run. +# Some programs (e.g. reverse-complement) rewritten for speed. +# Regular expressions much faster in common cases (although still far behind PCRE) +# Bignum stuff improved +# Better (but sometimes slower) locking in channels. + +fasta -n 25000000 + gcc -O2 fasta.c 5.99u 0.01s 6.00r + gc fasta 9.11u 0.00s 9.12r # -11% + gc_B fasta 8.60u 0.00s 8.62r # +12% ?? + +reverse-complement < output-of-fasta-25000000 + gcc -O2 reverse-complement.c 2.00u 0.80s 9.54r +# gccgo -O2 reverse-complement.go 4.57u 0.35s 4.94r # 33% faster + gc reverse-complement 2.01u 0.38s 2.40r # 3.3X faster + gc_B reverse-complement 1.88u 0.36s 2.24r # 3.2X faster +GOGC=off + gc reverse-complement 2.01u 0.35s 2.37r + gc_B reverse-complement 1.86u 0.32s 2.19r + +nbody -n 50000000 + gcc -O2 nbody.c 21.28u 0.00s 21.31r + gccgo -O2 nbody.go 80.02u 0.00s 80.05r # 33% faster + gc nbody 30.13u 0.00s 30.13r + gc_B nbody 29.89u 0.01s 29.91r + +binary-tree 15 # too slow to use 20 + gcc -O2 binary-tree.c -lm 0.86u 0.00s 0.87r + gccgo -O2 binary-tree.go 4.82u 0.41s 5.24r # 2.5X slower + gc binary-tree 7.23u 0.01s 7.25r # # -19% + gc binary-tree-freelist 0.43u 0.00s 0.44r # -9% + +fannkuch 12 + gcc -O2 fannkuch.c 60.17u 0.00s 60.17r + gccgo -O2 fannkuch.go 78.47u 0.01s 78.49r + gc fannkuch 128.86u 0.00s 128.96r + gc_B fannkuch 90.17u 0.00s 90.21r + +regex-dna 100000 + gcc -O2 regex-dna.c -lpcre 0.90u 0.00s 0.92r + gc regex-dna 9.48u 0.01s 9.50r # 3.1X faster + gc_B regex-dna 9.08u 0.00s 9.10r # 3.6X faster + +spectral-norm 5500 + gcc -O2 spectral-norm.c -lm 11.48u 0.00s 11.48r + gccgo -O2 spectral-norm.go 11.68u 0.00s 11.70r + gc spectral-norm 23.98u 0.00s 23.99r + gc_B spectral-norm 23.68u 0.00s 23.69r + +k-nucleotide 1000000 + gcc -O2 k-nucleotide.c 10.85u 0.04s 10.90r + gccgo -O2 k-nucleotide.go 25.26u 0.87s 26.14r + gc k-nucleotide 15.28u 0.06s 15.37r # restored; mysterious variation continues + gc_B k-nucleotide 15.97u 0.03s 16.00r + +mandelbrot 16000 + gcc -O2 mandelbrot.c 56.12u 0.01s 56.15r + gccgo -O2 mandelbrot.go 56.86u 0.01s 56.89r + gc mandelbrot 66.05u 0.00s 66.07r # -3% + gc_B mandelbrot 66.06u 0.00s 66.07r # -3% + +meteor 2100 + gcc -O2 meteor-contest.c 0.10u 0.00s 0.10r + gccgo -O2 meteor-contest.go 0.12u 0.00s 0.12r + gc meteor-contest 0.17u 0.00s 0.17r + gc_B meteor-contest 0.15u 0.00s 0.16r + +pidigits 10000 + gcc -O2 pidigits.c -lgmp 2.57u 0.00s 2.59r + gc pidigits 38.27u 0.02s 38.30r # 1.5X faster + gc_B pidigits 38.27u 0.02s 38.31r # 1.5X faster + +threadring 50000000 + gcc -O2 threadring.c 37.11u 170.59s 212.75r + gccgo -O2 threadring.go 89.67u 447.56s 442.55r # -6.5% + gc threadring 36.08u 0.04s 36.15r # +10% + +chameneos 6000000 + gcc -O2 chameneosredux.c -lpthread 19.02u 331.08s 90.79r + gc chameneosredux 12.54u 0.00s 12.55r + +Oct 19, 2010 + +# Another long-overdue update. Some of the code is new; parallel versions +# of some are added. A few significant improvements. + +fasta -n 25000000 + gcc -O2 fasta.c 4.92u 0.00s 4.93r + gccgo -O2 fasta.go 3.31u 0.00s 3.34r # new code + gc fasta 3.68u 0.00s 3.69r # 2.5X faster with no code + gc_B fasta 3.68u 0.00s 3.69r # 2.3X faster with no code + +reverse-complement < output-of-fasta-25000000 + gcc -O2 reverse-complement.c 1.93u 0.81s 11.24r + gccgo -O2 reverse-complement.go 1.58u 0.43s 2.04r # first run with new code? + gc reverse-complement 1.84u 0.34s 2.20r # 10% faster + gc_B reverse-complement 1.85u 0.32s 2.18r + +nbody -n 50000000 + gcc -O2 nbody.c 21.35u 0.00s 21.36r + gccgo -O2 nbody.go 21.62u 0.00s 21.66r # 3.7X faster - why?? + gc nbody 29.78u 0.00s 29.79r + gc_B nbody 29.72u 0.00s 29.72r + +binary-tree 15 # too slow to use 20 + gcc -O2 binary-tree.c -lm 0.86u 0.00s 0.88r + gccgo -O2 binary-tree.go 4.05u 0.02s 4.08r # 28% faster + gccgo -O2 binary-tree-freelist 0.34u 0.08s 0.34r + gc binary-tree 5.94u 0.00s 5.95r # 20% faster + gc binary-tree-freelist 0.50u 0.01s 0.54r + +fannkuch 12 + gcc -O2 fannkuch.c 60.45u 0.00s 60.45r + gccgo -O2 fannkuch.go 64.64u 0.00s 64.64r + gccgo -O2 fannkuch-parallel.go 115.63u 0.00s 31.58r + gc fannkuch 126.52u 0.04s 126.68r + gc fannkuch-parallel 238.82u 0.10s 65.93r # GOMAXPROCS=4 + gc_B fannkuch 88.99u 0.00s 89.02r + +regex-dna 100000 + gcc -O2 regex-dna.c -lpcre 0.89u 0.00s 0.89r + gc regex-dna 8.99u 0.02s 9.03r + gc regex-dna-parallel 8.94u 0.02s 3.68r # GOMAXPROCS=4 + gc_B regex-dna 9.12u 0.00s 9.14r + +spectral-norm 5500 + gcc -O2 spectral-norm.c -lm 11.55u 0.00s 11.57r + gccgo -O2 spectral-norm.go 11.73u 0.00s 11.75r + gc spectral-norm 23.74u 0.00s 23.79r + gc_B spectral-norm 24.49u 0.02s 24.54r + +k-nucleotide 1000000 + gcc -O2 k-nucleotide.c 11.44u 0.06s 11.50r + gccgo -O2 k-nucleotide.go 8.65u 0.04s 8.71r + gccgo -O2 k-nucleotide-parallel.go 8.75u 0.03s 2.97r # set GOMAXPROCS=4 + gc k-nucleotide 14.92u 0.05s 15.01r + gc k-nucleotide-parallel 16.96u 0.06s 6.53r # set GOMAXPROCS=4 + gc_B k-nucleotide 15.97u 0.03s 16.08r + +mandelbrot 16000 + gcc -O2 mandelbrot.c 56.32u 0.00s 56.35r + gccgo -O2 mandelbrot.go 55.62u 0.02s 55.77r + gc mandelbrot 64.85u 0.01s 64.94r + gc_B mandelbrot 65.02u 0.01s 65.14r + +meteor 2100 + gcc -O2 meteor-contest.c 0.10u 0.00s 0.10r + gccgo -O2 meteor-contest.go 0.10u 0.00s 0.11r + gc meteor-contest 0.17u 0.00s 0.18r + gc_B meteor-contest 0.16u 0.00s 0.16r + +pidigits 10000 + gcc -O2 pidigits.c -lgmp 2.58u 0.00s 2.59r + gccgo -O2 pidigits.go 14.06u 0.01s 14.09r # first run? + gc pidigits 8.47u 0.05s 8.55r # 4.5X faster due to package big + gc_B pidigits 8.33u 0.01s 8.36r # 4.5X faster due to package big + +threadring 50000000 + gcc -O2 threadring.c 28.18u 153.19s 186.47r + gccgo -O2 threadring.go 110.10u 516.48s 515.25r + gc threadring 40.39u 0.00s 40.40r + +chameneos 6000000 + gcc -O2 chameneosredux.c -lpthread 18.20u 301.55s 83.10r + gccgo -O2 chameneosredux.go 52.22u 324.54s 201.21r + gc chameneosredux 13.52u 0.00s 13.54r + +Dec 14, 2010 + +# Improved regex code (same algorithm) gets ~30%. + +regex-dna 100000 + gcc -O2 regex-dna.c -lpcre 0.77u 0.01s 0.78r + gc regex-dna 6.80u 0.00s 6.81r + gc regex-dna-parallel 6.82u 0.01s 2.75r + gc_B regex-dna 6.69u 0.02s 6.70r + +Feb 15, 2011 + +# Improved GC, still single-threaded but more efficient + +fasta -n 25000000 + gcc -O2 fasta.c 3.40u 0.00s 3.40r + gccgo -O2 fasta.go 3.51u 0.00s 3.50r + gc fasta 3.66u 0.01s 3.66r + gc_B fasta 3.66u 0.00s 3.66r + +reverse-complement < output-of-fasta-25000000 + gcc -O2 reverse-complement.c 1.86u 1.29s 4.93r + gccgo -O2 reverse-complement.go 2.18u 0.41s 2.60r + gc reverse-complement 1.67u 0.48s 2.15r + gc_B reverse-complement 1.71u 0.45s 2.15r + +nbody -n 50000000 + gcc -O2 -lm nbody.c 21.64u 0.00s 21.64r + gccgo -O2 nbody.go 21.46u 0.00s 21.45r + gc nbody 29.07u 0.00s 29.06r + gc_B nbody 31.61u 0.00s 31.61r + +binary-tree 15 # too slow to use 20 + gcc -O2 binary-tree.c -lm 0.88u 0.00s 0.87r + gccgo -O2 binary-tree.go 2.74u 0.07s 2.81r + gccgo -O2 binary-tree-freelist.go 0.01u 0.00s 0.00r + gc binary-tree 4.22u 0.02s 4.24r + gc binary-tree-freelist 0.54u 0.02s 0.55r + +fannkuch 12 + gcc -O2 fannkuch.c 57.64u 0.00s 57.64r + gccgo -O2 fannkuch.go 65.79u 0.00s 65.82r + gccgo -O2 fannkuch-parallel.go 160.91u 0.02s 43.90r + gc fannkuch 126.36u 0.03s 126.53r + gc fannkuch-parallel 175.23u 0.04s 45.49r + gc_B fannkuch 89.23u 0.00s 89.24r + +regex-dna 100000 + gcc -O2 regex-dna.c -lpcre 0.77u 0.01s 0.80r + gccgo -O2 regex-dna.go 12.38u 0.10s 12.52r + gccgo -O2 regex-dna-parallel.go 43.96u 4.64s 15.11r + gc regex-dna 7.03u 0.01s 7.05r + gc regex-dna-parallel 6.85u 0.05s 2.70r + gc_B regex-dna 6.87u 0.02s 6.89r + +spectral-norm 5500 + gcc -O2 spectral-norm.c -lm 12.29u 0.00s 12.28r + gccgo -O2 spectral-norm.go 11.79u 0.00s 11.79r + gc spectral-norm 24.00u 0.02s 24.05r + gc_B spectral-norm 24.59u 0.01s 24.59r + +k-nucleotide 1000000 + gcc -O2 k-nucleotide.c 9.75u 0.07s 9.82r + gccgo -O2 k-nucleotide.go 8.92u 0.06s 8.98r + gccgo -O2 k-nucleotide-parallel.go 8.40u 0.04s 2.76r + gc k-nucleotide 17.01u 0.03s 17.04r + gc k-nucleotide-parallel 16.51u 0.08s 6.21r + gc_B k-nucleotide 16.94u 0.08s 17.02r + +mandelbrot 16000 + gcc -O2 mandelbrot.c 54.60u 0.00s 54.66r + gccgo -O2 mandelbrot.go 59.38u 0.00s 59.41r + gc mandelbrot 64.93u 0.04s 65.08r + gc_B mandelbrot 64.85u 0.03s 64.92r + +meteor 2098 + gcc -O2 meteor-contest.c 0.10u 0.01s 0.10r + gccgo -O2 meteor-contest.go 0.11u 0.00s 0.11r + gc meteor-contest 0.18u 0.00s 0.17r + gc_B meteor-contest 0.17u 0.00s 0.16r + +pidigits 10000 + gcc -O2 pidigits.c -lgmp 2.24u 0.00s 2.23r + gccgo -O2 pidigits.go 14.05u 0.00s 14.06r + gc pidigits 6.34u 0.05s 6.38r + gc_B pidigits 6.37u 0.02s 6.38r + +threadring 50000000 + gcc -O2 threadring.c 30.50u 258.05s 325.72r + gccgo -O2 threadring.go 92.87u 748.39s 728.46r + gc threadring 38.03u 0.01s 38.04r + +# Apr 15, 2011 +# Move to new machine, Intel Xeon E5520@2.27GHz. +# (Was Opteron(tm) Processor 8214 HE) + +fasta -n 25000000 +OLD: + gcc -O2 fasta.c 3.39u 0.04s 3.42r + gccgo -O2 fasta.go 3.52u 0.00s 3.52r + gc fasta 3.63u 0.04s 3.67r + gc_B fasta 3.66u 0.00s 3.66r +NEW: + gcc -O2 fasta.c 1.45u 0.02s 1.47r + gccgo -O2 fasta.go 1.51u 0.01s 1.51r + gc fasta 2.04u 0.00s 2.04r + gc_B fasta 2.05u 0.00s 2.04r + +reverse-complement < output-of-fasta-25000000 +OLD: + gcc -O2 reverse-complement.c 1.87u 1.51s 7.02r + gccgo -O2 reverse-complement.go 1.56u 0.54s 3.37r + gc reverse-complement 1.73u 0.36s 2.08r + gc_B reverse-complement 1.75u 0.37s 2.12r +NEW: + gcc -O2 reverse-complement.c 1.20u 0.47s 12.96r + gccgo -O2 reverse-complement.go 0.88u 0.14s 1.01r + gc reverse-complement 1.13u 0.17s 1.30r + gc_B reverse-complement 1.11u 0.09s 1.20r + +nbody -n 50000000 +OLD: + gcc -O2 -lm nbody.c 21.90u 0.00s 21.92r + gccgo -O2 nbody.go 23.12u 0.03s 23.19r + gc nbody 29.07u 0.00s 29.07r + gc_B nbody 31.84u 0.00s 31.85r +NEW: + gcc -O2 -lm nbody.c 13.01u 0.00s 13.03r + gccgo -O2 nbody.go 13.35u 0.00s 13.37r + gc nbody 21.78u 0.00s 21.82r + gc_B nbody 21.72u 0.00s 21.76r + +binary-tree 15 # too slow to use 20 +OLD: + gcc -O2 binary-tree.c -lm 0.83u 0.02s 0.84r + gccgo -O2 binary-tree.go 2.61u 0.02s 2.62r + gccgo -O2 binary-tree-freelist.go 0.32u 0.01s 0.32r + gc binary-tree 3.93u 0.04s 3.97r + gc binary-tree-freelist 0.47u 0.03s 0.50r +NEW: + gcc -O2 binary-tree.c -lm 0.60u 0.00s 0.59r + gccgo -O2 binary-tree.go 1.53u 0.00s 1.52r + gccgo -O2 binary-tree-freelist.go 0.01u 0.00s 0.00r + gc binary-tree 1.93u 0.02s 1.95r + gc binary-tree-freelist 0.32u 0.01s 0.32r + +fannkuch 12 +OLD: + gcc -O2 fannkuch.c 57.64u 0.00s 57.64r + gccgo -O2 fannkuch.go 65.56u 0.01s 65.65r + gccgo -O2 fannkuch-parallel.go 179.12u 0.00s 49.82r + gc fannkuch 126.39u 0.00s 126.39r + gc fannkuch-parallel 172.49u 0.02s 45.44r + gc_B fannkuch 89.30u 0.00s 89.28r +NEW: + gcc -O2 fannkuch.c 45.17u 0.00s 45.26r + gccgo -O2 fannkuch.go 53.63u 0.00s 53.73r + gccgo -O2 fannkuch-parallel.go 216.72u 0.00s 58.42r + gc fannkuch 108.21u 0.00s 108.44r + gc fannkuch-parallel 227.20u 0.00s 57.27r + gc_B fannkuch 56.14u 0.00s 56.26r + +regex-dna 100000 +OLD: + gcc -O2 regex-dna.c -lpcre 0.77u 0.01s 0.78r + gccgo -O2 regex-dna.go 10.15u 0.02s 10.23r + gccgo -O2 regex-dna-parallel.go 33.81u 3.22s 11.62r + gc regex-dna 6.52u 0.04s 6.56r + gc regex-dna-parallel 6.84u 0.03s 2.70r + gc_B regex-dna 6.83u 0.01s 6.84r +NEW: + gcc -O2 regex-dna.c -lpcre 0.47u 0.00s 0.47r + gccgo -O2 regex-dna.go 6.00u 0.00s 6.00r + gccgo -O2 regex-dna-parallel.go 44.54u 1.57s 6.51r + gc regex-dna 5.41u 0.01s 5.42r + gc regex-dna-parallel 5.62u 0.01s 2.20r + gc_B regex-dna 5.50u 0.00s 5.50r + +spectral-norm 5500 +OLD: + gcc -O2 spectral-norm.c -lm 12.29u 0.00s 12.28r + gccgo -O2 spectral-norm.go 11.56u 0.00s 11.55r + gc spectral-norm 23.98u 0.00s 24.00r + gc_B spectral-norm 24.62u 0.00s 24.65r +NEW: + gcc -O2 spectral-norm.c -lm 15.79u 0.00s 15.82r + gccgo -O2 spectral-norm.go 15.32u 0.00s 15.35r + gc spectral-norm 19.62u 0.01s 19.67r + gc_B spectral-norm 19.62u 0.00s 19.66r + +k-nucleotide 1000000 +OLD: + gcc -O2 k-nucleotide.c 9.82u 0.06s 9.87r + gccgo -O2 k-nucleotide.go 8.30u 0.02s 8.32r + gccgo -O2 k-nucleotide-parallel.go 8.84u 0.05s 3.02r + gc k-nucleotide 15.38u 0.07s 15.44r + gc k-nucleotide-parallel 16.40u 0.03s 5.93r + gc_B k-nucleotide 15.19u 0.05s 15.23r +NEW: + gcc -O2 -k-nucleotide.c 4.88u 0.03s 4.92r + gccgo -O2 k-nucleotide.go 5.94u 0.01s 5.96r + gccgo -O2 k-nucleotide-parallel.go 6.44u 0.03s 1.47r + gc k-nucleotide 9.61u 0.01s 9.63r + gc k-nucleotide-parallel 9.70u 0.00s 3.39r + gc_B k-nucleotide 9.19u 0.03s 9.23r + +mandelbrot 16000 +OLD: + gcc -O2 mandelbrot.c 54.54u 0.00s 54.56r + gccgo -O2 mandelbrot.go 59.63u 0.03s 59.67r + gc mandelbrot 64.82u 0.00s 64.83r + gc_B mandelbrot 64.84u 0.00s 64.91r +NEW: + gcc -O2 mandelbrot.c 36.07u 0.01s 36.15r + gccgo -O2 mandelbrot.go 43.57u 0.00s 43.66r + gc mandelbrot 60.66u 0.00s 60.79r + gc_B mandelbrot 60.90u 0.00s 61.03r + +meteor 2098 +OLD: + gcc -O2 meteor-contest.c 0.11u 0.00s 0.10r + gccgo -O2 meteor-contest.go 0.10u 0.01s 0.10r + gc meteor-contest 0.18u 0.00s 0.17r + gc_B meteor-contest 0.17u 0.00s 0.16r +NEW: + gcc -O2 meteor-contest.c 0.10u 0.00s 0.09r + gccgo -O2 meteor-contest.go 0.10u 0.00s 0.09r + gc meteor-contest 0.14u 0.00s 0.14r + gc_B meteor-contest 0.13u 0.00s 0.13r + +pidigits 10000 +OLD: + gcc -O2 pidigits.c -lgmp 2.22u 0.00s 2.21r + gccgo -O2 pidigits.go 13.39u 0.00s 13.40r + gc pidigits 6.42u 0.04s 6.45r + gc_B pidigits 6.45u 0.02s 6.47r +NEW: + gcc -O2 pidigits.c -lgmp 2.27u 0.00s 2.29r + gccgo -O2 pidigits.go 9.21u 0.00s 9.22r + gc pidigits 3.60u 0.00s 3.60r + gc_B pidigits 3.56u 0.02s 3.58r + +threadring 50000000 +OLD: + gcc -O2 threadring.c -lpthread 34.51u 267.95s 336.12r + gccgo -O2 threadring.go 103.51u 588.57s 627.16r + gc threadring 54.68u 0.00s 54.73r +NEW: + gcc -O2 threadring.c 32.00u 259.39s 369.74r + gccgo -O2 threadring.go 133.06u 546.02s 595.33r + gc threadring 16.75u 0.02s 16.80r + +chameneos 6000000 +OLD: + gcc -O2 chameneosredux.c -lpthread 12.65u 31.02s 13.33r + gccgo -O2 chameneosredux.go 47.04u 302.84s 252.29r + gc chameneosredux 14.14u 0.00s 14.14r +NEW: + gcc -O2 chameneosredux.c -lpthread 8.05u 63.43s 11.16r + gccgo -O2 chameneosredux.go 82.95u 304.37s 207.64r + gc chameneosredux 9.42u 0.00s 9.43r + +# May 13, 2011 +# after gc update to inline append when possible - 35% faster + +regex-dna 100000 + gc regex-dna 3.94u 0.00s 3.95r + gc regex-dna-parallel 4.15u 0.01s 1.63r + gc_B regex-dna 4.01u 0.01s 4.02r + +# Aug 4, 2011 +# After various updates to locking code and some runtime changes. +# Slowdowns believed due to slower (but more correct) memmove. + +fannkuch 12 + gccgo -O2 fannkuch.go 51.59u 0.00s 51.69r # -4% + gccgo -O2 fannkuch-parallel.go 253.17u 0.00s 64.67r # -11% + gc fannkuch 103.14u 0.00s 103.36r # -5% + gc fannkuch-parallel 189.63u 0.00s 49.37r # +9% + gc_B fannkuch 49.19u 0.00s 49.29r # -14% + +regex-dna 100000 + gc regex-dna 3.78u 0.00s 3.78r # -43% + gc regex-dna-parallel 3.84u 0.02s 1.48r # -49% + gc_B regex-dna 3.62u 0.00s 3.63r # -52% + +k-nucleotide 1000000 + gc k-nucleotide 12.23u 0.02s 12.27r # +27% + gc k-nucleotide-parallel 12.76u 0.02s 4.37r # +29% + gc_B k-nucleotide 12.18u 0.01s 12.21r # +33% + +threadring 50000000 + gc threadring 17.49u 0.00s 17.53r # +4% + +chameneos 6000000 + gc chameneosredux 7.61u 0.00s 7.63r # -24% + +Aug 9, 2011 +# After custom algorithms for 1- 2- 4- 8-byte scalars. + +fannkuch 12 + gc fannkuch-parallel 157.17u 0.00s 41.08r # -17% + +k-nucleotide 1000000 + gc k-nucleotide 8.72u 0.03s 8.76r # -39% + gc k-nucleotide-parallel 8.79u 0.01s 3.14r # -39% + gc_B k-nucleotide 8.65u 0.03s 8.69r # -39% + +pidigits 10000 + gc pidigits 3.71u 0.02s 3.73r # +4% + gc_B pidigits 3.73u 0.00s 3.73r # +4% + +threadring 50000000 + gc threadring 14.51u 0.00s 14.54r # -17% + +chameneos 6000000 + gc chameneosredux 7.41u 0.00s 7.42r # -3% + +# A complete run at the Go 1 release. +# Significant changes: +# - gccgo is now enabled for all tests (goroutines are cheap enough) +# - threadring and chameneos are 14% faster, probably due to runtime changes +# - regex-dna 36% faster +# - fannkuch-parallel (only) slowed down 40% +# - gccgo on binary-tree-freelist is still optimized to nothing +# Other changes are modest. + +fasta -n 25000000 + gcc -O2 fasta.c 1.45u 0.02s 1.48r + gccgo -O2 fasta.go 1.46u 0.00s 1.47r + gc fasta 1.99u 0.01s 2.00r + gc_B fasta 1.99u 0.01s 2.01r + +reverse-complement < output-of-fasta-25000000 + gcc -O2 reverse-complement.c 0.95u 0.48s 4.99r + gccgo -O2 reverse-complement.go 0.93u 0.16s 1.09r + gc reverse-complement 1.20u 0.19s 1.39r + gc_B reverse-complement 1.04u 0.16s 1.20r + +nbody -n 50000000 + gcc -O2 -lm nbody.c 13.02u 0.00s 13.05r + gccgo -O2 nbody.go 14.46u 0.00s 14.49r + gc nbody 21.79u 0.00s 21.84r + gc_B nbody 21.74u 0.00s 21.79r + +binary-tree 15 # too slow to use 20 + gcc -O2 binary-tree.c -lm 0.60u 0.01s 0.61r + gccgo -O2 binary-tree.go 1.30u 0.01s 1.32r + gccgo -O2 binary-tree-freelist.go 0.00u 0.00s 0.00r + gc binary-tree 1.84u 0.01s 1.86r + gc binary-tree-freelist 0.33u 0.00s 0.33r + +fannkuch 12 + gcc -O2 fannkuch.c 45.24u 0.00s 45.34r + gccgo -O2 fannkuch.go 59.76u 0.01s 59.90r + gccgo -O2 fannkuch-parallel.go 218.20u 0.01s 61.60r + gc fannkuch 103.92u 0.00s 104.16r + gc fannkuch-parallel 221.61u 0.00s 60.49r + gc_B fannkuch 53.17u 0.00s 53.30r + +regex-dna 100000 + gcc -O2 regex-dna.c -lpcre 0.47u 0.00s 0.48r + gccgo -O2 regex-dna.go 6.52u 0.00s 6.54r + gccgo -O2 regex-dna-parallel.go 14.40u 0.73s 4.35r + gc regex-dna 2.63u 0.02s 2.66r # -36% + gc regex-dna-parallel 2.87u 0.01s 1.11r + gc_B regex-dna 2.65u 0.00s 2.66r + +spectral-norm 5500 + gcc -O2 spectral-norm.c -lm 15.78u 0.00s 15.82r + gccgo -O2 spectral-norm.go 15.79u 0.00s 15.83r + gc spectral-norm 19.76u 0.00s 19.80r + gc_B spectral-norm 19.73u 0.01s 19.78r + +k-nucleotide 1000000 + gcc -O2 k-nucleotide.c 5.59u 0.03s 5.63r + gccgo -O2 k-nucleotide.go 4.09u 0.03s 4.13r + gccgo -O2 k-nucleotide-parallel.go 4.50u 0.06s 1.63r + gc k-nucleotide 9.23u 0.02s 9.27r + gc k-nucleotide-parallel 9.87u 0.03s 3.55r + gc_B k-nucleotide 9.20u 0.00s 9.22r + +mandelbrot 16000 + gcc -O2 mandelbrot.c 36.09u 0.00s 36.18r + gccgo -O2 mandelbrot.go 41.69u 0.01s 41.80r + gc mandelbrot 60.91u 0.02s 61.07r + gc_B mandelbrot 60.90u 0.00s 61.04r + +meteor 2098 + gcc -O2 meteor-contest.c 0.09u 0.00s 0.09r + gccgo -O2 meteor-contest.go 0.09u 0.00s 0.09r + gc meteor-contest 0.14u 0.00s 0.15r + gc_B meteor-contest 0.14u 0.00s 0.14r + +pidigits 10000 + gcc -O2 pidigits.c -lgmp 2.27u 0.00s 2.27r + gccgo -O2 pidigits.go 8.65u 0.00s 8.67r + gc pidigits 3.70u 0.04s 3.75r + gc_B pidigits 3.72u 0.02s 3.75r + +threadring 50000000 + gcc -O2 threadring.c 40.91u 369.85s 323.31r + gccgo -O2 threadring.go 26.97u 30.82s 57.93r + gc threadring 12.81u 0.01s 12.85r # -13% + +chameneos 6000000 + gcc -O2 chameneosredux.c -lpthread 9.44u 72.90s 12.65r + gccgo -O2 chameneosredux.go 7.73u 7.53s 15.30r + gc chameneosredux 6.51u 0.00s 6.53r # - 14% + +# After http://codereview.appspot.com/6248049, moving panicindex +# calls out of line (putting the likely code into a single path and shortening +# loops). Significant changes since the last run (note: some are slower for +# unrelated and as yet undiagnosed reasons): + +nbody -n 50000000 + gc nbody 19.10u 0.01s 19.19r # -12% + gc_B nbody 19.19u 0.00s 19.23r # -12% + +binary-tree 15 # too slow to use 20 + gc binary-tree 1.49u 0.01s 1.51r # -19% + +fannkuch 12 + gc fannkuch 60.79u 0.00s 60.92r # -41% + gc fannkuch-parallel 183.51u 0.01s 51.75r # -14% + gc_B fannkuch 51.68u 0.00s 51.79r # -3% + +k-nucleotide 1000000 + gc k-nucleotide 9.74u 0.04s 9.80r # +6% + gc k-nucleotide-parallel 9.89u 0.05s 3.59r # +1% + gc_B k-nucleotide 9.39u 0.02s 9.43r # +2% + +mandelbrot (much slower, due to unrelated http://codereview.appspot.com/6209077) + gc mandelbrot 100.98u 0.00s 101.20r # +65% + gc_B mandelbrot 100.90u 0.01s 101.17r # +65% + +meteor 2098 + gc meteor-contest 0.13u 0.00s 0.13r # -13% + gc_B meteor-contest 0.13u 0.00s 0.13r # -7% + +# May 30, 2012. +# After http://codereview.appspot.com/6261051, restoring old code generated +# for floating-point constants. Mandelbrot is back to its previous numbers. + +mandelbrot 16000 + gcc -O2 mandelbrot.c 36.07u 0.00s 36.16r + gccgo -O2 mandelbrot.go 41.72u 0.01s 41.90r + gc mandelbrot 60.62u 0.00s 60.76r + gc_B mandelbrot 60.68u 0.00s 60.82r + +# May 30, 2012. +# After http://codereview.appspot.com/6248068, better FP code +# by avoiding MOVSD between registers. +# Plus some other timing changes that have crept in from other speedups, +# from garbage collection to Printf. + +fasta -n 25000000 + gc fasta 1.76u 0.00s 1.76r # -12% + gc_B fasta 1.71u 0.00s 1.72r # -12% + +nbody -n 50000000 + gc nbody 17.56u 0.00s 17.60r # -8% + gc_B nbody 17.30u 0.00s 17.34r # -10% + +fannkuch 12 + gc fannkuch-parallel 155.92u 0.01s 44.05r # -15% + +k-nucleotide 1000000 + gc k-nucleotide 9.22u 0.01s 9.26r # -5% + gc k-nucleotide-parallel 9.23u 0.03s 3.26r # -9% + gc_B k-nucleotide 9.22u 0.03s 9.28r # -2% + +mandelbrot 16000 + gc mandelbrot 44.80u 0.00s 44.90r # -27% + gc_B mandelbrot 44.81u 0.00s 44.92r # -26% + +pidigits 10000 + gc pidigits 3.51u 0.00s 3.52r # -6% + gc_B pidigits 3.51u 0.00s 3.52r # -6% + +# Aug 28, 2012 +# After some assembler work in package big. +pidigits 10000 + gc pidigits 2.85u 0.02s 2.88r # -22% + gc_B pidigits 2.88u 0.01s 2.90r # -21% + +# Sep 26, 2012 +# 64-bit ints, plus significantly better floating-point code. +# Interesting details: +# Generally something in the 0-10% slower range, some (binary tree) more +# Floating-point noticeably faster: +# nbody -25% +# mandelbrot -37% relative to Go 1. +# Other: +# regex-dna +47% +fasta -n 25000000 + gcc -O2 fasta.c 1.43u 0.03s 1.46r + gccgo -O2 fasta.go 1.47u 0.00s 1.47r + gc fasta 1.78u 0.01s 1.80r + gc_B fasta 1.76u 0.00s 1.76r + +reverse-complement < output-of-fasta-25000000 + gcc -O2 reverse-complement.c 1.14u 0.39s 11.19r + gccgo -O2 reverse-complement.go 0.91u 0.17s 1.09r + gc reverse-complement 1.12u 0.18s 1.31r + gc_B reverse-complement 1.12u 0.15s 1.28r + +nbody -n 50000000 + gcc -O2 nbody.c -lm 13.02u 0.00s 13.05r + gccgo -O2 nbody.go 13.90u 0.00s 13.93r + gc nbody 17.05u 0.00s 17.09r + gc_B nbody 16.30u 0.00s 16.34r + +binary-tree 15 # too slow to use 20 + gcc -O2 binary-tree.c -lm 0.61u 0.00s 0.61r + gccgo -O2 binary-tree.go 1.24u 0.04s 1.29r + gccgo -O2 binary-tree-freelist.go 0.21u 0.01s 0.22r + gc binary-tree 1.93u 0.02s 1.96r + gc binary-tree-freelist 0.32u 0.00s 0.33r + +fannkuch 12 + gcc -O2 fannkuch.c 45.19u 0.00s 45.29r + gccgo -O2 fannkuch.go 60.32u 0.00s 60.45r + gccgo -O2 fannkuch-parallel.go 185.59u 0.00s 59.49r + gc fannkuch 72.14u 0.00s 72.30r + gc fannkuch-parallel 172.54u 0.00s 43.59r + gc_B fannkuch 53.55u 0.00s 53.67r + +regex-dna 100000 + gcc -O2 regex-dna.c -lpcre 0.47u 0.00s 0.47r + gccgo -O2 regex-dna.go 6.49u 0.05s 6.56r + gccgo -O2 regex-dna-parallel.go 14.60u 0.67s 4.42r + gc regex-dna 3.91u 0.00s 3.92r + gc regex-dna-parallel 4.01u 0.03s 1.56r + gc_B regex-dna 3.91u 0.00s 3.92r + +spectral-norm 5500 + gcc -O2 spectral-norm.c -lm 15.85u 0.00s 15.89r + gccgo -O2 spectral-norm.go 15.86u 0.00s 15.89r + gc spectral-norm 19.72u 0.00s 19.76r + gc_B spectral-norm 19.68u 0.01s 19.74r + +k-nucleotide 1000000 + gcc -O2 k-nucleotide.c -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -lglib-2.0 4.90u 0.01s 4.93r + gccgo -O2 k-nucleotide.go 4.78u 0.01s 4.80r + gccgo -O2 k-nucleotide-parallel.go 6.49u 0.02s 2.18r + gc k-nucleotide 9.05u 0.02s 9.09r + gc k-nucleotide-parallel 9.27u 0.01s 3.29r + gc_B k-nucleotide 8.95u 0.03s 9.00r + +mandelbrot 16000 + gcc -O2 mandelbrot.c 36.11u 0.00s 36.19r + gccgo -O2 mandelbrot.go 43.67u 0.00s 43.77r + gc mandelbrot 38.57u 0.00s 38.66r + gc_B mandelbrot 38.59u 0.00s 38.68r + +meteor 2098 + gcc -O2 meteor-contest.c 0.09u 0.00s 0.09r + gccgo -O2 meteor-contest.go 0.09u 0.00s 0.09r + gc meteor-contest 0.13u 0.00s 0.14r + gc_B meteor-contest 0.12u 0.00s 0.13r + +pidigits 10000 + gcc -O2 pidigits.c -lgmp 2.26u 0.00s 2.27r + gccgo -O2 pidigits.go 9.05u 0.00s 9.07r + gc pidigits 2.88u 0.02s 2.90r + gc_B pidigits 2.89u 0.00s 2.90r + +threadring 50000000 + gcc -O2 threadring.c -lpthread 37.30u 327.81s 289.28r + gccgo -O2 threadring.go 42.83u 26.15s 69.14r + gc threadring 13.00u 0.00s 13.03r + +chameneos 6000000 + gcc -O2 chameneosredux.c -lpthread 8.80u 71.67s 12.19r + gccgo -O2 chameneosredux.go 11.28u 6.68s 18.00r + gc chameneosredux 6.94u 0.00s 6.96r + +# May 23, 2013 +# Go 1.1, which includes precise GC, new scheduler, faster maps. +# 20%-ish speedups across many benchmarks. +# gccgo showing significant improvement (even though it's not yet up to Go 1.1) +# +# Standouts: +# fannkuch, regex-dna, k-nucleotide, threadring, chameneos + +fasta -n 25000000 + gcc -m64 -O2 fasta.c 1.54u 0.01s 1.55r + gccgo -O2 fasta.go 1.42u 0.00s 1.43r + gc fasta 1.50u 0.01s 1.52r # -16% + gc_B fasta 1.46u 0.00s 1.46r # -17% + +reverse-complement < output-of-fasta-25000000 + gcc -m64 -O2 reverse-complement.c 0.87u 0.37s 4.36r + gccgo -O2 reverse-complement.go 0.77u 0.15s 0.93r # -15% + gc reverse-complement 0.99u 0.12s 1.12r # -15% + gc_B reverse-complement 0.85u 0.17s 1.02r # -21% + +nbody -n 50000000 + gcc -m64 -O2 nbody.c -lm 13.50u 0.00s 13.53r + gccgo -O2 nbody.go 13.98u 0.01s 14.02r + gc nbody 16.63u 0.01s 16.67r + gc_B nbody 15.74u 0.00s 15.76r + +binary-tree 15 # too slow to use 20 + gcc -m64 -O2 binary-tree.c -lm 0.61u 0.00s 0.61r + gccgo -O2 binary-tree.go 1.11u 0.01s 1.12r # -13% + gccgo -O2 binary-tree-freelist.go 0.22u 0.01s 0.23r + gc binary-tree 1.83u 0.02s 1.83r # -7% + gc binary-tree-freelist 0.32u 0.00s 0.32r + +fannkuch 12 + gcc -m64 -O2 fannkuch.c 45.56u 0.00s 45.67r + gccgo -O2 fannkuch.go 57.71u 0.00s 57.85r # -4% + gccgo -O2 fannkuch-parallel.go 146.31u 0.00s 37.50r #-37% + gc fannkuch 70.06u 0.03s 70.17r # -3% + gc fannkuch-parallel 131.88u 0.06s 33.59r # -23% + gc_B fannkuch 45.55u 0.02s 45.63r # -15% + +regex-dna 100000 + gcc -m64 -O2 regex-dna.c -lpcre 0.44u 0.01s 0.45r + gccgo -O2 regex-dna.go 5.59u 0.00s 5.61r # -14% + gccgo -O2 regex-dna-parallel.go 10.85u 0.30s 3.34r # -24% + gc regex-dna 2.23u 0.01s 2.25r # -43% + gc regex-dna-parallel 2.35u 0.00s 0.93r # -40% + gc_B regex-dna 2.24u 0.01s 2.25r # -43% + +spectral-norm 5500 + gcc -m64 -O2 spectral-norm.c -lm 14.84u 0.00s 14.88r + gccgo -O2 spectral-norm.go 15.33u 0.00s 15.37r + gc spectral-norm 16.75u 0.02s 16.79r # -15% + gc_B spectral-norm 16.77u 0.01s 16.79r # -15% + +k-nucleotide 1000000 + gcc -O2 k-nucleotide.c -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -lglib-2.0 4.50u 0.00s 4.52r + gccgo -O2 k-nucleotide.go 3.72u 0.04s 3.77r # -21% + gccgo -O2 k-nucleotide-parallel.go 3.88u 0.03s 1.42r # -35% + gc k-nucleotide 6.32u 0.01s 6.33r # -31% + gc k-nucleotide-parallel 6.47u 0.05s 2.13r # -33% + gc_B k-nucleotide 6.45u 0.01s 6.47r # - 28% + +mandelbrot 16000 + gcc -m64 -O2 mandelbrot.c 36.03u 0.00s 36.11r + gccgo -O2 mandelbrot.go 37.61u 0.00s 37.74r # -14% + gc mandelbrot 38.19u 0.05s 38.29r + gc_B mandelbrot 38.19u 0.03s 38.26r + +meteor 2098 + gcc -m64 -O2 meteor-contest.c 0.08u 0.00s 0.08r + gccgo -O2 meteor-contest.go 0.09u 0.01s 0.10r + gc meteor-contest 0.12u 0.00s 0.12r # -15% although perhaps just noise + gc_B meteor-contest 0.11u 0.00s 0.12r # -8% although perhaps just noise + +pidigits 10000 + gcc -m64 -O2 pidigits.c -lgmp 2.27u 0.00s 2.28r + gccgo -O2 pidigits.go 8.95u 0.02s 8.99r + gc pidigits 2.88u 0.14s 2.91r + gc_B pidigits 2.92u 0.10s 2.91r + +threadring 50000000 + gcc -m64 -O2 threadring.c -lpthread 14.75u 167.88s 212.23r + gccgo -O2 threadring.go 36.72u 12.08s 48.91r # -29% + gc threadring 10.93u 0.01s 10.95r # -16% + +chameneos 6000000 + gcc -m64 -O2 chameneosredux.c -lpthread 8.89u 56.62s 9.75r + gccgo -O2 chameneosredux.go 9.48u 2.48s 11.99r # -33% + gc chameneosredux 5.80u 0.00s 5.81r # -16% + diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/timing.sh b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/timing.sh new file mode 100644 index 0000000..9abcf78 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/shootout/timing.sh @@ -0,0 +1,252 @@ +#!/usr/bin/env bash +# Copyright 2009 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +set -e + +eval $(go tool dist env) +GC="go tool compile" +LD="go tool link" + +gccm="" +case "$O" in +8) + gccm=-m32;; +6) + gccm=-m64;; +esac + +EXE="out" +havepcre=true +haveglib=true +havegmp=true +case "$(uname)" in +*MINGW* | *WIN32* | *CYGWIN*) + havepcre=false + haveglib=false + havegmp=false + if which pkg-config >/dev/null 2>&1; then + if pkg-config --cflags libpcre >/dev/null 2>&1 + then + echo "havepcre" + havepcre=true + fi + if pkg-config --cflags glib-2.0 >/dev/null 2>&1 + then + haveglib=true + fi + if pkg-config --cflags gmp >/dev/null 2>&1 + then + havegmp=true + fi + fi + EXE=exe;; +esac + +PATH=.:$PATH + +havegccgo=false +if which gccgo >/dev/null 2>&1 +then + havegccgo=true +fi + +mode=run +case X"$1" in +X-test) + mode=test + shift +esac + +gc() { + $GC $1.go; $LD -o a.$EXE $1.o +} + +gc_B() { + $GC -B $1.go; $LD -o a.$EXE $1.o +} + +runonly() { + if [ $mode = run ] + then + "$@" + fi +} + +run() { + if [ $mode = test ] + then + if echo $1 | grep -q '^gc ' + then + $1 # compile the program + program=$(echo $1 | sed 's/gc //') + shift + echo $program + $1 <fasta-1000.txt > /tmp/$$ + case $program in + chameneosredux) + # exact numbers may vary but non-numbers should match + grep -v '[0-9]' /tmp/$$ > /tmp/$$x + grep -v '[0-9]' chameneosredux.txt > /tmp/$$y + cmp /tmp/$$x /tmp/$$y + rm -f /tmp/$$ /tmp/$$x /tmp/$$y + ;; + *) + cmp /tmp/$$ $program.txt + rm -f /tmp/$$ + esac + fi + return + fi + if ! $havegccgo && echo $1 | grep -q '^gccgo ' + then + return + fi + echo -n ' '$1' ' + $1 + shift + + echo $((time -p $* >/dev/null) 2>&1) | awk '{print $4 "u " $6 "s " $2 "r"}' +} + +fasta() { + runonly echo 'fasta -n 25000000' + run "gcc $gccm -O2 fasta.c" a.$EXE 25000000 + run 'gccgo -O2 fasta.go' a.$EXE -n 25000000 #commented out until WriteString is in bufio + run 'gc fasta' a.$EXE -n 25000000 + run 'gc_B fasta' a.$EXE -n 25000000 +} + +revcomp() { + runonly gcc -O2 fasta.c + runonly a.$EXE 25000000 > x + runonly echo 'reverse-complement < output-of-fasta-25000000' + run "gcc $gccm -O2 reverse-complement.c" a.$EXE < x + run 'gccgo -O2 reverse-complement.go' a.$EXE < x + run 'gc reverse-complement' a.$EXE < x + run 'gc_B reverse-complement' a.$EXE < x + rm x +} + +nbody() { + runonly echo 'nbody -n 50000000' + run "gcc $gccm -O2 nbody.c -lm" a.$EXE 50000000 + run 'gccgo -O2 nbody.go' a.$EXE -n 50000000 + run 'gc nbody' a.$EXE -n 50000000 + run 'gc_B nbody' a.$EXE -n 50000000 +} + +binarytree() { + runonly echo 'binary-tree 15 # too slow to use 20' + run "gcc $gccm -O2 binary-tree.c -lm" a.$EXE 15 + run 'gccgo -O2 binary-tree.go' a.$EXE -n 15 + run 'gccgo -O2 binary-tree-freelist.go' a.$EXE -n 15 + run 'gc binary-tree' a.$EXE -n 15 + run 'gc binary-tree-freelist' a.$EXE -n 15 +} + +fannkuch() { + runonly echo 'fannkuch 12' + run "gcc $gccm -O2 fannkuch.c" a.$EXE 12 + run 'gccgo -O2 fannkuch.go' a.$EXE -n 12 + run 'gccgo -O2 fannkuch-parallel.go' a.$EXE -n 12 + run 'gc fannkuch' a.$EXE -n 12 + run 'gc fannkuch-parallel' a.$EXE -n 12 + run 'gc_B fannkuch' a.$EXE -n 12 +} + +regexdna() { + runonly gcc -O2 fasta.c + runonly a.$EXE 100000 > x + runonly echo 'regex-dna 100000' + if $havepcre; then + run "gcc $gccm -O2 regex-dna.c $(pkg-config libpcre --cflags --libs)" a.$EXE <x + fi + run 'gccgo -O2 regex-dna.go' a.$EXE <x + run 'gccgo -O2 regex-dna-parallel.go' a.$EXE <x + run 'gc regex-dna' a.$EXE <x + run 'gc regex-dna-parallel' a.$EXE <x + run 'gc_B regex-dna' a.$EXE <x + rm x +} + +spectralnorm() { + runonly echo 'spectral-norm 5500' + run "gcc $gccm -O2 spectral-norm.c -lm" a.$EXE 5500 + run 'gccgo -O2 spectral-norm.go' a.$EXE -n 5500 + run 'gc spectral-norm' a.$EXE -n 5500 + run 'gc_B spectral-norm' a.$EXE -n 5500 +} + +knucleotide() { + runonly gcc -O2 fasta.c + runonly a.$EXE 1000000 > x # should be using 25000000 + runonly echo 'k-nucleotide 1000000' + if [ $mode = run ] && $haveglib; then + run "gcc -O2 k-nucleotide.c $(pkg-config glib-2.0 --cflags --libs)" a.$EXE <x + fi + run 'gccgo -O2 k-nucleotide.go' a.$EXE <x + run 'gccgo -O2 k-nucleotide-parallel.go' a.$EXE <x + run 'gc k-nucleotide' a.$EXE <x + run 'gc k-nucleotide-parallel' a.$EXE <x + run 'gc_B k-nucleotide' a.$EXE <x + rm x +} + +mandelbrot() { + runonly echo 'mandelbrot 16000' + run "gcc $gccm -O2 mandelbrot.c" a.$EXE 16000 + run 'gccgo -O2 mandelbrot.go' a.$EXE -n 16000 + run 'gc mandelbrot' a.$EXE -n 16000 + run 'gc_B mandelbrot' a.$EXE -n 16000 +} + +meteor() { + runonly echo 'meteor 2098' + run "gcc $gccm -O2 meteor-contest.c" a.$EXE 2098 + run 'gccgo -O2 meteor-contest.go' a.$EXE -n 2098 + run 'gc meteor-contest' a.$EXE -n 2098 + run 'gc_B meteor-contest' a.$EXE -n 2098 +} + +pidigits() { + runonly echo 'pidigits 10000' + if $havegmp; then + run "gcc $gccm -O2 pidigits.c -lgmp" a.$EXE 10000 + fi + run 'gccgo -O2 pidigits.go' a.$EXE -n 10000 + run 'gc pidigits' a.$EXE -n 10000 + run 'gc_B pidigits' a.$EXE -n 10000 +} + +threadring() { + runonly echo 'threadring 50000000' + run "gcc $gccm -O2 threadring.c -lpthread" a.$EXE 50000000 + run 'gccgo -O2 threadring.go' a.$EXE -n 50000000 + run 'gc threadring' a.$EXE -n 50000000 +} + +chameneos() { + runonly echo 'chameneos 6000000' + run "gcc $gccm -O2 chameneosredux.c -lpthread" a.$EXE 6000000 + run 'gccgo -O2 chameneosredux.go' a.$EXE 6000000 + run 'gc chameneosredux' a.$EXE 6000000 +} + +case $# in +0) + run="fasta revcomp nbody binarytree fannkuch regexdna spectralnorm knucleotide mandelbrot meteor pidigits threadring chameneos" + ;; +*) + run=$* +esac + +for i in $run +do + $i + runonly echo +done + +rm *.o *.$EXE # Clean up + diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/slices/slices.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/slices/slices.go new file mode 100644 index 0000000..8a237c5 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/slices/slices.go @@ -0,0 +1,218 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package slices defines various functions useful with slices of any type. +// Unless otherwise specified, these functions all apply to the elements +// of a slice at index 0 <= i < len(s). +// +// Note that the less function in IsSortedFunc, SortFunc, SortStableFunc requires a +// strict weak ordering (https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings), +// or the sorting may fail to sort correctly. A common case is when sorting slices of +// floating-point numbers containing NaN values. +package slices + +import "golang.org/x/exp/constraints" + +// Equal reports whether two slices are equal: the same length and all +// elements equal. If the lengths are different, Equal returns false. +// Otherwise, the elements are compared in increasing index order, and the +// comparison stops at the first unequal pair. +// Floating point NaNs are not considered equal. +func Equal[E comparable](s1, s2 []E) bool { + if len(s1) != len(s2) { + return false + } + for i := range s1 { + if s1[i] != s2[i] { + return false + } + } + return true +} + +// EqualFunc reports whether two slices are equal using a comparison +// function on each pair of elements. If the lengths are different, +// EqualFunc returns false. Otherwise, the elements are compared in +// increasing index order, and the comparison stops at the first index +// for which eq returns false. +func EqualFunc[E1, E2 any](s1 []E1, s2 []E2, eq func(E1, E2) bool) bool { + if len(s1) != len(s2) { + return false + } + for i, v1 := range s1 { + v2 := s2[i] + if !eq(v1, v2) { + return false + } + } + return true +} + +// Compare compares the elements of s1 and s2. +// The elements are compared sequentially, starting at index 0, +// until one element is not equal to the other. +// The result of comparing the first non-matching elements is returned. +// If both slices are equal until one of them ends, the shorter slice is +// considered less than the longer one. +// The result is 0 if s1 == s2, -1 if s1 < s2, and +1 if s1 > s2. +// Comparisons involving floating point NaNs are ignored. +func Compare[E constraints.Ordered](s1, s2 []E) int { + s2len := len(s2) + for i, v1 := range s1 { + if i >= s2len { + return +1 + } + v2 := s2[i] + switch { + case v1 < v2: + return -1 + case v1 > v2: + return +1 + } + } + if len(s1) < s2len { + return -1 + } + return 0 +} + +// CompareFunc is like Compare but uses a comparison function +// on each pair of elements. The elements are compared in increasing +// index order, and the comparisons stop after the first time cmp +// returns non-zero. +// The result is the first non-zero result of cmp; if cmp always +// returns 0 the result is 0 if len(s1) == len(s2), -1 if len(s1) < len(s2), +// and +1 if len(s1) > len(s2). +func CompareFunc[E1, E2 any](s1 []E1, s2 []E2, cmp func(E1, E2) int) int { + s2len := len(s2) + for i, v1 := range s1 { + if i >= s2len { + return +1 + } + v2 := s2[i] + if c := cmp(v1, v2); c != 0 { + return c + } + } + if len(s1) < s2len { + return -1 + } + return 0 +} + +// Index returns the index of the first occurrence of v in s, +// or -1 if not present. +func Index[E comparable](s []E, v E) int { + for i, vs := range s { + if v == vs { + return i + } + } + return -1 +} + +// IndexFunc returns the first index i satisfying f(s[i]), +// or -1 if none do. +func IndexFunc[E any](s []E, f func(E) bool) int { + for i, v := range s { + if f(v) { + return i + } + } + return -1 +} + +// Contains reports whether v is present in s. +func Contains[E comparable](s []E, v E) bool { + return Index(s, v) >= 0 +} + +// Insert inserts the values v... into s at index i, +// returning the modified slice. +// In the returned slice r, r[i] == v[0]. +// Insert panics if i is out of range. +// This function is O(len(s) + len(v)). +func Insert[S ~[]E, E any](s S, i int, v ...E) S { + tot := len(s) + len(v) + if tot <= cap(s) { + s2 := s[:tot] + copy(s2[i+len(v):], s[i:]) + copy(s2[i:], v) + return s2 + } + s2 := make(S, tot) + copy(s2, s[:i]) + copy(s2[i:], v) + copy(s2[i+len(v):], s[i:]) + return s2 +} + +// Delete removes the elements s[i:j] from s, returning the modified slice. +// Delete panics if s[i:j] is not a valid slice of s. +// Delete modifies the contents of the slice s; it does not create a new slice. +// Delete is O(len(s)-(j-i)), so if many items must be deleted, it is better to +// make a single call deleting them all together than to delete one at a time. +func Delete[S ~[]E, E any](s S, i, j int) S { + return append(s[:i], s[j:]...) +} + +// Clone returns a copy of the slice. +// The elements are copied using assignment, so this is a shallow clone. +func Clone[S ~[]E, E any](s S) S { + // Preserve nil in case it matters. + if s == nil { + return nil + } + return append(S([]E{}), s...) +} + +// Compact replaces consecutive runs of equal elements with a single copy. +// This is like the uniq command found on Unix. +// Compact modifies the contents of the slice s; it does not create a new slice. +func Compact[S ~[]E, E comparable](s S) S { + if len(s) == 0 { + return s + } + i := 1 + last := s[0] + for _, v := range s[1:] { + if v != last { + s[i] = v + i++ + last = v + } + } + return s[:i] +} + +// CompactFunc is like Compact but uses a comparison function. +func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S { + if len(s) == 0 { + return s + } + i := 1 + last := s[0] + for _, v := range s[1:] { + if !eq(v, last) { + s[i] = v + i++ + last = v + } + } + return s[:i] +} + +// Grow increases the slice's capacity, if necessary, to guarantee space for +// another n elements. After Grow(n), at least n elements can be appended +// to the slice without another allocation. Grow may modify elements of the +// slice between the length and the capacity. If n is negative or too large to +// allocate the memory, Grow panics. +func Grow[S ~[]E, E any](s S, n int) S { + return append(s, make(S, n)...)[:len(s)] +} + +// Clip removes unused capacity from the slice, returning s[:len(s):len(s)]. +func Clip[S ~[]E, E any](s S) S { + return s[:len(s):len(s)] +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/slices/slices_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/slices/slices_test.go new file mode 100644 index 0000000..efe9966 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/slices/slices_test.go @@ -0,0 +1,552 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package slices + +import ( + "math" + "strings" + "testing" + + "golang.org/x/exp/constraints" +) + +var equalIntTests = []struct { + s1, s2 []int + want bool +}{ + { + []int{1}, + nil, + false, + }, + { + []int{}, + nil, + true, + }, + { + []int{1, 2, 3}, + []int{1, 2, 3}, + true, + }, + { + []int{1, 2, 3}, + []int{1, 2, 3, 4}, + false, + }, +} + +var equalFloatTests = []struct { + s1, s2 []float64 + wantEqual bool + wantEqualNaN bool +}{ + { + []float64{1, 2}, + []float64{1, 2}, + true, + true, + }, + { + []float64{1, 2, math.NaN()}, + []float64{1, 2, math.NaN()}, + false, + true, + }, +} + +func TestEqual(t *testing.T) { + for _, test := range equalIntTests { + if got := Equal(test.s1, test.s2); got != test.want { + t.Errorf("Equal(%v, %v) = %t, want %t", test.s1, test.s2, got, test.want) + } + } + for _, test := range equalFloatTests { + if got := Equal(test.s1, test.s2); got != test.wantEqual { + t.Errorf("Equal(%v, %v) = %t, want %t", test.s1, test.s2, got, test.wantEqual) + } + } +} + +// equal is simply ==. +func equal[T comparable](v1, v2 T) bool { + return v1 == v2 +} + +// equalNaN is like == except that all NaNs are equal. +func equalNaN[T comparable](v1, v2 T) bool { + isNaN := func(f T) bool { return f != f } + return v1 == v2 || (isNaN(v1) && isNaN(v2)) +} + +// offByOne returns true if integers v1 and v2 differ by 1. +func offByOne[E constraints.Integer](v1, v2 E) bool { + return v1 == v2+1 || v1 == v2-1 +} + +func TestEqualFunc(t *testing.T) { + for _, test := range equalIntTests { + if got := EqualFunc(test.s1, test.s2, equal[int]); got != test.want { + t.Errorf("EqualFunc(%v, %v, equal[int]) = %t, want %t", test.s1, test.s2, got, test.want) + } + } + for _, test := range equalFloatTests { + if got := EqualFunc(test.s1, test.s2, equal[float64]); got != test.wantEqual { + t.Errorf("Equal(%v, %v, equal[float64]) = %t, want %t", test.s1, test.s2, got, test.wantEqual) + } + if got := EqualFunc(test.s1, test.s2, equalNaN[float64]); got != test.wantEqualNaN { + t.Errorf("Equal(%v, %v, equalNaN[float64]) = %t, want %t", test.s1, test.s2, got, test.wantEqualNaN) + } + } + + s1 := []int{1, 2, 3} + s2 := []int{2, 3, 4} + if EqualFunc(s1, s1, offByOne[int]) { + t.Errorf("EqualFunc(%v, %v, offByOne) = true, want false", s1, s1) + } + if !EqualFunc(s1, s2, offByOne[int]) { + t.Errorf("EqualFunc(%v, %v, offByOne) = false, want true", s1, s2) + } + + s3 := []string{"a", "b", "c"} + s4 := []string{"A", "B", "C"} + if !EqualFunc(s3, s4, strings.EqualFold) { + t.Errorf("EqualFunc(%v, %v, strings.EqualFold) = false, want true", s3, s4) + } + + cmpIntString := func(v1 int, v2 string) bool { + return string(rune(v1)-1+'a') == v2 + } + if !EqualFunc(s1, s3, cmpIntString) { + t.Errorf("EqualFunc(%v, %v, cmpIntString) = false, want true", s1, s3) + } +} + +var compareIntTests = []struct { + s1, s2 []int + want int +}{ + { + []int{1, 2, 3}, + []int{1, 2, 3, 4}, + -1, + }, + { + []int{1, 2, 3, 4}, + []int{1, 2, 3}, + +1, + }, + { + []int{1, 2, 3}, + []int{1, 4, 3}, + -1, + }, + { + []int{1, 4, 3}, + []int{1, 2, 3}, + +1, + }, +} + +var compareFloatTests = []struct { + s1, s2 []float64 + want int +}{ + { + []float64{1, 2, math.NaN()}, + []float64{1, 2, math.NaN()}, + 0, + }, + { + []float64{1, math.NaN(), 3}, + []float64{1, math.NaN(), 4}, + -1, + }, + { + []float64{1, math.NaN(), 3}, + []float64{1, 2, 4}, + -1, + }, + { + []float64{1, math.NaN(), 3}, + []float64{1, 2, math.NaN()}, + 0, + }, + { + []float64{1, math.NaN(), 3, 4}, + []float64{1, 2, math.NaN()}, + +1, + }, +} + +func TestCompare(t *testing.T) { + intWant := func(want bool) string { + if want { + return "0" + } + return "!= 0" + } + for _, test := range equalIntTests { + if got := Compare(test.s1, test.s2); (got == 0) != test.want { + t.Errorf("Compare(%v, %v) = %d, want %s", test.s1, test.s2, got, intWant(test.want)) + } + } + for _, test := range equalFloatTests { + if got := Compare(test.s1, test.s2); (got == 0) != test.wantEqualNaN { + t.Errorf("Compare(%v, %v) = %d, want %s", test.s1, test.s2, got, intWant(test.wantEqualNaN)) + } + } + + for _, test := range compareIntTests { + if got := Compare(test.s1, test.s2); got != test.want { + t.Errorf("Compare(%v, %v) = %d, want %d", test.s1, test.s2, got, test.want) + } + } + for _, test := range compareFloatTests { + if got := Compare(test.s1, test.s2); got != test.want { + t.Errorf("Compare(%v, %v) = %d, want %d", test.s1, test.s2, got, test.want) + } + } +} + +func equalToCmp[T comparable](eq func(T, T) bool) func(T, T) int { + return func(v1, v2 T) int { + if eq(v1, v2) { + return 0 + } + return 1 + } +} + +func cmp[T constraints.Ordered](v1, v2 T) int { + if v1 < v2 { + return -1 + } else if v1 > v2 { + return 1 + } else { + return 0 + } +} + +func TestCompareFunc(t *testing.T) { + intWant := func(want bool) string { + if want { + return "0" + } + return "!= 0" + } + for _, test := range equalIntTests { + if got := CompareFunc(test.s1, test.s2, equalToCmp(equal[int])); (got == 0) != test.want { + t.Errorf("CompareFunc(%v, %v, equalToCmp(equal[int])) = %d, want %s", test.s1, test.s2, got, intWant(test.want)) + } + } + for _, test := range equalFloatTests { + if got := CompareFunc(test.s1, test.s2, equalToCmp(equal[float64])); (got == 0) != test.wantEqual { + t.Errorf("CompareFunc(%v, %v, equalToCmp(equal[float64])) = %d, want %s", test.s1, test.s2, got, intWant(test.wantEqual)) + } + } + + for _, test := range compareIntTests { + if got := CompareFunc(test.s1, test.s2, cmp[int]); got != test.want { + t.Errorf("CompareFunc(%v, %v, cmp[int]) = %d, want %d", test.s1, test.s2, got, test.want) + } + } + for _, test := range compareFloatTests { + if got := CompareFunc(test.s1, test.s2, cmp[float64]); got != test.want { + t.Errorf("CompareFunc(%v, %v, cmp[float64]) = %d, want %d", test.s1, test.s2, got, test.want) + } + } + + s1 := []int{1, 2, 3} + s2 := []int{2, 3, 4} + if got := CompareFunc(s1, s2, equalToCmp(offByOne[int])); got != 0 { + t.Errorf("CompareFunc(%v, %v, offByOne) = %d, want 0", s1, s2, got) + } + + s3 := []string{"a", "b", "c"} + s4 := []string{"A", "B", "C"} + if got := CompareFunc(s3, s4, strings.Compare); got != 1 { + t.Errorf("CompareFunc(%v, %v, strings.Compare) = %d, want 1", s3, s4, got) + } + + compareLower := func(v1, v2 string) int { + return strings.Compare(strings.ToLower(v1), strings.ToLower(v2)) + } + if got := CompareFunc(s3, s4, compareLower); got != 0 { + t.Errorf("CompareFunc(%v, %v, compareLower) = %d, want 0", s3, s4, got) + } + + cmpIntString := func(v1 int, v2 string) int { + return strings.Compare(string(rune(v1)-1+'a'), v2) + } + if got := CompareFunc(s1, s3, cmpIntString); got != 0 { + t.Errorf("CompareFunc(%v, %v, cmpIntString) = %d, want 0", s1, s3, got) + } +} + +var indexTests = []struct { + s []int + v int + want int +}{ + { + nil, + 0, + -1, + }, + { + []int{}, + 0, + -1, + }, + { + []int{1, 2, 3}, + 2, + 1, + }, + { + []int{1, 2, 2, 3}, + 2, + 1, + }, + { + []int{1, 2, 3, 2}, + 2, + 1, + }, +} + +func TestIndex(t *testing.T) { + for _, test := range indexTests { + if got := Index(test.s, test.v); got != test.want { + t.Errorf("Index(%v, %v) = %d, want %d", test.s, test.v, got, test.want) + } + } +} + +func equalToIndex[T any](f func(T, T) bool, v1 T) func(T) bool { + return func(v2 T) bool { + return f(v1, v2) + } +} + +func TestIndexFunc(t *testing.T) { + for _, test := range indexTests { + if got := IndexFunc(test.s, equalToIndex(equal[int], test.v)); got != test.want { + t.Errorf("IndexFunc(%v, equalToIndex(equal[int], %v)) = %d, want %d", test.s, test.v, got, test.want) + } + } + + s1 := []string{"hi", "HI"} + if got := IndexFunc(s1, equalToIndex(equal[string], "HI")); got != 1 { + t.Errorf("IndexFunc(%v, equalToIndex(equal[string], %q)) = %d, want %d", s1, "HI", got, 1) + } + if got := IndexFunc(s1, equalToIndex(strings.EqualFold, "HI")); got != 0 { + t.Errorf("IndexFunc(%v, equalToIndex(strings.EqualFold, %q)) = %d, want %d", s1, "HI", got, 0) + } +} + +func TestContains(t *testing.T) { + for _, test := range indexTests { + if got := Contains(test.s, test.v); got != (test.want != -1) { + t.Errorf("Contains(%v, %v) = %t, want %t", test.s, test.v, got, test.want != -1) + } + } +} + +var insertTests = []struct { + s []int + i int + add []int + want []int +}{ + { + []int{1, 2, 3}, + 0, + []int{4}, + []int{4, 1, 2, 3}, + }, + { + []int{1, 2, 3}, + 1, + []int{4}, + []int{1, 4, 2, 3}, + }, + { + []int{1, 2, 3}, + 3, + []int{4}, + []int{1, 2, 3, 4}, + }, + { + []int{1, 2, 3}, + 2, + []int{4, 5}, + []int{1, 2, 4, 5, 3}, + }, +} + +func TestInsert(t *testing.T) { + s := []int{1, 2, 3} + if got := Insert(s, 0); !Equal(got, s) { + t.Errorf("Insert(%v, 0) = %v, want %v", s, got, s) + } + for _, test := range insertTests { + copy := Clone(test.s) + if got := Insert(copy, test.i, test.add...); !Equal(got, test.want) { + t.Errorf("Insert(%v, %d, %v...) = %v, want %v", test.s, test.i, test.add, got, test.want) + } + } +} + +var deleteTests = []struct { + s []int + i, j int + want []int +}{ + { + []int{1, 2, 3}, + 0, + 0, + []int{1, 2, 3}, + }, + { + []int{1, 2, 3}, + 0, + 1, + []int{2, 3}, + }, + { + []int{1, 2, 3}, + 3, + 3, + []int{1, 2, 3}, + }, + { + []int{1, 2, 3}, + 0, + 2, + []int{3}, + }, + { + []int{1, 2, 3}, + 0, + 3, + []int{}, + }, +} + +func TestDelete(t *testing.T) { + for _, test := range deleteTests { + copy := Clone(test.s) + if got := Delete(copy, test.i, test.j); !Equal(got, test.want) { + t.Errorf("Delete(%v, %d, %d) = %v, want %v", test.s, test.i, test.j, got, test.want) + } + } +} + +func TestClone(t *testing.T) { + s1 := []int{1, 2, 3} + s2 := Clone(s1) + if !Equal(s1, s2) { + t.Errorf("Clone(%v) = %v, want %v", s1, s2, s1) + } + s1[0] = 4 + want := []int{1, 2, 3} + if !Equal(s2, want) { + t.Errorf("Clone(%v) changed unexpectedly to %v", want, s2) + } + if got := Clone([]int(nil)); got != nil { + t.Errorf("Clone(nil) = %#v, want nil", got) + } + if got := Clone(s1[:0]); got == nil || len(got) != 0 { + t.Errorf("Clone(%v) = %#v, want %#v", s1[:0], got, s1[:0]) + } +} + +var compactTests = []struct { + s []int + want []int +}{ + { + nil, + nil, + }, + { + []int{1}, + []int{1}, + }, + { + []int{1, 2, 3}, + []int{1, 2, 3}, + }, + { + []int{1, 1, 2}, + []int{1, 2}, + }, + { + []int{1, 2, 1}, + []int{1, 2, 1}, + }, + { + []int{1, 2, 2, 3, 3, 4}, + []int{1, 2, 3, 4}, + }, +} + +func TestCompact(t *testing.T) { + for _, test := range compactTests { + copy := Clone(test.s) + if got := Compact(copy); !Equal(got, test.want) { + t.Errorf("Compact(%v) = %v, want %v", test.s, got, test.want) + } + } +} + +func TestCompactFunc(t *testing.T) { + for _, test := range compactTests { + copy := Clone(test.s) + if got := CompactFunc(copy, equal[int]); !Equal(got, test.want) { + t.Errorf("CompactFunc(%v, equal[int]) = %v, want %v", test.s, got, test.want) + } + } + + s1 := []string{"a", "a", "A", "B", "b"} + copy := Clone(s1) + want := []string{"a", "B"} + if got := CompactFunc(copy, strings.EqualFold); !Equal(got, want) { + t.Errorf("CompactFunc(%v, strings.EqualFold) = %v, want %v", s1, got, want) + } +} + +func TestGrow(t *testing.T) { + s1 := []int{1, 2, 3} + copy := Clone(s1) + s2 := Grow(copy, 1000) + if !Equal(s1, s2) { + t.Errorf("Grow(%v) = %v, want %v", s1, s2, s1) + } + if cap(s2) < 1000+len(s1) { + t.Errorf("after Grow(%v) cap = %d, want >= %d", s1, cap(s2), 1000+len(s1)) + } +} + +func TestClip(t *testing.T) { + s1 := []int{1, 2, 3, 4, 5, 6}[:3] + orig := Clone(s1) + if len(s1) != 3 { + t.Errorf("len(%v) = %d, want 3", s1, len(s1)) + } + if cap(s1) < 6 { + t.Errorf("cap(%v[:3]) = %d, want >= 6", orig, cap(s1)) + } + s2 := Clip(s1) + if !Equal(s1, s2) { + t.Errorf("Clip(%v) = %v, want %v", s1, s2, s1) + } + if cap(s2) != 3 { + t.Errorf("cap(Clip(%v)) = %d, want 3", orig, cap(s2)) + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/slices/sort.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/slices/sort.go new file mode 100644 index 0000000..c22e74b --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/slices/sort.go @@ -0,0 +1,127 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package slices + +import ( + "math/bits" + + "golang.org/x/exp/constraints" +) + +// Sort sorts a slice of any ordered type in ascending order. +// Sort may fail to sort correctly when sorting slices of floating-point +// numbers containing Not-a-number (NaN) values. +// Use slices.SortFunc(x, func(a, b float64) bool {return a < b || (math.IsNaN(a) && !math.IsNaN(b))}) +// instead if the input may contain NaNs. +func Sort[E constraints.Ordered](x []E) { + n := len(x) + pdqsortOrdered(x, 0, n, bits.Len(uint(n))) +} + +// SortFunc sorts the slice x in ascending order as determined by the less function. +// This sort is not guaranteed to be stable. +// +// SortFunc requires that less is a strict weak ordering. +// See https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings. +func SortFunc[E any](x []E, less func(a, b E) bool) { + n := len(x) + pdqsortLessFunc(x, 0, n, bits.Len(uint(n)), less) +} + +// SortStable sorts the slice x while keeping the original order of equal +// elements, using less to compare elements. +func SortStableFunc[E any](x []E, less func(a, b E) bool) { + stableLessFunc(x, len(x), less) +} + +// IsSorted reports whether x is sorted in ascending order. +func IsSorted[E constraints.Ordered](x []E) bool { + for i := len(x) - 1; i > 0; i-- { + if x[i] < x[i-1] { + return false + } + } + return true +} + +// IsSortedFunc reports whether x is sorted in ascending order, with less as the +// comparison function. +func IsSortedFunc[E any](x []E, less func(a, b E) bool) bool { + for i := len(x) - 1; i > 0; i-- { + if less(x[i], x[i-1]) { + return false + } + } + return true +} + +// BinarySearch searches for target in a sorted slice and returns the position +// where target is found, or the position where target would appear in the +// sort order; it also returns a bool saying whether the target is really found +// in the slice. The slice must be sorted in increasing order. +func BinarySearch[E constraints.Ordered](x []E, target E) (int, bool) { + // search returns the leftmost position where f returns true, or len(x) if f + // returns false for all x. This is the insertion position for target in x, + // and could point to an element that's either == target or not. + pos := search(len(x), func(i int) bool { return x[i] >= target }) + if pos >= len(x) || x[pos] != target { + return pos, false + } else { + return pos, true + } +} + +// BinarySearchFunc works like BinarySearch, but uses a custom comparison +// function. The slice must be sorted in increasing order, where "increasing" is +// defined by cmp. cmp(a, b) is expected to return an integer comparing the two +// parameters: 0 if a == b, a negative number if a < b and a positive number if +// a > b. +func BinarySearchFunc[E any](x []E, target E, cmp func(E, E) int) (int, bool) { + pos := search(len(x), func(i int) bool { return cmp(x[i], target) >= 0 }) + if pos >= len(x) || cmp(x[pos], target) != 0 { + return pos, false + } else { + return pos, true + } +} + +func search(n int, f func(int) bool) int { + // Define f(-1) == false and f(n) == true. + // Invariant: f(i-1) == false, f(j) == true. + i, j := 0, n + for i < j { + h := int(uint(i+j) >> 1) // avoid overflow when computing h + // i ≤ h < j + if !f(h) { + i = h + 1 // preserves f(i-1) == false + } else { + j = h // preserves f(j) == true + } + } + // i == j, f(i-1) == false, and f(j) (= f(i)) == true => answer is i. + return i +} + +type sortedHint int // hint for pdqsort when choosing the pivot + +const ( + unknownHint sortedHint = iota + increasingHint + decreasingHint +) + +// xorshift paper: https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf +type xorshift uint64 + +func (r *xorshift) Next() uint64 { + *r ^= *r << 13 + *r ^= *r >> 17 + *r ^= *r << 5 + return uint64(*r) +} + +func nextPowerOfTwo(length int) uint { + return 1 << bits.Len(uint(length)) +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/slices/sort_benchmark_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/slices/sort_benchmark_test.go new file mode 100644 index 0000000..88b753d --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/slices/sort_benchmark_test.go @@ -0,0 +1,202 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package slices + +import ( + "math/rand" + "sort" + "strings" + "testing" +) + +// These benchmarks compare sorting a large slice of int with sort.Ints vs. +// slices.Sort +func makeRandomInts(n int) []int { + rand.Seed(42) + ints := make([]int, n) + for i := 0; i < n; i++ { + ints[i] = rand.Intn(n) + } + return ints +} + +func makeSortedInts(n int) []int { + ints := make([]int, n) + for i := 0; i < n; i++ { + ints[i] = i + } + return ints +} + +func makeReversedInts(n int) []int { + ints := make([]int, n) + for i := 0; i < n; i++ { + ints[i] = n - i + } + return ints +} + +const N = 100_000 + +func BenchmarkSortInts(b *testing.B) { + for i := 0; i < b.N; i++ { + b.StopTimer() + ints := makeRandomInts(N) + b.StartTimer() + sort.Ints(ints) + } +} + +func BenchmarkSlicesSortInts(b *testing.B) { + for i := 0; i < b.N; i++ { + b.StopTimer() + ints := makeRandomInts(N) + b.StartTimer() + Sort(ints) + } +} + +func BenchmarkSlicesSortInts_Sorted(b *testing.B) { + for i := 0; i < b.N; i++ { + b.StopTimer() + ints := makeSortedInts(N) + b.StartTimer() + Sort(ints) + } +} + +func BenchmarkSlicesSortInts_Reversed(b *testing.B) { + for i := 0; i < b.N; i++ { + b.StopTimer() + ints := makeReversedInts(N) + b.StartTimer() + Sort(ints) + } +} + +// Since we're benchmarking these sorts against each other, make sure that they +// generate similar results. +func TestIntSorts(t *testing.T) { + ints := makeRandomInts(200) + ints2 := Clone(ints) + + sort.Ints(ints) + Sort(ints2) + + for i := range ints { + if ints[i] != ints2[i] { + t.Fatalf("ints2 mismatch at %d; %d != %d", i, ints[i], ints2[i]) + } + } +} + +// The following is a benchmark for sorting strings. + +// makeRandomStrings generates n random strings with alphabetic runes of +// varying lenghts. +func makeRandomStrings(n int) []string { + rand.Seed(42) + var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + ss := make([]string, n) + for i := 0; i < n; i++ { + var sb strings.Builder + slen := 2 + rand.Intn(50) + for j := 0; j < slen; j++ { + sb.WriteRune(letters[rand.Intn(len(letters))]) + } + ss[i] = sb.String() + } + return ss +} + +func TestStringSorts(t *testing.T) { + ss := makeRandomStrings(200) + ss2 := Clone(ss) + + sort.Strings(ss) + Sort(ss2) + + for i := range ss { + if ss[i] != ss2[i] { + t.Fatalf("ss2 mismatch at %d; %s != %s", i, ss[i], ss2[i]) + } + } +} + +func BenchmarkSortStrings(b *testing.B) { + for i := 0; i < b.N; i++ { + b.StopTimer() + ss := makeRandomStrings(N) + b.StartTimer() + sort.Strings(ss) + } +} + +func BenchmarkSlicesSortStrings(b *testing.B) { + for i := 0; i < b.N; i++ { + b.StopTimer() + ss := makeRandomStrings(N) + b.StartTimer() + Sort(ss) + } +} + +// These benchmarks compare sorting a slice of structs with sort.Sort vs. +// slices.SortFunc. +type myStruct struct { + a, b, c, d string + n int +} + +type myStructs []*myStruct + +func (s myStructs) Len() int { return len(s) } +func (s myStructs) Less(i, j int) bool { return s[i].n < s[j].n } +func (s myStructs) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +func makeRandomStructs(n int) myStructs { + rand.Seed(42) + structs := make([]*myStruct, n) + for i := 0; i < n; i++ { + structs[i] = &myStruct{n: rand.Intn(n)} + } + return structs +} + +func TestStructSorts(t *testing.T) { + ss := makeRandomStructs(200) + ss2 := make([]*myStruct, len(ss)) + for i := range ss { + ss2[i] = &myStruct{n: ss[i].n} + } + + sort.Sort(ss) + SortFunc(ss2, func(a, b *myStruct) bool { return a.n < b.n }) + + for i := range ss { + if *ss[i] != *ss2[i] { + t.Fatalf("ints2 mismatch at %d; %v != %v", i, *ss[i], *ss2[i]) + } + } +} + +func BenchmarkSortStructs(b *testing.B) { + for i := 0; i < b.N; i++ { + b.StopTimer() + ss := makeRandomStructs(N) + b.StartTimer() + sort.Sort(ss) + } +} + +func BenchmarkSortFuncStructs(b *testing.B) { + lessFunc := func(a, b *myStruct) bool { return a.n < b.n } + for i := 0; i < b.N; i++ { + b.StopTimer() + ss := makeRandomStructs(N) + b.StartTimer() + SortFunc(ss, lessFunc) + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/slices/sort_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/slices/sort_test.go new file mode 100644 index 0000000..9a52992 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/slices/sort_test.go @@ -0,0 +1,285 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package slices + +import ( + "math" + "math/rand" + "sort" + "strconv" + "strings" + "testing" +) + +var ints = [...]int{74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586} +var float64s = [...]float64{74.3, 59.0, math.Inf(1), 238.2, -784.0, 2.3, math.Inf(-1), 9845.768, -959.7485, 905, 7.8, 7.8, 74.3, 59.0, math.Inf(1), 238.2, -784.0, 2.3} +var float64sWithNaNs = [...]float64{74.3, 59.0, math.Inf(1), 238.2, -784.0, 2.3, math.NaN(), math.NaN(), math.Inf(-1), 9845.768, -959.7485, 905, 7.8, 7.8} +var strs = [...]string{"", "Hello", "foo", "bar", "foo", "f00", "%*&^*&^&", "***"} + +func TestSortIntSlice(t *testing.T) { + data := ints[:] + Sort(data) + if !IsSorted(data) { + t.Errorf("sorted %v", ints) + t.Errorf(" got %v", data) + } +} + +func TestSortFuncIntSlice(t *testing.T) { + data := ints[:] + SortFunc(data, func(a, b int) bool { return a < b }) + if !IsSorted(data) { + t.Errorf("sorted %v", ints) + t.Errorf(" got %v", data) + } +} + +func TestSortFloat64Slice(t *testing.T) { + data := float64s[:] + Sort(data) + if !IsSorted(data) { + t.Errorf("sorted %v", float64s) + t.Errorf(" got %v", data) + } +} + +func TestSortFloat64SliceWithNaNs(t *testing.T) { + data := float64sWithNaNs[:] + input := make([]float64, len(float64sWithNaNs)) + for i := range input { + input[i] = float64sWithNaNs[i] + } + // Make sure Sort doesn't panic when the slice contains NaNs. + Sort(data) + // Check whether the result is a permutation of the input. + sort.Float64s(data) + sort.Float64s(input) + for i, v := range input { + if data[i] != v && !(math.IsNaN(data[i]) && math.IsNaN(v)) { + t.Fatalf("the result is not a permutation of the input\ngot %v\nwant %v", data, input) + } + } +} + +func TestSortStringSlice(t *testing.T) { + data := strs[:] + Sort(data) + if !IsSorted(data) { + t.Errorf("sorted %v", strs) + t.Errorf(" got %v", data) + } +} + +func TestSortLarge_Random(t *testing.T) { + n := 1000000 + if testing.Short() { + n /= 100 + } + data := make([]int, n) + for i := 0; i < len(data); i++ { + data[i] = rand.Intn(100) + } + if IsSorted(data) { + t.Fatalf("terrible rand.rand") + } + Sort(data) + if !IsSorted(data) { + t.Errorf("sort didn't sort - 1M ints") + } +} + +type intPair struct { + a, b int +} + +type intPairs []intPair + +// Pairs compare on a only. +func intPairLess(x, y intPair) bool { + return x.a < y.a +} + +// Record initial order in B. +func (d intPairs) initB() { + for i := range d { + d[i].b = i + } +} + +// InOrder checks if a-equal elements were not reordered. +func (d intPairs) inOrder() bool { + lastA, lastB := -1, 0 + for i := 0; i < len(d); i++ { + if lastA != d[i].a { + lastA = d[i].a + lastB = d[i].b + continue + } + if d[i].b <= lastB { + return false + } + lastB = d[i].b + } + return true +} + +func TestStability(t *testing.T) { + n, m := 100000, 1000 + if testing.Short() { + n, m = 1000, 100 + } + data := make(intPairs, n) + + // random distribution + for i := 0; i < len(data); i++ { + data[i].a = rand.Intn(m) + } + if IsSortedFunc(data, intPairLess) { + t.Fatalf("terrible rand.rand") + } + data.initB() + SortStableFunc(data, intPairLess) + if !IsSortedFunc(data, intPairLess) { + t.Errorf("Stable didn't sort %d ints", n) + } + if !data.inOrder() { + t.Errorf("Stable wasn't stable on %d ints", n) + } + + // already sorted + data.initB() + SortStableFunc(data, intPairLess) + if !IsSortedFunc(data, intPairLess) { + t.Errorf("Stable shuffled sorted %d ints (order)", n) + } + if !data.inOrder() { + t.Errorf("Stable shuffled sorted %d ints (stability)", n) + } + + // sorted reversed + for i := 0; i < len(data); i++ { + data[i].a = len(data) - i + } + data.initB() + SortStableFunc(data, intPairLess) + if !IsSortedFunc(data, intPairLess) { + t.Errorf("Stable didn't sort %d ints", n) + } + if !data.inOrder() { + t.Errorf("Stable wasn't stable on %d ints", n) + } +} + +func TestBinarySearch(t *testing.T) { + str1 := []string{"foo"} + str2 := []string{"ab", "ca"} + str3 := []string{"mo", "qo", "vo"} + str4 := []string{"ab", "ad", "ca", "xy"} + + // slice with repeating elements + strRepeats := []string{"ba", "ca", "da", "da", "da", "ka", "ma", "ma", "ta"} + + // slice with all element equal + strSame := []string{"xx", "xx", "xx"} + + tests := []struct { + data []string + target string + wantPos int + wantFound bool + }{ + {[]string{}, "foo", 0, false}, + {[]string{}, "", 0, false}, + + {str1, "foo", 0, true}, + {str1, "bar", 0, false}, + {str1, "zx", 1, false}, + + {str2, "aa", 0, false}, + {str2, "ab", 0, true}, + {str2, "ad", 1, false}, + {str2, "ca", 1, true}, + {str2, "ra", 2, false}, + + {str3, "bb", 0, false}, + {str3, "mo", 0, true}, + {str3, "nb", 1, false}, + {str3, "qo", 1, true}, + {str3, "tr", 2, false}, + {str3, "vo", 2, true}, + {str3, "xr", 3, false}, + + {str4, "aa", 0, false}, + {str4, "ab", 0, true}, + {str4, "ac", 1, false}, + {str4, "ad", 1, true}, + {str4, "ax", 2, false}, + {str4, "ca", 2, true}, + {str4, "cc", 3, false}, + {str4, "dd", 3, false}, + {str4, "xy", 3, true}, + {str4, "zz", 4, false}, + + {strRepeats, "da", 2, true}, + {strRepeats, "db", 5, false}, + {strRepeats, "ma", 6, true}, + {strRepeats, "mb", 8, false}, + + {strSame, "xx", 0, true}, + {strSame, "ab", 0, false}, + {strSame, "zz", 3, false}, + } + for _, tt := range tests { + t.Run(tt.target, func(t *testing.T) { + { + pos, found := BinarySearch(tt.data, tt.target) + if pos != tt.wantPos || found != tt.wantFound { + t.Errorf("BinarySearch got (%v, %v), want (%v, %v)", pos, found, tt.wantPos, tt.wantFound) + } + } + + { + pos, found := BinarySearchFunc(tt.data, tt.target, strings.Compare) + if pos != tt.wantPos || found != tt.wantFound { + t.Errorf("BinarySearchFunc got (%v, %v), want (%v, %v)", pos, found, tt.wantPos, tt.wantFound) + } + } + }) + } +} + +func TestBinarySearchInts(t *testing.T) { + data := []int{20, 30, 40, 50, 60, 70, 80, 90} + tests := []struct { + target int + wantPos int + wantFound bool + }{ + {20, 0, true}, + {23, 1, false}, + {43, 3, false}, + {80, 6, true}, + } + for _, tt := range tests { + t.Run(strconv.Itoa(tt.target), func(t *testing.T) { + { + pos, found := BinarySearch(data, tt.target) + if pos != tt.wantPos || found != tt.wantFound { + t.Errorf("BinarySearch got (%v, %v), want (%v, %v)", pos, found, tt.wantPos, tt.wantFound) + } + } + + { + cmp := func(a, b int) int { + return a - b + } + pos, found := BinarySearchFunc(data, tt.target, cmp) + if pos != tt.wantPos || found != tt.wantFound { + t.Errorf("BinarySearchFunc got (%v, %v), want (%v, %v)", pos, found, tt.wantPos, tt.wantFound) + } + } + }) + } +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/slices/zsortfunc.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/slices/zsortfunc.go new file mode 100644 index 0000000..2a63247 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/slices/zsortfunc.go @@ -0,0 +1,479 @@ +// Code generated by gen_sort_variants.go; DO NOT EDIT. + +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package slices + +// insertionSortLessFunc sorts data[a:b] using insertion sort. +func insertionSortLessFunc[E any](data []E, a, b int, less func(a, b E) bool) { + for i := a + 1; i < b; i++ { + for j := i; j > a && less(data[j], data[j-1]); j-- { + data[j], data[j-1] = data[j-1], data[j] + } + } +} + +// siftDownLessFunc implements the heap property on data[lo:hi]. +// first is an offset into the array where the root of the heap lies. +func siftDownLessFunc[E any](data []E, lo, hi, first int, less func(a, b E) bool) { + root := lo + for { + child := 2*root + 1 + if child >= hi { + break + } + if child+1 < hi && less(data[first+child], data[first+child+1]) { + child++ + } + if !less(data[first+root], data[first+child]) { + return + } + data[first+root], data[first+child] = data[first+child], data[first+root] + root = child + } +} + +func heapSortLessFunc[E any](data []E, a, b int, less func(a, b E) bool) { + first := a + lo := 0 + hi := b - a + + // Build heap with greatest element at top. + for i := (hi - 1) / 2; i >= 0; i-- { + siftDownLessFunc(data, i, hi, first, less) + } + + // Pop elements, largest first, into end of data. + for i := hi - 1; i >= 0; i-- { + data[first], data[first+i] = data[first+i], data[first] + siftDownLessFunc(data, lo, i, first, less) + } +} + +// pdqsortLessFunc sorts data[a:b]. +// The algorithm based on pattern-defeating quicksort(pdqsort), but without the optimizations from BlockQuicksort. +// pdqsort paper: https://arxiv.org/pdf/2106.05123.pdf +// C++ implementation: https://github.com/orlp/pdqsort +// Rust implementation: https://docs.rs/pdqsort/latest/pdqsort/ +// limit is the number of allowed bad (very unbalanced) pivots before falling back to heapsort. +func pdqsortLessFunc[E any](data []E, a, b, limit int, less func(a, b E) bool) { + const maxInsertion = 12 + + var ( + wasBalanced = true // whether the last partitioning was reasonably balanced + wasPartitioned = true // whether the slice was already partitioned + ) + + for { + length := b - a + + if length <= maxInsertion { + insertionSortLessFunc(data, a, b, less) + return + } + + // Fall back to heapsort if too many bad choices were made. + if limit == 0 { + heapSortLessFunc(data, a, b, less) + return + } + + // If the last partitioning was imbalanced, we need to breaking patterns. + if !wasBalanced { + breakPatternsLessFunc(data, a, b, less) + limit-- + } + + pivot, hint := choosePivotLessFunc(data, a, b, less) + if hint == decreasingHint { + reverseRangeLessFunc(data, a, b, less) + // The chosen pivot was pivot-a elements after the start of the array. + // After reversing it is pivot-a elements before the end of the array. + // The idea came from Rust's implementation. + pivot = (b - 1) - (pivot - a) + hint = increasingHint + } + + // The slice is likely already sorted. + if wasBalanced && wasPartitioned && hint == increasingHint { + if partialInsertionSortLessFunc(data, a, b, less) { + return + } + } + + // Probably the slice contains many duplicate elements, partition the slice into + // elements equal to and elements greater than the pivot. + if a > 0 && !less(data[a-1], data[pivot]) { + mid := partitionEqualLessFunc(data, a, b, pivot, less) + a = mid + continue + } + + mid, alreadyPartitioned := partitionLessFunc(data, a, b, pivot, less) + wasPartitioned = alreadyPartitioned + + leftLen, rightLen := mid-a, b-mid + balanceThreshold := length / 8 + if leftLen < rightLen { + wasBalanced = leftLen >= balanceThreshold + pdqsortLessFunc(data, a, mid, limit, less) + a = mid + 1 + } else { + wasBalanced = rightLen >= balanceThreshold + pdqsortLessFunc(data, mid+1, b, limit, less) + b = mid + } + } +} + +// partitionLessFunc does one quicksort partition. +// Let p = data[pivot] +// Moves elements in data[a:b] around, so that data[i]<p and data[j]>=p for i<newpivot and j>newpivot. +// On return, data[newpivot] = p +func partitionLessFunc[E any](data []E, a, b, pivot int, less func(a, b E) bool) (newpivot int, alreadyPartitioned bool) { + data[a], data[pivot] = data[pivot], data[a] + i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned + + for i <= j && less(data[i], data[a]) { + i++ + } + for i <= j && !less(data[j], data[a]) { + j-- + } + if i > j { + data[j], data[a] = data[a], data[j] + return j, true + } + data[i], data[j] = data[j], data[i] + i++ + j-- + + for { + for i <= j && less(data[i], data[a]) { + i++ + } + for i <= j && !less(data[j], data[a]) { + j-- + } + if i > j { + break + } + data[i], data[j] = data[j], data[i] + i++ + j-- + } + data[j], data[a] = data[a], data[j] + return j, false +} + +// partitionEqualLessFunc partitions data[a:b] into elements equal to data[pivot] followed by elements greater than data[pivot]. +// It assumed that data[a:b] does not contain elements smaller than the data[pivot]. +func partitionEqualLessFunc[E any](data []E, a, b, pivot int, less func(a, b E) bool) (newpivot int) { + data[a], data[pivot] = data[pivot], data[a] + i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned + + for { + for i <= j && !less(data[a], data[i]) { + i++ + } + for i <= j && less(data[a], data[j]) { + j-- + } + if i > j { + break + } + data[i], data[j] = data[j], data[i] + i++ + j-- + } + return i +} + +// partialInsertionSortLessFunc partially sorts a slice, returns true if the slice is sorted at the end. +func partialInsertionSortLessFunc[E any](data []E, a, b int, less func(a, b E) bool) bool { + const ( + maxSteps = 5 // maximum number of adjacent out-of-order pairs that will get shifted + shortestShifting = 50 // don't shift any elements on short arrays + ) + i := a + 1 + for j := 0; j < maxSteps; j++ { + for i < b && !less(data[i], data[i-1]) { + i++ + } + + if i == b { + return true + } + + if b-a < shortestShifting { + return false + } + + data[i], data[i-1] = data[i-1], data[i] + + // Shift the smaller one to the left. + if i-a >= 2 { + for j := i - 1; j >= 1; j-- { + if !less(data[j], data[j-1]) { + break + } + data[j], data[j-1] = data[j-1], data[j] + } + } + // Shift the greater one to the right. + if b-i >= 2 { + for j := i + 1; j < b; j++ { + if !less(data[j], data[j-1]) { + break + } + data[j], data[j-1] = data[j-1], data[j] + } + } + } + return false +} + +// breakPatternsLessFunc scatters some elements around in an attempt to break some patterns +// that might cause imbalanced partitions in quicksort. +func breakPatternsLessFunc[E any](data []E, a, b int, less func(a, b E) bool) { + length := b - a + if length >= 8 { + random := xorshift(length) + modulus := nextPowerOfTwo(length) + + for idx := a + (length/4)*2 - 1; idx <= a+(length/4)*2+1; idx++ { + other := int(uint(random.Next()) & (modulus - 1)) + if other >= length { + other -= length + } + data[idx], data[a+other] = data[a+other], data[idx] + } + } +} + +// choosePivotLessFunc chooses a pivot in data[a:b]. +// +// [0,8): chooses a static pivot. +// [8,shortestNinther): uses the simple median-of-three method. +// [shortestNinther,∞): uses the Tukey ninther method. +func choosePivotLessFunc[E any](data []E, a, b int, less func(a, b E) bool) (pivot int, hint sortedHint) { + const ( + shortestNinther = 50 + maxSwaps = 4 * 3 + ) + + l := b - a + + var ( + swaps int + i = a + l/4*1 + j = a + l/4*2 + k = a + l/4*3 + ) + + if l >= 8 { + if l >= shortestNinther { + // Tukey ninther method, the idea came from Rust's implementation. + i = medianAdjacentLessFunc(data, i, &swaps, less) + j = medianAdjacentLessFunc(data, j, &swaps, less) + k = medianAdjacentLessFunc(data, k, &swaps, less) + } + // Find the median among i, j, k and stores it into j. + j = medianLessFunc(data, i, j, k, &swaps, less) + } + + switch swaps { + case 0: + return j, increasingHint + case maxSwaps: + return j, decreasingHint + default: + return j, unknownHint + } +} + +// order2LessFunc returns x,y where data[x] <= data[y], where x,y=a,b or x,y=b,a. +func order2LessFunc[E any](data []E, a, b int, swaps *int, less func(a, b E) bool) (int, int) { + if less(data[b], data[a]) { + *swaps++ + return b, a + } + return a, b +} + +// medianLessFunc returns x where data[x] is the median of data[a],data[b],data[c], where x is a, b, or c. +func medianLessFunc[E any](data []E, a, b, c int, swaps *int, less func(a, b E) bool) int { + a, b = order2LessFunc(data, a, b, swaps, less) + b, c = order2LessFunc(data, b, c, swaps, less) + a, b = order2LessFunc(data, a, b, swaps, less) + return b +} + +// medianAdjacentLessFunc finds the median of data[a - 1], data[a], data[a + 1] and stores the index into a. +func medianAdjacentLessFunc[E any](data []E, a int, swaps *int, less func(a, b E) bool) int { + return medianLessFunc(data, a-1, a, a+1, swaps, less) +} + +func reverseRangeLessFunc[E any](data []E, a, b int, less func(a, b E) bool) { + i := a + j := b - 1 + for i < j { + data[i], data[j] = data[j], data[i] + i++ + j-- + } +} + +func swapRangeLessFunc[E any](data []E, a, b, n int, less func(a, b E) bool) { + for i := 0; i < n; i++ { + data[a+i], data[b+i] = data[b+i], data[a+i] + } +} + +func stableLessFunc[E any](data []E, n int, less func(a, b E) bool) { + blockSize := 20 // must be > 0 + a, b := 0, blockSize + for b <= n { + insertionSortLessFunc(data, a, b, less) + a = b + b += blockSize + } + insertionSortLessFunc(data, a, n, less) + + for blockSize < n { + a, b = 0, 2*blockSize + for b <= n { + symMergeLessFunc(data, a, a+blockSize, b, less) + a = b + b += 2 * blockSize + } + if m := a + blockSize; m < n { + symMergeLessFunc(data, a, m, n, less) + } + blockSize *= 2 + } +} + +// symMergeLessFunc merges the two sorted subsequences data[a:m] and data[m:b] using +// the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum +// Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz +// Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in +// Computer Science, pages 714-723. Springer, 2004. +// +// Let M = m-a and N = b-n. Wolog M < N. +// The recursion depth is bound by ceil(log(N+M)). +// The algorithm needs O(M*log(N/M + 1)) calls to data.Less. +// The algorithm needs O((M+N)*log(M)) calls to data.Swap. +// +// The paper gives O((M+N)*log(M)) as the number of assignments assuming a +// rotation algorithm which uses O(M+N+gcd(M+N)) assignments. The argumentation +// in the paper carries through for Swap operations, especially as the block +// swapping rotate uses only O(M+N) Swaps. +// +// symMerge assumes non-degenerate arguments: a < m && m < b. +// Having the caller check this condition eliminates many leaf recursion calls, +// which improves performance. +func symMergeLessFunc[E any](data []E, a, m, b int, less func(a, b E) bool) { + // Avoid unnecessary recursions of symMerge + // by direct insertion of data[a] into data[m:b] + // if data[a:m] only contains one element. + if m-a == 1 { + // Use binary search to find the lowest index i + // such that data[i] >= data[a] for m <= i < b. + // Exit the search loop with i == b in case no such index exists. + i := m + j := b + for i < j { + h := int(uint(i+j) >> 1) + if less(data[h], data[a]) { + i = h + 1 + } else { + j = h + } + } + // Swap values until data[a] reaches the position before i. + for k := a; k < i-1; k++ { + data[k], data[k+1] = data[k+1], data[k] + } + return + } + + // Avoid unnecessary recursions of symMerge + // by direct insertion of data[m] into data[a:m] + // if data[m:b] only contains one element. + if b-m == 1 { + // Use binary search to find the lowest index i + // such that data[i] > data[m] for a <= i < m. + // Exit the search loop with i == m in case no such index exists. + i := a + j := m + for i < j { + h := int(uint(i+j) >> 1) + if !less(data[m], data[h]) { + i = h + 1 + } else { + j = h + } + } + // Swap values until data[m] reaches the position i. + for k := m; k > i; k-- { + data[k], data[k-1] = data[k-1], data[k] + } + return + } + + mid := int(uint(a+b) >> 1) + n := mid + m + var start, r int + if m > mid { + start = n - b + r = mid + } else { + start = a + r = m + } + p := n - 1 + + for start < r { + c := int(uint(start+r) >> 1) + if !less(data[p-c], data[c]) { + start = c + 1 + } else { + r = c + } + } + + end := n - start + if start < m && m < end { + rotateLessFunc(data, start, m, end, less) + } + if a < start && start < mid { + symMergeLessFunc(data, a, start, mid, less) + } + if mid < end && end < b { + symMergeLessFunc(data, mid, end, b, less) + } +} + +// rotateLessFunc rotates two consecutive blocks u = data[a:m] and v = data[m:b] in data: +// Data of the form 'x u v y' is changed to 'x v u y'. +// rotate performs at most b-a many calls to data.Swap, +// and it assumes non-degenerate arguments: a < m && m < b. +func rotateLessFunc[E any](data []E, a, m, b int, less func(a, b E) bool) { + i := m - a + j := b - m + + for i != j { + if i > j { + swapRangeLessFunc(data, m-i, m, j, less) + i -= j + } else { + swapRangeLessFunc(data, m-i, m+j-i, i, less) + j -= i + } + } + // i == j + swapRangeLessFunc(data, m-i, m, i, less) +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/slices/zsortordered.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/slices/zsortordered.go new file mode 100644 index 0000000..efaa1c8 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/slices/zsortordered.go @@ -0,0 +1,481 @@ +// Code generated by gen_sort_variants.go; DO NOT EDIT. + +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package slices + +import "golang.org/x/exp/constraints" + +// insertionSortOrdered sorts data[a:b] using insertion sort. +func insertionSortOrdered[E constraints.Ordered](data []E, a, b int) { + for i := a + 1; i < b; i++ { + for j := i; j > a && (data[j] < data[j-1]); j-- { + data[j], data[j-1] = data[j-1], data[j] + } + } +} + +// siftDownOrdered implements the heap property on data[lo:hi]. +// first is an offset into the array where the root of the heap lies. +func siftDownOrdered[E constraints.Ordered](data []E, lo, hi, first int) { + root := lo + for { + child := 2*root + 1 + if child >= hi { + break + } + if child+1 < hi && (data[first+child] < data[first+child+1]) { + child++ + } + if !(data[first+root] < data[first+child]) { + return + } + data[first+root], data[first+child] = data[first+child], data[first+root] + root = child + } +} + +func heapSortOrdered[E constraints.Ordered](data []E, a, b int) { + first := a + lo := 0 + hi := b - a + + // Build heap with greatest element at top. + for i := (hi - 1) / 2; i >= 0; i-- { + siftDownOrdered(data, i, hi, first) + } + + // Pop elements, largest first, into end of data. + for i := hi - 1; i >= 0; i-- { + data[first], data[first+i] = data[first+i], data[first] + siftDownOrdered(data, lo, i, first) + } +} + +// pdqsortOrdered sorts data[a:b]. +// The algorithm based on pattern-defeating quicksort(pdqsort), but without the optimizations from BlockQuicksort. +// pdqsort paper: https://arxiv.org/pdf/2106.05123.pdf +// C++ implementation: https://github.com/orlp/pdqsort +// Rust implementation: https://docs.rs/pdqsort/latest/pdqsort/ +// limit is the number of allowed bad (very unbalanced) pivots before falling back to heapsort. +func pdqsortOrdered[E constraints.Ordered](data []E, a, b, limit int) { + const maxInsertion = 12 + + var ( + wasBalanced = true // whether the last partitioning was reasonably balanced + wasPartitioned = true // whether the slice was already partitioned + ) + + for { + length := b - a + + if length <= maxInsertion { + insertionSortOrdered(data, a, b) + return + } + + // Fall back to heapsort if too many bad choices were made. + if limit == 0 { + heapSortOrdered(data, a, b) + return + } + + // If the last partitioning was imbalanced, we need to breaking patterns. + if !wasBalanced { + breakPatternsOrdered(data, a, b) + limit-- + } + + pivot, hint := choosePivotOrdered(data, a, b) + if hint == decreasingHint { + reverseRangeOrdered(data, a, b) + // The chosen pivot was pivot-a elements after the start of the array. + // After reversing it is pivot-a elements before the end of the array. + // The idea came from Rust's implementation. + pivot = (b - 1) - (pivot - a) + hint = increasingHint + } + + // The slice is likely already sorted. + if wasBalanced && wasPartitioned && hint == increasingHint { + if partialInsertionSortOrdered(data, a, b) { + return + } + } + + // Probably the slice contains many duplicate elements, partition the slice into + // elements equal to and elements greater than the pivot. + if a > 0 && !(data[a-1] < data[pivot]) { + mid := partitionEqualOrdered(data, a, b, pivot) + a = mid + continue + } + + mid, alreadyPartitioned := partitionOrdered(data, a, b, pivot) + wasPartitioned = alreadyPartitioned + + leftLen, rightLen := mid-a, b-mid + balanceThreshold := length / 8 + if leftLen < rightLen { + wasBalanced = leftLen >= balanceThreshold + pdqsortOrdered(data, a, mid, limit) + a = mid + 1 + } else { + wasBalanced = rightLen >= balanceThreshold + pdqsortOrdered(data, mid+1, b, limit) + b = mid + } + } +} + +// partitionOrdered does one quicksort partition. +// Let p = data[pivot] +// Moves elements in data[a:b] around, so that data[i]<p and data[j]>=p for i<newpivot and j>newpivot. +// On return, data[newpivot] = p +func partitionOrdered[E constraints.Ordered](data []E, a, b, pivot int) (newpivot int, alreadyPartitioned bool) { + data[a], data[pivot] = data[pivot], data[a] + i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned + + for i <= j && (data[i] < data[a]) { + i++ + } + for i <= j && !(data[j] < data[a]) { + j-- + } + if i > j { + data[j], data[a] = data[a], data[j] + return j, true + } + data[i], data[j] = data[j], data[i] + i++ + j-- + + for { + for i <= j && (data[i] < data[a]) { + i++ + } + for i <= j && !(data[j] < data[a]) { + j-- + } + if i > j { + break + } + data[i], data[j] = data[j], data[i] + i++ + j-- + } + data[j], data[a] = data[a], data[j] + return j, false +} + +// partitionEqualOrdered partitions data[a:b] into elements equal to data[pivot] followed by elements greater than data[pivot]. +// It assumed that data[a:b] does not contain elements smaller than the data[pivot]. +func partitionEqualOrdered[E constraints.Ordered](data []E, a, b, pivot int) (newpivot int) { + data[a], data[pivot] = data[pivot], data[a] + i, j := a+1, b-1 // i and j are inclusive of the elements remaining to be partitioned + + for { + for i <= j && !(data[a] < data[i]) { + i++ + } + for i <= j && (data[a] < data[j]) { + j-- + } + if i > j { + break + } + data[i], data[j] = data[j], data[i] + i++ + j-- + } + return i +} + +// partialInsertionSortOrdered partially sorts a slice, returns true if the slice is sorted at the end. +func partialInsertionSortOrdered[E constraints.Ordered](data []E, a, b int) bool { + const ( + maxSteps = 5 // maximum number of adjacent out-of-order pairs that will get shifted + shortestShifting = 50 // don't shift any elements on short arrays + ) + i := a + 1 + for j := 0; j < maxSteps; j++ { + for i < b && !(data[i] < data[i-1]) { + i++ + } + + if i == b { + return true + } + + if b-a < shortestShifting { + return false + } + + data[i], data[i-1] = data[i-1], data[i] + + // Shift the smaller one to the left. + if i-a >= 2 { + for j := i - 1; j >= 1; j-- { + if !(data[j] < data[j-1]) { + break + } + data[j], data[j-1] = data[j-1], data[j] + } + } + // Shift the greater one to the right. + if b-i >= 2 { + for j := i + 1; j < b; j++ { + if !(data[j] < data[j-1]) { + break + } + data[j], data[j-1] = data[j-1], data[j] + } + } + } + return false +} + +// breakPatternsOrdered scatters some elements around in an attempt to break some patterns +// that might cause imbalanced partitions in quicksort. +func breakPatternsOrdered[E constraints.Ordered](data []E, a, b int) { + length := b - a + if length >= 8 { + random := xorshift(length) + modulus := nextPowerOfTwo(length) + + for idx := a + (length/4)*2 - 1; idx <= a+(length/4)*2+1; idx++ { + other := int(uint(random.Next()) & (modulus - 1)) + if other >= length { + other -= length + } + data[idx], data[a+other] = data[a+other], data[idx] + } + } +} + +// choosePivotOrdered chooses a pivot in data[a:b]. +// +// [0,8): chooses a static pivot. +// [8,shortestNinther): uses the simple median-of-three method. +// [shortestNinther,∞): uses the Tukey ninther method. +func choosePivotOrdered[E constraints.Ordered](data []E, a, b int) (pivot int, hint sortedHint) { + const ( + shortestNinther = 50 + maxSwaps = 4 * 3 + ) + + l := b - a + + var ( + swaps int + i = a + l/4*1 + j = a + l/4*2 + k = a + l/4*3 + ) + + if l >= 8 { + if l >= shortestNinther { + // Tukey ninther method, the idea came from Rust's implementation. + i = medianAdjacentOrdered(data, i, &swaps) + j = medianAdjacentOrdered(data, j, &swaps) + k = medianAdjacentOrdered(data, k, &swaps) + } + // Find the median among i, j, k and stores it into j. + j = medianOrdered(data, i, j, k, &swaps) + } + + switch swaps { + case 0: + return j, increasingHint + case maxSwaps: + return j, decreasingHint + default: + return j, unknownHint + } +} + +// order2Ordered returns x,y where data[x] <= data[y], where x,y=a,b or x,y=b,a. +func order2Ordered[E constraints.Ordered](data []E, a, b int, swaps *int) (int, int) { + if data[b] < data[a] { + *swaps++ + return b, a + } + return a, b +} + +// medianOrdered returns x where data[x] is the median of data[a],data[b],data[c], where x is a, b, or c. +func medianOrdered[E constraints.Ordered](data []E, a, b, c int, swaps *int) int { + a, b = order2Ordered(data, a, b, swaps) + b, c = order2Ordered(data, b, c, swaps) + a, b = order2Ordered(data, a, b, swaps) + return b +} + +// medianAdjacentOrdered finds the median of data[a - 1], data[a], data[a + 1] and stores the index into a. +func medianAdjacentOrdered[E constraints.Ordered](data []E, a int, swaps *int) int { + return medianOrdered(data, a-1, a, a+1, swaps) +} + +func reverseRangeOrdered[E constraints.Ordered](data []E, a, b int) { + i := a + j := b - 1 + for i < j { + data[i], data[j] = data[j], data[i] + i++ + j-- + } +} + +func swapRangeOrdered[E constraints.Ordered](data []E, a, b, n int) { + for i := 0; i < n; i++ { + data[a+i], data[b+i] = data[b+i], data[a+i] + } +} + +func stableOrdered[E constraints.Ordered](data []E, n int) { + blockSize := 20 // must be > 0 + a, b := 0, blockSize + for b <= n { + insertionSortOrdered(data, a, b) + a = b + b += blockSize + } + insertionSortOrdered(data, a, n) + + for blockSize < n { + a, b = 0, 2*blockSize + for b <= n { + symMergeOrdered(data, a, a+blockSize, b) + a = b + b += 2 * blockSize + } + if m := a + blockSize; m < n { + symMergeOrdered(data, a, m, n) + } + blockSize *= 2 + } +} + +// symMergeOrdered merges the two sorted subsequences data[a:m] and data[m:b] using +// the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum +// Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz +// Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in +// Computer Science, pages 714-723. Springer, 2004. +// +// Let M = m-a and N = b-n. Wolog M < N. +// The recursion depth is bound by ceil(log(N+M)). +// The algorithm needs O(M*log(N/M + 1)) calls to data.Less. +// The algorithm needs O((M+N)*log(M)) calls to data.Swap. +// +// The paper gives O((M+N)*log(M)) as the number of assignments assuming a +// rotation algorithm which uses O(M+N+gcd(M+N)) assignments. The argumentation +// in the paper carries through for Swap operations, especially as the block +// swapping rotate uses only O(M+N) Swaps. +// +// symMerge assumes non-degenerate arguments: a < m && m < b. +// Having the caller check this condition eliminates many leaf recursion calls, +// which improves performance. +func symMergeOrdered[E constraints.Ordered](data []E, a, m, b int) { + // Avoid unnecessary recursions of symMerge + // by direct insertion of data[a] into data[m:b] + // if data[a:m] only contains one element. + if m-a == 1 { + // Use binary search to find the lowest index i + // such that data[i] >= data[a] for m <= i < b. + // Exit the search loop with i == b in case no such index exists. + i := m + j := b + for i < j { + h := int(uint(i+j) >> 1) + if data[h] < data[a] { + i = h + 1 + } else { + j = h + } + } + // Swap values until data[a] reaches the position before i. + for k := a; k < i-1; k++ { + data[k], data[k+1] = data[k+1], data[k] + } + return + } + + // Avoid unnecessary recursions of symMerge + // by direct insertion of data[m] into data[a:m] + // if data[m:b] only contains one element. + if b-m == 1 { + // Use binary search to find the lowest index i + // such that data[i] > data[m] for a <= i < m. + // Exit the search loop with i == m in case no such index exists. + i := a + j := m + for i < j { + h := int(uint(i+j) >> 1) + if !(data[m] < data[h]) { + i = h + 1 + } else { + j = h + } + } + // Swap values until data[m] reaches the position i. + for k := m; k > i; k-- { + data[k], data[k-1] = data[k-1], data[k] + } + return + } + + mid := int(uint(a+b) >> 1) + n := mid + m + var start, r int + if m > mid { + start = n - b + r = mid + } else { + start = a + r = m + } + p := n - 1 + + for start < r { + c := int(uint(start+r) >> 1) + if !(data[p-c] < data[c]) { + start = c + 1 + } else { + r = c + } + } + + end := n - start + if start < m && m < end { + rotateOrdered(data, start, m, end) + } + if a < start && start < mid { + symMergeOrdered(data, a, start, mid) + } + if mid < end && end < b { + symMergeOrdered(data, mid, end, b) + } +} + +// rotateOrdered rotates two consecutive blocks u = data[a:m] and v = data[m:b] in data: +// Data of the form 'x u v y' is changed to 'x v u y'. +// rotate performs at most b-a many calls to data.Swap, +// and it assumes non-degenerate arguments: a < m && m < b. +func rotateOrdered[E constraints.Ordered](data []E, a, m, b int) { + i := m - a + j := b - m + + for i != j { + if i > j { + swapRangeOrdered(data, m-i, m, j) + i -= j + } else { + swapRangeOrdered(data, m-i, m+j-i, i) + j -= i + } + } + // i == j + swapRangeOrdered(data, m-i, m, i) +} diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/utf8string/string.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/utf8string/string.go new file mode 100644 index 0000000..281d5ac --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/utf8string/string.go @@ -0,0 +1,203 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package utf8string provides an efficient way to index strings by rune rather than by byte. +package utf8string // import "golang.org/x/exp/utf8string" + +import ( + "errors" + "unicode/utf8" +) + +// String wraps a regular string with a small structure that provides more +// efficient indexing by code point index, as opposed to byte index. +// Scanning incrementally forwards or backwards is O(1) per index operation +// (although not as fast a range clause going forwards). Random access is +// O(N) in the length of the string, but the overhead is less than always +// scanning from the beginning. +// If the string is ASCII, random access is O(1). +// Unlike the built-in string type, String has internal mutable state and +// is not thread-safe. +type String struct { + str string + numRunes int + // If width > 0, the rune at runePos starts at bytePos and has the specified width. + width int + bytePos int + runePos int + nonASCII int // byte index of the first non-ASCII rune. +} + +// NewString returns a new UTF-8 string with the provided contents. +func NewString(contents string) *String { + return new(String).Init(contents) +} + +// Init initializes an existing String to hold the provided contents. +// It returns a pointer to the initialized String. +func (s *String) Init(contents string) *String { + s.str = contents + s.bytePos = 0 + s.runePos = 0 + for i := 0; i < len(contents); i++ { + if contents[i] >= utf8.RuneSelf { + // Not ASCII. + s.numRunes = utf8.RuneCountInString(contents) + _, s.width = utf8.DecodeRuneInString(contents) + s.nonASCII = i + return s + } + } + // ASCII is simple. Also, the empty string is ASCII. + s.numRunes = len(contents) + s.width = 0 + s.nonASCII = len(contents) + return s +} + +// String returns the contents of the String. This method also means the +// String is directly printable by fmt.Print. +func (s *String) String() string { + return s.str +} + +// RuneCount returns the number of runes (Unicode code points) in the String. +func (s *String) RuneCount() int { + return s.numRunes +} + +// IsASCII returns a boolean indicating whether the String contains only ASCII bytes. +func (s *String) IsASCII() bool { + return s.width == 0 +} + +// Slice returns the string sliced at rune positions [i:j]. +func (s *String) Slice(i, j int) string { + // ASCII is easy. Let the compiler catch the indexing error if there is one. + if j < s.nonASCII { + return s.str[i:j] + } + if i < 0 || j > s.numRunes || i > j { + panic(sliceOutOfRange) + } + if i == j { + return "" + } + // For non-ASCII, after At(i), bytePos is always the position of the indexed character. + var low, high int + switch { + case i < s.nonASCII: + low = i + case i == s.numRunes: + low = len(s.str) + default: + s.At(i) + low = s.bytePos + } + switch { + case j == s.numRunes: + high = len(s.str) + default: + s.At(j) + high = s.bytePos + } + return s.str[low:high] +} + +// At returns the rune with index i in the String. The sequence of runes is the same +// as iterating over the contents with a "for range" clause. +func (s *String) At(i int) rune { + // ASCII is easy. Let the compiler catch the indexing error if there is one. + if i < s.nonASCII { + return rune(s.str[i]) + } + + // Now we do need to know the index is valid. + if i < 0 || i >= s.numRunes { + panic(outOfRange) + } + + var r rune + + // Five easy common cases: within 1 spot of bytePos/runePos, or the beginning, or the end. + // With these cases, all scans from beginning or end work in O(1) time per rune. + switch { + + case i == s.runePos-1: // backing up one rune + r, s.width = utf8.DecodeLastRuneInString(s.str[0:s.bytePos]) + s.runePos = i + s.bytePos -= s.width + return r + case i == s.runePos+1: // moving ahead one rune + s.runePos = i + s.bytePos += s.width + fallthrough + case i == s.runePos: + r, s.width = utf8.DecodeRuneInString(s.str[s.bytePos:]) + return r + case i == 0: // start of string + r, s.width = utf8.DecodeRuneInString(s.str) + s.runePos = 0 + s.bytePos = 0 + return r + + case i == s.numRunes-1: // last rune in string + r, s.width = utf8.DecodeLastRuneInString(s.str) + s.runePos = i + s.bytePos = len(s.str) - s.width + return r + } + + // We need to do a linear scan. There are three places to start from: + // 1) The beginning + // 2) bytePos/runePos. + // 3) The end + // Choose the closest in rune count, scanning backwards if necessary. + forward := true + if i < s.runePos { + // Between beginning and pos. Which is closer? + // Since both i and runePos are guaranteed >= nonASCII, that's the + // lowest location we need to start from. + if i < (s.runePos-s.nonASCII)/2 { + // Scan forward from beginning + s.bytePos, s.runePos = s.nonASCII, s.nonASCII + } else { + // Scan backwards from where we are + forward = false + } + } else { + // Between pos and end. Which is closer? + if i-s.runePos < (s.numRunes-s.runePos)/2 { + // Scan forward from pos + } else { + // Scan backwards from end + s.bytePos, s.runePos = len(s.str), s.numRunes + forward = false + } + } + if forward { + // TODO: Is it much faster to use a range loop for this scan? + for { + r, s.width = utf8.DecodeRuneInString(s.str[s.bytePos:]) + if s.runePos == i { + break + } + s.runePos++ + s.bytePos += s.width + } + } else { + for { + r, s.width = utf8.DecodeLastRuneInString(s.str[0:s.bytePos]) + s.runePos-- + s.bytePos -= s.width + if s.runePos == i { + break + } + } + } + return r +} + +var outOfRange = errors.New("utf8string: index out of range") +var sliceOutOfRange = errors.New("utf8string: slice index out of range") diff --git a/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/utf8string/string_test.go b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/utf8string/string_test.go new file mode 100644 index 0000000..28511b2 --- /dev/null +++ b/dependencies/pkg/mod/golang.org/x/exp@v0.0.0-20220613132600-b0d781184e0d/utf8string/string_test.go @@ -0,0 +1,123 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package utf8string + +import ( + "math/rand" + "testing" + "unicode/utf8" +) + +var testStrings = []string{ + "", + "abcd", + "☺☻☹", + "日a本b語ç日ð本Ê語þ日¥本¼語i日©", + "日a本b語ç日ð本Ê語þ日¥本¼語i日©日a本b語ç日ð本Ê語þ日¥本¼語i日©日a本b語ç日ð本Ê語þ日¥本¼語i日©", + "\x80\x80\x80\x80", +} + +func TestScanForwards(t *testing.T) { + for _, s := range testStrings { + runes := []rune(s) + str := NewString(s) + if str.RuneCount() != len(runes) { + t.Errorf("%s: expected %d runes; got %d", s, len(runes), str.RuneCount()) + break + } + for i, expect := range runes { + got := str.At(i) + if got != expect { + t.Errorf("%s[%d]: expected %c (%U); got %c (%U)", s, i, expect, expect, got, got) + } + } + } +} + +func TestScanBackwards(t *testing.T) { + for _, s := range testStrings { + runes := []rune(s) + str := NewString(s) + if str.RuneCount() != len(runes) { + t.Errorf("%s: expected %d runes; got %d", s, len(runes), str.RuneCount()) + break + } + for i := len(runes) - 1; i >= 0; i-- { + expect := runes[i] + got := str.At(i) + if got != expect { + t.Errorf("%s[%d]: expected %c (%U); got %c (%U)", s, i, expect, expect, got, got) + } + } + } +} + +func randCount() int { + if testing.Short() { + return 100 + } + return 100000 +} + +func TestRandomAccess(t *testing.T) { + for _, s := range testStrings { + if len(s) == 0 { + continue + } + runes := []rune(s) + str := NewString(s) + if str.RuneCount() != len(runes) { + t.Errorf("%s: expected %d runes; got %d", s, len(runes), str.RuneCount()) + break + } + for j := 0; j < randCount(); j++ { + i := rand.Intn(len(runes)) + expect := runes[i] + got := str.At(i) + if got != expect { + t.Errorf("%s[%d]: expected %c (%U); got %c (%U)", s, i, expect, expect, got, got) + } + } + } +} + +func TestRandomSliceAccess(t *testing.T) { + for _, s := range testStrings { + if len(s) == 0 || s[0] == '\x80' { // the bad-UTF-8 string fools this simple test + continue + } + runes := []rune(s) + str := NewString(s) + if str.RuneCount() != len(runes) { + t.Errorf("%s: expected %d runes; got %d", s, len(runes), str.RuneCount()) + break + } + for k := 0; k < randCount(); k++ { + i := rand.Intn(len(runes)) + j := rand.Intn(len(runes) + 1) + if i > j { // include empty strings + continue + } + expect := string(runes[i:j]) + got := str.Slice(i, j) + if got != expect { + t.Errorf("%s[%d:%d]: expected %q got %q", s, i, j, expect, got) + } + } + } +} + +func TestLimitSliceAccess(t *testing.T) { + for _, s := range testStrings { + str := NewString(s) + if str.Slice(0, 0) != "" { + t.Error("failure with empty slice at beginning") + } + nr := utf8.RuneCountInString(s) + if str.Slice(nr, nr) != "" { + t.Error("failure with empty slice at end") + } + } +} |