parent
57c7433fdc
commit
9a18821cfc
|
@ -1,4 +1,4 @@
|
||||||
3cdba7b0650c
|
bce220d03774
|
||||||
|
|
||||||
The first line of this file holds the Mercurial revision number of the
|
The first line of this file holds the Mercurial revision number of the
|
||||||
last merge done from the master library sources.
|
last merge done from the master library sources.
|
||||||
|
|
|
@ -7,10 +7,12 @@ package zip
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"encoding/hex"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -62,13 +64,14 @@ var tests = []ZipTest{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "r.zip",
|
Name: "r.zip",
|
||||||
|
Source: returnRecursiveZip,
|
||||||
File: []ZipTestFile{
|
File: []ZipTestFile{
|
||||||
{
|
{
|
||||||
Name: "r/r.zip",
|
Name: "r/r.zip",
|
||||||
File: "r.zip",
|
Content: rZipBytes(),
|
||||||
Mtime: "03-04-10 00:24:16",
|
Mtime: "03-04-10 00:24:16",
|
||||||
Mode: 0666,
|
Mode: 0666,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -415,3 +418,49 @@ func returnCorruptNotStreamedZip() (r io.ReaderAt, size int64) {
|
||||||
// is what matters.
|
// is what matters.
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rZipBytes returns the bytes of a recursive zip file, without
|
||||||
|
// putting it on disk and triggering certain virus scanners.
|
||||||
|
func rZipBytes() []byte {
|
||||||
|
s := `
|
||||||
|
0000000 50 4b 03 04 14 00 00 00 08 00 08 03 64 3c f9 f4
|
||||||
|
0000010 89 64 48 01 00 00 b8 01 00 00 07 00 00 00 72 2f
|
||||||
|
0000020 72 2e 7a 69 70 00 25 00 da ff 50 4b 03 04 14 00
|
||||||
|
0000030 00 00 08 00 08 03 64 3c f9 f4 89 64 48 01 00 00
|
||||||
|
0000040 b8 01 00 00 07 00 00 00 72 2f 72 2e 7a 69 70 00
|
||||||
|
0000050 2f 00 d0 ff 00 25 00 da ff 50 4b 03 04 14 00 00
|
||||||
|
0000060 00 08 00 08 03 64 3c f9 f4 89 64 48 01 00 00 b8
|
||||||
|
0000070 01 00 00 07 00 00 00 72 2f 72 2e 7a 69 70 00 2f
|
||||||
|
0000080 00 d0 ff c2 54 8e 57 39 00 05 00 fa ff c2 54 8e
|
||||||
|
0000090 57 39 00 05 00 fa ff 00 05 00 fa ff 00 14 00 eb
|
||||||
|
00000a0 ff c2 54 8e 57 39 00 05 00 fa ff 00 05 00 fa ff
|
||||||
|
00000b0 00 14 00 eb ff 42 88 21 c4 00 00 14 00 eb ff 42
|
||||||
|
00000c0 88 21 c4 00 00 14 00 eb ff 42 88 21 c4 00 00 14
|
||||||
|
00000d0 00 eb ff 42 88 21 c4 00 00 14 00 eb ff 42 88 21
|
||||||
|
00000e0 c4 00 00 00 00 ff ff 00 00 00 ff ff 00 34 00 cb
|
||||||
|
00000f0 ff 42 88 21 c4 00 00 00 00 ff ff 00 00 00 ff ff
|
||||||
|
0000100 00 34 00 cb ff 42 e8 21 5e 0f 00 00 00 ff ff 0a
|
||||||
|
0000110 f0 66 64 12 61 c0 15 dc e8 a0 48 bf 48 af 2a b3
|
||||||
|
0000120 20 c0 9b 95 0d c4 67 04 42 53 06 06 06 40 00 06
|
||||||
|
0000130 00 f9 ff 6d 01 00 00 00 00 42 e8 21 5e 0f 00 00
|
||||||
|
0000140 00 ff ff 0a f0 66 64 12 61 c0 15 dc e8 a0 48 bf
|
||||||
|
0000150 48 af 2a b3 20 c0 9b 95 0d c4 67 04 42 53 06 06
|
||||||
|
0000160 06 40 00 06 00 f9 ff 6d 01 00 00 00 00 50 4b 01
|
||||||
|
0000170 02 14 00 14 00 00 00 08 00 08 03 64 3c f9 f4 89
|
||||||
|
0000180 64 48 01 00 00 b8 01 00 00 07 00 00 00 00 00 00
|
||||||
|
0000190 00 00 00 00 00 00 00 00 00 00 00 72 2f 72 2e 7a
|
||||||
|
00001a0 69 70 50 4b 05 06 00 00 00 00 01 00 01 00 35 00
|
||||||
|
00001b0 00 00 6d 01 00 00 00 00`
|
||||||
|
s = regexp.MustCompile(`[0-9a-f]{7}`).ReplaceAllString(s, "")
|
||||||
|
s = regexp.MustCompile(`\s+`).ReplaceAllString(s, "")
|
||||||
|
b, err := hex.DecodeString(s)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func returnRecursiveZip() (r io.ReaderAt, size int64) {
|
||||||
|
b := rZipBytes()
|
||||||
|
return bytes.NewReader(b), int64(len(b))
|
||||||
|
}
|
||||||
|
|
|
@ -166,8 +166,11 @@ func (c *Conn) clientHandshake() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var certToSend *Certificate
|
var certToSend *Certificate
|
||||||
|
var certRequested bool
|
||||||
certReq, ok := msg.(*certificateRequestMsg)
|
certReq, ok := msg.(*certificateRequestMsg)
|
||||||
if ok {
|
if ok {
|
||||||
|
certRequested = true
|
||||||
|
|
||||||
// RFC 4346 on the certificateAuthorities field:
|
// RFC 4346 on the certificateAuthorities field:
|
||||||
// A list of the distinguished names of acceptable certificate
|
// A list of the distinguished names of acceptable certificate
|
||||||
// authorities. These distinguished names may specify a desired
|
// authorities. These distinguished names may specify a desired
|
||||||
|
@ -238,9 +241,14 @@ func (c *Conn) clientHandshake() error {
|
||||||
}
|
}
|
||||||
finishedHash.Write(shd.marshal())
|
finishedHash.Write(shd.marshal())
|
||||||
|
|
||||||
if certToSend != nil {
|
// If the server requested a certificate then we have to send a
|
||||||
|
// Certificate message, even if it's empty because we don't have a
|
||||||
|
// certificate to send.
|
||||||
|
if certRequested {
|
||||||
certMsg = new(certificateMsg)
|
certMsg = new(certificateMsg)
|
||||||
certMsg.certificates = certToSend.Certificate
|
if certToSend != nil {
|
||||||
|
certMsg.certificates = certToSend.Certificate
|
||||||
|
}
|
||||||
finishedHash.Write(certMsg.marshal())
|
finishedHash.Write(certMsg.marshal())
|
||||||
c.writeRecord(recordTypeHandshake, certMsg.marshal())
|
c.writeRecord(recordTypeHandshake, certMsg.marshal())
|
||||||
}
|
}
|
||||||
|
|
|
@ -226,7 +226,7 @@ where * signifies zero or more repetitions and the type id of a value must
|
||||||
be predefined or be defined before the value in the stream.
|
be predefined or be defined before the value in the stream.
|
||||||
|
|
||||||
See "Gobs of data" for a design discussion of the gob wire format:
|
See "Gobs of data" for a design discussion of the gob wire format:
|
||||||
http://blog.golang.org/2011/03/gobs-of-data.html
|
http://golang.org/doc/articles/gobs_of_data.html
|
||||||
*/
|
*/
|
||||||
package gob
|
package gob
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
// RFC 4627.
|
// RFC 4627.
|
||||||
//
|
//
|
||||||
// See "JSON and Go" for an introduction to this package:
|
// See "JSON and Go" for an introduction to this package:
|
||||||
// http://blog.golang.org/2011/01/json-and-go.html
|
// http://golang.org/doc/articles/json_and_go.html
|
||||||
package json
|
package json
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -356,7 +356,7 @@ func lastBoundary(fd *formInfo, b []byte) int {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
if info.size == 0 { // ends with incomplete rune
|
if info.size == 0 { // ends with incomplete rune
|
||||||
if p == 0 { // starts wtih incomplete rune
|
if p == 0 { // starts with incomplete rune
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
i = p
|
i = p
|
||||||
|
|
|
@ -102,11 +102,6 @@ func init() {
|
||||||
defType("Pointer")
|
defType("Pointer")
|
||||||
|
|
||||||
defFun("Alignof")
|
defFun("Alignof")
|
||||||
defFun("New")
|
|
||||||
defFun("NewArray")
|
|
||||||
defFun("Offsetof")
|
defFun("Offsetof")
|
||||||
defFun("Reflect")
|
|
||||||
defFun("Sizeof")
|
defFun("Sizeof")
|
||||||
defFun("Typeof")
|
|
||||||
defFun("Unreflect")
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// These examples demonstrate more intricate uses of the flag package.
|
||||||
|
package flag_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Example 1: A single string flag called "species" with default value "gopher".
|
||||||
|
var species = flag.String("species", "gopher", "the species we are studying")
|
||||||
|
|
||||||
|
// Example 2: Two flags sharing a variable, so we can have a shorthand.
|
||||||
|
// The order of initialization is undefined, so make sure both use the
|
||||||
|
// same default value. They must be set up with an init function.
|
||||||
|
var gopherType string
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
const (
|
||||||
|
defaultGopher = "pocket"
|
||||||
|
usage = "the variety of gopher"
|
||||||
|
)
|
||||||
|
flag.StringVar(&gopherType, "gopher_type", defaultGopher, usage)
|
||||||
|
flag.StringVar(&gopherType, "g", defaultGopher, usage+" (shorthand)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example 3: A user-defined flag type, a slice of durations.
|
||||||
|
type interval []time.Duration
|
||||||
|
|
||||||
|
// String is the method to format the flag's value, part of the flag.Value interface.
|
||||||
|
// The String method's output will be used in diagnostics.
|
||||||
|
func (i *interval) String() string {
|
||||||
|
return fmt.Sprint(*i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set is the method to set the flag value, part of the flag.Value interface.
|
||||||
|
// Set's argument is a string to be parsed to set the flag.
|
||||||
|
// It's a comma-separated list, so we split it.
|
||||||
|
func (i *interval) Set(value string) error {
|
||||||
|
// If we wanted to allow the flag to be set multiple times,
|
||||||
|
// accumulating values, we would delete this if statement.
|
||||||
|
// That would permit usages such as
|
||||||
|
// -deltaT 10s -deltaT 15s
|
||||||
|
// and other combinations.
|
||||||
|
if len(*i) > 0 {
|
||||||
|
return errors.New("interval flag already set")
|
||||||
|
}
|
||||||
|
for _, dt := range strings.Split(value, ",") {
|
||||||
|
duration, err := time.ParseDuration(dt)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*i = append(*i, duration)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define a flag to accumulate durations. Because it has a special type,
|
||||||
|
// we need to use the Var function and therefore create the flag during
|
||||||
|
// init.
|
||||||
|
|
||||||
|
var intervalFlag interval
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// Tie the command-line flag to the intervalFlag variable and
|
||||||
|
// set a usage message.
|
||||||
|
flag.Var(&intervalFlag, "deltaT", "comma-separated list of intervals to use between events")
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example() {
|
||||||
|
// All the interesting pieces are with the variables declared above, but
|
||||||
|
// to enable the flag package to see the flags defined there, one must
|
||||||
|
// execute, typically at the start of main (not init!):
|
||||||
|
// flag.Parse()
|
||||||
|
// We don't run it here because this is not a main function and
|
||||||
|
// the testing suite has already parsed the flags.
|
||||||
|
}
|
|
@ -810,7 +810,7 @@ func TestMultiLine(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RecursiveInt accepts an string matching %d.%d.%d....
|
// RecursiveInt accepts a string matching %d.%d.%d....
|
||||||
// and parses it into a linked list.
|
// and parses it into a linked list.
|
||||||
// It allows us to benchmark recursive descent style scanners.
|
// It allows us to benchmark recursive descent style scanners.
|
||||||
type RecursiveInt struct {
|
type RecursiveInt struct {
|
||||||
|
@ -826,7 +826,7 @@ func (r *RecursiveInt) Scan(state ScanState, verb rune) (err error) {
|
||||||
next := new(RecursiveInt)
|
next := new(RecursiveInt)
|
||||||
_, err = Fscanf(state, ".%v", next)
|
_, err = Fscanf(state, ".%v", next)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == errors.New("input does not match format") || err == io.ErrUnexpectedEOF {
|
if err == io.ErrUnexpectedEOF {
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
|
@ -328,22 +328,22 @@ func (e *NoGoError) Error() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import returns details about the Go package named by the import path,
|
// Import returns details about the Go package named by the import path,
|
||||||
// interpreting local import paths relative to the src directory. If the path
|
// interpreting local import paths relative to the srcDir directory.
|
||||||
// is a local import path naming a package that can be imported using a
|
// If the path is a local import path naming a package that can be imported
|
||||||
// standard import path, the returned package will set p.ImportPath to
|
// using a standard import path, the returned package will set p.ImportPath
|
||||||
// that path.
|
// to that path.
|
||||||
//
|
//
|
||||||
// In the directory containing the package, .go, .c, .h, and .s files are
|
// In the directory containing the package, .go, .c, .h, and .s files are
|
||||||
// considered part of the package except for:
|
// considered part of the package except for:
|
||||||
//
|
//
|
||||||
// - .go files in package documentation
|
// - .go files in package documentation
|
||||||
// - files starting with _ or .
|
// - files starting with _ or . (likely editor temporary files)
|
||||||
// - files with build constraints not satisfied by the context
|
// - files with build constraints not satisfied by the context
|
||||||
//
|
//
|
||||||
// If an error occurs, Import returns a non-nil error also returns a non-nil
|
// If an error occurs, Import returns a non-nil error also returns a non-nil
|
||||||
// *Package containing partial information.
|
// *Package containing partial information.
|
||||||
//
|
//
|
||||||
func (ctxt *Context) Import(path string, src string, mode ImportMode) (*Package, error) {
|
func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Package, error) {
|
||||||
p := &Package{
|
p := &Package{
|
||||||
ImportPath: path,
|
ImportPath: path,
|
||||||
}
|
}
|
||||||
|
@ -363,11 +363,12 @@ func (ctxt *Context) Import(path string, src string, mode ImportMode) (*Package,
|
||||||
|
|
||||||
binaryOnly := false
|
binaryOnly := false
|
||||||
if IsLocalImport(path) {
|
if IsLocalImport(path) {
|
||||||
if src == "" {
|
pkga = "" // local imports have no installed path
|
||||||
|
if srcDir == "" {
|
||||||
return p, fmt.Errorf("import %q: import relative to unknown directory", path)
|
return p, fmt.Errorf("import %q: import relative to unknown directory", path)
|
||||||
}
|
}
|
||||||
if !ctxt.isAbsPath(path) {
|
if !ctxt.isAbsPath(path) {
|
||||||
p.Dir = ctxt.joinPath(src, path)
|
p.Dir = ctxt.joinPath(srcDir, path)
|
||||||
}
|
}
|
||||||
// Determine canonical import path, if any.
|
// Determine canonical import path, if any.
|
||||||
if ctxt.GOROOT != "" {
|
if ctxt.GOROOT != "" {
|
||||||
|
@ -640,8 +641,8 @@ func cleanImports(m map[string][]token.Position) ([]string, map[string][]token.P
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import is shorthand for Default.Import.
|
// Import is shorthand for Default.Import.
|
||||||
func Import(path, src string, mode ImportMode) (*Package, error) {
|
func Import(path, srcDir string, mode ImportMode) (*Package, error) {
|
||||||
return Default.Import(path, src, mode)
|
return Default.Import(path, srcDir, mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImportDir is shorthand for Default.ImportDir.
|
// ImportDir is shorthand for Default.ImportDir.
|
||||||
|
@ -874,7 +875,7 @@ func splitQuoted(s string) (r []string, err error) {
|
||||||
// !cgo (if cgo is disabled)
|
// !cgo (if cgo is disabled)
|
||||||
// tag (if tag is listed in ctxt.BuildTags)
|
// tag (if tag is listed in ctxt.BuildTags)
|
||||||
// !tag (if tag is not listed in ctxt.BuildTags)
|
// !tag (if tag is not listed in ctxt.BuildTags)
|
||||||
// a slash-separated list of any of these
|
// a comma-separated list of any of these
|
||||||
//
|
//
|
||||||
func (ctxt *Context) match(name string) bool {
|
func (ctxt *Context) match(name string) bool {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
|
@ -888,11 +889,11 @@ func (ctxt *Context) match(name string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(name, "!") { // negation
|
if strings.HasPrefix(name, "!") { // negation
|
||||||
return !ctxt.match(name[1:])
|
return len(name) > 1 && !ctxt.match(name[1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tags must be letters, digits, underscores.
|
// Tags must be letters, digits, underscores.
|
||||||
// Unlike in Go identifiers, all digits is fine (e.g., "386").
|
// Unlike in Go identifiers, all digits are fine (e.g., "386").
|
||||||
for _, c := range name {
|
for _, c := range name {
|
||||||
if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' {
|
if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' {
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -36,6 +36,7 @@ func TestMatch(t *testing.T) {
|
||||||
nomatch(runtime.GOOS + "," + runtime.GOARCH + ",!foo")
|
nomatch(runtime.GOOS + "," + runtime.GOARCH + ",!foo")
|
||||||
match(runtime.GOOS + "," + runtime.GOARCH + ",!bar")
|
match(runtime.GOOS + "," + runtime.GOARCH + ",!bar")
|
||||||
nomatch(runtime.GOOS + "," + runtime.GOARCH + ",bar")
|
nomatch(runtime.GOOS + "," + runtime.GOARCH + ",bar")
|
||||||
|
nomatch("!")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDotSlashImport(t *testing.T) {
|
func TestDotSlashImport(t *testing.T) {
|
||||||
|
|
|
@ -365,7 +365,7 @@ func (p *printer) setLineComment(text string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *printer) isMultiLine(n ast.Node) bool {
|
func (p *printer) isMultiLine(n ast.Node) bool {
|
||||||
return p.lineFor(n.End())-p.lineFor(n.Pos()) > 1
|
return p.lineFor(n.End())-p.lineFor(n.Pos()) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) {
|
func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) {
|
||||||
|
|
|
@ -500,7 +500,7 @@ type _ struct {
|
||||||
|
|
||||||
type _ struct {
|
type _ struct {
|
||||||
a, b,
|
a, b,
|
||||||
c, d int // this line should be indented
|
c, d int // this line should be indented
|
||||||
u, v, w, x float // this line should be indented
|
u, v, w, x float // this line should be indented
|
||||||
p, q,
|
p, q,
|
||||||
r, s float // this line should be indented
|
r, s float // this line should be indented
|
||||||
|
@ -562,10 +562,21 @@ var a2, b2,
|
||||||
|
|
||||||
var (
|
var (
|
||||||
a3, b3,
|
a3, b3,
|
||||||
c3, d3 int // this line should be indented
|
c3, d3 int // this line should be indented
|
||||||
a4, b4, c4 int // this line should be indented
|
a4, b4, c4 int // this line should be indented
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Test case from issue 3304: multi-line declarations must end
|
||||||
|
// a formatting section and not influence indentation of the
|
||||||
|
// next line.
|
||||||
|
var (
|
||||||
|
minRefreshTimeSec = flag.Int64("min_refresh_time_sec", 604800,
|
||||||
|
"minimum time window between two refreshes for a given user.")
|
||||||
|
x = flag.Int64("refresh_user_rollout_percent", 100,
|
||||||
|
"temporary flag to ramp up the refresh user rpc")
|
||||||
|
aVeryLongVariableName = stats.GetVarInt("refresh-user-count")
|
||||||
|
)
|
||||||
|
|
||||||
func _() {
|
func _() {
|
||||||
var privateKey2 = &Block{Type: "RSA PRIVATE KEY",
|
var privateKey2 = &Block{Type: "RSA PRIVATE KEY",
|
||||||
Headers: map[string]string{},
|
Headers: map[string]string{},
|
||||||
|
|
|
@ -577,6 +577,16 @@ c3, d3 int // this line should be indented
|
||||||
a4, b4, c4 int // this line should be indented
|
a4, b4, c4 int // this line should be indented
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Test case from issue 3304: multi-line declarations must end
|
||||||
|
// a formatting section and not influence indentation of the
|
||||||
|
// next line.
|
||||||
|
var (
|
||||||
|
minRefreshTimeSec = flag.Int64("min_refresh_time_sec", 604800,
|
||||||
|
"minimum time window between two refreshes for a given user.")
|
||||||
|
x = flag.Int64("refresh_user_rollout_percent", 100,
|
||||||
|
"temporary flag to ramp up the refresh user rpc")
|
||||||
|
aVeryLongVariableName = stats.GetVarInt("refresh-user-count")
|
||||||
|
)
|
||||||
|
|
||||||
func _() {
|
func _() {
|
||||||
var privateKey2 = &Block{Type: "RSA PRIVATE KEY",
|
var privateKey2 = &Block{Type: "RSA PRIVATE KEY",
|
||||||
|
|
|
@ -113,3 +113,36 @@ func TestClone(t *testing.T) {
|
||||||
t.Errorf("t3: got %q want %q", got, want)
|
t.Errorf("t3: got %q want %q", got, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTemplates(t *testing.T) {
|
||||||
|
names := []string{"t0", "a", "lhs", "rhs"}
|
||||||
|
// Some template definitions borrowed from TestClone.
|
||||||
|
const tmpl = `
|
||||||
|
{{define "a"}}{{template "lhs"}}{{.}}{{template "rhs"}}{{end}}
|
||||||
|
{{define "lhs"}} <a href=" {{end}}
|
||||||
|
{{define "rhs"}} "></a> {{end}}`
|
||||||
|
t0 := Must(New("t0").Parse(tmpl))
|
||||||
|
templates := t0.Templates()
|
||||||
|
if len(templates) != len(names) {
|
||||||
|
t.Errorf("expected %d templates; got %d", len(names), len(templates))
|
||||||
|
}
|
||||||
|
for _, name := range names {
|
||||||
|
found := false
|
||||||
|
for _, tmpl := range templates {
|
||||||
|
if name == tmpl.text.Name() {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
t.Error("could not find template", name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This used to crash; http://golang.org/issue/3281
|
||||||
|
func TestCloneCrash(t *testing.T) {
|
||||||
|
t1 := New("all")
|
||||||
|
Must(t1.New("t1").Parse(`{{define "foo"}}foo{{end}}`))
|
||||||
|
t1.Clone()
|
||||||
|
}
|
||||||
|
|
|
@ -26,10 +26,10 @@ type (
|
||||||
HTML string
|
HTML string
|
||||||
|
|
||||||
// HTMLAttr encapsulates an HTML attribute from a trusted source,
|
// HTMLAttr encapsulates an HTML attribute from a trusted source,
|
||||||
// for example: ` dir="ltr"`.
|
// for example, ` dir="ltr"`.
|
||||||
HTMLAttr string
|
HTMLAttr string
|
||||||
|
|
||||||
// JS encapsulates a known safe EcmaScript5 Expression, or example,
|
// JS encapsulates a known safe EcmaScript5 Expression, for example,
|
||||||
// `(x + y * z())`.
|
// `(x + y * z())`.
|
||||||
// Template authors are responsible for ensuring that typed expressions
|
// Template authors are responsible for ensuring that typed expressions
|
||||||
// do not break the intended precedence and that there is no
|
// do not break the intended precedence and that there is no
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html"
|
"html"
|
||||||
|
"io"
|
||||||
"text/template"
|
"text/template"
|
||||||
"text/template/parse"
|
"text/template/parse"
|
||||||
)
|
)
|
||||||
|
@ -751,3 +752,44 @@ func (e *escaper) template(name string) *template.Template {
|
||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Forwarding functions so that clients need only import this package
|
||||||
|
// to reach the general escaping functions of text/template.
|
||||||
|
|
||||||
|
// HTMLEscape writes to w the escaped HTML equivalent of the plain text data b.
|
||||||
|
func HTMLEscape(w io.Writer, b []byte) {
|
||||||
|
template.HTMLEscape(w, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTMLEscapeString returns the escaped HTML equivalent of the plain text data s.
|
||||||
|
func HTMLEscapeString(s string) string {
|
||||||
|
return template.HTMLEscapeString(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTMLEscaper returns the escaped HTML equivalent of the textual
|
||||||
|
// representation of its arguments.
|
||||||
|
func HTMLEscaper(args ...interface{}) string {
|
||||||
|
return template.HTMLEscaper(args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSEscape writes to w the escaped JavaScript equivalent of the plain text data b.
|
||||||
|
func JSEscape(w io.Writer, b []byte) {
|
||||||
|
template.JSEscape(w, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSEscapeString returns the escaped JavaScript equivalent of the plain text data s.
|
||||||
|
func JSEscapeString(s string) string {
|
||||||
|
return template.JSEscapeString(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSEscaper returns the escaped JavaScript equivalent of the textual
|
||||||
|
// representation of its arguments.
|
||||||
|
func JSEscaper(args ...interface{}) string {
|
||||||
|
return template.JSEscaper(args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// URLQueryEscaper returns the escaped value of the textual representation of
|
||||||
|
// its arguments in a form suitable for embedding in a URL query.
|
||||||
|
func URLQueryEscaper(args ...interface{}) string {
|
||||||
|
return template.URLQueryEscaper(args...)
|
||||||
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
@ -1637,6 +1638,14 @@ func TestIndirectPrint(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is a test for issue 3272.
|
||||||
|
func TestEmptyTemplate(t *testing.T) {
|
||||||
|
page := Must(New("page").ParseFiles(os.DevNull))
|
||||||
|
if err := page.ExecuteTemplate(os.Stdout, "page", "nothing"); err == nil {
|
||||||
|
t.Fatal("expected error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkEscapedExecute(b *testing.B) {
|
func BenchmarkEscapedExecute(b *testing.B) {
|
||||||
tmpl := Must(New("t").Parse(`<a onclick="alert('{{.}}')">{{.}}</a>`))
|
tmpl := Must(New("t").Parse(`<a onclick="alert('{{.}}')">{{.}}</a>`))
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
|
@ -31,6 +31,20 @@ type nameSpace struct {
|
||||||
set map[string]*Template
|
set map[string]*Template
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Templates returns a slice of the templates associated with t, including t
|
||||||
|
// itself.
|
||||||
|
func (t *Template) Templates() []*Template {
|
||||||
|
ns := t.nameSpace
|
||||||
|
ns.mu.Lock()
|
||||||
|
defer ns.mu.Unlock()
|
||||||
|
// Return a slice so we don't expose the map.
|
||||||
|
m := make([]*Template, 0, len(ns.set))
|
||||||
|
for _, v := range ns.set {
|
||||||
|
m = append(m, v)
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
// Execute applies a parsed template to the specified data object,
|
// Execute applies a parsed template to the specified data object,
|
||||||
// writing the output to wr.
|
// writing the output to wr.
|
||||||
func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
|
func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
|
||||||
|
@ -64,7 +78,13 @@ func (t *Template) lookupAndEscapeTemplate(name string) (tmpl *Template, err err
|
||||||
t.nameSpace.mu.Lock()
|
t.nameSpace.mu.Lock()
|
||||||
defer t.nameSpace.mu.Unlock()
|
defer t.nameSpace.mu.Unlock()
|
||||||
tmpl = t.set[name]
|
tmpl = t.set[name]
|
||||||
if (tmpl == nil) != (t.text.Lookup(name) == nil) {
|
if tmpl == nil {
|
||||||
|
return nil, fmt.Errorf("html/template: %q is undefined", name)
|
||||||
|
}
|
||||||
|
if tmpl.text.Tree == nil || tmpl.text.Root == nil {
|
||||||
|
return nil, fmt.Errorf("html/template: %q is an incomplete template", name)
|
||||||
|
}
|
||||||
|
if t.text.Lookup(name) == nil {
|
||||||
panic("html/template internal error: template escaping out of sync")
|
panic("html/template internal error: template escaping out of sync")
|
||||||
}
|
}
|
||||||
if tmpl != nil && !tmpl.escaped {
|
if tmpl != nil && !tmpl.escaped {
|
||||||
|
@ -160,9 +180,11 @@ func (t *Template) Clone() (*Template, error) {
|
||||||
if src == nil || src.escaped {
|
if src == nil || src.escaped {
|
||||||
return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name())
|
return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name())
|
||||||
}
|
}
|
||||||
x.Tree = &parse.Tree{
|
if x.Tree != nil {
|
||||||
Name: x.Tree.Name,
|
x.Tree = &parse.Tree{
|
||||||
Root: x.Tree.Root.CopyList(),
|
Name: x.Tree.Name,
|
||||||
|
Root: x.Tree.Root.CopyList(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ret.set[name] = &Template{
|
ret.set[name] = &Template{
|
||||||
false,
|
false,
|
||||||
|
@ -274,7 +296,7 @@ func (t *Template) ParseFiles(filenames ...string) (*Template, error) {
|
||||||
func parseFiles(t *Template, filenames ...string) (*Template, error) {
|
func parseFiles(t *Template, filenames ...string) (*Template, error) {
|
||||||
if len(filenames) == 0 {
|
if len(filenames) == 0 {
|
||||||
// Not really a problem, but be consistent.
|
// Not really a problem, but be consistent.
|
||||||
return nil, fmt.Errorf("template: no files named in call to ParseFiles")
|
return nil, fmt.Errorf("html/template: no files named in call to ParseFiles")
|
||||||
}
|
}
|
||||||
for _, filename := range filenames {
|
for _, filename := range filenames {
|
||||||
b, err := ioutil.ReadFile(filename)
|
b, err := ioutil.ReadFile(filename)
|
||||||
|
@ -331,7 +353,7 @@ func parseGlob(t *Template, pattern string) (*Template, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(filenames) == 0 {
|
if len(filenames) == 0 {
|
||||||
return nil, fmt.Errorf("template: pattern matches no files: %#q", pattern)
|
return nil, fmt.Errorf("html/template: pattern matches no files: %#q", pattern)
|
||||||
}
|
}
|
||||||
return parseFiles(t, filenames...)
|
return parseFiles(t, filenames...)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
// Package draw provides image composition functions.
|
// Package draw provides image composition functions.
|
||||||
//
|
//
|
||||||
// See "The Go image/draw package" for an introduction to this package:
|
// See "The Go image/draw package" for an introduction to this package:
|
||||||
// http://blog.golang.org/2011/09/go-imagedraw-package.html
|
// http://golang.org/doc/articles/image_draw.html
|
||||||
package draw
|
package draw
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
// Consecutive groups of suffixes in sa are labeled as sorted groups or
|
// Consecutive groups of suffixes in sa are labeled as sorted groups or
|
||||||
// unsorted groups. For a given pass of the sorter, all suffixes are ordered
|
// unsorted groups. For a given pass of the sorter, all suffixes are ordered
|
||||||
// up to their first h characters, and sa is h-ordered. Suffixes in their
|
// up to their first h characters, and sa is h-ordered. Suffixes in their
|
||||||
// final positions and unambiguouly sorted in h-order are in a sorted group.
|
// final positions and unambiguously sorted in h-order are in a sorted group.
|
||||||
// Consecutive groups of suffixes with identical first h characters are an
|
// Consecutive groups of suffixes with identical first h characters are an
|
||||||
// unsorted group. In each pass of the algorithm, unsorted groups are sorted
|
// unsorted group. In each pass of the algorithm, unsorted groups are sorted
|
||||||
// according to the group number of their following suffix.
|
// according to the group number of their following suffix.
|
||||||
|
@ -78,7 +78,7 @@ func sortedByFirstByte(data []byte) []int {
|
||||||
for _, b := range data {
|
for _, b := range data {
|
||||||
count[b]++
|
count[b]++
|
||||||
}
|
}
|
||||||
// make count[b] equal index of first occurence of b in sorted array
|
// make count[b] equal index of first occurrence of b in sorted array
|
||||||
sum := 0
|
sum := 0
|
||||||
for b := range count {
|
for b := range count {
|
||||||
count[b], sum = sum, count[b]+sum
|
count[b], sum = sum, count[b]+sum
|
||||||
|
|
|
@ -53,10 +53,13 @@ func ReadFile(filename string) ([]byte, error) {
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
// It's a good but not certain bet that FileInfo will tell us exactly how much to
|
// It's a good but not certain bet that FileInfo will tell us exactly how much to
|
||||||
// read, so let's try it but be prepared for the answer to be wrong.
|
// read, so let's try it but be prepared for the answer to be wrong.
|
||||||
fi, err := f.Stat()
|
|
||||||
var n int64
|
var n int64
|
||||||
if size := fi.Size(); err == nil && size < 2e9 { // Don't preallocate a huge buffer, just in case.
|
|
||||||
n = size
|
if fi, err := f.Stat(); err == nil {
|
||||||
|
// Don't preallocate a huge buffer, just in case.
|
||||||
|
if size := fi.Size(); size < 1e9 {
|
||||||
|
n = size
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// As initial capacity for readAll, use n + a little extra in case Size is zero,
|
// As initial capacity for readAll, use n + a little extra in case Size is zero,
|
||||||
// and to avoid another allocation after Read has filled the buffer. The readAll
|
// and to avoid another allocation after Read has filled the buffer. The readAll
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
// 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 syslog provides a simple interface to the system log service.
|
||||||
|
package syslog
|
||||||
|
|
||||||
|
// BUG(brainman): This package is not implemented on Windows yet.
|
|
@ -826,7 +826,7 @@ func (x nat) string(charset string) string {
|
||||||
// iterative approach. This threshold is represented by leafSize. Benchmarking of leafSize in the
|
// iterative approach. This threshold is represented by leafSize. Benchmarking of leafSize in the
|
||||||
// range 2..64 shows that values of 8 and 16 work well, with a 4x speedup at medium lengths and
|
// range 2..64 shows that values of 8 and 16 work well, with a 4x speedup at medium lengths and
|
||||||
// ~30x for 20000 digits. Use nat_test.go's BenchmarkLeafSize tests to optimize leafSize for
|
// ~30x for 20000 digits. Use nat_test.go's BenchmarkLeafSize tests to optimize leafSize for
|
||||||
// specfic hardware.
|
// specific hardware.
|
||||||
//
|
//
|
||||||
func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word, table []divisor) {
|
func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word, table []divisor) {
|
||||||
// split larger blocks recursively
|
// split larger blocks recursively
|
||||||
|
|
|
@ -248,7 +248,7 @@ func Erf(x float64) float64 {
|
||||||
R = rb0 + s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+s*rb6)))))
|
R = rb0 + s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+s*rb6)))))
|
||||||
S = 1 + s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(sb5+s*(sb6+s*sb7))))))
|
S = 1 + s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(sb5+s*(sb6+s*sb7))))))
|
||||||
}
|
}
|
||||||
z := Float64frombits(Float64bits(x) & 0xffffffff00000000) // pseudo-single (20-bit) precison x
|
z := Float64frombits(Float64bits(x) & 0xffffffff00000000) // pseudo-single (20-bit) precision x
|
||||||
r := Exp(-z*z-0.5625) * Exp((z-x)*(z+x)+R/S)
|
r := Exp(-z*z-0.5625) * Exp((z-x)*(z+x)+R/S)
|
||||||
if sign {
|
if sign {
|
||||||
return r/x - 1
|
return r/x - 1
|
||||||
|
@ -321,7 +321,7 @@ func Erfc(x float64) float64 {
|
||||||
R = rb0 + s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+s*rb6)))))
|
R = rb0 + s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+s*rb6)))))
|
||||||
S = 1 + s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(sb5+s*(sb6+s*sb7))))))
|
S = 1 + s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(sb5+s*(sb6+s*sb7))))))
|
||||||
}
|
}
|
||||||
z := Float64frombits(Float64bits(x) & 0xffffffff00000000) // pseudo-single (20-bit) precison x
|
z := Float64frombits(Float64bits(x) & 0xffffffff00000000) // pseudo-single (20-bit) precision x
|
||||||
r := Exp(-z*z-0.5625) * Exp((z-x)*(z+x)+R/S)
|
r := Exp(-z*z-0.5625) * Exp((z-x)*(z+x)+R/S)
|
||||||
if sign {
|
if sign {
|
||||||
return 2 - r/x
|
return 2 - r/x
|
||||||
|
|
|
@ -15,7 +15,9 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// hello world, the web server
|
// hello world, the web server
|
||||||
|
@ -28,14 +30,21 @@ func HelloServer(w http.ResponseWriter, req *http.Request) {
|
||||||
|
|
||||||
// Simple counter server. POSTing to it will set the value.
|
// Simple counter server. POSTing to it will set the value.
|
||||||
type Counter struct {
|
type Counter struct {
|
||||||
n int
|
mu sync.Mutex // protects n
|
||||||
|
n int
|
||||||
}
|
}
|
||||||
|
|
||||||
// This makes Counter satisfy the expvar.Var interface, so we can export
|
// This makes Counter satisfy the expvar.Var interface, so we can export
|
||||||
// it directly.
|
// it directly.
|
||||||
func (ctr *Counter) String() string { return fmt.Sprintf("%d", ctr.n) }
|
func (ctr *Counter) String() string {
|
||||||
|
ctr.mu.Lock()
|
||||||
|
defer ctr.mu.Unlock()
|
||||||
|
return fmt.Sprintf("%d", ctr.n)
|
||||||
|
}
|
||||||
|
|
||||||
func (ctr *Counter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
func (ctr *Counter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
|
ctr.mu.Lock()
|
||||||
|
defer ctr.mu.Unlock()
|
||||||
switch req.Method {
|
switch req.Method {
|
||||||
case "GET":
|
case "GET":
|
||||||
ctr.n++
|
ctr.n++
|
||||||
|
@ -95,54 +104,36 @@ func (ch Chan) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
// exec a program, redirecting output
|
// exec a program, redirecting output
|
||||||
func DateServer(rw http.ResponseWriter, req *http.Request) {
|
func DateServer(rw http.ResponseWriter, req *http.Request) {
|
||||||
rw.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
rw.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||||
r, w, err := os.Pipe()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(rw, "pipe: %s\n", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
p, err := os.StartProcess("/bin/date", []string{"date"}, &os.ProcAttr{Files: []*os.File{nil, w, w}})
|
date, err := exec.Command("/bin/date").Output()
|
||||||
defer r.Close()
|
|
||||||
w.Close()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(rw, "fork/exec: %s\n", err)
|
http.Error(rw, err.Error(), 500)
|
||||||
return
|
|
||||||
}
|
|
||||||
io.Copy(rw, r)
|
|
||||||
wait, err := p.Wait(0)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(rw, "wait: %s\n", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !wait.Exited() || wait.ExitStatus() != 0 {
|
|
||||||
fmt.Fprintf(rw, "date: %v\n", wait)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
rw.Write(date)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Logger(w http.ResponseWriter, req *http.Request) {
|
func Logger(w http.ResponseWriter, req *http.Request) {
|
||||||
log.Print(req.URL.Raw)
|
log.Print(req.URL)
|
||||||
w.WriteHeader(404)
|
http.Error(w, "oops", 404)
|
||||||
w.Write([]byte("oops"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var webroot = flag.String("root", "/home/rsc", "web root directory")
|
var webroot = flag.String("root", os.Getenv("HOME"), "web root directory")
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
// The counter is published as a variable directly.
|
// The counter is published as a variable directly.
|
||||||
ctr := new(Counter)
|
ctr := new(Counter)
|
||||||
http.Handle("/counter", ctr)
|
|
||||||
expvar.Publish("counter", ctr)
|
expvar.Publish("counter", ctr)
|
||||||
|
http.Handle("/counter", ctr)
|
||||||
http.Handle("/", http.HandlerFunc(Logger))
|
http.Handle("/", http.HandlerFunc(Logger))
|
||||||
http.Handle("/go/", http.StripPrefix("/go/", http.FileServer(http.Dir(*webroot))))
|
http.Handle("/go/", http.StripPrefix("/go/", http.FileServer(http.Dir(*webroot))))
|
||||||
http.Handle("/flags", http.HandlerFunc(FlagServer))
|
|
||||||
http.Handle("/args", http.HandlerFunc(ArgServer))
|
|
||||||
http.Handle("/go/hello", http.HandlerFunc(HelloServer))
|
|
||||||
http.Handle("/chan", ChanCreate())
|
http.Handle("/chan", ChanCreate())
|
||||||
http.Handle("/date", http.HandlerFunc(DateServer))
|
http.HandleFunc("/flags", FlagServer)
|
||||||
|
http.HandleFunc("/args", ArgServer)
|
||||||
|
http.HandleFunc("/go/hello", HelloServer)
|
||||||
|
http.HandleFunc("/date", DateServer)
|
||||||
err := http.ListenAndServe(":12345", nil)
|
err := http.ListenAndServe(":12345", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicln("ListenAndServe:", err)
|
log.Panicln("ListenAndServe:", err)
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// If the ifindex is zero, interfaceTable returns mappings of all
|
// If the ifindex is zero, interfaceTable returns mappings of all
|
||||||
// network interfaces. Otheriwse it returns a mapping of a specific
|
// network interfaces. Otherwise it returns a mapping of a specific
|
||||||
// interface.
|
// interface.
|
||||||
func interfaceTable(ifindex int) ([]Interface, error) {
|
func interfaceTable(ifindex int) ([]Interface, error) {
|
||||||
tab, err := syscall.NetlinkRIB(syscall.RTM_GETLINK, syscall.AF_UNSPEC)
|
tab, err := syscall.NetlinkRIB(syscall.RTM_GETLINK, syscall.AF_UNSPEC)
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
package net
|
package net
|
||||||
|
|
||||||
// If the ifindex is zero, interfaceTable returns mappings of all
|
// If the ifindex is zero, interfaceTable returns mappings of all
|
||||||
// network interfaces. Otheriwse it returns a mapping of a specific
|
// network interfaces. Otherwise it returns a mapping of a specific
|
||||||
// interface.
|
// interface.
|
||||||
func interfaceTable(ifindex int) ([]Interface, error) {
|
func interfaceTable(ifindex int) ([]Interface, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
|
@ -56,7 +56,7 @@ func getInterfaceList() ([]syscall.InterfaceInfo, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the ifindex is zero, interfaceTable returns mappings of all
|
// If the ifindex is zero, interfaceTable returns mappings of all
|
||||||
// network interfaces. Otheriwse it returns a mapping of a specific
|
// network interfaces. Otherwise it returns a mapping of a specific
|
||||||
// interface.
|
// interface.
|
||||||
func interfaceTable(ifindex int) ([]Interface, error) {
|
func interfaceTable(ifindex int) ([]Interface, error) {
|
||||||
ai, err := getAdapterList()
|
ai, err := getAdapterList()
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
package net
|
package net
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -67,7 +66,7 @@ func TestTCPListener(t *testing.T) {
|
||||||
case syscall.AF_INET6:
|
case syscall.AF_INET6:
|
||||||
testIPv6UnicastSocketOptions(t, fd)
|
testIPv6UnicastSocketOptions(t, fd)
|
||||||
}
|
}
|
||||||
l1.(io.Closer).Close()
|
l1.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +111,7 @@ func TestUDPListener(t *testing.T) {
|
||||||
case syscall.AF_INET6:
|
case syscall.AF_INET6:
|
||||||
testIPv6UnicastSocketOptions(t, fd)
|
testIPv6UnicastSocketOptions(t, fd)
|
||||||
}
|
}
|
||||||
l1.(io.Closer).Close()
|
l1.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +133,7 @@ func TestSimpleTCPListener(t *testing.T) {
|
||||||
checkFirstListener(t, tt.net, tt.laddr+":"+port, l1)
|
checkFirstListener(t, tt.net, tt.laddr+":"+port, l1)
|
||||||
l2, err := Listen(tt.net, tt.laddr+":"+port)
|
l2, err := Listen(tt.net, tt.laddr+":"+port)
|
||||||
checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2)
|
checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2)
|
||||||
l1.(io.Closer).Close()
|
l1.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +168,7 @@ func TestSimpleUDPListener(t *testing.T) {
|
||||||
checkFirstListener(t, tt.net, tt.laddr+":"+port, l1)
|
checkFirstListener(t, tt.net, tt.laddr+":"+port, l1)
|
||||||
l2, err := ListenPacket(tt.net, tt.laddr+":"+port)
|
l2, err := ListenPacket(tt.net, tt.laddr+":"+port)
|
||||||
checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2)
|
checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2)
|
||||||
l1.(io.Closer).Close()
|
l1.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,8 +529,9 @@ func TestProhibitionaryDialArgs(t *testing.T) {
|
||||||
defer l.Close()
|
defer l.Close()
|
||||||
|
|
||||||
for _, tt := range prohibitionaryDialArgTests {
|
for _, tt := range prohibitionaryDialArgTests {
|
||||||
_, err := Dial(tt.net, tt.addr+":"+port)
|
c, err := Dial(tt.net, tt.addr+":"+port)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
c.Close()
|
||||||
t.Fatalf("Dial(%q, %q) should fail", tt.net, tt.addr)
|
t.Fatalf("Dial(%q, %q) should fail", tt.net, tt.addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,3 +42,21 @@ func NewSyscallError(syscall string, err error) error {
|
||||||
}
|
}
|
||||||
return &SyscallError{syscall, err}
|
return &SyscallError{syscall, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsExist returns whether the error is known to report that a file or directory
|
||||||
|
// already exists. It is satisfied by ErrExist as well as some syscall errors.
|
||||||
|
func IsExist(err error) bool {
|
||||||
|
return isExist(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNotExist returns whether the error is known to report that a file or directory
|
||||||
|
// does not exist. It is satisfied by ErrNotExist as well as some syscall errors.
|
||||||
|
func IsNotExist(err error) bool {
|
||||||
|
return isNotExist(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsPermission returns whether the error is known to report that permission is denied.
|
||||||
|
// It is satisfied by ErrPermission as well as some syscall errors.
|
||||||
|
func IsPermission(err error) bool {
|
||||||
|
return isPermission(err)
|
||||||
|
}
|
||||||
|
|
|
@ -4,24 +4,21 @@
|
||||||
|
|
||||||
package os
|
package os
|
||||||
|
|
||||||
// IsExist returns whether the error is known to report that a file already exists.
|
func isExist(err error) bool {
|
||||||
func IsExist(err error) bool {
|
|
||||||
if pe, ok := err.(*PathError); ok {
|
if pe, ok := err.(*PathError); ok {
|
||||||
err = pe.Err
|
err = pe.Err
|
||||||
}
|
}
|
||||||
return contains(err.Error(), " exists")
|
return contains(err.Error(), " exists")
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsNotExist returns whether the error is known to report that a file does not exist.
|
func isNotExist(err error) bool {
|
||||||
func IsNotExist(err error) bool {
|
|
||||||
if pe, ok := err.(*PathError); ok {
|
if pe, ok := err.(*PathError); ok {
|
||||||
err = pe.Err
|
err = pe.Err
|
||||||
}
|
}
|
||||||
return contains(err.Error(), "does not exist")
|
return contains(err.Error(), "does not exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsPermission returns whether the error is known to report that permission is denied.
|
func isPermission(err error) bool {
|
||||||
func IsPermission(err error) bool {
|
|
||||||
if pe, ok := err.(*PathError); ok {
|
if pe, ok := err.(*PathError); ok {
|
||||||
err = pe.Err
|
err = pe.Err
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,27 +8,21 @@ package os
|
||||||
|
|
||||||
import "syscall"
|
import "syscall"
|
||||||
|
|
||||||
// IsExist returns whether the error is known to report that a file already exists.
|
func isExist(err error) bool {
|
||||||
// It is satisfied by ErrExist as well as some syscall errors.
|
|
||||||
func IsExist(err error) bool {
|
|
||||||
if pe, ok := err.(*PathError); ok {
|
if pe, ok := err.(*PathError); ok {
|
||||||
err = pe.Err
|
err = pe.Err
|
||||||
}
|
}
|
||||||
return err == syscall.EEXIST || err == ErrExist
|
return err == syscall.EEXIST || err == ErrExist
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsNotExist returns whether the error is known to report that a file does not exist.
|
func isNotExist(err error) bool {
|
||||||
// It is satisfied by ErrNotExist as well as some syscall errors.
|
|
||||||
func IsNotExist(err error) bool {
|
|
||||||
if pe, ok := err.(*PathError); ok {
|
if pe, ok := err.(*PathError); ok {
|
||||||
err = pe.Err
|
err = pe.Err
|
||||||
}
|
}
|
||||||
return err == syscall.ENOENT || err == ErrNotExist
|
return err == syscall.ENOENT || err == ErrNotExist
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsPermission returns whether the error is known to report that permission is denied.
|
func isPermission(err error) bool {
|
||||||
// It is satisfied by ErrPermission as well as some syscall errors.
|
|
||||||
func IsPermission(err error) bool {
|
|
||||||
if pe, ok := err.(*PathError); ok {
|
if pe, ok := err.(*PathError); ok {
|
||||||
err = pe.Err
|
err = pe.Err
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,10 @@
|
||||||
package os_test
|
package os_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -24,8 +26,56 @@ func TestErrIsExist(t *testing.T) {
|
||||||
t.Fatal("Open should have failed")
|
t.Fatal("Open should have failed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !os.IsExist(err) {
|
if s := checkErrorPredicate("os.IsExist", os.IsExist, err); s != "" {
|
||||||
t.Fatalf("os.IsExist does not work as expected for %#v", err)
|
t.Fatal(s)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testErrNotExist(name string) string {
|
||||||
|
f, err := os.Open(name)
|
||||||
|
if err == nil {
|
||||||
|
f.Close()
|
||||||
|
return "Open should have failed"
|
||||||
|
}
|
||||||
|
if s := checkErrorPredicate("os.IsNotExist", os.IsNotExist, err); s != "" {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.Chdir(name)
|
||||||
|
if err == nil {
|
||||||
|
return "Chdir should have failed"
|
||||||
|
}
|
||||||
|
if s := checkErrorPredicate("os.IsNotExist", os.IsNotExist, err); s != "" {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestErrIsNotExist(t *testing.T) {
|
||||||
|
tmpDir, err := ioutil.TempDir("", "_Go_ErrIsNotExist")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("create ErrIsNotExist tempdir: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
|
name := filepath.Join(tmpDir, "NotExists")
|
||||||
|
if s := testErrNotExist(name); s != "" {
|
||||||
|
t.Fatal(s)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
name = filepath.Join(name, "NotExists2")
|
||||||
|
if s := testErrNotExist(name); s != "" {
|
||||||
|
t.Fatal(s)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkErrorPredicate(predName string, pred func(error) bool, err error) string {
|
||||||
|
if !pred(err) {
|
||||||
|
return fmt.Sprintf("%s does not work as expected for %#v", predName, err)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
|
@ -6,30 +6,25 @@ package os
|
||||||
|
|
||||||
import "syscall"
|
import "syscall"
|
||||||
|
|
||||||
// IsExist returns whether the error is known to report that a file already exists.
|
func isExist(err error) bool {
|
||||||
// It is satisfied by ErrExist as well as some syscall errors.
|
|
||||||
func IsExist(err error) bool {
|
|
||||||
if pe, ok := err.(*PathError); ok {
|
if pe, ok := err.(*PathError); ok {
|
||||||
err = pe.Err
|
err = pe.Err
|
||||||
}
|
}
|
||||||
return err == syscall.EEXIST || err == syscall.ERROR_ALREADY_EXISTS ||
|
return err == syscall.ERROR_ALREADY_EXISTS ||
|
||||||
err == syscall.ERROR_FILE_EXISTS || err == ErrExist
|
err == syscall.ERROR_FILE_EXISTS || err == ErrExist
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsNotExist returns whether the error is known to report that a file does not exist.
|
func isNotExist(err error) bool {
|
||||||
// It is satisfied by ErrNotExist as well as some syscall errors.
|
|
||||||
func IsNotExist(err error) bool {
|
|
||||||
if pe, ok := err.(*PathError); ok {
|
if pe, ok := err.(*PathError); ok {
|
||||||
err = pe.Err
|
err = pe.Err
|
||||||
}
|
}
|
||||||
return err == syscall.ENOENT || err == ErrNotExist
|
return err == syscall.ERROR_FILE_NOT_FOUND ||
|
||||||
|
err == syscall.ERROR_PATH_NOT_FOUND || err == ErrNotExist
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsPermission returns whether the error is known to report that permission is denied.
|
func isPermission(err error) bool {
|
||||||
// It is satisfied by ErrPermission as well as some syscall errors.
|
|
||||||
func IsPermission(err error) bool {
|
|
||||||
if pe, ok := err.(*PathError); ok {
|
if pe, ok := err.(*PathError); ok {
|
||||||
err = pe.Err
|
err = pe.Err
|
||||||
}
|
}
|
||||||
return err == syscall.EACCES || err == syscall.EPERM || err == ErrPermission
|
return err == ErrPermission
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,7 +179,21 @@ func (f *File) pread(b []byte, off int64) (n int, err error) {
|
||||||
// write writes len(b) bytes to the File.
|
// write writes len(b) bytes to the File.
|
||||||
// It returns the number of bytes written and an error, if any.
|
// It returns the number of bytes written and an error, if any.
|
||||||
func (f *File) write(b []byte) (n int, err error) {
|
func (f *File) write(b []byte) (n int, err error) {
|
||||||
return syscall.Write(f.fd, b)
|
for {
|
||||||
|
m, err := syscall.Write(f.fd, b)
|
||||||
|
n += m
|
||||||
|
|
||||||
|
// If the syscall wrote some data but not all (short write)
|
||||||
|
// or it returned EINTR, then assume it stopped early for
|
||||||
|
// reasons that are uninteresting to the caller, and try again.
|
||||||
|
if 0 < m && m < len(b) || err == syscall.EINTR {
|
||||||
|
b = b[m:]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
panic("not reached")
|
||||||
}
|
}
|
||||||
|
|
||||||
// pwrite writes len(b) bytes to the File starting at byte offset off.
|
// pwrite writes len(b) bytes to the File starting at byte offset off.
|
||||||
|
|
|
@ -1045,3 +1045,22 @@ func TestSameFile(t *testing.T) {
|
||||||
t.Errorf("files should be different")
|
t.Errorf("files should be different")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDevNullFile(t *testing.T) {
|
||||||
|
f, err := Open(DevNull)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Open(%s): %v", DevNull, err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
fi, err := f.Stat()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Stat(%s): %v", DevNull, err)
|
||||||
|
}
|
||||||
|
name := filepath.Base(DevNull)
|
||||||
|
if fi.Name() != name {
|
||||||
|
t.Fatalf("wrong file name have %v want %v", fi.Name(), name)
|
||||||
|
}
|
||||||
|
if fi.Size() != 0 {
|
||||||
|
t.Fatalf("wrong file size have %d want 0", fi.Size())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ package filepath
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
@ -37,6 +38,9 @@ var ErrBadPattern = errors.New("syntax error in pattern")
|
||||||
// The only possible returned error is ErrBadPattern, when pattern
|
// The only possible returned error is ErrBadPattern, when pattern
|
||||||
// is malformed.
|
// is malformed.
|
||||||
//
|
//
|
||||||
|
// On Windows, escaping is disabled. Instead, '\\' is treated as
|
||||||
|
// path separator.
|
||||||
|
//
|
||||||
func Match(pattern, name string) (matched bool, err error) {
|
func Match(pattern, name string) (matched bool, err error) {
|
||||||
Pattern:
|
Pattern:
|
||||||
for len(pattern) > 0 {
|
for len(pattern) > 0 {
|
||||||
|
@ -95,9 +99,11 @@ Scan:
|
||||||
for i = 0; i < len(pattern); i++ {
|
for i = 0; i < len(pattern); i++ {
|
||||||
switch pattern[i] {
|
switch pattern[i] {
|
||||||
case '\\':
|
case '\\':
|
||||||
// error check handled in matchChunk: bad pattern.
|
if runtime.GOOS != "windows" {
|
||||||
if i+1 < len(pattern) {
|
// error check handled in matchChunk: bad pattern.
|
||||||
i++
|
if i+1 < len(pattern) {
|
||||||
|
i++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case '[':
|
case '[':
|
||||||
inrange = true
|
inrange = true
|
||||||
|
@ -167,10 +173,12 @@ func matchChunk(chunk, s string) (rest string, ok bool, err error) {
|
||||||
chunk = chunk[1:]
|
chunk = chunk[1:]
|
||||||
|
|
||||||
case '\\':
|
case '\\':
|
||||||
chunk = chunk[1:]
|
if runtime.GOOS != "windows" {
|
||||||
if len(chunk) == 0 {
|
chunk = chunk[1:]
|
||||||
err = ErrBadPattern
|
if len(chunk) == 0 {
|
||||||
return
|
err = ErrBadPattern
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
|
|
||||||
|
@ -191,7 +199,7 @@ func getEsc(chunk string) (r rune, nchunk string, err error) {
|
||||||
err = ErrBadPattern
|
err = ErrBadPattern
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if chunk[0] == '\\' {
|
if chunk[0] == '\\' && runtime.GOOS != "windows" {
|
||||||
chunk = chunk[1:]
|
chunk = chunk[1:]
|
||||||
if len(chunk) == 0 {
|
if len(chunk) == 0 {
|
||||||
err = ErrBadPattern
|
err = ErrBadPattern
|
||||||
|
|
|
@ -7,6 +7,7 @@ package filepath_test
|
||||||
import (
|
import (
|
||||||
. "path/filepath"
|
. "path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -76,21 +77,26 @@ func errp(e error) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMatch(t *testing.T) {
|
func TestMatch(t *testing.T) {
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
// XXX: Don't pass for windows.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, tt := range matchTests {
|
for _, tt := range matchTests {
|
||||||
ok, err := Match(tt.pattern, tt.s)
|
pattern := tt.pattern
|
||||||
|
s := tt.s
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
if strings.Index(pattern, "\\") >= 0 {
|
||||||
|
// no escape allowed on windows.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pattern = Clean(pattern)
|
||||||
|
s = Clean(s)
|
||||||
|
}
|
||||||
|
ok, err := Match(pattern, s)
|
||||||
if ok != tt.match || err != tt.err {
|
if ok != tt.match || err != tt.err {
|
||||||
t.Errorf("Match(%#q, %#q) = %v, %q want %v, %q", tt.pattern, tt.s, ok, errp(err), tt.match, errp(tt.err))
|
t.Errorf("Match(%#q, %#q) = %v, %q want %v, %q", pattern, s, ok, errp(err), tt.match, errp(tt.err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// contains returns true if vector contains the string s.
|
// contains returns true if vector contains the string s.
|
||||||
func contains(vector []string, s string) bool {
|
func contains(vector []string, s string) bool {
|
||||||
s = ToSlash(s)
|
|
||||||
for _, elem := range vector {
|
for _, elem := range vector {
|
||||||
if elem == s {
|
if elem == s {
|
||||||
return true
|
return true
|
||||||
|
@ -110,18 +116,20 @@ var globTests = []struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGlob(t *testing.T) {
|
func TestGlob(t *testing.T) {
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
// XXX: Don't pass for windows.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, tt := range globTests {
|
for _, tt := range globTests {
|
||||||
matches, err := Glob(tt.pattern)
|
pattern := tt.pattern
|
||||||
|
result := tt.result
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
pattern = Clean(pattern)
|
||||||
|
result = Clean(result)
|
||||||
|
}
|
||||||
|
matches, err := Glob(pattern)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Glob error for %q: %s", tt.pattern, err)
|
t.Errorf("Glob error for %q: %s", pattern, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !contains(matches, tt.result) {
|
if !contains(matches, result) {
|
||||||
t.Errorf("Glob(%#q) = %#v want %v", tt.pattern, matches, tt.result)
|
t.Errorf("Glob(%#q) = %#v want %v", pattern, matches, result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, pattern := range []string{"no_match", "../*/no_match"} {
|
for _, pattern := range []string{"no_match", "../*/no_match"} {
|
||||||
|
|
|
@ -66,9 +66,10 @@ type Type interface {
|
||||||
// It returns an empty string for unnamed types.
|
// It returns an empty string for unnamed types.
|
||||||
Name() string
|
Name() string
|
||||||
|
|
||||||
// PkgPath returns the type's package path.
|
// PkgPath returns a named type's package path, that is, the import path
|
||||||
// The package path is a full package import path like "encoding/base64".
|
// that uniquely identifies the package, such as "encoding/base64".
|
||||||
// PkgPath returns an empty string for unnamed or predeclared types.
|
// If the type was predeclared (string, error) or unnamed (*T, struct{}, []int),
|
||||||
|
// the package path will be the empty string.
|
||||||
PkgPath() string
|
PkgPath() string
|
||||||
|
|
||||||
// Size returns the number of bytes needed to store
|
// Size returns the number of bytes needed to store
|
||||||
|
@ -351,11 +352,18 @@ type structType struct {
|
||||||
|
|
||||||
// Method represents a single method.
|
// Method represents a single method.
|
||||||
type Method struct {
|
type Method struct {
|
||||||
PkgPath string // empty for uppercase Name
|
// Name is the method name.
|
||||||
|
// PkgPath is the package path that qualifies a lower case (unexported)
|
||||||
|
// method name. It is empty for upper case (exported) method names.
|
||||||
|
// The combination of PkgPath and Name uniquely identifies a method
|
||||||
|
// in a method set.
|
||||||
|
// See http://golang.org/ref/spec#Uniqueness_of_identifiers
|
||||||
Name string
|
Name string
|
||||||
Type Type
|
PkgPath string
|
||||||
Func Value
|
|
||||||
Index int
|
Type Type // method type
|
||||||
|
Func Value // func with receiver as first argument
|
||||||
|
Index int // index for Type.Method
|
||||||
}
|
}
|
||||||
|
|
||||||
// High bit says whether type has
|
// High bit says whether type has
|
||||||
|
@ -695,14 +703,20 @@ func (t *interfaceType) MethodByName(name string) (m Method, ok bool) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A StructField describes a single field in a struct.
|
||||||
type StructField struct {
|
type StructField struct {
|
||||||
PkgPath string // empty for uppercase Name
|
// Name is the field name.
|
||||||
Name string
|
// PkgPath is the package path that qualifies a lower case (unexported)
|
||||||
Type Type
|
// field name. It is empty for upper case (exported) field names.
|
||||||
Tag StructTag
|
// See http://golang.org/ref/spec#Uniqueness_of_identifiers
|
||||||
Offset uintptr
|
Name string
|
||||||
Index []int
|
PkgPath string
|
||||||
Anonymous bool
|
|
||||||
|
Type Type // field type
|
||||||
|
Tag StructTag // field tag string
|
||||||
|
Offset uintptr // offset within struct, in bytes
|
||||||
|
Index []int // index sequence for Type.FieldByIndex
|
||||||
|
Anonymous bool // is an anonymous field
|
||||||
}
|
}
|
||||||
|
|
||||||
// A StructTag is the tag string in a struct field.
|
// A StructTag is the tag string in a struct field.
|
||||||
|
|
|
@ -1624,6 +1624,15 @@ func MakeSlice(typ Type, len, cap int) Value {
|
||||||
if typ.Kind() != Slice {
|
if typ.Kind() != Slice {
|
||||||
panic("reflect.MakeSlice of non-slice type")
|
panic("reflect.MakeSlice of non-slice type")
|
||||||
}
|
}
|
||||||
|
if len < 0 {
|
||||||
|
panic("reflect.MakeSlice: negative len")
|
||||||
|
}
|
||||||
|
if cap < 0 {
|
||||||
|
panic("reflect.MakeSlice: negative cap")
|
||||||
|
}
|
||||||
|
if len > cap {
|
||||||
|
panic("reflect.MakeSlice: len > cap")
|
||||||
|
}
|
||||||
|
|
||||||
// Declare slice so that gc can see the base pointer in it.
|
// Declare slice so that gc can see the base pointer in it.
|
||||||
var x []byte
|
var x []byte
|
||||||
|
|
|
@ -183,17 +183,21 @@ func quickSort(data Interface, a, b, maxDepth int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sort sorts data.
|
||||||
|
// It makes one call to data.Len to determine n, and O(n*log(n)) calls to
|
||||||
|
// data.Less and data.Swap. The sort is not guaranteed to be stable.
|
||||||
func Sort(data Interface) {
|
func Sort(data Interface) {
|
||||||
// Switch to heapsort if depth of 2*ceil(lg(n)) is reached.
|
// Switch to heapsort if depth of 2*ceil(lg(n+1)) is reached.
|
||||||
n := data.Len()
|
n := data.Len()
|
||||||
maxDepth := 0
|
maxDepth := 0
|
||||||
for 1<<uint(maxDepth) < n {
|
for i := n; i > 0; i >>= 1 {
|
||||||
maxDepth++
|
maxDepth++
|
||||||
}
|
}
|
||||||
maxDepth *= 2
|
maxDepth *= 2
|
||||||
quickSort(data, 0, n, maxDepth)
|
quickSort(data, 0, n, maxDepth)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsSorted reports whether data is sorted.
|
||||||
func IsSorted(data Interface) bool {
|
func IsSorted(data Interface) bool {
|
||||||
n := data.Len()
|
n := data.Len()
|
||||||
for i := n - 1; i > 0; i-- {
|
for i := n - 1; i > 0; i-- {
|
||||||
|
|
|
@ -369,6 +369,7 @@ func (s *state) evalVariableNode(dot reflect.Value, v *parse.VariableNode, args
|
||||||
// $x.Field has $x as the first ident, Field as the second. Eval the var, then the fields.
|
// $x.Field has $x as the first ident, Field as the second. Eval the var, then the fields.
|
||||||
value := s.varValue(v.Ident[0])
|
value := s.varValue(v.Ident[0])
|
||||||
if len(v.Ident) == 1 {
|
if len(v.Ident) == 1 {
|
||||||
|
s.notAFunction(args, final)
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
return s.evalFieldChain(dot, value, v.Ident[1:], args, final)
|
return s.evalFieldChain(dot, value, v.Ident[1:], args, final)
|
||||||
|
|
|
@ -466,6 +466,10 @@ var execTests = []execTest{
|
||||||
{"bug6b", "{{vfunc .V0 .V0}}", "vfunc", tVal, true},
|
{"bug6b", "{{vfunc .V0 .V0}}", "vfunc", tVal, true},
|
||||||
{"bug6c", "{{vfunc .V1 .V0}}", "vfunc", tVal, true},
|
{"bug6c", "{{vfunc .V1 .V0}}", "vfunc", tVal, true},
|
||||||
{"bug6d", "{{vfunc .V1 .V1}}", "vfunc", tVal, true},
|
{"bug6d", "{{vfunc .V1 .V1}}", "vfunc", tVal, true},
|
||||||
|
// Legal parse but illegal execution: non-function should have no arguments.
|
||||||
|
{"bug7a", "{{3 2}}", "", tVal, false},
|
||||||
|
{"bug7b", "{{$x := 1}}{{$x 2}}", "", tVal, false},
|
||||||
|
{"bug7c", "{{$x := 1}}{{3 | $x}}", "", tVal, false},
|
||||||
}
|
}
|
||||||
|
|
||||||
func zeroArgs() string {
|
func zeroArgs() string {
|
||||||
|
|
|
@ -93,7 +93,7 @@ var multiExecTests = []execTest{
|
||||||
{"invoke dot []int", `{{template "dot" .SI}}`, "[3 4 5]", tVal, true},
|
{"invoke dot []int", `{{template "dot" .SI}}`, "[3 4 5]", tVal, true},
|
||||||
{"invoke dotV", `{{template "dotV" .U}}`, "v", tVal, true},
|
{"invoke dotV", `{{template "dotV" .U}}`, "v", tVal, true},
|
||||||
{"invoke nested int", `{{template "nested" .I}}`, "17", tVal, true},
|
{"invoke nested int", `{{template "nested" .I}}`, "17", tVal, true},
|
||||||
{"variable declared by template", `{{template "nested" $x=.SI}},{{index $x 1}}`, "[3 4 5],4", tVal, true},
|
{"variable declared by template", `{{template "nested" $x:=.SI}},{{index $x 1}}`, "[3 4 5],4", tVal, true},
|
||||||
|
|
||||||
// User-defined function: test argument evaluator.
|
// User-defined function: test argument evaluator.
|
||||||
{"testFunc literal", `{{oneArg "joe"}}`, "oneArg=joe", tVal, true},
|
{"testFunc literal", `{{oneArg "joe"}}`, "oneArg=joe", tVal, true},
|
||||||
|
|
|
@ -347,6 +347,9 @@ Loop:
|
||||||
default:
|
default:
|
||||||
l.backup()
|
l.backup()
|
||||||
word := l.input[l.start:l.pos]
|
word := l.input[l.start:l.pos]
|
||||||
|
if !l.atTerminator() {
|
||||||
|
return l.errorf("unexpected character %+U", r)
|
||||||
|
}
|
||||||
switch {
|
switch {
|
||||||
case key[word] > itemKeyword:
|
case key[word] > itemKeyword:
|
||||||
l.emit(key[word])
|
l.emit(key[word])
|
||||||
|
@ -365,6 +368,28 @@ Loop:
|
||||||
return lexInsideAction
|
return lexInsideAction
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// atTerminator reports whether the input is at valid termination character to
|
||||||
|
// appear after an identifier. Mostly to catch cases like "$x+2" not being
|
||||||
|
// acceptable without a space, in case we decide one day to implement
|
||||||
|
// arithmetic.
|
||||||
|
func (l *lexer) atTerminator() bool {
|
||||||
|
r := l.peek()
|
||||||
|
if isSpace(r) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
switch r {
|
||||||
|
case eof, ',', '|', ':':
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// Does r start the delimiter? This can be ambiguous (with delim=="//", $x/2 will
|
||||||
|
// succeed but should fail) but only in extremely rare cases caused by willfully
|
||||||
|
// bad choice of delimiter.
|
||||||
|
if rd, _ := utf8.DecodeRuneInString(l.rightDelim); rd == r {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// lexChar scans a character constant. The initial quote is already
|
// lexChar scans a character constant. The initial quote is already
|
||||||
// scanned. Syntax checking is done by the parse.
|
// scanned. Syntax checking is done by the parse.
|
||||||
func lexChar(l *lexer) stateFn {
|
func lexChar(l *lexer) stateFn {
|
||||||
|
|
|
@ -326,7 +326,7 @@ func (t *Tree) pipeline(context string) (pipe *PipeNode) {
|
||||||
for {
|
for {
|
||||||
if v := t.peek(); v.typ == itemVariable {
|
if v := t.peek(); v.typ == itemVariable {
|
||||||
t.next()
|
t.next()
|
||||||
if next := t.peek(); next.typ == itemColonEquals || next.typ == itemChar {
|
if next := t.peek(); next.typ == itemColonEquals || (next.typ == itemChar && next.val == ",") {
|
||||||
t.next()
|
t.next()
|
||||||
variable := newVariable(v.val)
|
variable := newVariable(v.val)
|
||||||
if len(variable.Ident) != 1 {
|
if len(variable.Ident) != 1 {
|
||||||
|
|
|
@ -201,6 +201,10 @@ var parseTests = []parseTest{
|
||||||
`{{range .X | .M}}"true"{{else}}"false"{{end}}`},
|
`{{range .X | .M}}"true"{{else}}"false"{{end}}`},
|
||||||
{"range []int", "{{range .SI}}{{.}}{{end}}", noError,
|
{"range []int", "{{range .SI}}{{.}}{{end}}", noError,
|
||||||
`{{range .SI}}{{.}}{{end}}`},
|
`{{range .SI}}{{.}}{{end}}`},
|
||||||
|
{"range 1 var", "{{range $x := .SI}}{{.}}{{end}}", noError,
|
||||||
|
`{{range $x := .SI}}{{.}}{{end}}`},
|
||||||
|
{"range 2 vars", "{{range $x, $y := .SI}}{{.}}{{end}}", noError,
|
||||||
|
`{{range $x, $y := .SI}}{{.}}{{end}}`},
|
||||||
{"constants", "{{range .SI 1 -3.2i true false 'a'}}{{end}}", noError,
|
{"constants", "{{range .SI 1 -3.2i true false 'a'}}{{end}}", noError,
|
||||||
`{{range .SI 1 -3.2i true false 'a'}}{{end}}`},
|
`{{range .SI 1 -3.2i true false 'a'}}{{end}}`},
|
||||||
{"template", "{{template `x`}}", noError,
|
{"template", "{{template `x`}}", noError,
|
||||||
|
@ -226,6 +230,17 @@ var parseTests = []parseTest{
|
||||||
{"invalid punctuation", "{{printf 3, 4}}", hasError, ""},
|
{"invalid punctuation", "{{printf 3, 4}}", hasError, ""},
|
||||||
{"multidecl outside range", "{{with $v, $u := 3}}{{end}}", hasError, ""},
|
{"multidecl outside range", "{{with $v, $u := 3}}{{end}}", hasError, ""},
|
||||||
{"too many decls in range", "{{range $u, $v, $w := 3}}{{end}}", hasError, ""},
|
{"too many decls in range", "{{range $u, $v, $w := 3}}{{end}}", hasError, ""},
|
||||||
|
// Equals (and other chars) do not assignments make (yet).
|
||||||
|
{"bug0a", "{{$x := 0}}{{$x}}", noError, "{{$x := 0}}{{$x}}"},
|
||||||
|
{"bug0b", "{{$x = 1}}{{$x}}", hasError, ""},
|
||||||
|
{"bug0c", "{{$x ! 2}}{{$x}}", hasError, ""},
|
||||||
|
{"bug0d", "{{$x % 3}}{{$x}}", hasError, ""},
|
||||||
|
// Check the parse fails for := rather than comma.
|
||||||
|
{"bug0e", "{{range $x := $y := 3}}{{end}}", hasError, ""},
|
||||||
|
// Another bug: variable read must ignore following punctuation.
|
||||||
|
{"bug1a", "{{$x:=.}}{{$x!2}}", hasError, ""}, // ! is just illegal here.
|
||||||
|
{"bug1b", "{{$x:=.}}{{$x+2}}", hasError, ""}, // $x+2 should not parse as ($x) (+2).
|
||||||
|
{"bug1c", "{{$x:=.}}{{$x +2}}", noError, "{{$x := .}}{{$x +2}}"}, // It's OK with a space.
|
||||||
}
|
}
|
||||||
|
|
||||||
var builtins = map[string]interface{}{
|
var builtins = map[string]interface{}{
|
||||||
|
|
|
@ -163,7 +163,7 @@ done
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
runtime="chan.c cpuprof.c goc2c.c lock_futex.c lock_sema.c mcache.c mcentral.c mfinal.c mfixalloc.c mgc0.c mheap.c msize.c proc.c runtime.c runtime.h signal_unix.c malloc.h malloc.goc mprof.goc runtime1.goc sema.goc sigqueue.goc string.goc time.goc"
|
runtime="chan.c cpuprof.c lock_futex.c lock_sema.c mcache.c mcentral.c mfinal.c mfixalloc.c mgc0.c mheap.c msize.c proc.c runtime.c runtime.h signal_unix.c malloc.h malloc.goc mprof.goc runtime1.goc sema.goc sigqueue.goc string.goc time.goc"
|
||||||
for f in $runtime; do
|
for f in $runtime; do
|
||||||
merge_c $f $f
|
merge_c $f $f
|
||||||
done
|
done
|
||||||
|
|
|
@ -966,6 +966,11 @@ runtime_mstart(void* mp)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Install signal handlers; after minit so that minit can
|
||||||
|
// prepare the thread to be able to handle the signals.
|
||||||
|
if(m == &runtime_m0)
|
||||||
|
runtime_initsig();
|
||||||
|
|
||||||
schedule(nil);
|
schedule(nil);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ void
|
||||||
runtime_panicstring(const char *s)
|
runtime_panicstring(const char *s)
|
||||||
{
|
{
|
||||||
Eface err;
|
Eface err;
|
||||||
|
|
||||||
if(runtime_m()->gcing) {
|
if(runtime_m()->gcing) {
|
||||||
runtime_printf("panic: %s\n", s);
|
runtime_printf("panic: %s\n", s);
|
||||||
runtime_throw("panic during gc");
|
runtime_throw("panic during gc");
|
||||||
|
@ -101,7 +101,7 @@ runtime_goargs(void)
|
||||||
{
|
{
|
||||||
String *s;
|
String *s;
|
||||||
int32 i;
|
int32 i;
|
||||||
|
|
||||||
// for windows implementation see "os" package
|
// for windows implementation see "os" package
|
||||||
if(Windows)
|
if(Windows)
|
||||||
return;
|
return;
|
||||||
|
@ -119,7 +119,7 @@ runtime_goenvs_unix(void)
|
||||||
{
|
{
|
||||||
String *s;
|
String *s;
|
||||||
int32 i, n;
|
int32 i, n;
|
||||||
|
|
||||||
for(n=0; argv[argc+1+n] != 0; n++)
|
for(n=0; argv[argc+1+n] != 0; n++)
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -195,8 +195,6 @@ void
|
||||||
runtime_check(void)
|
runtime_check(void)
|
||||||
{
|
{
|
||||||
__go_register_gc_roots(&runtime_roots);
|
__go_register_gc_roots(&runtime_roots);
|
||||||
|
|
||||||
runtime_initsig ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int64
|
int64
|
||||||
|
|
Loading…
Reference in New Issue