<commit_before>// Copyright 2016 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

package libkbfs

import (
	"encoding/base64"
	"fmt"
	"strings"

	"github.com/keybase/client/go/kbfs/kbfscrypto"
	"github.com/keybase/client/go/kbfs/kbfsmd"
	"github.com/keybase/client/go/kbfs/tlf"
	"github.com/keybase/client/go/logger"
	"github.com/keybase/client/go/protocol/keybase1"
	"github.com/pkg/errors"
	"golang.org/x/net/context"
)

// Runs fn (which may block) in a separate goroutine and waits for it
// to finish, unless ctx is cancelled. Returns nil only when fn was
// run to completion and succeeded.  Any closed-over variables updated
// in fn should be considered visible only if nil is returned.
func runUnlessCanceled(ctx context.Context, fn func() error) error {
	c := make(chan error, 1) // buffered, in case the request is canceled
	go func() {
		c <- fn()
	}()

	select {
	case <-ctx.Done():
		return ctx.Err()
	case err := <-c:
		return err
	}
}

// MakeRandomRequestID generates a random ID suitable for tagging a
// request in KBFS, and very likely to be universally unique.
func MakeRandomRequestID() (string, error) {
	// Use a random ID to tag each request.  We want this to be really
	// universally unique, as these request IDs might need to be
	// propagated all the way to the server.  Use a base64-encoded
	// random 128-bit number.
	buf := make([]byte, 128/8)
	err := kbfscrypto.RandRead(buf)
	if err != nil {
		return "", err
	}
	return base64.RawURLEncoding.EncodeToString(buf), nil
}

// BoolForString returns false if trimmed string is "" (empty), "0", "false", or "no"
func BoolForString(s string) bool {
	s = strings.TrimSpace(s)
	if s == "" || s == "0" || s == "false" || s == "no" {
		return false
	}
	return true
}

// PrereleaseBuild is set at compile time for prerelease builds
var PrereleaseBuild string

// VersionString returns semantic version string
func VersionString() string {
	if PrereleaseBuild != "" {
		return fmt.Sprintf("%s-%s", Version, PrereleaseBuild)
	}
	return Version
}

// CtxBackgroundSyncKeyType is the type for a context background sync key.
type CtxBackgroundSyncKeyType int

const (
	// CtxBackgroundSyncKey is set in the context for any change
	// notifications that are triggered from a background sync.
	// Observers can ignore these if they want, since they will have
	// already gotten the relevant notifications via LocalChanges.
	CtxBackgroundSyncKey CtxBackgroundSyncKeyType = iota
)

// Warninger is an interface that only waprs the Warning method.
type Warninger interface {
	Warning(format string, args ...interface{})
}

// CtxWithRandomIDReplayable returns a replayable context with a
// random id associated with the given log key.
func CtxWithRandomIDReplayable(ctx context.Context, tagKey interface{},
	tagName string, log Warninger) context.Context {
	ctx = logger.ConvertRPCTagsToLogTags(ctx)

	id, err := MakeRandomRequestID()
	if err != nil && log != nil {
		log.Warning("Couldn't generate a random request ID: %v", err)
	}
	return NewContextReplayable(ctx, func(ctx context.Context) context.Context {
		logTags := make(logger.CtxLogTags)
		logTags[tagKey] = tagName
		newCtx := logger.NewContextWithLogTags(ctx, logTags)
		if err == nil {
			newCtx = context.WithValue(newCtx, tagKey, id)
		}
		return newCtx
	})
}

// checkDataVersion validates that the data version for a
// block pointer is valid for the given version validator
func checkDataVersion(versioner dataVersioner, p path, ptr BlockPointer) error {
	if ptr.DataVer < FirstValidDataVer {
		return errors.WithStack(InvalidDataVersionError{ptr.DataVer})
	}
	if versioner != nil && ptr.DataVer > versioner.DataVersion() {
		return errors.WithStack(NewDataVersionError{p, ptr.DataVer})
	}
	return nil
}

func checkContext(ctx context.Context) error {
	select {
	case <-ctx.Done():
		return errors.WithStack(ctx.Err())
	default:
		return nil
	}
}

func chargedToForTLF(ctx context.Context, sessionGetter CurrentSessionGetter,
	rootIDGetter teamRootIDGetter, handle *TlfHandle) (
	keybase1.UserOrTeamID, error) {
	if handle.Type() == tlf.SingleTeam {
		chargedTo := handle.FirstResolvedWriter()
		if tid := chargedTo.AsTeamOrBust(); tid.IsSubTeam() {
			// Subteam blocks should be charged to the root team ID.
			rootID, err := rootIDGetter.GetTeamRootID(ctx, tid)
			if err != nil {
				return keybase1.UserOrTeamID(""), err
			}
			return rootID.AsUserOrTeam(), nil
		}
		return chargedTo, nil
	}

	// For private and public folders, use the session user.
	session, err := sessionGetter.GetCurrentSession(ctx)
	if err != nil {
		return keybase1.UserOrTeamID(""), err
	}
	return session.UID.AsUserOrTeam(), nil
}

// GetHandleFromFolderNameAndType returns a TLFHandle given a folder
// name (e.g., "u1,u2#u3") and a TLF type.
func GetHandleFromFolderNameAndType(
	ctx context.Context, kbpki KBPKI, idGetter tlfIDGetter, tlfName string,
	t tlf.Type) (*TlfHandle, error) {
	for {
		tlfHandle, err := ParseTlfHandle(ctx, kbpki, idGetter, tlfName, t)
		switch e := errors.Cause(err).(type) {
		case TlfNameNotCanonical:
			tlfName = e.NameToTry
		case nil:
			return tlfHandle, nil
		default:
			return nil, err
		}
	}
}

// getHandleFromFolderName returns a TLFHandle given a folder
// name (e.g., "u1,u2#u3") and a public/private bool.  DEPRECATED.
func getHandleFromFolderName(
	ctx context.Context, kbpki KBPKI, idGetter tlfIDGetter, tlfName string,
	public bool) (*TlfHandle, error) {
	// TODO(KBFS-2185): update the protocol to support requests
	// for single-team TLFs.
	t := tlf.Private
	if public {
		t = tlf.Public
	}
	return GetHandleFromFolderNameAndType(ctx, kbpki, idGetter, tlfName, t)
}

func isWriterFromHandle(
	ctx context.Context, h *TlfHandle, checker kbfsmd.TeamMembershipChecker,
	uid keybase1.UID, verifyingKey kbfscrypto.VerifyingKey) (
	bool, error) {
	if h.TypeForKeying() != tlf.TeamKeying {
		return h.IsWriter(uid), nil
	}

	// Team membership needs to be checked with the service.  For a
	// SingleTeam TLF, there is always only a single writer in the
	// handle.
	tid, err := h.FirstResolvedWriter().AsTeam()
	if err != nil {
		return false, err
	}
	return checker.IsTeamWriter(ctx, tid, uid, verifyingKey)
}

func isReaderFromHandle(
	ctx context.Context, h *TlfHandle, checker kbfsmd.TeamMembershipChecker,
	uid keybase1.UID) (bool, error) {
	if h.TypeForKeying() != tlf.TeamKeying {
		return h.IsReader(uid), nil
	}

	// Team membership needs to be checked with the service.  For a
	// SingleTeam TLF, there is always only a single writer in the
	// handle.
	tid, err := h.FirstResolvedWriter().AsTeam()
	if err != nil {
		return false, err
	}
	return checker.IsTeamReader(ctx, tid, uid)
}

func tlfToMerkleTreeID(id tlf.ID) keybase1.MerkleTreeID {
	switch id.Type() {
	case tlf.Private:
		return keybase1.MerkleTreeID_KBFS_PRIVATE
	case tlf.Public:
		return keybase1.MerkleTreeID_KBFS_PUBLIC
	case tlf.SingleTeam:
		return keybase1.MerkleTreeID_KBFS_PRIVATETEAM
	default:
		panic(fmt.Sprintf("Unexpected TLF type: %d", id.Type()))
	}
}

// IsOnlyWriterInNonTeamTlf returns true if and only if the TLF described by h
// is a non-team TLF, and the currently logged-in user is the only writer for
// the TLF.  In case of any error false is returned.
func IsOnlyWriterInNonTeamTlf(ctx context.Context, kbpki KBPKI,
	h *TlfHandle) bool {
	session, err := GetCurrentSessionIfPossible(
		ctx, kbpki, h.Type() == tlf.Public)
	if err != nil {
		return false
	}
	if h.TypeForKeying() == tlf.TeamKeying {
		return false
	}
	return tlf.UserIsOnlyWriter(session.Name, h.GetCanonicalName())
}
<commit_msg>REVERT BEFORE MERGING: this is just to trigger tests<commit_after>// Copyright 2016 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

package libkbfs

import (
	"encoding/base64"
	"fmt"
	"strings"

	"github.com/keybase/client/go/kbfs/kbfscrypto"
	"github.com/keybase/client/go/kbfs/kbfsmd"
	"github.com/keybase/client/go/kbfs/tlf"
	"github.com/keybase/client/go/logger"
	"github.com/keybase/client/go/protocol/keybase1"
	"github.com/pkg/errors"
	"golang.org/x/net/context"
)

// Runs fn (which may block) in a separate goroutine and waits for it
// to finish, unless ctx is cancelled. Returns nil only when fn was
// run to completion and succeeded.  Any closed-over variables updated
// in fn should be considered visible only if nil is returned.
// TODO: remove this edit.
func runUnlessCanceled(ctx context.Context, fn func() error) error {
	c := make(chan error, 1) // buffered, in case the request is canceled
	go func() {
		c <- fn()
	}()

	select {
	case <-ctx.Done():
		return ctx.Err()
	case err := <-c:
		return err
	}
}

// MakeRandomRequestID generates a random ID suitable for tagging a
// request in KBFS, and very likely to be universally unique.
func MakeRandomRequestID() (string, error) {
	// Use a random ID to tag each request.  We want this to be really
	// universally unique, as these request IDs might need to be
	// propagated all the way to the server.  Use a base64-encoded
	// random 128-bit number.
	buf := make([]byte, 128/8)
	err := kbfscrypto.RandRead(buf)
	if err != nil {
		return "", err
	}
	return base64.RawURLEncoding.EncodeToString(buf), nil
}

// BoolForString returns false if trimmed string is "" (empty), "0", "false", or "no"
func BoolForString(s string) bool {
	s = strings.TrimSpace(s)
	if s == "" || s == "0" || s == "false" || s == "no" {
		return false
	}
	return true
}

// PrereleaseBuild is set at compile time for prerelease builds
var PrereleaseBuild string

// VersionString returns semantic version string
func VersionString() string {
	if PrereleaseBuild != "" {
		return fmt.Sprintf("%s-%s", Version, PrereleaseBuild)
	}
	return Version
}

// CtxBackgroundSyncKeyType is the type for a context background sync key.
type CtxBackgroundSyncKeyType int

const (
	// CtxBackgroundSyncKey is set in the context for any change
	// notifications that are triggered from a background sync.
	// Observers can ignore these if they want, since they will have
	// already gotten the relevant notifications via LocalChanges.
	CtxBackgroundSyncKey CtxBackgroundSyncKeyType = iota
)

// Warninger is an interface that only waprs the Warning method.
type Warninger interface {
	Warning(format string, args ...interface{})
}

// CtxWithRandomIDReplayable returns a replayable context with a
// random id associated with the given log key.
func CtxWithRandomIDReplayable(ctx context.Context, tagKey interface{},
	tagName string, log Warninger) context.Context {
	ctx = logger.ConvertRPCTagsToLogTags(ctx)

	id, err := MakeRandomRequestID()
	if err != nil && log != nil {
		log.Warning("Couldn't generate a random request ID: %v", err)
	}
	return NewContextReplayable(ctx, func(ctx context.Context) context.Context {
		logTags := make(logger.CtxLogTags)
		logTags[tagKey] = tagName
		newCtx := logger.NewContextWithLogTags(ctx, logTags)
		if err == nil {
			newCtx = context.WithValue(newCtx, tagKey, id)
		}
		return newCtx
	})
}

// checkDataVersion validates that the data version for a
// block pointer is valid for the given version validator
func checkDataVersion(versioner dataVersioner, p path, ptr BlockPointer) error {
	if ptr.DataVer < FirstValidDataVer {
		return errors.WithStack(InvalidDataVersionError{ptr.DataVer})
	}
	if versioner != nil && ptr.DataVer > versioner.DataVersion() {
		return errors.WithStack(NewDataVersionError{p, ptr.DataVer})
	}
	return nil
}

func checkContext(ctx context.Context) error {
	select {
	case <-ctx.Done():
		return errors.WithStack(ctx.Err())
	default:
		return nil
	}
}

func chargedToForTLF(ctx context.Context, sessionGetter CurrentSessionGetter,
	rootIDGetter teamRootIDGetter, handle *TlfHandle) (
	keybase1.UserOrTeamID, error) {
	if handle.Type() == tlf.SingleTeam {
		chargedTo := handle.FirstResolvedWriter()
		if tid := chargedTo.AsTeamOrBust(); tid.IsSubTeam() {
			// Subteam blocks should be charged to the root team ID.
			rootID, err := rootIDGetter.GetTeamRootID(ctx, tid)
			if err != nil {
				return keybase1.UserOrTeamID(""), err
			}
			return rootID.AsUserOrTeam(), nil
		}
		return chargedTo, nil
	}

	// For private and public folders, use the session user.
	session, err := sessionGetter.GetCurrentSession(ctx)
	if err != nil {
		return keybase1.UserOrTeamID(""), err
	}
	return session.UID.AsUserOrTeam(), nil
}

