mirror of https://github.com/golang/go.git
[dev.boringcrypto] all: merge master into dev.boringcrypto
Merge at CL 144340, in order to cherry-pick CL 149459 next to it, which fixes a BoringCrypto specific breakage in the toolchain. Change-Id: I30aeac344bbff279449e27876dc8f9c406e55e43
This commit is contained in:
commit
11e916773e
|
|
@ -14,6 +14,7 @@ import (
|
|||
// io.ByteScanner, and io.RuneScanner interfaces by reading from
|
||||
// a byte slice.
|
||||
// Unlike a Buffer, a Reader is read-only and supports seeking.
|
||||
// The zero value for Reader operates like a Reader of an empty slice.
|
||||
type Reader struct {
|
||||
s []byte
|
||||
i int64 // current reading index
|
||||
|
|
@ -75,10 +76,10 @@ func (r *Reader) ReadByte() (byte, error) {
|
|||
|
||||
// UnreadByte complements ReadByte in implementing the io.ByteScanner interface.
|
||||
func (r *Reader) UnreadByte() error {
|
||||
r.prevRune = -1
|
||||
if r.i <= 0 {
|
||||
return errors.New("bytes.Reader.UnreadByte: at beginning of slice")
|
||||
}
|
||||
r.prevRune = -1
|
||||
r.i--
|
||||
return nil
|
||||
}
|
||||
|
|
@ -101,6 +102,9 @@ func (r *Reader) ReadRune() (ch rune, size int, err error) {
|
|||
|
||||
// UnreadRune complements ReadRune in implementing the io.RuneScanner interface.
|
||||
func (r *Reader) UnreadRune() error {
|
||||
if r.i <= 0 {
|
||||
return errors.New("bytes.Reader.UnreadRune: at beginning of slice")
|
||||
}
|
||||
if r.prevRune < 0 {
|
||||
return errors.New("bytes.Reader.UnreadRune: previous operation was not ReadRune")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -276,3 +276,45 @@ func TestReaderReset(t *testing.T) {
|
|||
t.Errorf("ReadAll: got %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReaderZero(t *testing.T) {
|
||||
if l := (&Reader{}).Len(); l != 0 {
|
||||
t.Errorf("Len: got %d, want 0", l)
|
||||
}
|
||||
|
||||
if n, err := (&Reader{}).Read(nil); n != 0 || err != io.EOF {
|
||||
t.Errorf("Read: got %d, %v; want 0, io.EOF", n, err)
|
||||
}
|
||||
|
||||
if n, err := (&Reader{}).ReadAt(nil, 11); n != 0 || err != io.EOF {
|
||||
t.Errorf("ReadAt: got %d, %v; want 0, io.EOF", n, err)
|
||||
}
|
||||
|
||||
if b, err := (&Reader{}).ReadByte(); b != 0 || err != io.EOF {
|
||||
t.Errorf("ReadByte: got %d, %v; want 0, io.EOF", b, err)
|
||||
}
|
||||
|
||||
if ch, size, err := (&Reader{}).ReadRune(); ch != 0 || size != 0 || err != io.EOF {
|
||||
t.Errorf("ReadRune: got %d, %d, %v; want 0, 0, io.EOF", ch, size, err)
|
||||
}
|
||||
|
||||
if offset, err := (&Reader{}).Seek(11, io.SeekStart); offset != 11 || err != nil {
|
||||
t.Errorf("Seek: got %d, %v; want 11, nil", offset, err)
|
||||
}
|
||||
|
||||
if s := (&Reader{}).Size(); s != 0 {
|
||||
t.Errorf("Size: got %d, want 0", s)
|
||||
}
|
||||
|
||||
if (&Reader{}).UnreadByte() == nil {
|
||||
t.Errorf("UnreadByte: got nil, want error")
|
||||
}
|
||||
|
||||
if (&Reader{}).UnreadRune() == nil {
|
||||
t.Errorf("UnreadRune: got nil, want error")
|
||||
}
|
||||
|
||||
if n, err := (&Reader{}).WriteTo(ioutil.Discard); n != 0 || err != nil {
|
||||
t.Errorf("WriteTo: got %d, %v; want 0, nil", n, err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,6 +64,9 @@ Flags:
|
|||
instead of $GOROOT/pkg/$GOOS_$GOARCH.
|
||||
-l
|
||||
Disable inlining.
|
||||
-lang version
|
||||
Set language version to compile, as in -lang=go1.12.
|
||||
Default is current version.
|
||||
-largemodel
|
||||
Generate code that assumes a large memory model.
|
||||
-linkobj file
|
||||
|
|
|
|||
|
|
@ -762,12 +762,20 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
|||
sc := v.AuxValAndOff()
|
||||
off := sc.Off()
|
||||
val := sc.Val()
|
||||
if val == 1 {
|
||||
if val == 1 || val == -1 {
|
||||
var asm obj.As
|
||||
if v.Op == ssa.OpAMD64ADDQconstmodify {
|
||||
asm = x86.AINCQ
|
||||
if val == 1 {
|
||||
asm = x86.AINCQ
|
||||
} else {
|
||||
asm = x86.ADECQ
|
||||
}
|
||||
} else {
|
||||
asm = x86.AINCL
|
||||
if val == 1 {
|
||||
asm = x86.AINCL
|
||||
} else {
|
||||
asm = x86.ADECL
|
||||
}
|
||||
}
|
||||
p := s.Prog(asm)
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
|
|
|
|||
|
|
@ -117,8 +117,8 @@ var runtimeDecls = [...]struct {
|
|||
{"selectsetpc", funcTag, 56},
|
||||
{"selectgo", funcTag, 93},
|
||||
{"block", funcTag, 5},
|
||||
{"makeslice", funcTag, 95},
|
||||
{"makeslice64", funcTag, 96},
|
||||
{"makeslice", funcTag, 94},
|
||||
{"makeslice64", funcTag, 95},
|
||||
{"growslice", funcTag, 97},
|
||||
{"memmove", funcTag, 98},
|
||||
{"memclrNoHeapPointers", funcTag, 99},
|
||||
|
|
@ -249,10 +249,10 @@ func runtimeTypes() []*types.Type {
|
|||
typs[91] = types.NewPtr(typs[11])
|
||||
typs[92] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[91]), anonfield(typs[79])}, []*Node{anonfield(typs[11])})
|
||||
typs[93] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[1]), anonfield(typs[32])}, []*Node{anonfield(typs[32]), anonfield(typs[11])})
|
||||
typs[94] = types.NewSlice(typs[2])
|
||||
typs[95] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[32])}, []*Node{anonfield(typs[94])})
|
||||
typs[96] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[94])})
|
||||
typs[97] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[94]), anonfield(typs[32])}, []*Node{anonfield(typs[94])})
|
||||
typs[94] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[32]), anonfield(typs[32])}, []*Node{anonfield(typs[58])})
|
||||
typs[95] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[15]), anonfield(typs[15])}, []*Node{anonfield(typs[58])})
|
||||
typs[96] = types.NewSlice(typs[2])
|
||||
typs[97] = functype(nil, []*Node{anonfield(typs[1]), anonfield(typs[96]), anonfield(typs[32])}, []*Node{anonfield(typs[96])})
|
||||
typs[98] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[47])}, nil)
|
||||
typs[99] = functype(nil, []*Node{anonfield(typs[58]), anonfield(typs[47])}, nil)
|
||||
typs[100] = functype(nil, []*Node{anonfield(typs[3]), anonfield(typs[3]), anonfield(typs[47])}, []*Node{anonfield(typs[11])})
|
||||
|
|
|
|||
|
|
@ -153,8 +153,8 @@ func selectsetpc(cas *byte)
|
|||
func selectgo(cas0 *byte, order0 *byte, ncases int) (int, bool)
|
||||
func block()
|
||||
|
||||
func makeslice(typ *byte, len int, cap int) (ary []any)
|
||||
func makeslice64(typ *byte, len int64, cap int64) (ary []any)
|
||||
func makeslice(typ *byte, len int, cap int) unsafe.Pointer
|
||||
func makeslice64(typ *byte, len int64, cap int64) unsafe.Pointer
|
||||
func growslice(typ *byte, old []any, cap int) (ary []any)
|
||||
func memmove(to *any, frm *any, length uintptr)
|
||||
func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
// 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.
|
||||
|
||||
package gc
|
||||
|
||||
import (
|
||||
"internal/testenv"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const aliasSrc = `
|
||||
package x
|
||||
|
||||
type T = int
|
||||
`
|
||||
|
||||
func TestInvalidLang(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testenv.MustHaveGoBuild(t)
|
||||
|
||||
dir, err := ioutil.TempDir("", "TestInvalidLang")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
src := filepath.Join(dir, "alias.go")
|
||||
if err := ioutil.WriteFile(src, []byte(aliasSrc), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
outfile := filepath.Join(dir, "alias.o")
|
||||
|
||||
if testLang(t, "go9.99", src, outfile) == nil {
|
||||
t.Error("compilation with -lang=go9.99 succeeded unexpectedly")
|
||||
}
|
||||
|
||||
if testLang(t, "go1.8", src, outfile) == nil {
|
||||
t.Error("compilation with -lang=go1.8 succeeded unexpectedly")
|
||||
}
|
||||
|
||||
if err := testLang(t, "go1.9", src, outfile); err != nil {
|
||||
t.Errorf("compilation with -lang=go1.9 failed unexpectedly: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func testLang(t *testing.T, lang, src, outfile string) error {
|
||||
run := []string{testenv.GoToolPath(t), "tool", "compile", "-lang", lang, "-o", outfile, src}
|
||||
t.Log(run)
|
||||
out, err := exec.Command(run[0], run[1:]...).CombinedOutput()
|
||||
t.Logf("%s", out)
|
||||
return err
|
||||
}
|
||||
|
|
@ -19,11 +19,13 @@ import (
|
|||
"cmd/internal/sys"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
|
@ -211,6 +213,7 @@ func Main(archInit func(*Arch)) {
|
|||
flag.StringVar(&flag_installsuffix, "installsuffix", "", "set pkg directory `suffix`")
|
||||
objabi.Flagcount("j", "debug runtime-initialized variables", &Debug['j'])
|
||||
objabi.Flagcount("l", "disable inlining", &Debug['l'])
|
||||
flag.StringVar(&flag_lang, "lang", defaultLang(), "release to compile for")
|
||||
flag.StringVar(&linkobj, "linkobj", "", "write linker-specific object to `file`")
|
||||
objabi.Flagcount("live", "debug liveness analysis", &debuglive)
|
||||
objabi.Flagcount("m", "print optimization decisions", &Debug['m'])
|
||||
|
|
@ -277,6 +280,8 @@ func Main(archInit func(*Arch)) {
|
|||
Exit(2)
|
||||
}
|
||||
|
||||
checkLang()
|
||||
|
||||
thearch.LinkArch.Init(Ctxt)
|
||||
|
||||
if outfile == "" {
|
||||
|
|
@ -1304,3 +1309,66 @@ func recordFlags(flags ...string) {
|
|||
Ctxt.Data = append(Ctxt.Data, s)
|
||||
s.P = cmd.Bytes()[1:]
|
||||
}
|
||||
|
||||
// flag_lang is the language version we are compiling for, set by the -lang flag.
|
||||
var flag_lang string
|
||||
|
||||
// defaultLang returns the default value for the -lang flag.
|
||||
func defaultLang() string {
|
||||
tags := build.Default.ReleaseTags
|
||||
return tags[len(tags)-1]
|
||||
}
|
||||
|
||||
// goVersionRE is a regular expression that matches the valid
|
||||
// arguments to the -lang flag.
|
||||
var goVersionRE = regexp.MustCompile(`^go([1-9][0-9]*)\.(0|[1-9][0-9]*)$`)
|
||||
|
||||
// A lang is a language version broken into major and minor numbers.
|
||||
type lang struct {
|
||||
major, minor int
|
||||
}
|
||||
|
||||
// langWant is the desired language version set by the -lang flag.
|
||||
var langWant lang
|
||||
|
||||
// langSupported reports whether language version major.minor is supported.
|
||||
func langSupported(major, minor int) bool {
|
||||
return langWant.major > major || (langWant.major == major && langWant.minor >= minor)
|
||||
}
|
||||
|
||||
// checkLang verifies that the -lang flag holds a valid value, and
|
||||
// exits if not. It initializes data used by langSupported.
|
||||
func checkLang() {
|
||||
var err error
|
||||
langWant, err = parseLang(flag_lang)
|
||||
if err != nil {
|
||||
log.Fatalf("invalid value %q for -lang: %v", flag_lang, err)
|
||||
}
|
||||
|
||||
if def := defaultLang(); flag_lang != def {
|
||||
defVers, err := parseLang(def)
|
||||
if err != nil {
|
||||
log.Fatalf("internal error parsing default lang %q: %v", def, err)
|
||||
}
|
||||
if langWant.major > defVers.major || (langWant.major == defVers.major && langWant.major > defVers.minor) {
|
||||
log.Fatalf("invalid value %q for -lang: max known version is %q", flag_lang, def)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parseLang parses a -lang option into a langVer.
|
||||
func parseLang(s string) (lang, error) {
|
||||
matches := goVersionRE.FindStringSubmatch(s)
|
||||
if matches == nil {
|
||||
return lang{}, fmt.Errorf(`should be something like "go1.12"`)
|
||||
}
|
||||
major, err := strconv.Atoi(matches[1])
|
||||
if err != nil {
|
||||
return lang{}, err
|
||||
}
|
||||
minor, err := strconv.Atoi(matches[2])
|
||||
if err != nil {
|
||||
return lang{}, err
|
||||
}
|
||||
return lang{major: major, minor: minor}, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -417,8 +417,11 @@ func (p *noder) typeDecl(decl *syntax.TypeDecl) *Node {
|
|||
param.Pragma = 0
|
||||
}
|
||||
|
||||
return p.nod(decl, ODCLTYPE, n, nil)
|
||||
|
||||
nod := p.nod(decl, ODCLTYPE, n, nil)
|
||||
if param.Alias && !langSupported(1, 9) {
|
||||
yyerrorl(nod.Pos, "type aliases only supported as of -lang=go1.9")
|
||||
}
|
||||
return nod
|
||||
}
|
||||
|
||||
func (p *noder) declNames(names []*syntax.Name) []*Node {
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ package gc
|
|||
|
||||
import "strconv"
|
||||
|
||||
const _Op_name = "XXXNAMENONAMETYPEPACKLITERALADDSUBORXORADDSTRADDRANDANDAPPENDARRAYBYTESTRARRAYBYTESTRTMPARRAYRUNESTRSTRARRAYBYTESTRARRAYBYTETMPSTRARRAYRUNEASAS2AS2FUNCAS2RECVAS2MAPRAS2DOTTYPEASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLFIELDDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTINDINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMULDIVMODLSHRSHANDANDNOTNEWNOTCOMPLUSMINUSORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICE3SLICE3ARRRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFBLOCKBREAKCASEXCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELPROCRANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYDDDDDDARGINLCALLEFACEITABIDATASPTRCLOSUREVARCFUNCCHECKNILVARDEFVARKILLVARLIVEINDREGSPRETJMPGETGEND"
|
||||
const _Op_name = "XXXNAMENONAMETYPEPACKLITERALADDSUBORXORADDSTRADDRANDANDAPPENDARRAYBYTESTRARRAYBYTESTRTMPARRAYRUNESTRSTRARRAYBYTESTRARRAYBYTETMPSTRARRAYRUNEASAS2AS2FUNCAS2RECVAS2MAPRAS2DOTTYPEASOPCALLCALLFUNCCALLMETHCALLINTERCALLPARTCAPCLOSECLOSURECOMPLITMAPLITSTRUCTLITARRAYLITSLICELITPTRLITCONVCONVIFACECONVNOPCOPYDCLDCLFUNCDCLFIELDDCLCONSTDCLTYPEDELETEDOTDOTPTRDOTMETHDOTINTERXDOTDOTTYPEDOTTYPE2EQNELTLEGEGTINDINDEXINDEXMAPKEYSTRUCTKEYLENMAKEMAKECHANMAKEMAPMAKESLICEMULDIVMODLSHRSHANDANDNOTNEWNOTCOMPLUSMINUSORORPANICPRINTPRINTNPARENSENDSLICESLICEARRSLICESTRSLICEHEADERSLICE3SLICE3ARRRECOVERRECVRUNESTRSELRECVSELRECV2IOTAREALIMAGCOMPLEXALIGNOFOFFSETOFSIZEOFBLOCKBREAKCASEXCASECONTINUEDEFEREMPTYFALLFORFORUNTILGOTOIFLABELPROCRANGERETURNSELECTSWITCHTYPESWTCHANTMAPTSTRUCTTINTERTFUNCTARRAYDDDDDDARGINLCALLEFACEITABIDATASPTRCLOSUREVARCFUNCCHECKNILVARDEFVARKILLVARLIVEINDREGSPRETJMPGETGEND"
|
||||
|
||||
var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 36, 39, 45, 49, 55, 61, 73, 88, 100, 112, 127, 139, 141, 144, 151, 158, 165, 175, 179, 183, 191, 199, 208, 216, 219, 224, 231, 238, 244, 253, 261, 269, 275, 279, 288, 295, 299, 302, 309, 317, 325, 332, 338, 341, 347, 354, 362, 366, 373, 381, 383, 385, 387, 389, 391, 393, 396, 401, 409, 412, 421, 424, 428, 436, 443, 452, 455, 458, 461, 464, 467, 470, 476, 479, 482, 485, 489, 494, 498, 503, 508, 514, 519, 523, 528, 536, 544, 550, 559, 566, 570, 577, 584, 592, 596, 600, 604, 611, 618, 626, 632, 637, 642, 646, 651, 659, 664, 669, 673, 676, 684, 688, 690, 695, 699, 704, 710, 716, 722, 728, 733, 737, 744, 750, 755, 761, 764, 770, 777, 782, 786, 791, 795, 805, 810, 818, 824, 831, 838, 846, 852, 856, 859}
|
||||
var _Op_index = [...]uint16{0, 3, 7, 13, 17, 21, 28, 31, 34, 36, 39, 45, 49, 55, 61, 73, 88, 100, 112, 127, 139, 141, 144, 151, 158, 165, 175, 179, 183, 191, 199, 208, 216, 219, 224, 231, 238, 244, 253, 261, 269, 275, 279, 288, 295, 299, 302, 309, 317, 325, 332, 338, 341, 347, 354, 362, 366, 373, 381, 383, 385, 387, 389, 391, 393, 396, 401, 409, 412, 421, 424, 428, 436, 443, 452, 455, 458, 461, 464, 467, 470, 476, 479, 482, 485, 489, 494, 498, 503, 508, 514, 519, 523, 528, 536, 544, 555, 561, 570, 577, 581, 588, 595, 603, 607, 611, 615, 622, 629, 637, 643, 648, 653, 657, 662, 670, 675, 680, 684, 687, 695, 699, 701, 706, 710, 715, 721, 727, 733, 739, 744, 748, 755, 761, 766, 772, 775, 781, 788, 793, 797, 802, 806, 816, 821, 829, 835, 842, 849, 857, 863, 867, 870}
|
||||
|
||||
func (i Op) String() string {
|
||||
if i >= Op(len(_Op_index)-1) {
|
||||
|
|
|
|||
|
|
@ -2321,6 +2321,12 @@ func (s *state) expr(n *Node) *ssa.Value {
|
|||
data := s.expr(n.Right)
|
||||
return s.newValue2(ssa.OpIMake, n.Type, tab, data)
|
||||
|
||||
case OSLICEHEADER:
|
||||
p := s.expr(n.Left)
|
||||
l := s.expr(n.List.First())
|
||||
c := s.expr(n.List.Second())
|
||||
return s.newValue3(ssa.OpSliceMake, n.Type, p, l, c)
|
||||
|
||||
case OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR:
|
||||
v := s.expr(n.Left)
|
||||
var i, j, k *ssa.Value
|
||||
|
|
|
|||
|
|
@ -636,65 +636,66 @@ const (
|
|||
ODCLCONST // const pi = 3.14
|
||||
ODCLTYPE // type Int int or type Int = int
|
||||
|
||||
ODELETE // delete(Left, Right)
|
||||
ODOT // Left.Sym (Left is of struct type)
|
||||
ODOTPTR // Left.Sym (Left is of pointer to struct type)
|
||||
ODOTMETH // Left.Sym (Left is non-interface, Right is method name)
|
||||
ODOTINTER // Left.Sym (Left is interface, Right is method name)
|
||||
OXDOT // Left.Sym (before rewrite to one of the preceding)
|
||||
ODOTTYPE // Left.Right or Left.Type (.Right during parsing, .Type once resolved); after walk, .Right contains address of interface type descriptor and .Right.Right contains address of concrete type descriptor
|
||||
ODOTTYPE2 // Left.Right or Left.Type (.Right during parsing, .Type once resolved; on rhs of OAS2DOTTYPE); after walk, .Right contains address of interface type descriptor
|
||||
OEQ // Left == Right
|
||||
ONE // Left != Right
|
||||
OLT // Left < Right
|
||||
OLE // Left <= Right
|
||||
OGE // Left >= Right
|
||||
OGT // Left > Right
|
||||
OIND // *Left
|
||||
OINDEX // Left[Right] (index of array or slice)
|
||||
OINDEXMAP // Left[Right] (index of map)
|
||||
OKEY // Left:Right (key:value in struct/array/map literal)
|
||||
OSTRUCTKEY // Sym:Left (key:value in struct literal, after type checking)
|
||||
OLEN // len(Left)
|
||||
OMAKE // make(List) (before type checking converts to one of the following)
|
||||
OMAKECHAN // make(Type, Left) (type is chan)
|
||||
OMAKEMAP // make(Type, Left) (type is map)
|
||||
OMAKESLICE // make(Type, Left, Right) (type is slice)
|
||||
OMUL // Left * Right
|
||||
ODIV // Left / Right
|
||||
OMOD // Left % Right
|
||||
OLSH // Left << Right
|
||||
ORSH // Left >> Right
|
||||
OAND // Left & Right
|
||||
OANDNOT // Left &^ Right
|
||||
ONEW // new(Left)
|
||||
ONOT // !Left
|
||||
OCOM // ^Left
|
||||
OPLUS // +Left
|
||||
OMINUS // -Left
|
||||
OOROR // Left || Right
|
||||
OPANIC // panic(Left)
|
||||
OPRINT // print(List)
|
||||
OPRINTN // println(List)
|
||||
OPAREN // (Left)
|
||||
OSEND // Left <- Right
|
||||
OSLICE // Left[List[0] : List[1]] (Left is untypechecked or slice)
|
||||
OSLICEARR // Left[List[0] : List[1]] (Left is array)
|
||||
OSLICESTR // Left[List[0] : List[1]] (Left is string)
|
||||
OSLICE3 // Left[List[0] : List[1] : List[2]] (Left is untypedchecked or slice)
|
||||
OSLICE3ARR // Left[List[0] : List[1] : List[2]] (Left is array)
|
||||
ORECOVER // recover()
|
||||
ORECV // <-Left
|
||||
ORUNESTR // Type(Left) (Type is string, Left is rune)
|
||||
OSELRECV // Left = <-Right.Left: (appears as .Left of OCASE; Right.Op == ORECV)
|
||||
OSELRECV2 // List = <-Right.Left: (apperas as .Left of OCASE; count(List) == 2, Right.Op == ORECV)
|
||||
OIOTA // iota
|
||||
OREAL // real(Left)
|
||||
OIMAG // imag(Left)
|
||||
OCOMPLEX // complex(Left, Right)
|
||||
OALIGNOF // unsafe.Alignof(Left)
|
||||
OOFFSETOF // unsafe.Offsetof(Left)
|
||||
OSIZEOF // unsafe.Sizeof(Left)
|
||||
ODELETE // delete(Left, Right)
|
||||
ODOT // Left.Sym (Left is of struct type)
|
||||
ODOTPTR // Left.Sym (Left is of pointer to struct type)
|
||||
ODOTMETH // Left.Sym (Left is non-interface, Right is method name)
|
||||
ODOTINTER // Left.Sym (Left is interface, Right is method name)
|
||||
OXDOT // Left.Sym (before rewrite to one of the preceding)
|
||||
ODOTTYPE // Left.Right or Left.Type (.Right during parsing, .Type once resolved); after walk, .Right contains address of interface type descriptor and .Right.Right contains address of concrete type descriptor
|
||||
ODOTTYPE2 // Left.Right or Left.Type (.Right during parsing, .Type once resolved; on rhs of OAS2DOTTYPE); after walk, .Right contains address of interface type descriptor
|
||||
OEQ // Left == Right
|
||||
ONE // Left != Right
|
||||
OLT // Left < Right
|
||||
OLE // Left <= Right
|
||||
OGE // Left >= Right
|
||||
OGT // Left > Right
|
||||
OIND // *Left
|
||||
OINDEX // Left[Right] (index of array or slice)
|
||||
OINDEXMAP // Left[Right] (index of map)
|
||||
OKEY // Left:Right (key:value in struct/array/map literal)
|
||||
OSTRUCTKEY // Sym:Left (key:value in struct literal, after type checking)
|
||||
OLEN // len(Left)
|
||||
OMAKE // make(List) (before type checking converts to one of the following)
|
||||
OMAKECHAN // make(Type, Left) (type is chan)
|
||||
OMAKEMAP // make(Type, Left) (type is map)
|
||||
OMAKESLICE // make(Type, Left, Right) (type is slice)
|
||||
OMUL // Left * Right
|
||||
ODIV // Left / Right
|
||||
OMOD // Left % Right
|
||||
OLSH // Left << Right
|
||||
ORSH // Left >> Right
|
||||
OAND // Left & Right
|
||||
OANDNOT // Left &^ Right
|
||||
ONEW // new(Left)
|
||||
ONOT // !Left
|
||||
OCOM // ^Left
|
||||
OPLUS // +Left
|
||||
OMINUS // -Left
|
||||
OOROR // Left || Right
|
||||
OPANIC // panic(Left)
|
||||
OPRINT // print(List)
|
||||
OPRINTN // println(List)
|
||||
OPAREN // (Left)
|
||||
OSEND // Left <- Right
|
||||
OSLICE // Left[List[0] : List[1]] (Left is untypechecked or slice)
|
||||
OSLICEARR // Left[List[0] : List[1]] (Left is array)
|
||||
OSLICESTR // Left[List[0] : List[1]] (Left is string)
|
||||
OSLICE3 // Left[List[0] : List[1] : List[2]] (Left is untypedchecked or slice)
|
||||
OSLICE3ARR // Left[List[0] : List[1] : List[2]] (Left is array)
|
||||
OSLICEHEADER // sliceheader{Left, List[0], List[1]} (Left is unsafe.Pointer, List[0] is length, List[1] is capacity)
|
||||
ORECOVER // recover()
|
||||
ORECV // <-Left
|
||||
ORUNESTR // Type(Left) (Type is string, Left is rune)
|
||||
OSELRECV // Left = <-Right.Left: (appears as .Left of OCASE; Right.Op == ORECV)
|
||||
OSELRECV2 // List = <-Right.Left: (apperas as .Left of OCASE; count(List) == 2, Right.Op == ORECV)
|
||||
OIOTA // iota
|
||||
OREAL // real(Left)
|
||||
OIMAG // imag(Left)
|
||||
OCOMPLEX // complex(Left, Right)
|
||||
OALIGNOF // unsafe.Alignof(Left)
|
||||
OOFFSETOF // unsafe.Offsetof(Left)
|
||||
OSIZEOF // unsafe.Sizeof(Left)
|
||||
|
||||
// statements
|
||||
OBLOCK // { List } (block of code)
|
||||
|
|
|
|||
|
|
@ -1086,6 +1086,47 @@ func typecheck1(n *Node, top int) *Node {
|
|||
n.Right = assignconv(r, t.Elem(), "send")
|
||||
n.Type = nil
|
||||
|
||||
case OSLICEHEADER:
|
||||
// Errors here are Fatalf instead of yyerror because only the compiler
|
||||
// can construct an OSLICEHEADER node.
|
||||
// Components used in OSLICEHEADER that are supplied by parsed source code
|
||||
// have already been typechecked in e.g. OMAKESLICE earlier.
|
||||
ok |= Erv
|
||||
|
||||
t := n.Type
|
||||
if !t.IsSlice() {
|
||||
Fatalf("invalid type %v for OSLICEHEADER", n.Type)
|
||||
}
|
||||
|
||||
if !n.Left.Type.IsUnsafePtr() {
|
||||
Fatalf("need unsafe.Pointer for OSLICEHEADER")
|
||||
}
|
||||
|
||||
if x := n.List.Len(); x != 2 {
|
||||
Fatalf("expected 2 params (len, cap) for OSLICEHEADER, got %d", x)
|
||||
}
|
||||
|
||||
n.Left = typecheck(n.Left, Erv)
|
||||
l := typecheck(n.List.First(), Erv)
|
||||
c := typecheck(n.List.Second(), Erv)
|
||||
l = defaultlit(l, types.Types[TINT])
|
||||
c = defaultlit(c, types.Types[TINT])
|
||||
|
||||
if Isconst(l, CTINT) && l.Int64() < 0 {
|
||||
Fatalf("len for OSLICEHEADER must be non-negative")
|
||||
}
|
||||
|
||||
if Isconst(c, CTINT) && c.Int64() < 0 {
|
||||
Fatalf("cap for OSLICEHEADER must be non-negative")
|
||||
}
|
||||
|
||||
if Isconst(l, CTINT) && Isconst(c, CTINT) && l.Val().U.(*Mpint).Cmp(c.Val().U.(*Mpint)) > 0 {
|
||||
Fatalf("len larger than cap for OSLICEHEADER")
|
||||
}
|
||||
|
||||
n.List.SetFirst(l)
|
||||
n.List.SetSecond(c)
|
||||
|
||||
case OSLICE, OSLICE3:
|
||||
ok |= Erv
|
||||
n.Left = typecheck(n.Left, Erv)
|
||||
|
|
|
|||
|
|
@ -1118,6 +1118,11 @@ opswitch:
|
|||
case ORECV:
|
||||
Fatalf("walkexpr ORECV") // should see inside OAS only
|
||||
|
||||
case OSLICEHEADER:
|
||||
n.Left = walkexpr(n.Left, init)
|
||||
n.List.SetFirst(walkexpr(n.List.First(), init))
|
||||
n.List.SetSecond(walkexpr(n.List.Second(), init))
|
||||
|
||||
case OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR:
|
||||
n.Left = walkexpr(n.Left, init)
|
||||
low, high, max := n.SliceBounds()
|
||||
|
|
@ -1339,8 +1344,13 @@ opswitch:
|
|||
}
|
||||
|
||||
fn := syslook(fnname)
|
||||
fn = substArgTypes(fn, t.Elem()) // any-1
|
||||
n = mkcall1(fn, t, init, typename(t.Elem()), conv(len, argtype), conv(cap, argtype))
|
||||
n.Left = mkcall1(fn, types.Types[TUNSAFEPTR], init, typename(t.Elem()), conv(len, argtype), conv(cap, argtype))
|
||||
n.Left.SetNonNil(true)
|
||||
n.List.Set2(conv(len, types.Types[TINT]), conv(cap, types.Types[TINT]))
|
||||
n.Op = OSLICEHEADER
|
||||
n.Type = t
|
||||
n = typecheck(n, Erv)
|
||||
n = walkexpr(n, init)
|
||||
}
|
||||
|
||||
case ORUNESTR:
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ package main_test
|
|||
import (
|
||||
"bytes"
|
||||
"cmd/internal/sys"
|
||||
"context"
|
||||
"debug/elf"
|
||||
"debug/macho"
|
||||
"flag"
|
||||
|
|
@ -108,6 +109,12 @@ var testGo string
|
|||
var testTmpDir string
|
||||
var testBin string
|
||||
|
||||
// testCtx is canceled when the test binary is about to time out.
|
||||
//
|
||||
// If https://golang.org/issue/28135 is accepted, uses of this variable in test
|
||||
// functions should be replaced by t.Context().
|
||||
var testCtx = context.Background()
|
||||
|
||||
// The TestMain function creates a go command for testing purposes and
|
||||
// deletes it after the tests have been run.
|
||||
func TestMain(m *testing.M) {
|
||||
|
|
@ -120,6 +127,20 @@ func TestMain(m *testing.M) {
|
|||
os.Unsetenv("GOROOT_FINAL")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
timeoutFlag := flag.Lookup("test.timeout")
|
||||
if timeoutFlag != nil {
|
||||
// TODO(golang.org/issue/28147): The go command does not pass the
|
||||
// test.timeout flag unless either -timeout or -test.timeout is explicitly
|
||||
// set on the command line.
|
||||
if d := timeoutFlag.Value.(flag.Getter).Get().(time.Duration); d != 0 {
|
||||
aBitShorter := d * 95 / 100
|
||||
var cancel context.CancelFunc
|
||||
testCtx, cancel = context.WithTimeout(testCtx, aBitShorter)
|
||||
defer cancel()
|
||||
}
|
||||
}
|
||||
|
||||
if *proxyAddr != "" {
|
||||
StartProxy()
|
||||
select {}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ package main_test
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"internal/testenv"
|
||||
"io/ioutil"
|
||||
|
|
@ -55,21 +56,28 @@ func TestScript(t *testing.T) {
|
|||
|
||||
// A testScript holds execution state for a single test script.
|
||||
type testScript struct {
|
||||
t *testing.T
|
||||
workdir string // temporary work dir ($WORK)
|
||||
log bytes.Buffer // test execution log (printed at end of test)
|
||||
mark int // offset of next log truncation
|
||||
cd string // current directory during test execution; initially $WORK/gopath/src
|
||||
name string // short name of test ("foo")
|
||||
file string // full file name ("testdata/script/foo.txt")
|
||||
lineno int // line number currently executing
|
||||
line string // line currently executing
|
||||
env []string // environment list (for os/exec)
|
||||
envMap map[string]string // environment mapping (matches env)
|
||||
stdout string // standard output from last 'go' command; for 'stdout' command
|
||||
stderr string // standard error from last 'go' command; for 'stderr' command
|
||||
stopped bool // test wants to stop early
|
||||
start time.Time // time phase started
|
||||
t *testing.T
|
||||
workdir string // temporary work dir ($WORK)
|
||||
log bytes.Buffer // test execution log (printed at end of test)
|
||||
mark int // offset of next log truncation
|
||||
cd string // current directory during test execution; initially $WORK/gopath/src
|
||||
name string // short name of test ("foo")
|
||||
file string // full file name ("testdata/script/foo.txt")
|
||||
lineno int // line number currently executing
|
||||
line string // line currently executing
|
||||
env []string // environment list (for os/exec)
|
||||
envMap map[string]string // environment mapping (matches env)
|
||||
stdout string // standard output from last 'go' command; for 'stdout' command
|
||||
stderr string // standard error from last 'go' command; for 'stderr' command
|
||||
stopped bool // test wants to stop early
|
||||
start time.Time // time phase started
|
||||
background []backgroundCmd // backgrounded 'exec' and 'go' commands
|
||||
}
|
||||
|
||||
type backgroundCmd struct {
|
||||
cmd *exec.Cmd
|
||||
wait <-chan struct{}
|
||||
neg bool // if true, cmd should fail
|
||||
}
|
||||
|
||||
var extraEnvKeys = []string{
|
||||
|
|
@ -146,6 +154,17 @@ func (ts *testScript) run() {
|
|||
}
|
||||
|
||||
defer func() {
|
||||
// On a normal exit from the test loop, background processes are cleaned up
|
||||
// before we print PASS. If we return early (e.g., due to a test failure),
|
||||
// don't print anything about the processes that were still running.
|
||||
for _, bg := range ts.background {
|
||||
interruptProcess(bg.cmd.Process)
|
||||
}
|
||||
for _, bg := range ts.background {
|
||||
<-bg.wait
|
||||
}
|
||||
ts.background = nil
|
||||
|
||||
markTime()
|
||||
// Flush testScript log to testing.T log.
|
||||
ts.t.Log("\n" + ts.abbrev(ts.log.String()))
|
||||
|
|
@ -284,14 +303,23 @@ Script:
|
|||
|
||||
// Command can ask script to stop early.
|
||||
if ts.stopped {
|
||||
return
|
||||
// Break instead of returning, so that we check the status of any
|
||||
// background processes and print PASS.
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for _, bg := range ts.background {
|
||||
interruptProcess(bg.cmd.Process)
|
||||
}
|
||||
ts.cmdWait(false, nil)
|
||||
|
||||
// Final phase ended.
|
||||
rewind()
|
||||
markTime()
|
||||
fmt.Fprintf(&ts.log, "PASS\n")
|
||||
if !ts.stopped {
|
||||
fmt.Fprintf(&ts.log, "PASS\n")
|
||||
}
|
||||
}
|
||||
|
||||
// scriptCmds are the script command implementations.
|
||||
|
|
@ -317,6 +345,7 @@ var scriptCmds = map[string]func(*testScript, bool, []string){
|
|||
"stdout": (*testScript).cmdStdout,
|
||||
"stop": (*testScript).cmdStop,
|
||||
"symlink": (*testScript).cmdSymlink,
|
||||
"wait": (*testScript).cmdWait,
|
||||
}
|
||||
|
||||
// addcrlf adds CRLF line endings to the named files.
|
||||
|
|
@ -451,26 +480,43 @@ func (ts *testScript) cmdEnv(neg bool, args []string) {
|
|||
|
||||
// exec runs the given command.
|
||||
func (ts *testScript) cmdExec(neg bool, args []string) {
|
||||
if len(args) < 1 {
|
||||
ts.fatalf("usage: exec program [args...]")
|
||||
if len(args) < 1 || (len(args) == 1 && args[0] == "&") {
|
||||
ts.fatalf("usage: exec program [args...] [&]")
|
||||
}
|
||||
|
||||
var err error
|
||||
ts.stdout, ts.stderr, err = ts.exec(args[0], args[1:]...)
|
||||
if ts.stdout != "" {
|
||||
fmt.Fprintf(&ts.log, "[stdout]\n%s", ts.stdout)
|
||||
}
|
||||
if ts.stderr != "" {
|
||||
fmt.Fprintf(&ts.log, "[stderr]\n%s", ts.stderr)
|
||||
if len(args) > 0 && args[len(args)-1] == "&" {
|
||||
var cmd *exec.Cmd
|
||||
cmd, err = ts.execBackground(args[0], args[1:len(args)-1]...)
|
||||
if err == nil {
|
||||
wait := make(chan struct{})
|
||||
go func() {
|
||||
ctxWait(testCtx, cmd)
|
||||
close(wait)
|
||||
}()
|
||||
ts.background = append(ts.background, backgroundCmd{cmd, wait, neg})
|
||||
}
|
||||
ts.stdout, ts.stderr = "", ""
|
||||
} else {
|
||||
ts.stdout, ts.stderr, err = ts.exec(args[0], args[1:]...)
|
||||
if ts.stdout != "" {
|
||||
fmt.Fprintf(&ts.log, "[stdout]\n%s", ts.stdout)
|
||||
}
|
||||
if ts.stderr != "" {
|
||||
fmt.Fprintf(&ts.log, "[stderr]\n%s", ts.stderr)
|
||||
}
|
||||
if err == nil && neg {
|
||||
ts.fatalf("unexpected command success")
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintf(&ts.log, "[%v]\n", err)
|
||||
if !neg {
|
||||
if testCtx.Err() != nil {
|
||||
ts.fatalf("test timed out while running command")
|
||||
} else if !neg {
|
||||
ts.fatalf("unexpected command failure")
|
||||
}
|
||||
} else {
|
||||
if neg {
|
||||
ts.fatalf("unexpected command success")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -545,6 +591,14 @@ func (ts *testScript) cmdSkip(neg bool, args []string) {
|
|||
if neg {
|
||||
ts.fatalf("unsupported: ! skip")
|
||||
}
|
||||
|
||||
// Before we mark the test as skipped, shut down any background processes and
|
||||
// make sure they have returned the correct status.
|
||||
for _, bg := range ts.background {
|
||||
interruptProcess(bg.cmd.Process)
|
||||
}
|
||||
ts.cmdWait(false, nil)
|
||||
|
||||
if len(args) == 1 {
|
||||
ts.t.Skip(args[0])
|
||||
}
|
||||
|
|
@ -687,6 +741,52 @@ func (ts *testScript) cmdSymlink(neg bool, args []string) {
|
|||
ts.check(os.Symlink(args[2], ts.mkabs(args[0])))
|
||||
}
|
||||
|
||||
// wait waits for background commands to exit, setting stderr and stdout to their result.
|
||||
func (ts *testScript) cmdWait(neg bool, args []string) {
|
||||
if neg {
|
||||
ts.fatalf("unsupported: ! wait")
|
||||
}
|
||||
if len(args) > 0 {
|
||||
ts.fatalf("usage: wait")
|
||||
}
|
||||
|
||||
var stdouts, stderrs []string
|
||||
for _, bg := range ts.background {
|
||||
<-bg.wait
|
||||
|
||||
args := append([]string{filepath.Base(bg.cmd.Args[0])}, bg.cmd.Args[1:]...)
|
||||
fmt.Fprintf(&ts.log, "[background] %s: %v\n", strings.Join(args, " "), bg.cmd.ProcessState)
|
||||
|
||||
cmdStdout := bg.cmd.Stdout.(*strings.Builder).String()
|
||||
if cmdStdout != "" {
|
||||
fmt.Fprintf(&ts.log, "[stdout]\n%s", cmdStdout)
|
||||
stdouts = append(stdouts, cmdStdout)
|
||||
}
|
||||
|
||||
cmdStderr := bg.cmd.Stderr.(*strings.Builder).String()
|
||||
if cmdStderr != "" {
|
||||
fmt.Fprintf(&ts.log, "[stderr]\n%s", cmdStderr)
|
||||
stderrs = append(stderrs, cmdStderr)
|
||||
}
|
||||
|
||||
if bg.cmd.ProcessState.Success() {
|
||||
if bg.neg {
|
||||
ts.fatalf("unexpected command success")
|
||||
}
|
||||
} else {
|
||||
if testCtx.Err() != nil {
|
||||
ts.fatalf("test timed out while running command")
|
||||
} else if !bg.neg {
|
||||
ts.fatalf("unexpected command failure")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ts.stdout = strings.Join(stdouts, "")
|
||||
ts.stderr = strings.Join(stderrs, "")
|
||||
ts.background = nil
|
||||
}
|
||||
|
||||
// Helpers for command implementations.
|
||||
|
||||
// abbrev abbreviates the actual work directory in the string s to the literal string "$WORK".
|
||||
|
|
@ -716,10 +816,51 @@ func (ts *testScript) exec(command string, args ...string) (stdout, stderr strin
|
|||
var stdoutBuf, stderrBuf strings.Builder
|
||||
cmd.Stdout = &stdoutBuf
|
||||
cmd.Stderr = &stderrBuf
|
||||
err = cmd.Run()
|
||||
if err = cmd.Start(); err == nil {
|
||||
err = ctxWait(testCtx, cmd)
|
||||
}
|
||||
return stdoutBuf.String(), stderrBuf.String(), err
|
||||
}
|
||||
|
||||
// execBackground starts the given command line (an actual subprocess, not simulated)
|
||||
// in ts.cd with environment ts.env.
|
||||
func (ts *testScript) execBackground(command string, args ...string) (*exec.Cmd, error) {
|
||||
cmd := exec.Command(command, args...)
|
||||
cmd.Dir = ts.cd
|
||||
cmd.Env = append(ts.env, "PWD="+ts.cd)
|
||||
var stdoutBuf, stderrBuf strings.Builder
|
||||
cmd.Stdout = &stdoutBuf
|
||||
cmd.Stderr = &stderrBuf
|
||||
return cmd, cmd.Start()
|
||||
}
|
||||
|
||||
// ctxWait is like cmd.Wait, but terminates cmd with os.Interrupt if ctx becomes done.
|
||||
//
|
||||
// This differs from exec.CommandContext in that it prefers os.Interrupt over os.Kill.
|
||||
// (See https://golang.org/issue/21135.)
|
||||
func ctxWait(ctx context.Context, cmd *exec.Cmd) error {
|
||||
errc := make(chan error, 1)
|
||||
go func() { errc <- cmd.Wait() }()
|
||||
|
||||
select {
|
||||
case err := <-errc:
|
||||
return err
|
||||
case <-ctx.Done():
|
||||
interruptProcess(cmd.Process)
|
||||
return <-errc
|
||||
}
|
||||
}
|
||||
|
||||
// interruptProcess sends os.Interrupt to p if supported, or os.Kill otherwise.
|
||||
func interruptProcess(p *os.Process) {
|
||||
if err := p.Signal(os.Interrupt); err != nil {
|
||||
// Per https://golang.org/pkg/os/#Signal, “Interrupt is not implemented on
|
||||
// Windows; using it with os.Process.Signal will return an error.”
|
||||
// Fall back to Kill instead.
|
||||
p.Kill()
|
||||
}
|
||||
}
|
||||
|
||||
// expand applies environment variable expansion to the string s.
|
||||
func (ts *testScript) expand(s string) string {
|
||||
return os.Expand(s, func(key string) string { return ts.envMap[key] })
|
||||
|
|
|
|||
|
|
@ -99,16 +99,23 @@ The commands are:
|
|||
With no arguments, print the environment (useful for debugging).
|
||||
Otherwise add the listed key=value pairs to the environment.
|
||||
|
||||
- [!] exec program [args...]
|
||||
- [!] exec program [args...] [&]
|
||||
Run the given executable program with the arguments.
|
||||
It must (or must not) succeed.
|
||||
Note that 'exec' does not terminate the script (unlike in Unix shells).
|
||||
|
||||
If the last token is '&', the program executes in the background. The standard
|
||||
output and standard error of the previous command is cleared, but the output
|
||||
of the background process is buffered — and checking of its exit status is
|
||||
delayed — until the next call to 'wait', 'skip', or 'stop' or the end of the
|
||||
test. At the end of the test, any remaining background processes are
|
||||
terminated using os.Interrupt (if supported) or os.Kill.
|
||||
|
||||
- [!] exists [-readonly] file...
|
||||
Each of the listed files or directories must (or must not) exist.
|
||||
If -readonly is given, the files or directories must be unwritable.
|
||||
|
||||
- [!] go args...
|
||||
- [!] go args... [&]
|
||||
Run the (test copy of the) go command with the given arguments.
|
||||
It must (or must not) succeed.
|
||||
|
||||
|
|
@ -131,11 +138,11 @@ The commands are:
|
|||
|
||||
- [!] stderr [-count=N] pattern
|
||||
Apply the grep command (see above) to the standard error
|
||||
from the most recent exec or go command.
|
||||
from the most recent exec, go, or wait command.
|
||||
|
||||
- [!] stdout [-count=N] pattern
|
||||
Apply the grep command (see above) to the standard output
|
||||
from the most recent exec or go command.
|
||||
from the most recent exec, go, or wait command.
|
||||
|
||||
- stop [message]
|
||||
Stop the test early (marking it as passing), including the message if given.
|
||||
|
|
@ -143,6 +150,13 @@ The commands are:
|
|||
- symlink file -> target
|
||||
Create file as a symlink to target. The -> (like in ls -l output) is required.
|
||||
|
||||
- wait
|
||||
Wait for all 'exec' and 'go' commands started in the background (with the '&'
|
||||
token) to exit, and display success or failure status for them.
|
||||
After a call to wait, the 'stderr' and 'stdout' commands will apply to the
|
||||
concatenation of the corresponding streams of the background commands,
|
||||
in the order in which those commands were started.
|
||||
|
||||
When TestScript runs a script and the script fails, by default TestScript shows
|
||||
the execution of the most recent phase of the script (since the last # comment)
|
||||
and only shows the # comments for earlier phases. For example, here is a
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
[!exec:echo] skip
|
||||
[!exec:false] skip
|
||||
|
||||
exec echo foo
|
||||
stdout foo
|
||||
|
||||
exec echo foo &
|
||||
exec echo bar &
|
||||
! exec false &
|
||||
|
||||
# Starting a background process should clear previous output.
|
||||
! stdout foo
|
||||
|
||||
# Wait should set the output to the concatenated outputs of the background
|
||||
# programs, in the order in which they were started.
|
||||
wait
|
||||
stdout 'foo\nbar'
|
||||
|
||||
# The end of the test should interrupt or kill any remaining background
|
||||
# programs.
|
||||
[!exec:sleep] skip
|
||||
! exec sleep 86400 &
|
||||
|
|
@ -11,7 +11,6 @@ package tls
|
|||
// https://www.imperialviolet.org/2013/02/04/luckythirteen.html.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
|
|
@ -30,10 +29,7 @@ import (
|
|||
// The configuration config must be non-nil and must include
|
||||
// at least one certificate or else set GetCertificate.
|
||||
func Server(conn net.Conn, config *Config) *Conn {
|
||||
return &Conn{
|
||||
conn: conn, config: config,
|
||||
input: *bytes.NewReader(nil), // Issue 28269
|
||||
}
|
||||
return &Conn{conn: conn, config: config}
|
||||
}
|
||||
|
||||
// Client returns a new TLS client side connection
|
||||
|
|
@ -41,10 +37,7 @@ func Server(conn net.Conn, config *Config) *Conn {
|
|||
// The config cannot be nil: users must set either ServerName or
|
||||
// InsecureSkipVerify in the config.
|
||||
func Client(conn net.Conn, config *Config) *Conn {
|
||||
return &Conn{
|
||||
conn: conn, config: config, isClient: true,
|
||||
input: *bytes.NewReader(nil), // Issue 28269
|
||||
}
|
||||
return &Conn{conn: conn, config: config, isClient: true}
|
||||
}
|
||||
|
||||
// A listener implements a network listener (net.Listener) for TLS connections.
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ type Context struct {
|
|||
// which defaults to the list of Go releases the current release is compatible with.
|
||||
// In addition to the BuildTags and ReleaseTags, build constraints
|
||||
// consider the values of GOARCH and GOOS as satisfied tags.
|
||||
// The last element in ReleaseTags is assumed to be the current release.
|
||||
BuildTags []string
|
||||
ReleaseTags []string
|
||||
|
||||
|
|
@ -296,6 +297,7 @@ func defaultContext() Context {
|
|||
// say "+build go1.x", and code that should only be built before Go 1.x
|
||||
// (perhaps it is the stub to use in that case) should say "+build !go1.x".
|
||||
// NOTE: If you add to this list, also update the doc comment in doc.go.
|
||||
// NOTE: The last element in ReleaseTags should be the current release.
|
||||
const version = 11 // go1.11
|
||||
for i := 1; i <= version; i++ {
|
||||
c.ReleaseTags = append(c.ReleaseTags, "go1."+strconv.Itoa(i))
|
||||
|
|
|
|||
|
|
@ -47,27 +47,18 @@ type x86 struct {
|
|||
|
||||
var PPC64 ppc64
|
||||
|
||||
// For ppc64x, it is safe to check only for ISA level starting on ISA v3.00,
|
||||
// For ppc64(le), it is safe to check only for ISA level starting on ISA v3.00,
|
||||
// since there are no optional categories. There are some exceptions that also
|
||||
// require kernel support to work (darn, scv), so there are feature bits for
|
||||
// those as well. The minimum processor requirement is POWER8 (ISA 2.07), so we
|
||||
// maintain some of the old feature checks for optional categories for
|
||||
// safety.
|
||||
// those as well. The minimum processor requirement is POWER8 (ISA 2.07).
|
||||
// The struct is padded to avoid false sharing.
|
||||
type ppc64 struct {
|
||||
_ CacheLinePad
|
||||
HasVMX bool // Vector unit (Altivec)
|
||||
HasDFP bool // Decimal Floating Point unit
|
||||
HasVSX bool // Vector-scalar unit
|
||||
HasHTM bool // Hardware Transactional Memory
|
||||
HasISEL bool // Integer select
|
||||
HasVCRYPTO bool // Vector cryptography
|
||||
HasHTMNOSC bool // HTM: kernel-aborted transaction in syscalls
|
||||
HasDARN bool // Hardware random number generator (requires kernel enablement)
|
||||
HasSCV bool // Syscall vectored (requires kernel enablement)
|
||||
IsPOWER8 bool // ISA v2.07 (POWER8)
|
||||
IsPOWER9 bool // ISA v3.00 (POWER9)
|
||||
_ CacheLinePad
|
||||
_ CacheLinePad
|
||||
HasDARN bool // Hardware random number generator (requires kernel enablement)
|
||||
HasSCV bool // Syscall vectored (requires kernel enablement)
|
||||
IsPOWER8 bool // ISA v2.07 (POWER8)
|
||||
IsPOWER9 bool // ISA v3.00 (POWER9)
|
||||
_ CacheLinePad
|
||||
}
|
||||
|
||||
var ARM arm
|
||||
|
|
|
|||
|
|
@ -21,44 +21,22 @@ const (
|
|||
_PPC_FEATURE2_ARCH_3_00 = 0x00800000
|
||||
|
||||
// CPU features
|
||||
_PPC_FEATURE_HAS_ALTIVEC = 0x10000000
|
||||
_PPC_FEATURE_HAS_DFP = 0x00000400
|
||||
_PPC_FEATURE_HAS_VSX = 0x00000080
|
||||
_PPC_FEATURE2_HAS_HTM = 0x40000000
|
||||
_PPC_FEATURE2_HAS_ISEL = 0x08000000
|
||||
_PPC_FEATURE2_HAS_VEC_CRYPTO = 0x02000000
|
||||
_PPC_FEATURE2_HTM_NOSC = 0x01000000
|
||||
_PPC_FEATURE2_DARN = 0x00200000
|
||||
_PPC_FEATURE2_SCV = 0x00100000
|
||||
_PPC_FEATURE2_DARN = 0x00200000
|
||||
_PPC_FEATURE2_SCV = 0x00100000
|
||||
)
|
||||
|
||||
func doinit() {
|
||||
options = []option{
|
||||
{Name: "htm", Feature: &PPC64.HasHTM},
|
||||
{Name: "htmnosc", Feature: &PPC64.HasHTMNOSC},
|
||||
{Name: "darn", Feature: &PPC64.HasDARN},
|
||||
{Name: "scv", Feature: &PPC64.HasSCV},
|
||||
{Name: "power9", Feature: &PPC64.IsPOWER9},
|
||||
|
||||
// These capabilities should always be enabled on ppc64 and ppc64le:
|
||||
{Name: "power8", Feature: &PPC64.IsPOWER8, Required: true},
|
||||
{Name: "vmx", Feature: &PPC64.HasVMX, Required: true},
|
||||
{Name: "dfp", Feature: &PPC64.HasDFP, Required: true},
|
||||
{Name: "vsx", Feature: &PPC64.HasVSX, Required: true},
|
||||
{Name: "isel", Feature: &PPC64.HasISEL, Required: true},
|
||||
{Name: "vcrypto", Feature: &PPC64.HasVCRYPTO, Required: true},
|
||||
}
|
||||
|
||||
// HWCAP feature bits
|
||||
PPC64.HasVMX = isSet(HWCap, _PPC_FEATURE_HAS_ALTIVEC)
|
||||
PPC64.HasDFP = isSet(HWCap, _PPC_FEATURE_HAS_DFP)
|
||||
PPC64.HasVSX = isSet(HWCap, _PPC_FEATURE_HAS_VSX)
|
||||
|
||||
// HWCAP2 feature bits
|
||||
PPC64.IsPOWER8 = isSet(HWCap2, _PPC_FEATURE2_ARCH_2_07)
|
||||
PPC64.HasHTM = isSet(HWCap2, _PPC_FEATURE2_HAS_HTM)
|
||||
PPC64.HasISEL = isSet(HWCap2, _PPC_FEATURE2_HAS_ISEL)
|
||||
PPC64.HasVCRYPTO = isSet(HWCap2, _PPC_FEATURE2_HAS_VEC_CRYPTO)
|
||||
PPC64.HasHTMNOSC = isSet(HWCap2, _PPC_FEATURE2_HTM_NOSC)
|
||||
PPC64.IsPOWER9 = isSet(HWCap2, _PPC_FEATURE2_ARCH_3_00)
|
||||
PPC64.HasDARN = isSet(HWCap2, _PPC_FEATURE2_DARN)
|
||||
PPC64.HasSCV = isSet(HWCap2, _PPC_FEATURE2_SCV)
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ const debugFloat = false // enable for debugging
|
|||
// precision of the argument with the largest precision value before any
|
||||
// rounding takes place, and the rounding mode remains unchanged. Thus,
|
||||
// uninitialized Floats provided as result arguments will have their
|
||||
// precision set to a reasonable value determined by the operands and
|
||||
// precision set to a reasonable value determined by the operands, and
|
||||
// their mode is the zero value for RoundingMode (ToNearestEven).
|
||||
//
|
||||
// By setting the desired precision to 24 or 53 and using matching rounding
|
||||
|
|
@ -56,6 +56,12 @@ const debugFloat = false // enable for debugging
|
|||
// The zero (uninitialized) value for a Float is ready to use and represents
|
||||
// the number +0.0 exactly, with precision 0 and rounding mode ToNearestEven.
|
||||
//
|
||||
// Operations always take pointer arguments (*Float) rather
|
||||
// than Float values, and each unique Float value requires
|
||||
// its own unique *Float pointer. To "copy" a Float value,
|
||||
// an existing (or newly allocated) Float must be set to
|
||||
// a new value using the Float.Set method; shallow copies
|
||||
// of Floats are not supported and may lead to errors.
|
||||
type Float struct {
|
||||
prec uint32
|
||||
mode RoundingMode
|
||||
|
|
|
|||
|
|
@ -15,6 +15,13 @@ import (
|
|||
|
||||
// An Int represents a signed multi-precision integer.
|
||||
// The zero value for an Int represents the value 0.
|
||||
//
|
||||
// Operations always take pointer arguments (*Int) rather
|
||||
// than Int values, and each unique Int value requires
|
||||
// its own unique *Int pointer. To "copy" an Int value,
|
||||
// an existing (or newly allocated) Int must be set to
|
||||
// a new value using the Int.Set method; shallow copies
|
||||
// of Ints are not supported and may lead to errors.
|
||||
type Int struct {
|
||||
neg bool // sign
|
||||
abs nat // absolute value of the integer
|
||||
|
|
|
|||
|
|
@ -13,6 +13,13 @@ import (
|
|||
|
||||
// A Rat represents a quotient a/b of arbitrary precision.
|
||||
// The zero value for a Rat represents the value 0.
|
||||
//
|
||||
// Operations always take pointer arguments (*Rat) rather
|
||||
// than Rat values, and each unique Rat value requires
|
||||
// its own unique *Rat pointer. To "copy" a Rat value,
|
||||
// an existing (or newly allocated) Rat must be set to
|
||||
// a new value using the Rat.Set method; shallow copies
|
||||
// of Rats are not supported and may lead to errors.
|
||||
type Rat struct {
|
||||
// To make zero values for Rat work w/o initialization,
|
||||
// a zero value of b (len(b) == 0) acts like b == 1.
|
||||
|
|
|
|||
|
|
@ -53,8 +53,9 @@ var (
|
|||
// available.
|
||||
ErrNotSupported = &ProtocolError{"feature not supported"}
|
||||
|
||||
// ErrUnexpectedTrailer is returned by the Transport when a server
|
||||
// replies with a Trailer header, but without a chunked reply.
|
||||
// Deprecated: ErrUnexpectedTrailer is no longer returned by
|
||||
// anything in the net/http package. Callers should not
|
||||
// compare errors against this variable.
|
||||
ErrUnexpectedTrailer = &ProtocolError{"trailer header without chunked transfer encoding"}
|
||||
|
||||
// ErrMissingBoundary is returned by Request.MultipartReader when the
|
||||
|
|
|
|||
|
|
@ -157,6 +157,34 @@ var respTests = []respTest{
|
|||
"Body here\ncontinued",
|
||||
},
|
||||
|
||||
// Trailer header but no TransferEncoding
|
||||
{
|
||||
"HTTP/1.0 200 OK\r\n" +
|
||||
"Trailer: Content-MD5, Content-Sources\r\n" +
|
||||
"Content-Length: 10\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"\r\n" +
|
||||
"Body here\n",
|
||||
|
||||
Response{
|
||||
Status: "200 OK",
|
||||
StatusCode: 200,
|
||||
Proto: "HTTP/1.0",
|
||||
ProtoMajor: 1,
|
||||
ProtoMinor: 0,
|
||||
Request: dummyReq("GET"),
|
||||
Header: Header{
|
||||
"Connection": {"close"},
|
||||
"Content-Length": {"10"},
|
||||
"Trailer": []string{"Content-MD5, Content-Sources"},
|
||||
},
|
||||
Close: true,
|
||||
ContentLength: 10,
|
||||
},
|
||||
|
||||
"Body here\n",
|
||||
},
|
||||
|
||||
// Chunked response with Content-Length.
|
||||
{
|
||||
"HTTP/1.1 200 OK\r\n" +
|
||||
|
|
|
|||
|
|
@ -740,6 +740,16 @@ func fixTrailer(header Header, te []string) (Header, error) {
|
|||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
if !chunked(te) {
|
||||
// Trailer and no chunking:
|
||||
// this is an invalid use case for trailer header.
|
||||
// Nevertheless, no error will be returned and we
|
||||
// let users decide if this is a valid HTTP message.
|
||||
// The Trailer header will be kept in Response.Header
|
||||
// but not populate Response.Trailer.
|
||||
// See issue #27197.
|
||||
return nil, nil
|
||||
}
|
||||
header.Del("Trailer")
|
||||
|
||||
trailer := make(Header)
|
||||
|
|
@ -763,10 +773,6 @@ func fixTrailer(header Header, te []string) (Header, error) {
|
|||
if len(trailer) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
if !chunked(te) {
|
||||
// Trailer and no chunking
|
||||
return nil, ErrUnexpectedTrailer
|
||||
}
|
||||
return trailer, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -266,8 +266,11 @@ func testGdbPython(t *testing.T, cgo bool) {
|
|||
infoLocalsRe1 := regexp.MustCompile(`slicevar *= *\[\]string *= *{"def"}`)
|
||||
// Format output from gdb v8.2
|
||||
infoLocalsRe2 := regexp.MustCompile(`^slicevar = .*\nmapvar = .*\nstrvar = 0x[0-9a-f]+ "abc"`)
|
||||
// Format output from gdb v7.7
|
||||
infoLocalsRe3 := regexp.MustCompile(`^mapvar = .*\nstrvar = "abc"\nslicevar *= *\[\]string`)
|
||||
if bl := blocks["info locals"]; !infoLocalsRe1.MatchString(bl) &&
|
||||
!infoLocalsRe2.MatchString(bl) {
|
||||
!infoLocalsRe2.MatchString(bl) &&
|
||||
!infoLocalsRe3.MatchString(bl) {
|
||||
t.Fatalf("info locals failed: %s", bl)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ func panicmakeslicecap() {
|
|||
panic(errorString("makeslice: cap out of range"))
|
||||
}
|
||||
|
||||
func makeslice(et *_type, len, cap int) slice {
|
||||
func makeslice(et *_type, len, cap int) unsafe.Pointer {
|
||||
mem, overflow := math.MulUintptr(et.size, uintptr(cap))
|
||||
if overflow || mem > maxAlloc || len < 0 || len > cap {
|
||||
// NOTE: Produce a 'len out of range' error instead of a
|
||||
|
|
@ -45,12 +45,11 @@ func makeslice(et *_type, len, cap int) slice {
|
|||
}
|
||||
panicmakeslicecap()
|
||||
}
|
||||
p := mallocgc(mem, et, true)
|
||||
|
||||
return slice{p, len, cap}
|
||||
return mallocgc(mem, et, true)
|
||||
}
|
||||
|
||||
func makeslice64(et *_type, len64, cap64 int64) slice {
|
||||
func makeslice64(et *_type, len64, cap64 int64) unsafe.Pointer {
|
||||
len := int(len64)
|
||||
if int64(len) != len64 {
|
||||
panicmakeslicelen()
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import (
|
|||
// A Reader implements the io.Reader, io.ReaderAt, io.Seeker, io.WriterTo,
|
||||
// io.ByteScanner, and io.RuneScanner interfaces by reading
|
||||
// from a string.
|
||||
// The zero value for Reader operates like a Reader of an empty string.
|
||||
type Reader struct {
|
||||
s string
|
||||
i int64 // current reading index
|
||||
|
|
@ -70,10 +71,10 @@ func (r *Reader) ReadByte() (byte, error) {
|
|||
}
|
||||
|
||||
func (r *Reader) UnreadByte() error {
|
||||
r.prevRune = -1
|
||||
if r.i <= 0 {
|
||||
return errors.New("strings.Reader.UnreadByte: at beginning of string")
|
||||
}
|
||||
r.prevRune = -1
|
||||
r.i--
|
||||
return nil
|
||||
}
|
||||
|
|
@ -94,6 +95,9 @@ func (r *Reader) ReadRune() (ch rune, size int, err error) {
|
|||
}
|
||||
|
||||
func (r *Reader) UnreadRune() error {
|
||||
if r.i <= 0 {
|
||||
return errors.New("strings.Reader.UnreadRune: at beginning of string")
|
||||
}
|
||||
if r.prevRune < 0 {
|
||||
return errors.New("strings.Reader.UnreadRune: previous operation was not ReadRune")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -190,3 +190,45 @@ func TestReaderReset(t *testing.T) {
|
|||
t.Errorf("ReadAll: got %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReaderZero(t *testing.T) {
|
||||
if l := (&strings.Reader{}).Len(); l != 0 {
|
||||
t.Errorf("Len: got %d, want 0", l)
|
||||
}
|
||||
|
||||
if n, err := (&strings.Reader{}).Read(nil); n != 0 || err != io.EOF {
|
||||
t.Errorf("Read: got %d, %v; want 0, io.EOF", n, err)
|
||||
}
|
||||
|
||||
if n, err := (&strings.Reader{}).ReadAt(nil, 11); n != 0 || err != io.EOF {
|
||||
t.Errorf("ReadAt: got %d, %v; want 0, io.EOF", n, err)
|
||||
}
|
||||
|
||||
if b, err := (&strings.Reader{}).ReadByte(); b != 0 || err != io.EOF {
|
||||
t.Errorf("ReadByte: got %d, %v; want 0, io.EOF", b, err)
|
||||
}
|
||||
|
||||
if ch, size, err := (&strings.Reader{}).ReadRune(); ch != 0 || size != 0 || err != io.EOF {
|
||||
t.Errorf("ReadRune: got %d, %d, %v; want 0, 0, io.EOF", ch, size, err)
|
||||
}
|
||||
|
||||
if offset, err := (&strings.Reader{}).Seek(11, io.SeekStart); offset != 11 || err != nil {
|
||||
t.Errorf("Seek: got %d, %v; want 11, nil", offset, err)
|
||||
}
|
||||
|
||||
if s := (&strings.Reader{}).Size(); s != 0 {
|
||||
t.Errorf("Size: got %d, want 0", s)
|
||||
}
|
||||
|
||||
if (&strings.Reader{}).UnreadByte() == nil {
|
||||
t.Errorf("UnreadByte: got nil, want error")
|
||||
}
|
||||
|
||||
if (&strings.Reader{}).UnreadRune() == nil {
|
||||
t.Errorf("UnreadRune: got nil, want error")
|
||||
}
|
||||
|
||||
if n, err := (&strings.Reader{}).WriteTo(ioutil.Discard); n != 0 || err != nil {
|
||||
t.Errorf("WriteTo: got %d, %v; want 0, nil", n, err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ func SubMem(arr []int, b, c, d int) int {
|
|||
arr[d] -= 15
|
||||
// 386:`DECL\s\([A-Z]+\)\([A-Z]+\*4\)`
|
||||
arr[b]--
|
||||
// amd64:`DECQ\s64\([A-Z]+\)`
|
||||
arr[8]--
|
||||
// 386:"SUBL\t4"
|
||||
// amd64:"SUBQ\t8"
|
||||
return arr[0] - arr[1]
|
||||
|
|
|
|||
Loading…
Reference in New Issue