// GetHandleFromFolderNameAndType returns a TLFHandle given a folder
// name (e.g., "u1,u2#u3") and a TLF type.
func GetHandleFromFolderNameAndType(
	ctx context.Context, kbpki KBPKI, idGetter tlfIDGetter, tlfName string,
	t tlf.Type) (*TlfHandle, error) {
	for {
		tlfHandle, err := ParseTlfHandle(ctx, kbpki, idGetter, tlfName, t)
		switch e := errors.Cause(err).(type) {
		case TlfNameNotCanonical:
			tlfName = e.NameToTry
		case nil:
			return tlfHandle, nil
		default:
			return nil, err
		}
	}
}

// getHandleFromFolderName returns a TLFHandle given a folder
// name (e.g., "u1,u2#u3") and a public/private bool.  DEPRECATED.
func getHandleFromFolderName(
	ctx context.Context, kbpki KBPKI, idGetter tlfIDGetter, tlfName string,
	public bool) (*TlfHandle, error) {
	// TODO(KBFS-2185): update the protocol to support requests
	// for single-team TLFs.
	t := tlf.Private
	if public {
		t = tlf.Public
	}
	return GetHandleFromFolderNameAndType(ctx, kbpki, idGetter, tlfName, t)
}

func isWriterFromHandle(
	ctx context.Context, h *TlfHandle, checker kbfsmd.TeamMembershipChecker,
	uid keybase1.UID, verifyingKey kbfscrypto.VerifyingKey) (
	bool, error) {
	if h.TypeForKeying() != tlf.TeamKeying {
		return h.IsWriter(uid), nil
	}

	// Team membership needs to be checked with the service.  For a
	// SingleTeam TLF, there is always only a single writer in the
	// handle.
	tid, err := h.FirstResolvedWriter().AsTeam()
	if err != nil {
		return false, err
	}
	return checker.IsTeamWriter(ctx, tid, uid, verifyingKey)
}

func isReaderFromHandle(
	ctx context.Context, h *TlfHandle, checker kbfsmd.TeamMembershipChecker,
	uid keybase1.UID) (bool, error) {
	if h.TypeForKeying() != tlf.TeamKeying {
		return h.IsReader(uid), nil
	}

	// Team membership needs to be checked with the service.  For a
	// SingleTeam TLF, there is always only a single writer in the
	// handle.
	tid, err := h.FirstResolvedWriter().AsTeam()
	if err != nil {
		return false, err
	}
	return checker.IsTeamReader(ctx, tid, uid)
}

func tlfToMerkleTreeID(id tlf.ID) keybase1.MerkleTreeID {
	switch id.Type() {
	case tlf.Private:
		return keybase1.MerkleTreeID_KBFS_PRIVATE
	case tlf.Public:
		return keybase1.MerkleTreeID_KBFS_PUBLIC
	case tlf.SingleTeam:
		return keybase1.MerkleTreeID_KBFS_PRIVATETEAM
	default:
		panic(fmt.Sprintf("Unexpected TLF type: %d", id.Type()))
	}
}

// IsOnlyWriterInNonTeamTlf returns true if and only if the TLF described by h
// is a non-team TLF, and the currently logged-in user is the only writer for
// the TLF.  In case of any error false is returned.
func IsOnlyWriterInNonTeamTlf(ctx context.Context, kbpki KBPKI,
	h *TlfHandle) bool {
	session, err := GetCurrentSessionIfPossible(
		ctx, kbpki, h.Type() == tlf.Public)
	if err != nil {
		return false
	}
	if h.TypeForKeying() == tlf.TeamKeying {
		return false
	}
	return tlf.UserIsOnlyWriter(session.Name, h.GetCanonicalName())
}
<|endoftext|>


<commit_before>package markdown

import (
	"fmt"
	"strings"
)

// Render translates markdown to HTML
func Render(markdown string) (html string) {
	header := 0
	temp := handleItalic(handleBold(markdown))
	pos := 0
	list := 0
	html = ""
	for {
		char := temp[pos]
		if char == '#' {
			for char == '#' {
				header++
				pos++
				char = temp[pos]
			}
			html += fmt.Sprintf("<h%d>", header)
			pos++
			continue
		}
		if char == '*' {
			if list == 0 {
				html += "
"
			}
			html += "
"
			list++
			pos += 2
			continue
		}
		if char == '\n' {
			if list > 0 {
				html += "
"
			}
			if header > 0 {
				html += fmt.Sprintf("</h%d>", header)
				header = 0
			}
			pos++
			continue
		}
		html += string(char)
		pos++
		if pos >= len(temp) {
			break
		}
	}
	if header > 0 {
		return html + fmt.Sprintf("</h%d>", header)
	}
	if list > 0 {
		return html + "

"
	}
	return "
" + html + "
"
}

func handleBold(markdown string) string {
	markdown = strings.Replace(markdown, "__", "", 1)
	markdown = strings.Replace(markdown, "__", "", 1)
	return markdown
}

func handleItalic(markdown string) (result string) {
	markdown = strings.Replace(markdown, "_", "", 1)
	markdown = strings.Replace(markdown, "_", "", 1)
	return markdown
}
<commit_msg>Throw out old impl<commit_after>package markdown

import (
	"strings"
)

// Render translates markdown to HTML
func Render(markdown string) (html string) {
	markdown = handleBold(markdown)
	markdown = handleItalic(markdown)
	return wrapParagraph(markdown)
}

func wrapParagraph(s string) string {
	return "
" + s + "
"
}

func handleBold(markdown string) string {
	markdown = strings.Replace(markdown, "__", "", 1)
	markdown = strings.Replace(markdown, "__", "", 1)
	return markdown
}

func handleItalic(markdown string) (result string) {
	markdown = strings.Replace(markdown, "_", "", 1)
	markdown = strings.Replace(markdown, "_", "", 1)
	return markdown
}
<|endoftext|>


<commit_before>// Copyright 2017 Ole Krüger.
// Licensed under the MIT license which can be found in the LICENSE file.

package dpt

import (
	"fmt"
)

// DPT_10001 represents DPT 10.001 / TimeOfDay p. 34.
// Weekday is NOT a golang Weekday, but a KNX Day [0,...,7].
// It may be 0, indicating "no day" provided.
type DPT_10001 struct {
	Weekday uint8
	Hour    uint8
	Minutes uint8
	Seconds uint8
}

func (d DPT_10001) Pack() []byte {
	var buf = []byte{0, 0, 0, 0}
	if d.IsValid() {
		buf[1] = d.Weekday<<5 | d.Hour&0x1F
		buf[2] = d.Minutes
		buf[3] = d.Seconds
	}
	return []byte(buf)
}

func (d *DPT_10001) Unpack(data []byte) error {
	if len(data) != 4 {
		return nil
	}

	d.Weekday = uint8(data[1] >> 5)
	d.Hour = uint8(data[1] & 0x1F)
	d.Minutes = uint8(data[2] & 0x3F)
	d.Seconds = uint8(data[3] & 0x3F)

	if !d.IsValid() {
		return fmt.Errorf("payload is out of range")
	}

	return nil
}

func (d DPT_10001) Unit() string {
	return ""
}

func (d DPT_10001) IsValid() bool {
	return (d.Weekday <= 7 && d.Hour <= 23 && d.Minutes <= 59 && d.Hour <= 59)
}

func (d DPT_10001) String() string {
	weekday := []string{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}
	if 0 < d.Weekday && d.Weekday <= 7 {
		return fmt.Sprintf("%s %02d:%02d:%02d", weekday[d.Weekday - 1], d.Hour, d.Minutes, d.Seconds)
	} else {
		return fmt.Sprintf("%02d:%02d:%02d", d.Hour, d.Minutes, d.Seconds)
	}
}
<commit_msg>Fix formatting<commit_after>// Copyright 2017 Ole Krüger.
// Licensed under the MIT license which can be found in the LICENSE file.

package dpt

import (
	"fmt"
)

// DPT_10001 represents DPT 10.001 / TimeOfDay p. 34.
// Weekday is NOT a golang Weekday, but a KNX Day [0,...,7].
// It may be 0, indicating "no day" provided.
type DPT_10001 struct {
	Weekday uint8
	Hour    uint8
	Minutes uint8
	Seconds uint8
}

func (d DPT_10001) Pack() []byte {
	var buf = []byte{0, 0, 0, 0}
	if d.IsValid() {
		buf[1] = d.Weekday<<5 | d.Hour&0x1F
		buf[2] = d.Minutes
		buf[3] = d.Seconds
	}
	return []byte(buf)
}

func (d *DPT_10001) Unpack(data []byte) error {
	if len(data) != 4 {
		return nil
	}

	d.Weekday = uint8(data[1] >> 5)
	d.Hour = uint8(data[1] & 0x1F)
	d.Minutes = uint8(data[2] & 0x3F)
	d.Seconds = uint8(data[3] & 0x3F)

	if !d.IsValid() {
		return fmt.Errorf("payload is out of range")
	}

	return nil
}

func (d DPT_10001) Unit() string {
	return ""
}

func (d DPT_10001) IsValid() bool {
	return (d.Weekday <= 7 && d.Hour <= 23 && d.Minutes <= 59 && d.Hour <= 59)
}

func (d DPT_10001) String() string {
	weekday := []string{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}
	if 0 < d.Weekday && d.Weekday <= 7 {
		return fmt.Sprintf("%s %02d:%02d:%02d", weekday[d.Weekday-1], d.Hour, d.Minutes, d.Seconds)
	} else {
		return fmt.Sprintf("%02d:%02d:%02d", d.Hour, d.Minutes, d.Seconds)
	}
}
<|endoftext|>


<commit_before>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file tests types.Check by using it to
// typecheck the standard library and tests.

package types

import (
	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/scanner"
	"go/token"
	"io/ioutil"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
	"time"
)

var verbose = flag.Bool("types.v", false, "verbose mode")

var (
	pkgCount int // number of packages processed
	start    = time.Now()
)

func TestStdlib(t *testing.T) {
	walkDirs(t, filepath.Join(runtime.GOROOT(), "src/pkg"))
	if *verbose {
		fmt.Println(pkgCount, "packages typechecked in", time.Since(start))
	}
}

func testTestDir(t *testing.T, path string, ignore ...string) {
	files, err := ioutil.ReadDir(path)
	if err != nil {
		t.Fatal(err)
	}

	excluded := make(map[string]bool)
	for _, filename := range ignore {
		excluded[filename] = true
	}

	fset := token.NewFileSet()
	for _, f := range files {
		// filter directory contents
		if f.IsDir() || !strings.HasSuffix(f.Name(), ".go") || excluded[f.Name()] {
			continue
		}

		// parse file
		filename := filepath.Join(path, f.Name())
		// TODO(gri) The parser loses comments when bailing out early,
		//           and then we don't see the errorcheck command for
		//           some files. Use parser.AllErrors for now. Fix this.
		file, err := parser.ParseFile(fset, filename, nil, parser.ParseComments|parser.AllErrors)

		// check per-file instructions
		// For now we only check some cases.
		expectErrors := false
		if len(file.Comments) > 0 {
			if group := file.Comments[0]; len(group.List) > 0 {
				cmd := strings.TrimSpace(group.List[0].Text[2:]) // 2: ignore // or /* of comment
				switch cmd {
				case "skip", "compiledir":
					continue
				case "errorcheck":
					expectErrors = true
				}
			}
		}

		// type-check file if it parsed cleanly
		if err == nil {
			_, err = Check(filename, fset, []*ast.File{file})
		}

		if expectErrors {
			if err == nil {
				t.Errorf("expected errors but found none in %s", filename)
			}
		} else {
			if err != nil {
				t.Error(err)
			}
		}
	}
}

func TestStdtest(t *testing.T) {
	testTestDir(t, filepath.Join(runtime.GOROOT(), "test"),
		"cmplxdivide.go",       // also needs file cmplxdivide1.go - ignore
		"goto.go", "label1.go", // TODO(gri) implement missing label checks
		"mapnan.go", "sigchld.go", // don't work on Windows; testTestDir should consult build tags
		"sizeof.go", "switch.go", // TODO(gri) tone down duplicate checking in expr switches
		"typeswitch2.go", // TODO(gri) implement duplicate checking in type switches
	)
}

func TestStdfixed(t *testing.T) {
	testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "fixedbugs"),
		"bug050.go", "bug088.go", "bug106.go", // TODO(gri) parser loses comments when bailing out early
		"bug222.go", "bug282.go", "bug306.go", // TODO(gri) parser loses comments when bailing out early
		"issue4776.go",                        // TODO(gri) parser loses comments when bailing out early
		"bug136.go", "bug179.go", "bug344.go", // TODO(gri) implement missing label checks
		"bug251.go",                           // TODO(gri) incorrect cycle checks for interface types
		"bug165.go",                           // TODO(gri) isComparable not working for incomplete struct type
		"bug200.go",                           // TODO(gri) complete duplicate checking in expr switches
		"bug223.go", "bug413.go", "bug459.go", // TODO(gri) complete initialization checks
		"bug248.go", "bug302.go", "bug369.go", // complex test instructions - ignore
		"bug250.go",    // TODO(gri) fix recursive interfaces
		"bug376.go",    // TODO(gri) built-ins must be called (no built-in function expressions)
		"issue3924.go", // TODO(gri) && and || produce bool result (not untyped bool)
		"issue4847.go", // TODO(gri) initialization cycle error not found
	)
}

func TestStdken(t *testing.T) {
	testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "ken"))
}

// Package paths of excluded packages.
var excluded = map[string]bool{
	"builtin": true,
}

// typecheck typechecks the given package files.
func typecheck(t *testing.T, path string, filenames []string) {
	fset := token.NewFileSet()

	// parse package files
	var files []*ast.File
	for _, filename := range filenames {
		file, err := parser.ParseFile(fset, filename, nil, parser.AllErrors)
		if err != nil {
			// the parser error may be a list of individual errors; report them all
			if list, ok := err.(scanner.ErrorList); ok {
				for _, err := range list {
					t.Error(err)
				}
				return
			}
			t.Error(err)
			return
		}

		if *verbose {
			if len(files) == 0 {
				fmt.Println("package", file.Name.Name)
			}
			fmt.Println("\t", filename)
		}

		files = append(files, file)
	}

	// typecheck package files
	var conf Config
	conf.Error = func(err error) { t.Error(err) }
	conf.Check(path, fset, files, nil)
	pkgCount++
}

// pkgfiles returns the list of package files for the given directory.
func pkgfiles(t *testing.T, dir string) []string {
	ctxt := build.Default
	ctxt.CgoEnabled = false
	pkg, err := ctxt.ImportDir(dir, 0)
	if err != nil {
		if _, nogo := err.(*build.NoGoError); !nogo {
			t.Error(err)
		}
		return nil
	}
	if excluded[pkg.ImportPath] {
		return nil
	}
	var filenames []string
	for _, name := range pkg.GoFiles {
		filenames = append(filenames, filepath.Join(pkg.Dir, name))
	}
	for _, name := range pkg.TestGoFiles {
		filenames = append(filenames, filepath.Join(pkg.Dir, name))
	}
	return filenames
}

// Note: Could use filepath.Walk instead of walkDirs but that wouldn't
//       necessarily be shorter or clearer after adding the code to
//       terminate early for -short tests.

func walkDirs(t *testing.T, dir string) {
	// limit run time for short tests
	if testing.Short() && time.Since(start) >= 750*time.Millisecond {
		return
	}

	fis, err := ioutil.ReadDir(dir)
	if err != nil {
		t.Error(err)
		return
	}

	// typecheck package in directory
	if files := pkgfiles(t, dir); files != nil {
		typecheck(t, dir, files)
	}

	// traverse subdirectories, but don't walk into testdata
	for _, fi := range fis {
		if fi.IsDir() && fi.Name() != "testdata" {
			walkDirs(t, filepath.Join(dir, fi.Name()))
		}
	}
}
<commit_msg>go.tools/go/types: enable more std lib tests<commit_after>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file tests types.Check by using it to
// typecheck the standard library and tests.

package types

import (
	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/scanner"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
	"time"
)

var verbose = flag.Bool("types.v", false, "verbose mode")

var (
	pkgCount int // number of packages processed
	start    = time.Now()
)

func TestStdlib(t *testing.T) {
	walkDirs(t, filepath.Join(runtime.GOROOT(), "src/pkg"))
	if *verbose {
		fmt.Println(pkgCount, "packages typechecked in", time.Since(start))
	}
}

// firstComment returns the contents of the first comment in
// the given file, assuming there's one within the first KB.
func firstComment(filename string) string {
	f, err := os.Open(filename)
	if err != nil {
		return ""
	}
	defer f.Close()

	var src [1 << 10]byte // read at most 1KB
	n, _ := f.Read(src[:])

	var s scanner.Scanner
	s.Init(fset.AddFile("", fset.Base(), n), src[:n], nil, scanner.ScanComments)
	for {
		_, tok, lit := s.Scan()
		switch tok {
		case token.COMMENT:
			// remove trailing */ of multi-line comment
			if lit[1] == '*' {
				lit = lit[:len(lit)-2]
			}
			return strings.TrimSpace(lit[2:])
		case token.EOF:
			return ""
		}
	}
}

func testTestDir(t *testing.T, path string, ignore ...string) {
	files, err := ioutil.ReadDir(path)
	if err != nil {
		t.Fatal(err)
	}

	excluded := make(map[string]bool)
	for _, filename := range ignore {
		excluded[filename] = true
	}

	fset := token.NewFileSet()
	for _, f := range files {
		// filter directory contents
		if f.IsDir() || !strings.HasSuffix(f.Name(), ".go") || excluded[f.Name()] {
			continue
		}

		// get per-file instructions
		expectErrors := false
		filename := filepath.Join(path, f.Name())
		if cmd := firstComment(filename); cmd != "" {
			switch cmd {
			case "skip", "compiledir":
				continue // ignore this file
			case "errorcheck":
				expectErrors = true
			}
		}

		// parse and type-check file
		file, err := parser.ParseFile(fset, filename, nil, 0)
		if err == nil {
			_, err = Check(filename, fset, []*ast.File{file})
		}

		if expectErrors {
			if err == nil {
				t.Errorf("expected errors but found none in %s", filename)
			}
		} else {
			if err != nil {
				t.Error(err)
			}
		}
	}
}

func TestStdtest(t *testing.T) {
	testTestDir(t, filepath.Join(runtime.GOROOT(), "test"),
		"cmplxdivide.go",       // also needs file cmplxdivide1.go - ignore
		"goto.go", "label1.go", // TODO(gri) implement missing label checks
		"mapnan.go", "sigchld.go", // don't work on Windows; testTestDir should consult build tags
		"sizeof.go", "switch.go", // TODO(gri) tone down duplicate checking in expr switches
		"typeswitch2.go", // TODO(gri) implement duplicate checking in type switches
	)
}

func TestStdfixed(t *testing.T) {
	testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "fixedbugs"),
		"bug136.go", "bug179.go", "bug344.go", // TODO(gri) implement missing label checks
		"bug251.go",                           // TODO(gri) incorrect cycle checks for interface types
		"bug165.go",                           // TODO(gri) isComparable not working for incomplete struct type
		"bug200.go",                           // TODO(gri) complete duplicate checking in expr switches
		"bug223.go", "bug413.go", "bug459.go", // TODO(gri) complete initialization checks
		"bug248.go", "bug302.go", "bug369.go", // complex test instructions - ignore
		"bug250.go",    // TODO(gri) fix recursive interfaces
		"bug376.go",    // TODO(gri) built-ins must be called (no built-in function expressions)
		"issue3924.go", // TODO(gri) && and || produce bool result (not untyped bool)
		"issue4847.go", // TODO(gri) initialization cycle error not found
	)
}

func TestStdken(t *testing.T) {
	testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "ken"))
}

// Package paths of excluded packages.
var excluded = map[string]bool{
	"builtin": true,
}

// typecheck typechecks the given package files.
func typecheck(t *testing.T, path string, filenames []string) {
	fset := token.NewFileSet()

	// parse package files
	var files []*ast.File
	for _, filename := range filenames {
		file, err := parser.ParseFile(fset, filename, nil, parser.AllErrors)
		if err != nil {
			// the parser error may be a list of individual errors; report them all
			if list, ok := err.(scanner.ErrorList); ok {
				for _, err := range list {
					t.Error(err)
				}
				return
			}
			t.Error(err)
			return
		}

		if *verbose {
			if len(files) == 0 {
				fmt.Println("package", file.Name.Name)
			}
			fmt.Println("\t", filename)
		}

		files = append(files, file)
	}

	// typecheck package files
	var conf Config
	conf.Error = func(err error) { t.Error(err) }
	conf.Check(path, fset, files, nil)
	pkgCount++
}

// pkgfiles returns the list of package files for the given directory.
func pkgfiles(t *testing.T, dir string) []string {
	ctxt := build.Default
	ctxt.CgoEnabled = false
	pkg, err := ctxt.ImportDir(dir, 0)
	if err != nil {
		if _, nogo := err.(*build.NoGoError); !nogo {
			t.Error(err)
		}
		return nil
	}
	if excluded[pkg.ImportPath] {
		return nil
	}
	var filenames []string
	for _, name := range pkg.GoFiles {
		filenames = append(filenames, filepath.Join(pkg.Dir, name))
	}
	for _, name := range pkg.TestGoFiles {
		filenames = append(filenames, filepath.Join(pkg.Dir, name))
	}
	return filenames
}

// Note: Could use filepath.Walk instead of walkDirs but that wouldn't
//       necessarily be shorter or clearer after adding the code to
//       terminate early for -short tests.

func walkDirs(t *testing.T, dir string) {
	// limit run time for short tests
	if testing.Short() && time.Since(start) >= 750*time.Millisecond {
		return
	}

	fis, err := ioutil.ReadDir(dir)
	if err != nil {
		t.Error(err)
		return
	}

	// typecheck package in directory
	if files := pkgfiles(t, dir); files != nil {
		typecheck(t, dir, files)
	}

	// traverse subdirectories, but don't walk into testdata
	for _, fi := range fis {
		if fi.IsDir() && fi.Name() != "testdata" {
			walkDirs(t, filepath.Join(dir, fi.Name()))
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file tests types.Check by using it to
// typecheck the standard library.

package types

import (
	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/scanner"
	"go/token"
	"io/ioutil"
	"path/filepath"
	"runtime"
	"testing"
	"time"
)

var verbose = flag.Bool("types.v", false, "verbose mode")

var (
	pkgCount int // number of packages processed
	start    = time.Now()
)

func TestStdlib(t *testing.T) {
	walkDirs(t, filepath.Join(runtime.GOROOT(), "src/pkg"))
	if *verbose {
		fmt.Println(pkgCount, "packages typechecked in", time.Since(start))
	}
}

// Package paths of excluded packages.
var excluded = map[string]bool{
	"builtin": true,
}

// typecheck typechecks the given package files.
func typecheck(t *testing.T, path string, filenames []string) {
	fset := token.NewFileSet()

	// parse package files
	var files []*ast.File
	for _, filename := range filenames {
		file, err := parser.ParseFile(fset, filename, nil, parser.AllErrors)
		if err != nil {
			// the parser error may be a list of individual errors; report them all
			if list, ok := err.(scanner.ErrorList); ok {
				for _, err := range list {
					t.Error(err)
				}
				return
			}
			t.Error(err)
			return
		}

		if *verbose {
			if len(files) == 0 {
				fmt.Println("package", file.Name.Name)
			}
			fmt.Println("\t", filename)
		}

		files = append(files, file)
	}

	// typecheck package files
	var conf Config
	conf.Error = func(err error) { t.Error(err) }
	conf.Check(path, fset, files, nil)
	pkgCount++
}

// pkgfiles returns the list of package files for the given directory.
func pkgfiles(t *testing.T, dir string) []string {
	ctxt := build.Default
	ctxt.CgoEnabled = false
	pkg, err := ctxt.ImportDir(dir, 0)
	if err != nil {
		if _, nogo := err.(*build.NoGoError); !nogo {
			t.Error(err)
		}
		return nil
	}
	if excluded[pkg.ImportPath] {
		return nil
	}
	var filenames []string
	for _, name := range pkg.GoFiles {
		filenames = append(filenames, filepath.Join(pkg.Dir, name))
	}
	for _, name := range pkg.TestGoFiles {
		filenames = append(filenames, filepath.Join(pkg.Dir, name))
	}
	return filenames
}

// Note: Could use filepath.Walk instead of walkDirs but that wouldn't
//       necessarily be shorter or clearer after adding the code to
//       terminate early for -short tests.

func walkDirs(t *testing.T, dir string) {
	// limit run time for short tests
	if testing.Short() && time.Since(start) >= 750*time.Millisecond {
		return
	}

	fis, err := ioutil.ReadDir(dir)
	if err != nil {
		t.Error(err)
		return
	}

	// typecheck package in directory
	if files := pkgfiles(t, dir); files != nil {
		typecheck(t, dir, files)
	}

	// traverse subdirectories, but don't walk into testdata
	for _, fi := range fis {
		if fi.IsDir() && fi.Name() != "testdata" {
			walkDirs(t, filepath.Join(dir, fi.Name()))
		}
	}
}
<commit_msg>go.tools/go/types: check type-checker against $GOROOT/test<commit_after>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file tests types.Check by using it to
// typecheck the standard library and tests.

package types

import (
	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/scanner"
	"go/token"
	"io/ioutil"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
	"time"
)

var verbose = flag.Bool("types.v", false, "verbose mode")

var (
	pkgCount int // number of packages processed
	start    = time.Now()
)

func TestStdlib(t *testing.T) {
	walkDirs(t, filepath.Join(runtime.GOROOT(), "src/pkg"))
	if *verbose {
		fmt.Println(pkgCount, "packages typechecked in", time.Since(start))
	}
}

func TestStdtest(t *testing.T) {
	path := filepath.Join(runtime.GOROOT(), "test")

	files, err := ioutil.ReadDir(path)
	if err != nil {
		t.Fatal(err)
	}

	fset := token.NewFileSet()
	for _, f := range files {
		// filter directory contents
		if f.IsDir() || !strings.HasSuffix(f.Name(), ".go") {
			continue
		}

		// explicitly exclude files that the type-checker still has problems with
		switch f.Name() {
		case "cmplxdivide.go":
			// This test also needs file cmplxdivide1.go; ignore.
			continue
		case "goto.go", "label1.go":
			// TODO(gri) implement missing label checks
			continue
		case "map1.go":
			// TODO(gri) fix map key checking
			continue
		case "shift2.go":
			// TODO(gri) fix constant shift expression error
			// (default type for 1.0<<1 is int, not float64).
			continue
		case "sizeof.go", "switch.go":
			// TODO(gri) tone down duplicate checking in expression switches
			continue
		case "switch4.go":
			// TODO(gri) fix fallthrough checking
			continue
		case "typeswitch2.go":
			// TODO(gri) implement duplicate checking in type switches
			continue
		}

		// parse file
		filename := filepath.Join(path, f.Name())
		// TODO(gri) The parser loses comments when bailing out early,
		//           and then we don't see the errorcheck command for
		//           some files. Use parser.AllErrors for now. Fix this.
		file, err := parser.ParseFile(fset, filename, nil, parser.ParseComments|parser.AllErrors)

		// check per-file instructions
		// For now we only check two cases.
		expectErrors := false
		if len(file.Comments) > 0 {
			if group := file.Comments[0]; len(group.List) > 0 {
				cmd := strings.TrimSpace(group.List[0].Text[2:]) // 2: ignore // or /* of comment
				switch cmd {
				case "skip":
					continue
				case "errorcheck":
					expectErrors = true
				}
			}
		}

		// type-check file if it parsed cleanly
		if err == nil {
			_, err = Check(filename, fset, []*ast.File{file})
		}

		if expectErrors {
			if err == nil {
				t.Errorf("expected errors but found none in %s", filename)
			}
		} else {
			if err != nil {
				t.Error(err)
			}
		}
	}
}

// Package paths of excluded packages.
var excluded = map[string]bool{
	"builtin": true,
}

// typecheck typechecks the given package files.
func typecheck(t *testing.T, path string, filenames []string) {
	fset := token.NewFileSet()

	// parse package files
	var files []*ast.File
	for _, filename := range filenames {
		file, err := parser.ParseFile(fset, filename, nil, parser.AllErrors)
		if err != nil {
			// the parser error may be a list of individual errors; report them all
			if list, ok := err.(scanner.ErrorList); ok {
				for _, err := range list {
					t.Error(err)
				}
				return
			}
			t.Error(err)
			return
		}

		if *verbose {
			if len(files) == 0 {
				fmt.Println("package", file.Name.Name)
			}
			fmt.Println("\t", filename)
		}

		files = append(files, file)
	}

	// typecheck package files
	var conf Config
	conf.Error = func(err error) { t.Error(err) }
	conf.Check(path, fset, files, nil)
	pkgCount++
}

// pkgfiles returns the list of package files for the given directory.
func pkgfiles(t *testing.T, dir string) []string {
	ctxt := build.Default
	ctxt.CgoEnabled = false
	pkg, err := ctxt.ImportDir(dir, 0)
	if err != nil {
		if _, nogo := err.(*build.NoGoError); !nogo {
			t.Error(err)
		}
		return nil
	}
	if excluded[pkg.ImportPath] {
		return nil
	}
	var filenames []string
	for _, name := range pkg.GoFiles {
		filenames = append(filenames, filepath.Join(pkg.Dir, name))
	}
	for _, name := range pkg.TestGoFiles {
		filenames = append(filenames, filepath.Join(pkg.Dir, name))
	}
	return filenames
}

// Note: Could use filepath.Walk instead of walkDirs but that wouldn't
//       necessarily be shorter or clearer after adding the code to
//       terminate early for -short tests.

func walkDirs(t *testing.T, dir string) {
	// limit run time for short tests
	if testing.Short() && time.Since(start) >= 750*time.Millisecond {
		return
	}

	fis, err := ioutil.ReadDir(dir)
	if err != nil {
		t.Error(err)
		return
	}

	// typecheck package in directory
	if files := pkgfiles(t, dir); files != nil {
		typecheck(t, dir, files)
	}

	// traverse subdirectories, but don't walk into testdata
	for _, fi := range fis {
		if fi.IsDir() && fi.Name() != "testdata" {
			walkDirs(t, filepath.Join(dir, fi.Name()))
		}
	}
}
<|endoftext|>


<commit_before>/*
Command-line interface for http://www.multitran.ru/
*/
package main

import (
	"errors"
	"flag"
	"fmt"
	"gomultitran/webapi"
	"os"
	"sort"
	"strings"
	"unicode/utf8"
)

var lang string
var availableLangs []string

// Set command-line flags
func init() {
	// Get languages in alphabetical order
	availableLangs = make([]string, len(webapi.Languages))
	var i int
	for k, _ := range webapi.Languages {
		availableLangs[i] = k
		i++
	}
	sort.Strings(availableLangs)
	// Get list of available languages for usage
	usage := "Translation language. Available values:\n\t" +
		strings.Join(availableLangs, "\n\t")
	defaultLang := "english"
	flag.StringVar(&lang, "language", defaultLang, usage)
	flag.StringVar(&lang, "l", defaultLang, "Same as -language")
}

// Usage text
func usage() {
	fmt.Fprintf(os.Stderr, "Usage: %s [-l|-language lang] query\n",
		os.Args[0])
	flag.PrintDefaults()
}

// Validate command-line arguments
func parseArgs() (query string, err error) {
	var found bool
	for _, v := range availableLangs {
		if v == lang {
			found = true
		}
	}
	if !found {
		err = errors.New("Language not available")
	}
	query = strings.Join(flag.Args(), " ")
	if len(query) == 0 {
		err = errors.New("Query required")
	}
	return
}

// Get maximum length of word topic (left column)
func getMaxTopicLen(wl *[]webapi.WordList) int {
	var maxLen int
	var max string
	for _, wlist := range *wl {
		for _, w := range wlist.Words {
			for _, m := range w.Meanings {
				if len(m.Abbrev) > maxLen {
					maxLen = len(m.Abbrev)
					max = m.Abbrev
				}
			}
		}
	}
	return utf8.RuneCountInString(max)
}

// Print WordList heading
func printWordList(wlist *webapi.WordList, maxTopicLen int) {
	length := utf8.RuneCountInString(wlist.Query)
	fmt.Printf(" %s\n", strings.Repeat("=", length))
	fmt.Printf(" %s\n", wlist.Query)
	fmt.Printf(" %s\n", strings.Repeat("=", length))
	printWordListContents(wlist, maxTopicLen)
}

// Print WordList contents
func printWordListContents(wlist *webapi.WordList, maxTopicLen int) {
	for _, word := range wlist.Words {
		partLen := 0
		if len(word.Part) > 0 {
			partLen += utf8.RuneCountInString(word.Part) + 1
		}
		length := utf8.RuneCountInString(word.Word) + partLen
		// fmt.Printf("%s\n", strings.Repeat("-", length))
		fmt.Printf(" %s %s\n", word.Word, word.Part)
		fmt.Printf(" %s\n", strings.Repeat("-", length))
		printWord(&word, maxTopicLen)
	}
}

// Print one word
func printWord(word *webapi.Word, maxTopicLen int) {
	for _, m := range word.Meanings {
		fmt.Printf(" %*s  ", maxTopicLen, m.Abbrev)
		words := make([]string, 0, len(m.Words))
		for _, w := range m.Words {
			// Add space to additional info if needed
			if len(w.Add) > 0 && !strings.HasPrefix(w.Add, " ") {
				w.Add = " " + w.Add
			}
			words = append(words,
				fmt.Sprintf("%s%s", w.Word, w.Add))
		}
		fmt.Printf("%s\n", strings.Join(words, ", "))
	}
}

// Print meaning list
func printResult(result *[]webapi.WordList) {
	// Get longest column for pretty printing
	maxTopicLen := getMaxTopicLen(result)
	for _, wlist := range *result {
		printWordList(&wlist, maxTopicLen)
		fmt.Printf("\n")
	}
}

func main() {
	flag.Usage = usage
	flag.Parse()
	query, err := parseArgs()
	if err != nil {
		fmt.Printf("Error: %s\n", err)
		usage()
		return
	}
	result, err := webapi.Query(query, webapi.Languages[lang])
	if err != nil {
		fmt.Printf("Error: %s\n", err)
		return
	}
	printResult(&result)
}
<commit_msg>Move webapi.go to bitbucket<commit_after>/*
Command-line interface for http://www.multitran.ru/
*/
package main

import (
	"errors"
	"flag"
	"fmt"
	"bitbucket.org/vladimir_g/gomultitran/webapi"
	"os"
	"sort"
	"strings"
	"unicode/utf8"
)

var lang string
var availableLangs []string

// Set command-line flags
func init() {
	// Get languages in alphabetical order
	availableLangs = make([]string, len(webapi.Languages))
	var i int
	for k, _ := range webapi.Languages {
		availableLangs[i] = k
		i++
	}
	sort.Strings(availableLangs)
	// Get list of available languages for usage
	usage := "Translation language. Available values:\n\t" +
		strings.Join(availableLangs, "\n\t")
	defaultLang := "english"
	flag.StringVar(&lang, "language", defaultLang, usage)
	flag.StringVar(&lang, "l", defaultLang, "Same as -language")
}

// Usage text
func usage() {
	fmt.Fprintf(os.Stderr, "Usage: %s [-l|-language lang] query\n",
		os.Args[0])
	flag.PrintDefaults()
}

// Validate command-line arguments
func parseArgs() (query string, err error) {
	var found bool
	for _, v := range availableLangs {
		if v == lang {
			found = true
		}
	}
	if !found {
		err = errors.New("Language not available")
	}
	query = strings.Join(flag.Args(), " ")
	if len(query) == 0 {
		err = errors.New("Query required")
	}
	return
}

// Get maximum length of word topic (left column)
func getMaxTopicLen(wl *[]webapi.WordList) int {
	var maxLen int
	var max string
	for _, wlist := range *wl {
		for _, w := range wlist.Words {
			for _, m := range w.Meanings {
				if len(m.Abbrev) > maxLen {
					maxLen = len(m.Abbrev)
					max = m.Abbrev
				}
			}
		}
	}
	return utf8.RuneCountInString(max)
}

// Print WordList heading
func printWordList(wlist *webapi.WordList, maxTopicLen int) {
	length := utf8.RuneCountInString(wlist.Query)
	fmt.Printf(" %s\n", strings.Repeat("=", length))
	fmt.Printf(" %s\n", wlist.Query)
	fmt.Printf(" %s\n", strings.Repeat("=", length))
	printWordListContents(wlist, maxTopicLen)
}

// Print WordList contents
func printWordListContents(wlist *webapi.WordList, maxTopicLen int) {
	for _, word := range wlist.Words {
		partLen := 0
		if len(word.Part) > 0 {
			partLen += utf8.RuneCountInString(word.Part) + 1
		}
		length := utf8.RuneCountInString(word.Word) + partLen
		// fmt.Printf("%s\n", strings.Repeat("-", length))
		fmt.Printf(" %s %s\n", word.Word, word.Part)
		fmt.Printf(" %s\n", strings.Repeat("-", length))
		printWord(&word, maxTopicLen)
	}
}

// Print one word
func printWord(word *webapi.Word, maxTopicLen int) {
	for _, m := range word.Meanings {
		fmt.Printf(" %*s  ", maxTopicLen, m.Abbrev)
		words := make([]string, 0, len(m.Words))
		for _, w := range m.Words {
			// Add space to additional info if needed
			if len(w.Add) > 0 && !strings.HasPrefix(w.Add, " ") {
				w.Add = " " + w.Add
			}
			words = append(words,
				fmt.Sprintf("%s%s", w.Word, w.Add))
		}
		fmt.Printf("%s\n", strings.Join(words, ", "))
	}
}

// Print meaning list
func printResult(result *[]webapi.WordList) {
	// Get longest column for pretty printing
	maxTopicLen := getMaxTopicLen(result)
	for _, wlist := range *result {
		printWordList(&wlist, maxTopicLen)
		fmt.Printf("\n")
	}
}

func main() {
	flag.Usage = usage
	flag.Parse()
	query, err := parseArgs()
	if err != nil {
		fmt.Printf("Error: %s\n", err)
		usage()
		return
	}
	result, err := webapi.Query(query, webapi.Languages[lang])
	if err != nil {
		fmt.Printf("Error: %s\n", err)
		return
	}
	printResult(&result)
}
<|endoftext|>


<commit_before>package labyrinth

import "github.com/hajimehoshi/ebiten"

type wizard struct {
	image             *ebiten.Image
	TopLeft           *coord
	moveSpeed         int
	fireballs         []*fireball
	fireCreator       *fireballCreator
	upKeys            []ebiten.Key
	downKeys          []ebiten.Key
	minPlayAreaHeight int
}

// newWizard returns an initialized wizard
func newWizard(i *ebiten.Image, speed int, fbc *fireballCreator, upkeys, downkeys []ebiten.Key, minPlayAreaHeight int) *wizard {
	c := &coord{
		x: 50,
		y: minPlayAreaHeight,
	}

	return &wizard{
		image:             i,
		TopLeft:           c,
		moveSpeed:         speed,
		fireCreator:       fbc,
		upKeys:            upkeys,
		downKeys:          downkeys,
		minPlayAreaHeight: minPlayAreaHeight,
	}
}

func (w *wizard) Update(keys *KeyboardWrapper) error {
	movedUp := false
	for _, k := range w.upKeys {
		if keys.IsKeyPressed(k) && !movedUp {
			w.moveUp()
			movedUp = true
		}
	}

	movedDown := false
	for _, k := range w.downKeys {
		if keys.IsKeyPressed(k) && !movedDown {
			w.moveDown()
			movedDown = true
		}
	}

	if keys.IsKeyPressed(ebiten.KeySpace) {
		if len(w.fireballs) == 0 {
			// We cannot send a pointer to newFireball because then when we move
			// the fireball it will move the wizard! Comical, yes but not desired.
			f := w.fireCreator.newFireball(*center(w.TopLeft, w.image), normalFireball)
			w.fireballs = append(w.fireballs, f)
		}
	}

	activeFireballs := []*fireball{}
	for _, f := range w.fireballs {
		if err := f.Update(); err != nil {
			return err
		}
		if f.active {
			activeFireballs = append(activeFireballs, f)
		}
	}

	// Only keep active fireballs in the array
	w.fireballs = activeFireballs

	return nil
}

func (w *wizard) moveUp() {
	w.TopLeft.y -= w.moveSpeed
	if w.TopLeft.y <= w.minPlayAreaHeight {
		w.TopLeft.y = w.minPlayAreaHeight
	}
}

func (w *wizard) moveDown() {
	w.TopLeft.y += w.moveSpeed
	_, h := w.image.Size()
	if w.TopLeft.y+h >= ScreenHeight {
		w.TopLeft.y = ScreenHeight - h
	}
}

func (w *wizard) Draw(r *ebiten.Image) error {
	r.DrawImage(w.image, &ebiten.DrawImageOptions{
		ImageParts: w,
	})

	for _, f := range w.fireballs {
		if err := f.Draw(r); err != nil {
			return err
		}
	}

	return nil
}

func (w *wizard) Len() int {
	return 1
}

func (w *wizard) Dst(i int) (x0, y0, x1, y1 int) {
	return defaultStationaryDST(i, w.TopLeft, w.image)
}

func (w *wizard) Src(i int) (x0, y0, x1, y1 int) {
	width, height := w.image.Size()
	return 0, 0, width, height
}

func (w *wizard) activate(p *powerup) {
	// TODO implement powerup logic here, somehow.
}
<commit_msg>wizard interacts with powerup<commit_after>package labyrinth

import "github.com/hajimehoshi/ebiten"

type wizard struct {
	image             *ebiten.Image
	TopLeft           *coord
	moveSpeed         int
	fireballs         []*fireball
	fireCreator       *fireballCreator
	upKeys            []ebiten.Key
	downKeys          []ebiten.Key
	minPlayAreaHeight int
}

// newWizard returns an initialized wizard
func newWizard(i *ebiten.Image, speed int, fbc *fireballCreator, upkeys, downkeys []ebiten.Key, minPlayAreaHeight int) *wizard {
	c := &coord{
		x: 50,
		y: minPlayAreaHeight,
	}

	return &wizard{
		image:             i,
		TopLeft:           c,
		moveSpeed:         speed,
		fireCreator:       fbc,
		upKeys:            upkeys,
		downKeys:          downkeys,
		minPlayAreaHeight: minPlayAreaHeight,
	}
}

func (w *wizard) Update(keys *KeyboardWrapper) error {
	movedUp := false
	for _, k := range w.upKeys {
		if keys.IsKeyPressed(k) && !movedUp {
			w.moveUp()
			movedUp = true
		}
	}

	movedDown := false
	for _, k := range w.downKeys {
		if keys.IsKeyPressed(k) && !movedDown {
			w.moveDown()
			movedDown = true
		}
	}

	if keys.IsKeyPressed(ebiten.KeySpace) {
		if len(w.fireballs) == 0 {
			// We cannot send a pointer to newFireball because then when we move
			// the fireball it will move the wizard! Comical, yes but not desired.
			f := w.fireCreator.newFireball(*center(w.TopLeft, w.image), normalFireball)
			w.fireballs = append(w.fireballs, f)
		}
	}

	activeFireballs := []*fireball{}
	for _, f := range w.fireballs {
		if err := f.Update(); err != nil {
			return err
		}
		if f.active {
			activeFireballs = append(activeFireballs, f)
		}
	}

	// Only keep active fireballs in the array
	w.fireballs = activeFireballs

	return nil
}

func (w *wizard) moveUp() {
	w.TopLeft.y -= w.moveSpeed
	if w.TopLeft.y <= w.minPlayAreaHeight {
		w.TopLeft.y = w.minPlayAreaHeight
	}
}

func (w *wizard) moveDown() {
	w.TopLeft.y += w.moveSpeed
	_, h := w.image.Size()
	if w.TopLeft.y+h >= ScreenHeight {
		w.TopLeft.y = ScreenHeight - h
	}
}

func (w *wizard) Draw(r *ebiten.Image) error {
	r.DrawImage(w.image, &ebiten.DrawImageOptions{
		ImageParts: w,
	})

	for _, f := range w.fireballs {
		if err := f.Draw(r); err != nil {
			return err
		}
	}

	return nil
}

func (w *wizard) Len() int {
	return 1
}

func (w *wizard) Dst(i int) (x0, y0, x1, y1 int) {
	return defaultStationaryDST(i, w.TopLeft, w.image)
}

func (w *wizard) Src(i int) (x0, y0, x1, y1 int) {
	width, height := w.image.Size()
	return 0, 0, width, height
}

func (w *wizard) activate(p *powerup) {
	// TODO implement powerup logic here, somehow.
	switch {
	case p.class == fastPowerup:
		w.moveSpeed += 5
	}
}
<|endoftext|>


<commit_before>package dtls

import (
	"context"
	"crypto/tls"
	"sync"
	"testing"
	"time"

	"github.com/pion/dtls/v2/pkg/crypto/selfsign"
	"github.com/pion/logging"
	"github.com/pion/transport/test"
)

const nonZeroRetransmitInterval = 100 * time.Millisecond

func TestHandshaker(t *testing.T) {
	// Check for leaking routines
	report := test.CheckRoutines(t)
	defer report()

	loggerFactory := logging.NewDefaultLoggerFactory()
	logger := loggerFactory.NewLogger("dtls")

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	cipherSuites, err := parseCipherSuites(nil, true, false)
	if err != nil {
		t.Fatal(err)
	}
	clientCert, err := selfsign.GenerateSelfSigned()
	if err != nil {
		t.Fatal(err)
	}

	ca, cb := flightTestPipe(ctx)
	ca.state.isClient = true

	var wg sync.WaitGroup
	wg.Add(2)

	ctxCliFinished, cancelCli := context.WithCancel(ctx)
	ctxSrvFinished, cancelSrv := context.WithCancel(ctx)
	go func() {
		defer wg.Done()
		cfg := &handshakeConfig{
			localCipherSuites:     cipherSuites,
			localCertificates:     []tls.Certificate{clientCert},
			localSignatureSchemes: defaultSignatureSchemes(),
			insecureSkipVerify:    true,
			log:                   logger,
			onFlightState: func(f flightVal, s handshakeState) {
				if s == handshakeFinished {
					cancelCli()
				}
			},
			retransmitInterval: nonZeroRetransmitInterval,
		}

		fsm := newHandshakeFSM(&ca.state, ca.handshakeCache, cfg, flight1)
		switch err := fsm.Run(ctx, ca, handshakePreparing); err {
		case context.Canceled:
		case context.DeadlineExceeded:
			t.Error("Timeout")
		default:
			t.Error(err)
		}
	}()

	go func() {
		defer wg.Done()
		cfg := &handshakeConfig{
			localCipherSuites:     cipherSuites,
			localCertificates:     []tls.Certificate{clientCert},
			localSignatureSchemes: defaultSignatureSchemes(),
			insecureSkipVerify:    true,
			log:                   logger,
			onFlightState: func(f flightVal, s handshakeState) {
				if s == handshakeFinished {
					cancelSrv()
				}
			},
		}

		fsm := newHandshakeFSM(&cb.state, cb.handshakeCache, cfg, flight0)
		switch err := fsm.Run(ctx, cb, handshakePreparing); err {
		case context.Canceled:
		case context.DeadlineExceeded:
			t.Error("Timeout")
		default:
			t.Error(err)
		}
	}()

	<-ctxCliFinished.Done()
	<-ctxSrvFinished.Done()

	cancel()
	wg.Wait()
}

func flightTestPipe(ctx context.Context) (*flightTestConn, *flightTestConn) {
	ca := newHandshakeCache()
	cb := newHandshakeCache()
	chA := make(chan chan struct{})
	chB := make(chan chan struct{})
	return &flightTestConn{
			handshakeCache: ca,
			otherEndCache:  cb,
			recv:           chA,
			otherEndRecv:   chB,
			done:           ctx.Done(),
		}, &flightTestConn{
			handshakeCache: cb,
			otherEndCache:  ca,
			recv:           chB,
			otherEndRecv:   chA,
			done:           ctx.Done(),
		}
}

type flightTestConn struct {
	state          State
	handshakeCache *handshakeCache
	recv           chan chan struct{}
	done           <-chan struct{}
	epoch          uint16

	otherEndCache *handshakeCache
	otherEndRecv  chan chan struct{}
}

func (c *flightTestConn) recvHandshake() <-chan chan struct{} {
	return c.recv
}

func (c *flightTestConn) setLocalEpoch(epoch uint16) {
	c.epoch = epoch
}

func (c *flightTestConn) notify(ctx context.Context, level alertLevel, desc alertDescription) error {
	return nil
}

func (c *flightTestConn) writePackets(ctx context.Context, pkts []*packet) error {
	for _, p := range pkts {
		if h, ok := p.record.content.(*handshake); ok {
			handshakeRaw, err := p.record.Marshal()
			if err != nil {
				return err
			}

			c.handshakeCache.push(handshakeRaw[recordLayerHeaderSize:], p.record.recordLayerHeader.epoch, h.handshakeHeader.messageSequence, h.handshakeHeader.handshakeType, c.state.isClient)

			content, err := h.handshakeMessage.Marshal()
			if err != nil {
				return err
			}
			h.handshakeHeader.length = uint32(len(content))
			h.handshakeHeader.fragmentLength = uint32(len(content))
			hdr, err := h.handshakeHeader.Marshal()
			if err != nil {
				return err
			}
			c.otherEndCache.push(
				append(hdr, content...), p.record.recordLayerHeader.epoch, h.handshakeHeader.messageSequence, h.handshakeHeader.handshakeType, c.state.isClient)
		}
	}
	go func() {
		select {
		case c.otherEndRecv <- make(chan struct{}):
		case <-c.done:
		}
	}()

	// Avoid deadlock on JS/WASM environment due to context switch problem.
	time.Sleep(10 * time.Millisecond)

	return nil
}

func (c *flightTestConn) handleQueuedPackets(ctx context.Context) error {
	return nil
}
<commit_msg>Test to verify HelloVerifyRequest retransmit cond<commit_after>package dtls

import (
	"context"
	"crypto/tls"
	"sync"
	"testing"
	"time"

	"github.com/pion/dtls/v2/pkg/crypto/selfsign"
	"github.com/pion/logging"
	"github.com/pion/transport/test"
)

const nonZeroRetransmitInterval = 100 * time.Millisecond

func TestHandshaker(t *testing.T) {
	// Check for leaking routines
	report := test.CheckRoutines(t)
	defer report()

	loggerFactory := logging.NewDefaultLoggerFactory()
	logger := loggerFactory.NewLogger("dtls")

	cipherSuites, err := parseCipherSuites(nil, true, false)
	if err != nil {
		t.Fatal(err)
	}
	clientCert, err := selfsign.GenerateSelfSigned()
	if err != nil {
		t.Fatal(err)
	}

	genFilters := map[string]func() (packetFilter, packetFilter, func(t *testing.T)){
		"PassThrough": func() (packetFilter, packetFilter, func(t *testing.T)) {
			return nil, nil, nil
		},
		"HelloVerifyRequestLost": func() (packetFilter, packetFilter, func(t *testing.T)) {
			var (
				cntHelloVerifyRequest  = 0
				cntClientHelloNoCookie = 0
			)
			const helloVerifyDrop = 5
			return func(p *packet) bool {
					h, ok := p.record.content.(*handshake)
					if !ok {
						return true
					}
					if hmch, ok := h.handshakeMessage.(*handshakeMessageClientHello); ok {
						if len(hmch.cookie) == 0 {
							cntClientHelloNoCookie++
						}
					}
					return true
				},
				func(p *packet) bool {
					h, ok := p.record.content.(*handshake)
					if !ok {
						return true
					}
					if _, ok := h.handshakeMessage.(*handshakeMessageHelloVerifyRequest); ok {
						cntHelloVerifyRequest++
						return cntHelloVerifyRequest > helloVerifyDrop
					}
					return true
				},
				func(t *testing.T) {
					if cntHelloVerifyRequest != helloVerifyDrop+1 {
						t.Errorf("Number of HelloVerifyRequest retransmit is wrong, expected: %d times, got: %d times", helloVerifyDrop+1, cntHelloVerifyRequest)
					}
					if cntClientHelloNoCookie != cntHelloVerifyRequest {
						t.Errorf(
							"HelloVerifyRequest must be triggered only by ClientHello, but HelloVerifyRequest was sent %d times and ClientHello was sent %d times",
							cntHelloVerifyRequest, cntClientHelloNoCookie,
						)
					}
				}
		},
	}

	for name, filters := range genFilters {
		f1, f2, report := filters()
		t.Run(name, func(t *testing.T) {
			ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
			defer cancel()

			if report != nil {
				defer report(t)
			}

			ca, cb := flightTestPipe(ctx, f1, f2)
			ca.state.isClient = true

			var wg sync.WaitGroup
			wg.Add(2)

			ctxCliFinished, cancelCli := context.WithCancel(ctx)
			ctxSrvFinished, cancelSrv := context.WithCancel(ctx)
			go func() {
				defer wg.Done()
				cfg := &handshakeConfig{
					localCipherSuites:     cipherSuites,
					localCertificates:     []tls.Certificate{clientCert},
					localSignatureSchemes: defaultSignatureSchemes(),
					insecureSkipVerify:    true,
					log:                   logger,
					onFlightState: func(f flightVal, s handshakeState) {
						if s == handshakeFinished {
							cancelCli()
						}
					},
					retransmitInterval: nonZeroRetransmitInterval,
				}

				fsm := newHandshakeFSM(&ca.state, ca.handshakeCache, cfg, flight1)
				switch err := fsm.Run(ctx, ca, handshakePreparing); err {
				case context.Canceled:
				case context.DeadlineExceeded:
					t.Error("Timeout")
				default:
					t.Error(err)
				}
			}()

			go func() {
				defer wg.Done()
				cfg := &handshakeConfig{
					localCipherSuites:     cipherSuites,
					localCertificates:     []tls.Certificate{clientCert},
					localSignatureSchemes: defaultSignatureSchemes(),
					insecureSkipVerify:    true,
					log:                   logger,
					onFlightState: func(f flightVal, s handshakeState) {
						if s == handshakeFinished {
							cancelSrv()
						}
					},
					retransmitInterval: nonZeroRetransmitInterval,
				}

				fsm := newHandshakeFSM(&cb.state, cb.handshakeCache, cfg, flight0)
				switch err := fsm.Run(ctx, cb, handshakePreparing); err {
				case context.Canceled:
				case context.DeadlineExceeded:
					t.Error("Timeout")
				default:
					t.Error(err)
				}
			}()

			<-ctxCliFinished.Done()
			<-ctxSrvFinished.Done()

			cancel()
			wg.Wait()
		})
	}
}

type packetFilter func(*packet) bool

func flightTestPipe(ctx context.Context, filter1 packetFilter, filter2 packetFilter) (*flightTestConn, *flightTestConn) {
	ca := newHandshakeCache()
	cb := newHandshakeCache()
	chA := make(chan chan struct{})
	chB := make(chan chan struct{})
	return &flightTestConn{
			handshakeCache: ca,
			otherEndCache:  cb,
			recv:           chA,
			otherEndRecv:   chB,
			done:           ctx.Done(),
			filter:         filter1,
		}, &flightTestConn{
			handshakeCache: cb,
			otherEndCache:  ca,
			recv:           chB,
			otherEndRecv:   chA,
			done:           ctx.Done(),
			filter:         filter2,
		}
}

type flightTestConn struct {
	state          State
	handshakeCache *handshakeCache
	recv           chan chan struct{}
	done           <-chan struct{}
	epoch          uint16

	filter packetFilter

	otherEndCache *handshakeCache
	otherEndRecv  chan chan struct{}
}

func (c *flightTestConn) recvHandshake() <-chan chan struct{} {
	return c.recv
}

func (c *flightTestConn) setLocalEpoch(epoch uint16) {
	c.epoch = epoch
}

func (c *flightTestConn) notify(ctx context.Context, level alertLevel, desc alertDescription) error {
	return nil
}

func (c *flightTestConn) writePackets(ctx context.Context, pkts []*packet) error {
	for _, p := range pkts {
		if c.filter != nil && !c.filter(p) {
			continue
		}
		if h, ok := p.record.content.(*handshake); ok {
			handshakeRaw, err := p.record.Marshal()
			if err != nil {
				return err
			}

			c.handshakeCache.push(handshakeRaw[recordLayerHeaderSize:], p.record.recordLayerHeader.epoch, h.handshakeHeader.messageSequence, h.handshakeHeader.handshakeType, c.state.isClient)

			content, err := h.handshakeMessage.Marshal()
			if err != nil {
				return err
			}
			h.handshakeHeader.length = uint32(len(content))
			h.handshakeHeader.fragmentLength = uint32(len(content))
			hdr, err := h.handshakeHeader.Marshal()
			if err != nil {
				return err
			}
			c.otherEndCache.push(
				append(hdr, content...), p.record.recordLayerHeader.epoch, h.handshakeHeader.messageSequence, h.handshakeHeader.handshakeType, c.state.isClient)
		}
	}
	go func() {
		select {
		case c.otherEndRecv <- make(chan struct{}):
		case <-c.done:
		}
	}()

	// Avoid deadlock on JS/WASM environment due to context switch problem.
	time.Sleep(10 * time.Millisecond)

	return nil
}

func (c *flightTestConn) handleQueuedPackets(ctx context.Context) error {
	return nil
}
<|endoftext|>


<commit_before>// The Harness for a Revel program.
//
// It has a couple responsibilities:
// 1. Parse the user program, generating a main.go file that registers
//    controller classes and starts the user's server.
// 2. Build and run the user program.  Show compile errors.
// 3. Monitor the user source and re-build / restart the program when necessary.
//
// Source files are generated in the app/tmp directory.

package harness

import (
	"fmt"
	"github.com/robfig/revel"
	"go/build"
	"io"
	"net"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"os/signal"
	"path"
	"path/filepath"
	"strings"
	"sync/atomic"
)

var (
	watcher    *revel.Watcher
	doNotWatch = []string{"tmp", "views", "routes"}

	lastRequestHadError int32
)

// Harness reverse proxies requests to the application server.
// It builds / runs / rebuilds / restarts the server when code is changed.
type Harness struct {
	app        *App
	serverHost string
	port       int
	proxy      *httputil.ReverseProxy
}

func renderError(w http.ResponseWriter, r *http.Request, err error) {
	revel.RenderError(revel.NewRequest(r), revel.NewResponse(w), err)
}

// ServeHTTP handles all requests.
// It checks for changes to app, rebuilds if necessary, and forwards the request.
func (hp *Harness) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// Don't rebuild the app for favicon requests.
	if lastRequestHadError > 0 && r.URL.Path == "/favicon.ico" {
		return
	}

	// Flush any change events and rebuild app if necessary.
	// Render an error page if the rebuild / restart failed.
	err := watcher.Notify()
	if err != nil {
		atomic.CompareAndSwapInt32(&lastRequestHadError, 0, 1)
		renderError(w, r, err)
		return
	}
	atomic.CompareAndSwapInt32(&lastRequestHadError, 1, 0)

	// Reverse proxy the request.
	// (Need special code for websockets, courtesy of bradfitz)
	if r.Header.Get("Upgrade") == "websocket" {
		proxyWebsocket(w, r, hp.serverHost)
	} else {
		hp.proxy.ServeHTTP(w, r)
	}
}

// Return a reverse proxy that forwards requests to the given port.
func NewHarness() *Harness {
	// Get a template loader to render errors.
	// Prefer the app's views/errors directory, and fall back to the stock error pages.
	revel.MainTemplateLoader = revel.NewTemplateLoader(
		[]string{path.Join(revel.RevelPath, "templates")})
	revel.MainTemplateLoader.Refresh()

	addr := revel.HttpAddr
	port := revel.Config.IntDefault("harness.port", 0)

	// If the server is running on the wildcard address, use "localhost"
	if addr == "" {
		addr = "localhost"
	}

	if port == 0 {
		port = getFreePort()
	}

	serverUrl, _ := url.ParseRequestURI(fmt.Sprintf("http://%s:%d", addr, port))

	harness := &Harness{
		port:       port,
		serverHost: serverUrl.String()[len("http://"):],
		proxy:      httputil.NewSingleHostReverseProxy(serverUrl),
	}
	return harness
}

// Rebuild the Revel application and run it on the given port.
func (h *Harness) Refresh() (err *revel.Error) {
	if h.app != nil {
		h.app.Kill()
	}

	revel.TRACE.Println("Rebuild")
	h.app, err = Build()
	if err != nil {
		return
	}

	h.app.Port = h.port
	if err2 := h.app.Cmd().Start(); err2 != nil {
		return &revel.Error{
			Title:       "App failed to start up",
			Description: err2.Error(),
		}
	}

	return
}

func (h *Harness) WatchDir(info os.FileInfo) bool {
	return !revel.ContainsString(doNotWatch, info.Name())
}

func (h *Harness) WatchFile(filename string) bool {
	return strings.HasSuffix(filename, ".go")
}

// Run the harness, which listens for requests and proxies them to the app
// server, which it runs and rebuilds as necessary.
func (h *Harness) Run() {
	var paths []string
	if revel.Config.BoolDefault("watch.gopath", true) {
		gopaths := filepath.SplitList(build.Default.GOPATH)
		paths = append(paths, gopaths...)
	}
	paths = append(paths, revel.CodePaths...)
	watcher = revel.NewWatcher()
	watcher.Listen(h, paths...)

	go func() {
		revel.INFO.Printf("Listening on %s:%d", revel.HttpAddr, revel.HttpPort)
		err := http.ListenAndServe(fmt.Sprintf("%s:%d", revel.HttpAddr, revel.HttpPort), h)
		if err != nil {
			revel.ERROR.Fatalln("Failed to start reverse proxy:", err)
		}
	}()

	// Kill the app on signal.
	ch := make(chan os.Signal)
	signal.Notify(ch, os.Interrupt, os.Kill)
	<-ch
	if h.app != nil {
		h.app.Kill()
	}
	os.Exit(1)
}

// Find an unused port
func getFreePort() (port int) {
	conn, err := net.Listen("tcp", ":0")
	if err != nil {
		revel.ERROR.Fatal(err)
	}

	port = conn.Addr().(*net.TCPAddr).Port
	err = conn.Close()
	if err != nil {
		revel.ERROR.Fatal(err)
	}
	return port
}

// proxyWebsocket copies data between websocket client and server until one side
// closes the connection.  (ReverseProxy doesn't work with websocket requests.)
func proxyWebsocket(w http.ResponseWriter, r *http.Request, host string) {
	d, err := net.Dial("tcp", host)
	if err != nil {
		http.Error(w, "Error contacting backend server.", 500)
		revel.ERROR.Printf("Error dialing websocket backend %s: %v", host, err)
		return
	}
	hj, ok := w.(http.Hijacker)
	if !ok {
		http.Error(w, "Not a hijacker?", 500)
		return
	}
	nc, _, err := hj.Hijack()
	if err != nil {
		revel.ERROR.Printf("Hijack error: %v", err)
		return
	}
	defer nc.Close()
	defer d.Close()

	err = r.Write(d)
	if err != nil {
		revel.ERROR.Printf("Error copying request to target: %v", err)
		return
	}

	errc := make(chan error, 2)
	cp := func(dst io.Writer, src io.Reader) {
		_, err := io.Copy(dst, src)
		errc <- err
	}
	go cp(d, nc)
	go cp(nc, d)
	<-errc
}
<commit_msg>Make watch.gopath false by default<commit_after>// The Harness for a Revel program.
//
// It has a couple responsibilities:
// 1. Parse the user program, generating a main.go file that registers
//    controller classes and starts the user's server.
// 2. Build and run the user program.  Show compile errors.
// 3. Monitor the user source and re-build / restart the program when necessary.
//
// Source files are generated in the app/tmp directory.

package harness

import (
	"fmt"
	"github.com/robfig/revel"
	"go/build"
	"io"
	"net"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"os/signal"
	"path"
	"path/filepath"
	"strings"
	"sync/atomic"
)

var (
	watcher    *revel.Watcher
	doNotWatch = []string{"tmp", "views", "routes"}

	lastRequestHadError int32
)

// Harness reverse proxies requests to the application server.
// It builds / runs / rebuilds / restarts the server when code is changed.
type Harness struct {
	app        *App
	serverHost string
	port       int
	proxy      *httputil.ReverseProxy
}

func renderError(w http.ResponseWriter, r *http.Request, err error) {
	revel.RenderError(revel.NewRequest(r), revel.NewResponse(w), err)
}

// ServeHTTP handles all requests.
// It checks for changes to app, rebuilds if necessary, and forwards the request.
func (hp *Harness) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// Don't rebuild the app for favicon requests.
	if lastRequestHadError > 0 && r.URL.Path == "/favicon.ico" {
		return
	}

	// Flush any change events and rebuild app if necessary.
	// Render an error page if the rebuild / restart failed.
	err := watcher.Notify()
	if err != nil {
		atomic.CompareAndSwapInt32(&lastRequestHadError, 0, 1)
		renderError(w, r, err)
		return
	}
	atomic.CompareAndSwapInt32(&lastRequestHadError, 1, 0)

	// Reverse proxy the request.
	// (Need special code for websockets, courtesy of bradfitz)
	if r.Header.Get("Upgrade") == "websocket" {
		proxyWebsocket(w, r, hp.serverHost)
	} else {
		hp.proxy.ServeHTTP(w, r)
	}
}

// Return a reverse proxy that forwards requests to the given port.
func NewHarness() *Harness {
	// Get a template loader to render errors.
	// Prefer the app's views/errors directory, and fall back to the stock error pages.
	revel.MainTemplateLoader = revel.NewTemplateLoader(
		[]string{path.Join(revel.RevelPath, "templates")})
	revel.MainTemplateLoader.Refresh()

	addr := revel.HttpAddr
	port := revel.Config.IntDefault("harness.port", 0)

	// If the server is running on the wildcard address, use "localhost"
	if addr == "" {
		addr = "localhost"
	}

	if port == 0 {
		port = getFreePort()
	}

	serverUrl, _ := url.ParseRequestURI(fmt.Sprintf("http://%s:%d", addr, port))

	harness := &Harness{
		port:       port,
		serverHost: serverUrl.String()[len("http://"):],
		proxy:      httputil.NewSingleHostReverseProxy(serverUrl),
	}
	return harness
}

// Rebuild the Revel application and run it on the given port.
func (h *Harness) Refresh() (err *revel.Error) {
	if h.app != nil {
		h.app.Kill()
	}

	revel.TRACE.Println("Rebuild")
	h.app, err = Build()
	if err != nil {
		return
	}

	h.app.Port = h.port
	if err2 := h.app.Cmd().Start(); err2 != nil {
		return &revel.Error{
			Title:       "App failed to start up",
			Description: err2.Error(),
		}
	}

	return
}

func (h *Harness) WatchDir(info os.FileInfo) bool {
	return !revel.ContainsString(doNotWatch, info.Name())
}

func (h *Harness) WatchFile(filename string) bool {
	return strings.HasSuffix(filename, ".go")
}

// Run the harness, which listens for requests and proxies them to the app
// server, which it runs and rebuilds as necessary.
func (h *Harness) Run() {
	var paths []string
	if revel.Config.BoolDefault("watch.gopath", false) {
		gopaths := filepath.SplitList(build.Default.GOPATH)
		paths = append(paths, gopaths...)
	}
	paths = append(paths, revel.CodePaths...)
	watcher = revel.NewWatcher()
	watcher.Listen(h, paths...)

	go func() {
		revel.INFO.Printf("Listening on %s:%d", revel.HttpAddr, revel.HttpPort)
		err := http.ListenAndServe(fmt.Sprintf("%s:%d", revel.HttpAddr, revel.HttpPort), h)
		if err != nil {
			revel.ERROR.Fatalln("Failed to start reverse proxy:", err)
		}
	}()

	// Kill the app on signal.
	ch := make(chan os.Signal)
	signal.Notify(ch, os.Interrupt, os.Kill)
	<-ch
	if h.app != nil {
		h.app.Kill()
	}
	os.Exit(1)
}

// Find an unused port
func getFreePort() (port int) {
	conn, err := net.Listen("tcp", ":0")
	if err != nil {
		revel.ERROR.Fatal(err)
	}

	port = conn.Addr().(*net.TCPAddr).Port
	err = conn.Close()
	if err != nil {
		revel.ERROR.Fatal(err)
	}
	return port
}

// proxyWebsocket copies data between websocket client and server until one side
// closes the connection.  (ReverseProxy doesn't work with websocket requests.)
func proxyWebsocket(w http.ResponseWriter, r *http.Request, host string) {
	d, err := net.Dial("tcp", host)
	if err != nil {
		http.Error(w, "Error contacting backend server.", 500)
		revel.ERROR.Printf("Error dialing websocket backend %s: %v", host, err)
		return
	}
	hj, ok := w.(http.Hijacker)
	if !ok {
		http.Error(w, "Not a hijacker?", 500)
		return
	}
	nc, _, err := hj.Hijack()
	if err != nil {
		revel.ERROR.Printf("Hijack error: %v", err)
		return
	}
	defer nc.Close()
	defer d.Close()

	err = r.Write(d)
	if err != nil {
		revel.ERROR.Printf("Error copying request to target: %v", err)
		return
	}

	errc := make(chan error, 2)
	cp := func(dst io.Writer, src io.Reader) {
		_, err := io.Copy(dst, src)
		errc <- err
	}
	go cp(d, nc)
	go cp(nc, d)
	<-errc
}
<|endoftext|>


<commit_before>// Copyright 2016 The Cockroach Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
//
// Author: Marc Berhault (marc@cockroachlabs.com)

// +build jemalloc

package snappy

// #cgo darwin LDFLAGS: -Wl,-undefined -Wl,dynamic_lookup
// #cgo linux LDFLAGS: -Wl,-unresolved-symbols=ignore-all

import _ "github.com/cockroachdb/c-jemalloc"
<commit_msg>Invert jemalloc build rule<commit_after>// Copyright 2016 The Cockroach Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
//
// Author: Marc Berhault (marc@cockroachlabs.com)

// +build !stdmalloc

package snappy

// #cgo darwin LDFLAGS: -Wl,-undefined -Wl,dynamic_lookup
// #cgo linux LDFLAGS: -Wl,-unresolved-symbols=ignore-all

import _ "github.com/cockroachdb/c-jemalloc"
<|endoftext|>


<commit_before>package channels

type broadcast struct {
    c chan broadcast
    v []byte
}

type Broadcaster struct {
    ListenChannel chan chan (chan broadcast)
    SendChannel   chan <- []byte
}

type Receiver struct {
    C chan broadcast
}

func NewBroadcaster() Broadcaster {
    listenc := make(chan (chan (chan broadcast)))
    sendc := make(chan []byte)
    go func() {
        currc := make(chan broadcast, 1)
        for {
            select {
            case v := <-sendc:
                if v == nil {
                    currc <- broadcast{}
                    return
                }
                c := make(chan broadcast, 1)
                b := broadcast{c: c, v: v}
                currc <- b
                currc = c
            case r := <-listenc:
                r <- currc
            }
        }
    }()

    return Broadcaster{
        ListenChannel: listenc,
        SendChannel:   sendc,
    }
}

func (b Broadcaster) Listen() Receiver {
    c := make(chan chan broadcast, 0)
    b.ListenChannel <- c
    return Receiver{<-c}
}

func (b Broadcaster) Write(v []byte) {
    b.SendChannel <- v
}

func (r *Receiver) Read() []byte {
    b := <-r.C
    v := b.v
    r.C <- b
    r.C = b.c

    return v
}
<commit_msg>Remove dead code<commit_after><|endoftext|>


<commit_before>package hypervisor

import (
	"encoding/binary"
	"fmt"
	"hyper/lib/glog"
	"hyper/lib/telnet"
	"net"
	"time"
)

// Message
type DecodedMessage struct {
	code    uint32
	message []byte
}

type FinishCmd struct {
	Seq uint64 `json:"seq"`
}

func waitConsoleOutput(ctx *VmContext) {

	conn, err := UnixSocketConnect(ctx.ConsoleSockName)
	if err != nil {
		glog.Error("failed to connected to ", ctx.ConsoleSockName, " ", err.Error())
		return
	}

	glog.V(1).Info("connected to ", ctx.ConsoleSockName)

	tc, err := telnet.NewConn(conn)
	if err != nil {
		glog.Error("fail to init telnet connection to ", ctx.ConsoleSockName, ": ", err.Error())
		return
	}
	glog.V(1).Infof("connected %s as telnet mode.", ctx.ConsoleSockName)

	cout := make(chan string, 128)
	go TtyLiner(tc, cout)

	for {
		line, ok := <-cout
		if ok {
			glog.V(1).Info("[console] ", line)
		} else {
			glog.Info("console output end")
			break
		}
	}
}

func newVmMessage(m *DecodedMessage) []byte {
	length := len(m.message) + 8
	msg := make([]byte, length)
	binary.BigEndian.PutUint32(msg[:], uint32(m.code))
	binary.BigEndian.PutUint32(msg[4:], uint32(length))
	copy(msg[8:], m.message)
	return msg
}

func readVmMessage(conn *net.UnixConn) (*DecodedMessage, error) {
	needRead := 8
	length := 0
	read := 0
	buf := make([]byte, 512)
	res := []byte{}
	for read < needRead {
		want := needRead - read
		if want > 512 {
			want = 512
		}
		glog.V(1).Infof("trying to read %d bytes", want)
		nr, err := conn.Read(buf[:want])
		if err != nil {
			glog.Error("read init data failed")
			return nil, err
		}

		res = append(res, buf[:nr]...)
		read = read + nr

		glog.V(1).Infof("read %d/%d [length = %d]", read, needRead, length)

		if length == 0 && read >= 8 {
			length = int(binary.BigEndian.Uint32(res[4:8]))
			glog.V(1).Infof("data length is %d", length)
			if length > 8 {
				needRead = length
			}
		}
	}

	return &DecodedMessage{
		code:    binary.BigEndian.Uint32(res[:4]),
		message: res[8:],
	}, nil
}

func waitInitReady(ctx *VmContext) {
	conn, err := UnixSocketConnect(ctx.HyperSockName)
	if err != nil {
		glog.Error("Cannot connect to hyper socket ", err.Error())
		ctx.Hub <- &InitFailedEvent{
			Reason: "Cannot connect to hyper socket " + err.Error(),
		}
		return
	}

	glog.Info("Wating for init messages...")

	msg, err := readVmMessage(conn.(*net.UnixConn))
	if err != nil {
		glog.Error("read init message failed... ", err.Error())
		ctx.Hub <- &InitFailedEvent{
			Reason: "read init message failed... " + err.Error(),
		}
		conn.Close()
	} else if msg.code == INIT_READY {
		glog.Info("Get init ready message")
		ctx.Hub <- &InitConnectedEvent{conn: conn.(*net.UnixConn)}
		go waitCmdToInit(ctx, conn.(*net.UnixConn))
	} else {
		glog.Warningf("Get init message %d", msg.code)
		ctx.Hub <- &InitFailedEvent{
			Reason: fmt.Sprintf("Get init message %d", msg.code),
		}
		conn.Close()
	}
}

func connectToInit(ctx *VmContext) {
	conn, err := UnixSocketConnect(ctx.HyperSockName)
	if err != nil {
		glog.Error("Cannot re-connect to hyper socket ", err.Error())
		ctx.Hub <- &InitFailedEvent{
			Reason: "Cannot re-connect to hyper socket " + err.Error(),
		}
		return
	}

	go waitCmdToInit(ctx, conn.(*net.UnixConn))
}

func waitCmdToInit(ctx *VmContext, init *net.UnixConn) {
	looping := true
	cmds := []*DecodedMessage{}

	var pingTimer *time.Timer = nil
	var pongTimer *time.Timer = nil

	go waitInitAck(ctx, init)

	for looping {
		cmd, ok := <-ctx.vm
		if !ok {
			glog.Info("vm channel closed, quit")
			break
		}
		if cmd.code == INIT_ACK || cmd.code == INIT_ERROR {
			if len(cmds) > 0 {
				if cmd.code == INIT_ACK {
					if cmds[0].code != INIT_PING {
						ctx.Hub <- &CommandAck{
							reply: cmds[0].code,
							msg:   cmd.message,
						}
					}
				} else {
					ctx.Hub <- &CommandError{
						context: cmds[0],
						msg:     cmd.message,
					}
				}
				cmds = cmds[1:]

				if pongTimer != nil {
					glog.V(1).Info("ack got, clear pong timer")
					pongTimer.Stop()
					pongTimer = nil
				}
				if pingTimer == nil {
					pingTimer = time.AfterFunc(30*time.Second, func() {
						defer func() { recover() }()
						glog.V(1).Info("Send ping message to init")
						ctx.vm <- &DecodedMessage{
							code:    INIT_PING,
							message: []byte{},
						}
						pingTimer = nil
					})
				} else {
					pingTimer.Reset(30 * time.Second)
				}
			} else {
				glog.Error("got ack but no command in queue")
			}
		} else if cmd.code == INIT_FINISHPOD {
			num := len(cmd.message) / 4
			results := make([]uint32, num)
			for i := 0; i < num; i++ {
				results[i] = binary.BigEndian.Uint32(cmd.message[i*4 : i*4+4])
			}

			glog.V(1).Infof("Pod finished, returned %d values", num)

			ctx.Hub <- &PodFinished{
				result: results,
			}
		} else {
			if glog.V(1) {
				glog.Infof("send command %d to init, payload: '%s'.", cmd.code, string(cmd.message))
			}
			if cmd.code == INIT_DESTROYPOD {
				glog.Info("Sending shutdown command, last round of command to init")
				looping = false
			}
			init.Write(newVmMessage(cmd))
			cmds = append(cmds, cmd)
			if pongTimer == nil {
				glog.V(1).Info("message sent, set pong timer")
				pongTimer = time.AfterFunc(30*time.Second, func() {
					ctx.Hub <- &Interrupted{Reason: "init not reply ping mesg"}
				})
			}
		}
	}
}

func waitInitAck(ctx *VmContext, init *net.UnixConn) {
	for {
		res, err := readVmMessage(init)
		if err != nil {
			ctx.Hub <- &Interrupted{Reason: "init socket failed " + err.Error()}
			return
		} else if res.code == INIT_ACK || res.code == INIT_ERROR || res.code == INIT_FINISHPOD {
			ctx.vm <- res
		}
	}
}
<commit_msg>check the finish/ack message of INIT_DESTROYPOD command<commit_after>package hypervisor

import (
	"encoding/binary"
	"fmt"
	"hyper/lib/glog"
	"hyper/lib/telnet"
	"net"
	"time"
)

// Message
type DecodedMessage struct {
	code    uint32
	message []byte
}

type FinishCmd struct {
	Seq uint64 `json:"seq"`
}

func waitConsoleOutput(ctx *VmContext) {

	conn, err := UnixSocketConnect(ctx.ConsoleSockName)
	if err != nil {
		glog.Error("failed to connected to ", ctx.ConsoleSockName, " ", err.Error())
		return
	}

	glog.V(1).Info("connected to ", ctx.ConsoleSockName)

	tc, err := telnet.NewConn(conn)
	if err != nil {
		glog.Error("fail to init telnet connection to ", ctx.ConsoleSockName, ": ", err.Error())
		return
	}
	glog.V(1).Infof("connected %s as telnet mode.", ctx.ConsoleSockName)

	cout := make(chan string, 128)
	go TtyLiner(tc, cout)

	for {
		line, ok := <-cout
		if ok {
			glog.V(1).Info("[console] ", line)
		} else {
			glog.Info("console output end")
			break
		}
	}
}

func newVmMessage(m *DecodedMessage) []byte {
	length := len(m.message) + 8
	msg := make([]byte, length)
	binary.BigEndian.PutUint32(msg[:], uint32(m.code))
	binary.BigEndian.PutUint32(msg[4:], uint32(length))
	copy(msg[8:], m.message)
	return msg
}

func readVmMessage(conn *net.UnixConn) (*DecodedMessage, error) {
	needRead := 8
	length := 0
	read := 0
	buf := make([]byte, 512)
	res := []byte{}
	for read < needRead {
		want := needRead - read
		if want > 512 {
			want = 512
		}
		glog.V(1).Infof("trying to read %d bytes", want)
		nr, err := conn.Read(buf[:want])
		if err != nil {
			glog.Error("read init data failed")
			return nil, err
		}

		res = append(res, buf[:nr]...)
		read = read + nr

		glog.V(1).Infof("read %d/%d [length = %d]", read, needRead, length)

		if length == 0 && read >= 8 {
			length = int(binary.BigEndian.Uint32(res[4:8]))
			glog.V(1).Infof("data length is %d", length)
			if length > 8 {
				needRead = length
			}
		}
	}

	return &DecodedMessage{
		code:    binary.BigEndian.Uint32(res[:4]),
		message: res[8:],
	}, nil
}

func waitInitReady(ctx *VmContext) {
	conn, err := UnixSocketConnect(ctx.HyperSockName)
	if err != nil {
		glog.Error("Cannot connect to hyper socket ", err.Error())
		ctx.Hub <- &InitFailedEvent{
			Reason: "Cannot connect to hyper socket " + err.Error(),
		}
		return
	}

	glog.Info("Wating for init messages...")

	msg, err := readVmMessage(conn.(*net.UnixConn))
	if err != nil {
		glog.Error("read init message failed... ", err.Error())
		ctx.Hub <- &InitFailedEvent{
			Reason: "read init message failed... " + err.Error(),
		}
		conn.Close()
	} else if msg.code == INIT_READY {
		glog.Info("Get init ready message")
		ctx.Hub <- &InitConnectedEvent{conn: conn.(*net.UnixConn)}
		go waitCmdToInit(ctx, conn.(*net.UnixConn))
	} else {
		glog.Warningf("Get init message %d", msg.code)
		ctx.Hub <- &InitFailedEvent{
			Reason: fmt.Sprintf("Get init message %d", msg.code),
		}
		conn.Close()
	}
}

func connectToInit(ctx *VmContext) {
	conn, err := UnixSocketConnect(ctx.HyperSockName)
	if err != nil {
		glog.Error("Cannot re-connect to hyper socket ", err.Error())
		ctx.Hub <- &InitFailedEvent{
			Reason: "Cannot re-connect to hyper socket " + err.Error(),
		}
		return
	}

	go waitCmdToInit(ctx, conn.(*net.UnixConn))
}

func waitCmdToInit(ctx *VmContext, init *net.UnixConn) {
	looping := true
	cmds := []*DecodedMessage{}

	var pingTimer *time.Timer = nil
	var pongTimer *time.Timer = nil

	go waitInitAck(ctx, init)

	for looping {
		cmd, ok := <-ctx.vm
		if !ok {
			glog.Info("vm channel closed, quit")
			break
		}
		if cmd.code == INIT_ACK || cmd.code == INIT_ERROR {
			if len(cmds) > 0 {
				if cmds[0].code == INIT_DESTROYPOD {
					glog.Info("got response of shutdown command, last round of command to init")
					looping = false
				}
				if cmd.code == INIT_ACK {
					if cmds[0].code != INIT_PING {
						ctx.Hub <- &CommandAck{
							reply: cmds[0].code,
							msg:   cmd.message,
						}
					}
				} else {
					ctx.Hub <- &CommandError{
						context: cmds[0],
						msg:     cmd.message,
					}
				}
				cmds = cmds[1:]

				if pongTimer != nil {
					glog.V(1).Info("ack got, clear pong timer")
					pongTimer.Stop()
					pongTimer = nil
				}
				if pingTimer == nil {
					pingTimer = time.AfterFunc(30*time.Second, func() {
						defer func() { recover() }()
						glog.V(1).Info("Send ping message to init")
						ctx.vm <- &DecodedMessage{
							code:    INIT_PING,
							message: []byte{},
						}
						pingTimer = nil
					})
				} else {
					pingTimer.Reset(30 * time.Second)
				}
			} else {
				glog.Error("got ack but no command in queue")
			}
		} else if cmd.code == INIT_FINISHPOD {
			num := len(cmd.message) / 4
			results := make([]uint32, num)
			for i := 0; i < num; i++ {
				results[i] = binary.BigEndian.Uint32(cmd.message[i*4 : i*4+4])
			}

			for _,c := range cmds {
				if c.code == INIT_DESTROYPOD {
					glog.Info("got pod finish message after having send destroy message")
					looping = false
					ctx.Hub <- &CommandAck {
						reply: c.code,
					}
					break
				}
			}

			glog.V(1).Infof("Pod finished, returned %d values", num)

			ctx.Hub <- &PodFinished{
				result: results,
			}
		} else {
			if glog.V(1) {
				glog.Infof("send command %d to init, payload: '%s'.", cmd.code, string(cmd.message))
			}
			init.Write(newVmMessage(cmd))
			cmds = append(cmds, cmd)
			if pongTimer == nil {
				glog.V(1).Info("message sent, set pong timer")
				pongTimer = time.AfterFunc(30*time.Second, func() {
					ctx.Hub <- &Interrupted{Reason: "init not reply ping mesg"}
				})
			}
		}
	}

	if pingTimer != nil {
		pingTimer.Stop()
	}
	if pongTimer != nil {
		pongTimer.Stop()
	}
}

func waitInitAck(ctx *VmContext, init *net.UnixConn) {
	for {
		res, err := readVmMessage(init)
		if err != nil {
			ctx.Hub <- &Interrupted{Reason: "init socket failed " + err.Error()}
			return
		} else if res.code == INIT_ACK || res.code == INIT_ERROR || res.code == INIT_FINISHPOD {
			ctx.vm <- res
		}
	}
}
<|endoftext|>


<commit_before>package slack

import (
	"errors"
	"fmt"
	"net/url"
)

type adminResponse struct {
	OK    bool   `json:"ok"`
	Error string `json:"error"`
}

func adminRequest(method string, teamName string, values url.Values, debug bool) (*adminResponse, error) {
	adminResponse := &adminResponse{}
	err := parseAdminResponse(method, teamName, values, adminResponse, debug)
	if err != nil {
		return nil, err
	}

	if !adminResponse.OK {
		return nil, errors.New(adminResponse.Error)
	}

	return adminResponse, nil
}

// DisableUser disabled a user account
func (api *Client) DisableUser(teamName string, user string) error {
	values := url.Values{
		"user":       {user},
		"token":      {api.config.token},
		"set_active": {"true"},
		"_attempts":  {"1"},
	}

	_, err := adminRequest("setInactive", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to disable user (%s): %s", user, err)
	}

	return nil
}

// InviteGuest invites a user to Slack as a single-channel guest
func (api *Client) InviteGuest(
	teamName string,
	channel string,
	firstName string,
	lastName string,
	emailAddress string,
) error {
	values := url.Values{
		"email":            {emailAddress},
		"channels":         {channel},
		"first_name":       {firstName},
		"last_name":        {lastName},
		"ultra_restricted": {"1"},
		"token":            {api.config.token},
		"set_active":       {"true"},
		"_attempts":        {"1"},
	}

	_, err := adminRequest("invite", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to invite single-channel guest: %s", err)
	}

	return nil
}

// InviteRestricted invites a user to Slack as a restricted account
func (api *Client) InviteRestricted(
	teamName string,
	channel string,
	firstName string,
	lastName string,
	emailAddress string,
) error {
	values := url.Values{
		"email":      {emailAddress},
		"channels":   {channel},
		"first_name": {firstName},
		"last_name":  {lastName},
		"restricted": {"1"},
		"token":      {api.config.token},
		"set_active": {"true"},
		"_attempts":  {"1"},
	}

	_, err := adminRequest("invite", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to restricted account: %s", err)
	}

	return nil
}

// SetRegular enables the specified user
func (api *Client) SetRegular(teamName string, user string) error {
	values := url.Values{
		"user":       {user},
		"token":      {api.config.token},
		"set_active": {"true"},
		"_attempts":  {"1"},
	}

	_, err := adminRequest("setRegular", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to change the user (%s) to a regular user: %s", user, err)
	}

	return nil
}

// SendSSOBindingEmail sends an SSO binding email to the specified user
func (api *Client) SendSSOBindingEmail(teamName string, user string) error {
	values := url.Values{
		"user":       {user},
		"token":      {api.config.token},
		"set_active": {"true"},
		"_attempts":  {"1"},
	}

	_, err := adminRequest("sendSSOBind", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to send SSO binding email for user (%s): %s", user, err)
	}

	return nil
}
<commit_msg>Fix admin conflicts<commit_after>package slack

import (
	"errors"
	"fmt"
	"net/url"
)

type adminResponse struct {
	OK    bool   `json:"ok"`
	Error string `json:"error"`
}

func adminRequest(method string, teamName string, values url.Values, debug bool) (*adminResponse, error) {
	adminResponse := &adminResponse{}
	err := parseAdminResponse(method, teamName, values, adminResponse, debug)
	if err != nil {
		return nil, err
	}

	if !adminResponse.OK {
		return nil, errors.New(adminResponse.Error)
	}

	return adminResponse, nil
}

// DisableUser disabled a user account, given a user ID
func (api *Client) DisableUser(teamName string, uid string) error {
	values := url.Values{
		"user":       {uid},
		"token":      {api.config.token},
		"set_active": {"true"},
		"_attempts":  {"1"},
	}

	_, err := adminRequest("setInactive", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to disable user with id '%s': %s", uid, err)
	}

	return nil
}

// InviteGuest invites a user to Slack as a single-channel guest
func (api *Client) InviteGuest(
	teamName string,
	channel string,
	firstName string,
	lastName string,
	emailAddress string,
) error {
	values := url.Values{
		"email":            {emailAddress},
		"channels":         {channel},
		"first_name":       {firstName},
		"last_name":        {lastName},
		"ultra_restricted": {"1"},
		"token":            {api.config.token},
		"set_active":       {"true"},
		"_attempts":        {"1"},
	}

	_, err := adminRequest("invite", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to invite single-channel guest: %s", err)
	}

	return nil
}

// InviteRestricted invites a user to Slack as a restricted account
func (api *Client) InviteRestricted(
	teamName string,
	channel string,
	firstName string,
	lastName string,
	emailAddress string,
) error {
	values := url.Values{
		"email":      {emailAddress},
		"channels":   {channel},
		"first_name": {firstName},
		"last_name":  {lastName},
		"restricted": {"1"},
		"token":      {api.config.token},
		"set_active": {"true"},
		"_attempts":  {"1"},
	}

	_, err := adminRequest("invite", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to restricted account: %s", err)
	}

	return nil
}

// SetRegular enables the specified user
func (api *Client) SetRegular(teamName string, user string) error {
	values := url.Values{
		"user":       {user},
		"token":      {api.config.token},
		"set_active": {"true"},
		"_attempts":  {"1"},
	}

	_, err := adminRequest("setRegular", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to change the user (%s) to a regular user: %s", user, err)
	}

	return nil
}

// SendSSOBindingEmail sends an SSO binding email to the specified user
func (api *Client) SendSSOBindingEmail(teamName string, user string) error {
	values := url.Values{
		"user":       {user},
		"token":      {api.config.token},
		"set_active": {"true"},
		"_attempts":  {"1"},
	}

	_, err := adminRequest("sendSSOBind", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to send SSO binding email for user (%s): %s", user, err)
	}

	return nil
}

// SetUltraRestricted converts a user into a single-channel guest
func (api *Client) SetUltraRestricted(teamName, uid, channel string) error {
	values := url.Values{
		"user":       {uid},
		"channel":    {channel},
		"token":      {api.config.token},
		"set_active": {"true"},
		"_attempts":  {"1"},
	}

	_, err := adminRequest("setUltraRestricted", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to ultra-restrict account: %s", err)
	}

	return nil
}

// SetRestricted converts a user into a restricted account
func (api *Client) SetRestricted(teamName, uid string) error {
	values := url.Values{
		"user":       {uid},
		"token":      {api.config.token},
		"set_active": {"true"},
		"_attempts":  {"1"},
	}

	_, err := adminRequest("setRestricted", teamName, values, api.debug)
	if err != nil {
		return fmt.Errorf("Failed to restrict account: %s", err)
	}

	return nil
}
<|endoftext|>