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

package http

import (
	"log"
	"net"
	"strconv"
	"strings"
	"time"
)

// A Cookie represents an HTTP cookie as sent in the Set-Cookie header of an
// HTTP response or the Cookie header of an HTTP request.
//
// See https://tools.ietf.org/html/rfc6265 for details.
type Cookie struct {
	Name  string
	Value string

	Path       string    // optional
	Domain     string    // optional
	Expires    time.Time // optional
	RawExpires string    // for reading cookies only

	// MaxAge=0 means no 'Max-Age' attribute specified.
	// MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'
	// MaxAge>0 means Max-Age attribute present and given in seconds
	MaxAge   int
	Secure   bool
	HttpOnly bool
	SameSite SameSite
	Raw      string
	Unparsed []string // Raw text of unparsed attribute-value pairs
}

// SameSite allows a server to define a cookie attribute making it impossible for
// the browser to send this cookie along with cross-site requests. The main
// goal is to mitigate the risk of cross-origin information leakage, and provides
// some protection against cross-site request forgery attacks.
//
// See https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00 for details.
type SameSite int

const (
	SameSiteDefaultMode SameSite = iota + 1
	SameSiteLaxMode
	SameSiteStrictMode
)

// readSetCookies parses all "Set-Cookie" values from
// the header h and returns the successfully parsed Cookies.
func readSetCookies(h Header) []*Cookie {
	cookieCount := len(h["Set-Cookie"])
	if cookieCount == 0 {
		return []*Cookie{}
	}
	cookies := make([]*Cookie, 0, cookieCount)
	for _, line := range h["Set-Cookie"] {
		parts := strings.Split(strings.TrimSpace(line), ";")
		if len(parts) == 1 && parts[0] == "" {
			continue
		}
		parts[0] = strings.TrimSpace(parts[0])
		j := strings.Index(parts[0], "=")
		if j < 0 {
			continue
		}
		name, value := parts[0][:j], parts[0][j+1:]
		if !isCookieNameValid(name) {
			continue
		}
		value, ok := parseCookieValue(value, true)
		if !ok {
			continue
		}
		c := &Cookie{
			Name:  name,
			Value: value,
			Raw:   line,
		}
		for i := 1; i < len(parts); i++ {
			parts[i] = strings.TrimSpace(parts[i])
			if len(parts[i]) == 0 {
				continue
			}

			attr, val := parts[i], ""
			if j := strings.Index(attr, "="); j >= 0 {
				attr, val = attr[:j], attr[j+1:]
			}
			lowerAttr := strings.ToLower(attr)
			val, ok = parseCookieValue(val, false)
			if !ok {
				c.Unparsed = append(c.Unparsed, parts[i])
				continue
			}
			switch lowerAttr {
			case "samesite":
				lowerVal := strings.ToLower(val)
				switch lowerVal {
				case "lax":
					c.SameSite = SameSiteLaxMode
				case "strict":
					c.SameSite = SameSiteStrictMode
				default:
					c.SameSite = SameSiteDefaultMode
				}
				continue
			case "secure":
				c.Secure = true
				continue
			case "httponly":
				c.HttpOnly = true
				continue
			case "domain":
				c.Domain = val
				continue
			case "max-age":
				secs, err := strconv.Atoi(val)
				if err != nil || secs != 0 && val[0] == '0' {
					break
				}
				if secs <= 0 {
					secs = -1
				}
				c.MaxAge = secs
				continue
			case "expires":
				c.RawExpires = val
				exptime, err := time.Parse(time.RFC1123, val)
				if err != nil {
					exptime, err = time.Parse("Mon, 02-Jan-2006 15:04:05 MST", val)
					if err != nil {
						c.Expires = time.Time{}
						break
					}
				}
				c.Expires = exptime.UTC()
				continue
			case "path":
				c.Path = val
				continue
			}
			c.Unparsed = append(c.Unparsed, parts[i])
		}
		cookies = append(cookies, c)
	}
	return cookies
}

// SetCookie adds a Set-Cookie header to the provided ResponseWriter's headers.
// The provided cookie must have a valid Name. Invalid cookies may be
// silently dropped.
func SetCookie(w ResponseWriter, cookie *Cookie) {
	if v := cookie.String(); v != "" {
		w.Header().Add("Set-Cookie", v)
	}
}

// String returns the serialization of the cookie for use in a Cookie
// header (if only Name and Value are set) or a Set-Cookie response
// header (if other fields are set).
// If c is nil or c.Name is invalid, the empty string is returned.
func (c *Cookie) String() string {
	if c == nil || !isCookieNameValid(c.Name) {
		return ""
	}
	var b strings.Builder
	b.WriteString(sanitizeCookieName(c.Name))
	b.WriteRune('=')
	b.WriteString(sanitizeCookieValue(c.Value))

	if len(c.Path) > 0 {
		b.WriteString("; Path=")
		b.WriteString(sanitizeCookiePath(c.Path))
	}
	if len(c.Domain) > 0 {
		if validCookieDomain(c.Domain) {
			// A c.Domain containing illegal characters is not
			// sanitized but simply dropped which turns the cookie
			// into a host-only cookie. A leading dot is okay
			// but won't be sent.
			d := c.Domain
			if d[0] == '.' {
				d = d[1:]
			}
			b.WriteString("; Domain=")
			b.WriteString(d)
		} else {
			log.Printf("net/http: invalid Cookie.Domain %q; dropping domain attribute", c.Domain)
		}
	}
	var buf [len(TimeFormat)]byte
	if validCookieExpires(c.Expires) {
		b.WriteString("; Expires=")
		b.Write(c.Expires.UTC().AppendFormat(buf[:0], TimeFormat))
	}
	if c.MaxAge > 0 {
		b.WriteString("; Max-Age=")
		b.Write(strconv.AppendInt(buf[:0], int64(c.MaxAge), 10))
	} else if c.MaxAge < 0 {
		b.WriteString("; Max-Age=0")
	}
	if c.HttpOnly {
		b.WriteString("; HttpOnly")
	}
	if c.Secure {
		b.WriteString("; Secure")
	}
	switch c.SameSite {
	case SameSiteDefaultMode:
		b.WriteString("; SameSite")
	case SameSiteLaxMode:
		b.WriteString("; SameSite=Lax")
	case SameSiteStrictMode:
		b.WriteString("; SameSite=Strict")
	}
	return b.String()
}

// readCookies parses all "Cookie" values from the header h and
// returns the successfully parsed Cookies.
//
// if filter isn't empty, only cookies of that name are returned
func readCookies(h Header, filter string) []*Cookie {
	lines, ok := h["Cookie"]
	if !ok {
		return []*Cookie{}
	}

	cookies := []*Cookie{}
	for _, line := range lines {
		parts := strings.Split(strings.TrimSpace(line), ";")
		if len(parts) == 1 && parts[0] == "" {
			continue
		}
		// Per-line attributes
		for i := 0; i < len(parts); i++ {
			parts[i] = strings.TrimSpace(parts[i])
			if len(parts[i]) == 0 {
				continue
			}
			name, val := parts[i], ""
			if j := strings.Index(name, "="); j >= 0 {
				name, val = name[:j], name[j+1:]
			}
			if !isCookieNameValid(name) {
				continue
			}
			if filter != "" && filter != name {
				continue
			}
			val, ok := parseCookieValue(val, true)
			if !ok {
				continue
			}
			cookies = append(cookies, &Cookie{Name: name, Value: val})
		}
	}
	return cookies
}

// validCookieDomain returns whether v is a valid cookie domain-value.
func validCookieDomain(v string) bool {
	if isCookieDomainName(v) {
		return true
	}
	if net.ParseIP(v) != nil && !strings.Contains(v, ":") {
		return true
	}
	return false
}

// validCookieExpires returns whether v is a valid cookie expires-value.
func validCookieExpires(t time.Time) bool {
	// IETF RFC 6265 Section 5.1.1.5, the year must not be less than 1601
	return t.Year() >= 1601
}

// isCookieDomainName returns whether s is a valid domain name or a valid
// domain name with a leading dot '.'.  It is almost a direct copy of
// package net's isDomainName.
func isCookieDomainName(s string) bool {
	if len(s) == 0 {
		return false
	}
	if len(s) > 255 {
		return false
	}

	if s[0] == '.' {
		// A cookie a domain attribute may start with a leading dot.
		s = s[1:]
	}
	last := byte('.')
	ok := false // Ok once we've seen a letter.
	partlen := 0
	for i := 0; i < len(s); i++ {
		c := s[i]
		switch {
		default:
			return false
		case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z':
			// No '_' allowed here (in contrast to package net).
			ok = true
			partlen++
		case '0' <= c && c <= '9':
			// fine
			partlen++
		case c == '-':
			// Byte before dash cannot be dot.
			if last == '.' {
				return false
			}
			partlen++
		case c == '.':
			// Byte before dot cannot be dot, dash.
			if last == '.' || last == '-' {
				return false
			}
			if partlen > 63 || partlen == 0 {
				return false
			}
			partlen = 0
		}
		last = c
	}
	if last == '-' || partlen > 63 {
		return false
	}

	return ok
}

var cookieNameSanitizer = strings.NewReplacer("\n", "-", "\r", "-")

func sanitizeCookieName(n string) string {
	return cookieNameSanitizer.Replace(n)
}

// https://tools.ietf.org/html/rfc6265#section-4.1.1
// cookie-value      = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
// cookie-octet      = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
//           ; US-ASCII characters excluding CTLs,
//           ; whitespace DQUOTE, comma, semicolon,
//           ; and backslash
// We loosen this as spaces and commas are common in cookie values
// but we produce a quoted cookie-value in when value starts or ends
// with a comma or space.
// See https://golang.org/issue/7243 for the discussion.
func sanitizeCookieValue(v string) string {
	v = sanitizeOrWarn("Cookie.Value", validCookieValueByte, v)
	if len(v) == 0 {
		return v
	}
	if strings.IndexByte(v, ' ') >= 0 || strings.IndexByte(v, ',') >= 0 {
		return `"` + v + `"`
	}
	return v
}

func validCookieValueByte(b byte) bool {
	return 0x20 <= b && b < 0x7f && b != '"' && b != ';' && b != '\\'
}

// path-av           = "Path=" path-value
// path-value        = <any CHAR except CTLs or ";">
func sanitizeCookiePath(v string) string {
	return sanitizeOrWarn("Cookie.Path", validCookiePathByte, v)
}

func validCookiePathByte(b byte) bool {
	return 0x20 <= b && b < 0x7f && b != ';'
}

func sanitizeOrWarn(fieldName string, valid func(byte) bool, v string) string {
	ok := true
	for i := 0; i < len(v); i++ {
		if valid(v[i]) {
			continue
		}
		log.Printf("net/http: invalid byte %q in %s; dropping invalid bytes", v[i], fieldName)
		ok = false
		break
	}
	if ok {
		return v
	}
	buf := make([]byte, 0, len(v))
	for i := 0; i < len(v); i++ {
		if b := v[i]; valid(b) {
			buf = append(buf, b)
		}
	}
	return string(buf)
}

func parseCookieValue(raw string, allowDoubleQuote bool) (string, bool) {
	// Strip the quotes, if present.
	if allowDoubleQuote && len(raw) > 1 && raw[0] == '"' && raw[len(raw)-1] == '"' {
		raw = raw[1 : len(raw)-1]
	}
	for i := 0; i < len(raw); i++ {
		if !validCookieValueByte(raw[i]) {
			return "", false
		}
	}
	return raw, true
}

func isCookieNameValid(raw string) bool {
	if raw == "" {
		return false
	}
	return strings.IndexFunc(raw, isNotToken) < 0
}
<commit_msg>net/http: fix typo in the SameSite docs<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package http

import (
	"log"
	"net"
	"strconv"
	"strings"
	"time"
)

// A Cookie represents an HTTP cookie as sent in the Set-Cookie header of an
// HTTP response or the Cookie header of an HTTP request.
//
// See https://tools.ietf.org/html/rfc6265 for details.
type Cookie struct {
	Name  string
	Value string

	Path       string    // optional
	Domain     string    // optional
	Expires    time.Time // optional
	RawExpires string    // for reading cookies only

	// MaxAge=0 means no 'Max-Age' attribute specified.
	// MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'
	// MaxAge>0 means Max-Age attribute present and given in seconds
	MaxAge   int
	Secure   bool
	HttpOnly bool
	SameSite SameSite
	Raw      string
	Unparsed []string // Raw text of unparsed attribute-value pairs
}

// SameSite allows a server to define a cookie attribute making it impossible for
// the browser to send this cookie along with cross-site requests. The main
// goal is to mitigate the risk of cross-origin information leakage, and provide
// some protection against cross-site request forgery attacks.
//
// See https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00 for details.
type SameSite int

const (
	SameSiteDefaultMode SameSite = iota + 1
	SameSiteLaxMode
	SameSiteStrictMode
)

// readSetCookies parses all "Set-Cookie" values from
// the header h and returns the successfully parsed Cookies.
func readSetCookies(h Header) []*Cookie {
	cookieCount := len(h["Set-Cookie"])
	if cookieCount == 0 {
		return []*Cookie{}
	}
	cookies := make([]*Cookie, 0, cookieCount)
	for _, line := range h["Set-Cookie"] {
		parts := strings.Split(strings.TrimSpace(line), ";")
		if len(parts) == 1 && parts[0] == "" {
			continue
		}
		parts[0] = strings.TrimSpace(parts[0])
		j := strings.Index(parts[0], "=")
		if j < 0 {
			continue
		}
		name, value := parts[0][:j], parts[0][j+1:]
		if !isCookieNameValid(name) {
			continue
		}
		value, ok := parseCookieValue(value, true)
		if !ok {
			continue
		}
		c := &Cookie{
			Name:  name,
			Value: value,
			Raw:   line,
		}
		for i := 1; i < len(parts); i++ {
			parts[i] = strings.TrimSpace(parts[i])
			if len(parts[i]) == 0 {
				continue
			}

			attr, val := parts[i], ""
			if j := strings.Index(attr, "="); j >= 0 {
				attr, val = attr[:j], attr[j+1:]
			}
			lowerAttr := strings.ToLower(attr)
			val, ok = parseCookieValue(val, false)
			if !ok {
				c.Unparsed = append(c.Unparsed, parts[i])
				continue
			}
			switch lowerAttr {
			case "samesite":
				lowerVal := strings.ToLower(val)
				switch lowerVal {
				case "lax":
					c.SameSite = SameSiteLaxMode
				case "strict":
					c.SameSite = SameSiteStrictMode
				default:
					c.SameSite = SameSiteDefaultMode
				}
				continue
			case "secure":
				c.Secure = true
				continue
			case "httponly":
				c.HttpOnly = true
				continue
			case "domain":
				c.Domain = val
				continue
			case "max-age":
				secs, err := strconv.Atoi(val)
				if err != nil || secs != 0 && val[0] == '0' {
					break
				}
				if secs <= 0 {
					secs = -1
				}
				c.MaxAge = secs
				continue
			case "expires":
				c.RawExpires = val
				exptime, err := time.Parse(time.RFC1123, val)
				if err != nil {
					exptime, err = time.Parse("Mon, 02-Jan-2006 15:04:05 MST", val)
					if err != nil {
						c.Expires = time.Time{}
						break
					}
				}
				c.Expires = exptime.UTC()
				continue
			case "path":
				c.Path = val
				continue
			}
			c.Unparsed = append(c.Unparsed, parts[i])
		}
		cookies = append(cookies, c)
	}
	return cookies
}

// SetCookie adds a Set-Cookie header to the provided ResponseWriter's headers.
// The provided cookie must have a valid Name. Invalid cookies may be
// silently dropped.
func SetCookie(w ResponseWriter, cookie *Cookie) {
	if v := cookie.String(); v != "" {
		w.Header().Add("Set-Cookie", v)
	}
}

// String returns the serialization of the cookie for use in a Cookie
// header (if only Name and Value are set) or a Set-Cookie response
// header (if other fields are set).
// If c is nil or c.Name is invalid, the empty string is returned.
func (c *Cookie) String() string {
	if c == nil || !isCookieNameValid(c.Name) {
		return ""
	}
	var b strings.Builder
	b.WriteString(sanitizeCookieName(c.Name))
	b.WriteRune('=')
	b.WriteString(sanitizeCookieValue(c.Value))

	if len(c.Path) > 0 {
		b.WriteString("; Path=")
		b.WriteString(sanitizeCookiePath(c.Path))
	}
	if len(c.Domain) > 0 {
		if validCookieDomain(c.Domain) {
			// A c.Domain containing illegal characters is not
			// sanitized but simply dropped which turns the cookie
			// into a host-only cookie. A leading dot is okay
			// but won't be sent.
			d := c.Domain
			if d[0] == '.' {
				d = d[1:]
			}
			b.WriteString("; Domain=")
			b.WriteString(d)
		} else {
			log.Printf("net/http: invalid Cookie.Domain %q; dropping domain attribute", c.Domain)
		}
	}
	var buf [len(TimeFormat)]byte
	if validCookieExpires(c.Expires) {
		b.WriteString("; Expires=")
		b.Write(c.Expires.UTC().AppendFormat(buf[:0], TimeFormat))
	}
	if c.MaxAge > 0 {
		b.WriteString("; Max-Age=")
		b.Write(strconv.AppendInt(buf[:0], int64(c.MaxAge), 10))
	} else if c.MaxAge < 0 {
		b.WriteString("; Max-Age=0")
	}
	if c.HttpOnly {
		b.WriteString("; HttpOnly")
	}
	if c.Secure {
		b.WriteString("; Secure")
	}
	switch c.SameSite {
	case SameSiteDefaultMode:
		b.WriteString("; SameSite")
	case SameSiteLaxMode:
		b.WriteString("; SameSite=Lax")
	case SameSiteStrictMode:
		b.WriteString("; SameSite=Strict")
	}
	return b.String()
}

// readCookies parses all "Cookie" values from the header h and
// returns the successfully parsed Cookies.
//
// if filter isn't empty, only cookies of that name are returned
func readCookies(h Header, filter string) []*Cookie {
	lines, ok := h["Cookie"]
	if !ok {
		return []*Cookie{}
	}

	cookies := []*Cookie{}
	for _, line := range lines {
		parts := strings.Split(strings.TrimSpace(line), ";")
		if len(parts) == 1 && parts[0] == "" {
			continue
		}
		// Per-line attributes
		for i := 0; i < len(parts); i++ {
			parts[i] = strings.TrimSpace(parts[i])
			if len(parts[i]) == 0 {
				continue
			}
			name, val := parts[i], ""
			if j := strings.Index(name, "="); j >= 0 {
				name, val = name[:j], name[j+1:]
			}
			if !isCookieNameValid(name) {
				continue
			}
			if filter != "" && filter != name {
				continue
			}
			val, ok := parseCookieValue(val, true)
			if !ok {
				continue
			}
			cookies = append(cookies, &Cookie{Name: name, Value: val})
		}
	}
	return cookies
}

// validCookieDomain returns whether v is a valid cookie domain-value.
func validCookieDomain(v string) bool {
	if isCookieDomainName(v) {
		return true
	}
	if net.ParseIP(v) != nil && !strings.Contains(v, ":") {
		return true
	}
	return false
}

// validCookieExpires returns whether v is a valid cookie expires-value.
func validCookieExpires(t time.Time) bool {
	// IETF RFC 6265 Section 5.1.1.5, the year must not be less than 1601
	return t.Year() >= 1601
}

// isCookieDomainName returns whether s is a valid domain name or a valid
// domain name with a leading dot '.'.  It is almost a direct copy of
// package net's isDomainName.
func isCookieDomainName(s string) bool {
	if len(s) == 0 {
		return false
	}
	if len(s) > 255 {
		return false
	}

	if s[0] == '.' {
		// A cookie a domain attribute may start with a leading dot.
		s = s[1:]
	}
	last := byte('.')
	ok := false // Ok once we've seen a letter.
	partlen := 0
	for i := 0; i < len(s); i++ {
		c := s[i]
		switch {
		default:
			return false
		case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z':
			// No '_' allowed here (in contrast to package net).
			ok = true
			partlen++
		case '0' <= c && c <= '9':
			// fine
			partlen++
		case c == '-':
			// Byte before dash cannot be dot.
			if last == '.' {
				return false
			}
			partlen++
		case c == '.':
			// Byte before dot cannot be dot, dash.
			if last == '.' || last == '-' {
				return false
			}
			if partlen > 63 || partlen == 0 {
				return false
			}
			partlen = 0
		}
		last = c
	}
	if last == '-' || partlen > 63 {
		return false
	}

	return ok
}

var cookieNameSanitizer = strings.NewReplacer("\n", "-", "\r", "-")

func sanitizeCookieName(n string) string {
	return cookieNameSanitizer.Replace(n)
}

// https://tools.ietf.org/html/rfc6265#section-4.1.1
// cookie-value      = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
// cookie-octet      = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
//           ; US-ASCII characters excluding CTLs,
//           ; whitespace DQUOTE, comma, semicolon,
//           ; and backslash
// We loosen this as spaces and commas are common in cookie values
// but we produce a quoted cookie-value in when value starts or ends
// with a comma or space.
// See https://golang.org/issue/7243 for the discussion.
func sanitizeCookieValue(v string) string {
	v = sanitizeOrWarn("Cookie.Value", validCookieValueByte, v)
	if len(v) == 0 {
		return v
	}
	if strings.IndexByte(v, ' ') >= 0 || strings.IndexByte(v, ',') >= 0 {
		return `"` + v + `"`
	}
	return v
}

func validCookieValueByte(b byte) bool {
	return 0x20 <= b && b < 0x7f && b != '"' && b != ';' && b != '\\'
}

// path-av           = "Path=" path-value
// path-value        = <any CHAR except CTLs or ";">
func sanitizeCookiePath(v string) string {
	return sanitizeOrWarn("Cookie.Path", validCookiePathByte, v)
}

func validCookiePathByte(b byte) bool {
	return 0x20 <= b && b < 0x7f && b != ';'
}

func sanitizeOrWarn(fieldName string, valid func(byte) bool, v string) string {
	ok := true
	for i := 0; i < len(v); i++ {
		if valid(v[i]) {
			continue
		}
		log.Printf("net/http: invalid byte %q in %s; dropping invalid bytes", v[i], fieldName)
		ok = false
		break
	}
	if ok {
		return v
	}
	buf := make([]byte, 0, len(v))
	for i := 0; i < len(v); i++ {
		if b := v[i]; valid(b) {
			buf = append(buf, b)
		}
	}
	return string(buf)
}

func parseCookieValue(raw string, allowDoubleQuote bool) (string, bool) {
	// Strip the quotes, if present.
	if allowDoubleQuote && len(raw) > 1 && raw[0] == '"' && raw[len(raw)-1] == '"' {
		raw = raw[1 : len(raw)-1]
	}
	for i := 0; i < len(raw); i++ {
		if !validCookieValueByte(raw[i]) {
			return "", false
		}
	}
	return raw, true
}

func isCookieNameValid(raw string) bool {
	if raw == "" {
		return false
	}
	return strings.IndexFunc(raw, isNotToken) < 0
}
<|endoftext|>


<commit_before>// Provides a midi master clock and various other utils for working with midi
package midi

import (
	"os"
	"time"
)

const (
	START    = 0xfa
	STOP     = 0xfc
	TICK     = 0xf8
	CONTINUE = 0xfb
)

type Clock struct {
	cmd       chan []byte
	pulseRate chan time.Duration
	dev       *os.File
}

// Create a new midi clock. The clock starts to send tick events as soon as it is created.
//dev, err := os.OpenFile("/dev/snd/midiC1D0", os.O_WRONLY, 0664)
//if err != nil {
//	log.Fatal(err)
//}
//
//clk := midi.NewClock(dev)
//clk.SetBpm(120.00)
//clk.Start()
func NewClock(midiDevice *os.File) *Clock {
	clk := new(Clock)
	clk.dev = midiDevice
	clk.cmd = make(chan []byte)
	clk.pulseRate = make(chan time.Duration)

	go clk.run()

	return clk
}

// Change the BPM of the clock
func (clk *Clock) SetBpm(bpm float64) {
	clk.pulseRate <- bpmToPulseInterval(bpm)
}

// Send MIDI sequencer start event
func (clk *Clock) Start() {
	clk.cmd <- []byte{START}
}

// Send MIDI sequencer stop event
func (clk *Clock) Stop() {
	clk.cmd <- []byte{STOP}
}

// Send MIDI sequencer stop event
func (clk *Clock) Continue() {
	clk.cmd <- []byte{CONTINUE}
}

func (clk *Clock) run() {
	pulseRate := bpmToPulseInterval(120)
	tick := []byte{TICK}
	var t VarTicker
	t.SetDuration(pulseRate)

	go func() {
		for range t.C {
			clk.dev.Write(tick)
		}
	}()

	for {
		select {
		case newPulseRate := <-clk.pulseRate:
			t.SetDuration(newPulseRate)
		case cmd := <-clk.cmd:
			clk.dev.Write(cmd)
		}
	}

}

// Converts bpm to a 24ppqn pulse interval in microseconds
func bpmToPulseInterval(bpm float64) time.Duration {
	return time.Duration((6000000/(bpm/10))/24) * time.Microsecond
}
<commit_msg>Renamed constants<commit_after>// Provides a midi master clock and various other utils for working with midi
package midi

import (
	"os"
	"time"
)

const (
	Start    = 0xfa
	Stop     = 0xfc
	Tick     = 0xf8
	Continue = 0xfb
)

type Clock struct {
	cmd       chan []byte
	pulseRate chan time.Duration
	dev       *os.File
}

// Create a new midi clock. The clock starts to send tick events as soon as it is created.
//dev, err := os.OpenFile("/dev/snd/midiC1D0", os.O_WRONLY, 0664)
//if err != nil {
//	log.Fatal(err)
//}
//
//clk := midi.NewClock(dev)
//clk.SetBpm(120.00)
//clk.Start()
func NewClock(midiDevice *os.File) *Clock {
	clk := new(Clock)
	clk.dev = midiDevice
	clk.cmd = make(chan []byte)
	clk.pulseRate = make(chan time.Duration)

	go clk.run()

	return clk
}

// Change the BPM of the clock
func (clk *Clock) SetBpm(bpm float64) {
	clk.pulseRate <- bpmToPulseInterval(bpm)
}

// Send MIDI sequencer start event
func (clk *Clock) Start() {
	clk.cmd <- []byte{Start}
}

// Send MIDI sequencer stop event
func (clk *Clock) Stop() {
	clk.cmd <- []byte{Stop}
}

// Send MIDI sequencer stop event
func (clk *Clock) Continue() {
	clk.cmd <- []byte{Continue}
}

func (clk *Clock) run() {
	pulseRate := bpmToPulseInterval(120)
	tick := []byte{Tick}
	var t VarTicker
	t.SetDuration(pulseRate)

	go func() {
		for range t.C {
			clk.dev.Write(tick)
		}
	}()

	for {
		select {
		case newPulseRate := <-clk.pulseRate:
			t.SetDuration(newPulseRate)
		case cmd := <-clk.cmd:
			clk.dev.Write(cmd)
		}
	}

}

// Converts bpm to a 24ppqn pulse interval in microseconds
func bpmToPulseInterval(bpm float64) time.Duration {
	return time.Duration((6000000/(bpm/10))/24) * time.Microsecond
}
<|endoftext|>


<commit_before>package tests_test

import (
	"flag"

	. "github.com/onsi/ginkgo"
	"github.com/onsi/ginkgo/extensions/table"
	. "github.com/onsi/gomega"
	"k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/util/intstr"

	v12 "kubevirt.io/kubevirt/pkg/api/v1"
	"kubevirt.io/kubevirt/pkg/kubecli"
	"kubevirt.io/kubevirt/tests"
)

var _ = Describe("Probes", func() {
	flag.Parse()

	virtClient, err := kubecli.GetKubevirtClient()
	tests.PanicOnError(err)

	BeforeEach(func() {
		tests.BeforeTestCleanup()
	})

	Context("for readiness", func() {

		tcpProbe := &v12.Probe{
			PeriodSeconds:       5,
			InitialDelaySeconds: 5,
			Handler: v12.Handler{

				TCPSocket: &v1.TCPSocketAction{
					Port: intstr.Parse("1500"),
				},
			},
		}

		httpProbe := &v12.Probe{
			PeriodSeconds:       5,
			InitialDelaySeconds: 5,
			Handler: v12.Handler{

				HTTPGet: &v1.HTTPGetAction{
					Port: intstr.Parse("1500"),
				},
			},
		}
		table.DescribeTable("should succeed", func(readinessProbe *v12.Probe, serverStarter func(vmi *v12.VirtualMachineInstance, port int)) {
			By("Specifying a VMI with a readiness probe")
			vmi := tests.NewRandomVMIWithEphemeralDiskAndUserdata(tests.ContainerDiskFor(tests.ContainerDiskCirros), "#!/bin/bash\necho 'hello'\n")
			vmi.Spec.ReadinessProbe = readinessProbe
			vmi, err = virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Create(vmi)
			Expect(err).ToNot(HaveOccurred())
			tests.WaitForSuccessfulVMIStart(vmi)

			Expect(podReady(tests.GetRunningPodByVirtualMachineInstance(vmi, tests.NamespaceTestDefault))).To(Equal(v1.ConditionFalse))

			By("Starting the server inside the VMI")
			serverStarter(vmi, 1500)

			By("Checking that the VMI will be marked as ready to receive traffic")
			Eventually(func() v1.ConditionStatus {
				pod := tests.GetRunningPodByVirtualMachineInstance(vmi, tests.NamespaceTestDefault)
				return podReady(pod)
			}, 30, 1).Should(Equal(v1.ConditionTrue))
		},
			table.Entry("with working TCP probe and tcp server", tcpProbe, tests.StartTCPServer),
			table.Entry("with working HTTP probe and http server", httpProbe, tests.StartHTTPServer),
		)

		table.DescribeTable("should fail", func(readinessProbe *v12.Probe) {
			By("Specifying a VMI with a readiness probe")
			vmi := tests.NewRandomVMIWithEphemeralDiskAndUserdata(tests.ContainerDiskFor(tests.ContainerDiskCirros), "#!/bin/bash\necho 'hello'\n")
			vmi.Spec.ReadinessProbe = readinessProbe
			vmi, err = virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Create(vmi)
			Expect(err).ToNot(HaveOccurred())
			tests.WaitForSuccessfulVMIStart(vmi)

			Expect(podReady(tests.GetRunningPodByVirtualMachineInstance(vmi, tests.NamespaceTestDefault))).To(Equal(v1.ConditionFalse))

			By("Checking that the VMI will consistently stay in a not-ready state")
			Consistently(func() v1.ConditionStatus {
				pod := tests.GetRunningPodByVirtualMachineInstance(vmi, tests.NamespaceTestDefault)
				return podReady(pod)
			}, 30, 1).Should(Equal(v1.ConditionFalse))
		},
			table.Entry("with working TCP probe and no running server", tcpProbe),
			table.Entry("with working HTTP probe and no running server", httpProbe),
		)
	})
})

func podReady(pod *v1.Pod) v1.ConditionStatus {
	for _, cond := range pod.Status.Conditions {
		if cond.Type == v1.PodReady {
			return cond.Status
		}
	}
	return v1.ConditionFalse
}
<commit_msg>Functional tests for liveness probes<commit_after>package tests_test

import (
	"flag"

	. "github.com/onsi/ginkgo"
	"github.com/onsi/ginkgo/extensions/table"
	. "github.com/onsi/gomega"
	"k8s.io/api/core/v1"
	v13 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/intstr"

	v12 "kubevirt.io/kubevirt/pkg/api/v1"
	"kubevirt.io/kubevirt/pkg/kubecli"
	"kubevirt.io/kubevirt/tests"
)

var _ = Describe("Probes", func() {
	flag.Parse()

	virtClient, err := kubecli.GetKubevirtClient()
	tests.PanicOnError(err)

	BeforeEach(func() {
		tests.BeforeTestCleanup()
	})

	Context("for readiness", func() {

		tcpProbe := &v12.Probe{
			PeriodSeconds:       5,
			InitialDelaySeconds: 5,
			Handler: v12.Handler{

				TCPSocket: &v1.TCPSocketAction{
					Port: intstr.Parse("1500"),
				},
			},
		}

		httpProbe := &v12.Probe{
			PeriodSeconds:       5,
			InitialDelaySeconds: 5,
			Handler: v12.Handler{

				HTTPGet: &v1.HTTPGetAction{
					Port: intstr.Parse("1500"),
				},
			},
		}
		table.DescribeTable("should succeed", func(readinessProbe *v12.Probe, serverStarter func(vmi *v12.VirtualMachineInstance, port int)) {
			By("Specifying a VMI with a readiness probe")
			vmi := tests.NewRandomVMIWithEphemeralDiskAndUserdata(tests.ContainerDiskFor(tests.ContainerDiskCirros), "#!/bin/bash\necho 'hello'\n")
			vmi.Spec.ReadinessProbe = readinessProbe
			vmi, err = virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Create(vmi)
			Expect(err).ToNot(HaveOccurred())
			// It may come to modify retries on the VMI because of the kubelet updating the pod, which can trigger controllers more often
			tests.WaitForSuccessfulVMIStartIgnoreWarnings(vmi)

			Expect(podReady(tests.GetRunningPodByVirtualMachineInstance(vmi, tests.NamespaceTestDefault))).To(Equal(v1.ConditionFalse))

			By("Starting the server inside the VMI")
			serverStarter(vmi, 1500)

			By("Checking that the VMI will be marked as ready to receive traffic")
			Eventually(func() v1.ConditionStatus {
				pod := tests.GetRunningPodByVirtualMachineInstance(vmi, tests.NamespaceTestDefault)
				return podReady(pod)
			}, 30, 1).Should(Equal(v1.ConditionTrue))
		},
			table.Entry("with working TCP probe and tcp server", tcpProbe, tests.StartTCPServer),
			table.Entry("with working HTTP probe and http server", httpProbe, tests.StartHTTPServer),
		)

		table.DescribeTable("should fail", func(readinessProbe *v12.Probe) {
			By("Specifying a VMI with a readiness probe")
			vmi := tests.NewRandomVMIWithEphemeralDiskAndUserdata(tests.ContainerDiskFor(tests.ContainerDiskCirros), "#!/bin/bash\necho 'hello'\n")
			vmi.Spec.ReadinessProbe = readinessProbe
			vmi, err = virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Create(vmi)
			Expect(err).ToNot(HaveOccurred())
			// It may come to modify retries on the VMI because of the kubelet updating the pod, which can trigger controllers more often
			tests.WaitForSuccessfulVMIStartIgnoreWarnings(vmi)

			Expect(podReady(tests.GetRunningPodByVirtualMachineInstance(vmi, tests.NamespaceTestDefault))).To(Equal(v1.ConditionFalse))

			By("Checking that the VMI will consistently stay in a not-ready state")
			Consistently(func() v1.ConditionStatus {
				pod := tests.GetRunningPodByVirtualMachineInstance(vmi, tests.NamespaceTestDefault)
				return podReady(pod)
			}, 30, 1).Should(Equal(v1.ConditionFalse))
		},
			table.Entry("with working TCP probe and no running server", tcpProbe),
			table.Entry("with working HTTP probe and no running server", httpProbe),
		)
	})

	Context("for liveness", func() {

		tcpProbe := &v12.Probe{
			PeriodSeconds:       5,
			InitialDelaySeconds: 30,
			Handler: v12.Handler{

				TCPSocket: &v1.TCPSocketAction{
					Port: intstr.Parse("1500"),
				},
			},
		}

		httpProbe := &v12.Probe{
			PeriodSeconds:       5,
			InitialDelaySeconds: 30,
			Handler: v12.Handler{

				HTTPGet: &v1.HTTPGetAction{
					Port: intstr.Parse("1500"),
				},
			},
		}
		table.DescribeTable("should not fail the VMI", func(livenessProbe *v12.Probe, serverStarter func(vmi *v12.VirtualMachineInstance, port int)) {
			By("Specifying a VMI with a readiness probe")
			vmi := tests.NewRandomVMIWithEphemeralDiskAndUserdata(tests.ContainerDiskFor(tests.ContainerDiskCirros), "#!/bin/bash\necho 'hello'\n")
			vmi.Spec.LivenessProbe = livenessProbe
			vmi, err = virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Create(vmi)
			Expect(err).ToNot(HaveOccurred())
			// It may come to modify retries on the VMI because of the kubelet updating the pod, which can trigger controllers more often
			tests.WaitForSuccessfulVMIStartIgnoreWarnings(vmi)

			By("Starting the server inside the VMI")
			serverStarter(vmi, 1500)

			By("Checking that the VMI is still running after a minute")
			Consistently(func() bool {
				vmi, err := virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Get(vmi.Name, &v13.GetOptions{})
				Expect(err).ToNot(HaveOccurred())
				return vmi.IsFinal()
			}, 60, 1).Should(Not(BeTrue()))
		},
			table.Entry("with working TCP probe and tcp server", tcpProbe, tests.StartTCPServer),
			table.Entry("with working HTTP probe and http server", httpProbe, tests.StartHTTPServer),
		)

		table.DescribeTable("should fail the VMI", func(livenessProbe *v12.Probe) {
			By("Specifying a VMI with a readiness probe")
			vmi := tests.NewRandomVMIWithEphemeralDiskAndUserdata(tests.ContainerDiskFor(tests.ContainerDiskCirros), "#!/bin/bash\necho 'hello'\n")
			vmi.Spec.LivenessProbe = livenessProbe
			vmi, err = virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Create(vmi)
			Expect(err).ToNot(HaveOccurred())
			// It may come to modify retries on the VMI because of the kubelet updating the pod, which can trigger controllers more often
			tests.WaitForSuccessfulVMIStartIgnoreWarnings(vmi)

			By("Checking that the VMI is in a final state after a minute")
			Eventually(func() bool {
				vmi, err := virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Get(vmi.Name, &v13.GetOptions{})
				Expect(err).ToNot(HaveOccurred())
				return vmi.IsFinal()
			}, 60, 1).Should(BeTrue())
		},
			table.Entry("with working TCP probe and no running server", tcpProbe),
			table.Entry("with working HTTP probe and no running server", httpProbe),
		)
	})
})

func podReady(pod *v1.Pod) v1.ConditionStatus {
	for _, cond := range pod.Status.Conditions {
		if cond.Type == v1.PodReady {
			return cond.Status
		}
	}
	return v1.ConditionFalse
}
<|endoftext|>


<commit_before>package conn

import (
	"errors"
	"fmt"

	handshake "github.com/jbenet/go-ipfs/net/handshake"
	hspb "github.com/jbenet/go-ipfs/net/handshake/pb"
	u "github.com/jbenet/go-ipfs/util"

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
	proto "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/goprotobuf/proto"
	ma "github.com/jbenet/go-multiaddr"
)

// Handshake1 exchanges local and remote versions and compares them
// closes remote and returns an error in case of major difference
func Handshake1(ctx context.Context, c Conn) error {
	rpeer := c.RemotePeer()
	lpeer := c.LocalPeer()

	var remoteH, localH *hspb.Handshake1
	localH = handshake.Handshake1Msg()

	myVerBytes, err := proto.Marshal(localH)
	if err != nil {
		return err
	}

	c.Out() <- myVerBytes
	log.Debugf("Sent my version (%s) to %s", localH, rpeer)

	select {
	case <-ctx.Done():
		return ctx.Err()

	case <-c.Closing():
		return errors.New("remote closed connection during version exchange")

	case data, ok := <-c.In():
		if !ok {
			return fmt.Errorf("error retrieving from conn: %v", rpeer)
		}

		remoteH = new(hspb.Handshake1)
		err = proto.Unmarshal(data, remoteH)
		if err != nil {
			return fmt.Errorf("could not decode remote version: %q", err)
		}

		log.Debugf("Received remote version (%s) from %s", remoteH, rpeer)
	}

	if err := handshake.Handshake1Compatible(localH, remoteH); err != nil {
		log.Infof("%s (%s) incompatible version with %s (%s)", lpeer, localH, rpeer, remoteH)
		return err
	}

	log.Debugf("%s version handshake compatible %s", lpeer, rpeer)
	return nil
}

// Handshake3 exchanges local and remote service information
func Handshake3(ctx context.Context, c Conn) error {
	rpeer := c.RemotePeer()
	lpeer := c.LocalPeer()

	var remoteH, localH *hspb.Handshake3
	localH = handshake.Handshake3Msg(lpeer)

	rma := c.RemoteMultiaddr()
	localH.ObservedAddr = proto.String(rma.String())

	localB, err := proto.Marshal(localH)
	if err != nil {
		return err
	}

	c.Out() <- localB
	log.Debugf("Handshake1: sent to %s", rpeer)

	select {
	case <-ctx.Done():
		return ctx.Err()

	case <-c.Closing():
		return errors.New("Handshake3: error remote connection closed")

	case remoteB, ok := <-c.In():
		if !ok {
			return fmt.Errorf("Handshake3 error receiving from conn: %v", rpeer)
		}

		remoteH = new(hspb.Handshake3)
		err = proto.Unmarshal(remoteB, remoteH)
		if err != nil {
			return fmt.Errorf("Handshake3 could not decode remote msg: %q", err)
		}

		log.Debugf("Handshake3 received from %s", rpeer)
	}

	if err := handshake.Handshake3UpdatePeer(rpeer, remoteH); err != nil {
		log.Errorf("Handshake3 failed to update %s", rpeer)
		return err
	}

	return nil
}

func CheckNAT(obsaddr string) (bool, error) {
	oma, err := ma.NewMultiaddr(obsaddr)
	if err != nil {
		return false, err
	}
	addrs, err := u.GetLocalAddresses()
	if err != nil {
		return false, err
	}
	_ = oma
	_ = addrs

	panic("not yet implemented!")
}
<commit_msg>print NAT if detected<commit_after>package conn

import (
	"errors"
	"fmt"
	"strings"

	handshake "github.com/jbenet/go-ipfs/net/handshake"
	hspb "github.com/jbenet/go-ipfs/net/handshake/pb"
	u "github.com/jbenet/go-ipfs/util"

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
	proto "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/goprotobuf/proto"
	ma "github.com/jbenet/go-multiaddr"
)

// Handshake1 exchanges local and remote versions and compares them
// closes remote and returns an error in case of major difference
func Handshake1(ctx context.Context, c Conn) error {
	rpeer := c.RemotePeer()
	lpeer := c.LocalPeer()

	var remoteH, localH *hspb.Handshake1
	localH = handshake.Handshake1Msg()

	myVerBytes, err := proto.Marshal(localH)
	if err != nil {
		return err
	}

	c.Out() <- myVerBytes
	log.Debugf("Sent my version (%s) to %s", localH, rpeer)

	select {
	case <-ctx.Done():
		return ctx.Err()

	case <-c.Closing():
		return errors.New("remote closed connection during version exchange")

	case data, ok := <-c.In():
		if !ok {
			return fmt.Errorf("error retrieving from conn: %v", rpeer)
		}

		remoteH = new(hspb.Handshake1)
		err = proto.Unmarshal(data, remoteH)
		if err != nil {
			return fmt.Errorf("could not decode remote version: %q", err)
		}

		log.Debugf("Received remote version (%s) from %s", remoteH, rpeer)
	}

	if err := handshake.Handshake1Compatible(localH, remoteH); err != nil {
		log.Infof("%s (%s) incompatible version with %s (%s)", lpeer, localH, rpeer, remoteH)
		return err
	}

	log.Debugf("%s version handshake compatible %s", lpeer, rpeer)
	return nil
}

// Handshake3 exchanges local and remote service information
func Handshake3(ctx context.Context, c Conn) error {
	rpeer := c.RemotePeer()
	lpeer := c.LocalPeer()

	var remoteH, localH *hspb.Handshake3
	localH = handshake.Handshake3Msg(lpeer)

	rma := c.RemoteMultiaddr()
	localH.ObservedAddr = proto.String(rma.String())

	localB, err := proto.Marshal(localH)
	if err != nil {
		return err
	}

	c.Out() <- localB
	log.Debugf("Handshake1: sent to %s", rpeer)

	select {
	case <-ctx.Done():
		return ctx.Err()

	case <-c.Closing():
		return errors.New("Handshake3: error remote connection closed")

	case remoteB, ok := <-c.In():
		if !ok {
			return fmt.Errorf("Handshake3 error receiving from conn: %v", rpeer)
		}

		remoteH = new(hspb.Handshake3)
		err = proto.Unmarshal(remoteB, remoteH)
		if err != nil {
			return fmt.Errorf("Handshake3 could not decode remote msg: %q", err)
		}

		log.Debugf("Handshake3 received from %s", rpeer)
	}

	if err := handshake.Handshake3UpdatePeer(rpeer, remoteH); err != nil {
		log.Errorf("Handshake3 failed to update %s", rpeer)
		return err
	}

	nat, err := CheckNAT(remoteH.GetObservedAddr())
	if err != nil {
		log.Errorf("Error in NAT detection: %s", err)
	}
	if nat {
		log.Warning("We are probably behind a NAT!")
	}

	return nil
}

func CheckNAT(obsaddr string) (bool, error) {
	oma, err := ma.NewMultiaddr(obsaddr)
	if err != nil {
		return false, err
	}
	addrs, err := u.GetLocalAddresses()
	if err != nil {
		return false, err
	}

	omastr := oma.String()
	for _, addr := range addrs {
		if strings.HasPrefix(addr.String(), omastr) {
			return false, nil
		}
	}

	return true, nil
}
<|endoftext|>


<commit_before>package wallet

import (
	"fmt"
	"io"
	"os"
	"path/filepath"

	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/encoding"
	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/Sia/persist"
	"github.com/NebulousLabs/fastrand"

	"github.com/NebulousLabs/bolt"
)

const (
	logFile    = modules.WalletDir + ".log"
	dbFile     = modules.WalletDir + ".db"
	compatFile = modules.WalletDir + ".json"
)

var (
	dbMetadata = persist.Metadata{
		Header:  "Wallet Database",
		Version: "1.1.0",
	}
)

// spendableKeyFile stores an encrypted spendable key on disk.
type spendableKeyFile struct {
	UID                    uniqueID
	EncryptionVerification crypto.Ciphertext
	SpendableKey           crypto.Ciphertext
}

// openDB loads the set database and populates it with the necessary buckets.
func (w *Wallet) openDB(filename string) (err error) {
	w.db, err = persist.OpenDatabase(dbMetadata, filename)
	if err != nil {
		return err
	}
	// initialize the database
	err = w.db.Update(func(tx *bolt.Tx) error {
		for _, b := range dbBuckets {
			_, err := tx.CreateBucketIfNotExists(b)
			if err != nil {
				return fmt.Errorf("could not create bucket %v: %v", string(b), err)
			}
		}
		// if the wallet does not have a UID, create one
		if tx.Bucket(bucketWallet).Get(keyUID) == nil {
			uid := make([]byte, len(uniqueID{}))
			fastrand.Read(uid[:])
			tx.Bucket(bucketWallet).Put(keyUID, uid)
		}
		// if fields in bucketWallet are nil, set them to zero to prevent unmarshal errors
		wb := tx.Bucket(bucketWallet)
		if wb.Get(keyConsensusHeight) == nil {
			wb.Put(keyConsensusHeight, encoding.Marshal(uint64(0)))
		}
		if wb.Get(keyAuxiliarySeedFiles) == nil {
			wb.Put(keyAuxiliarySeedFiles, encoding.Marshal([]seedFile{}))
		}
		if wb.Get(keySpendableKeyFiles) == nil {
			wb.Put(keySpendableKeyFiles, encoding.Marshal([]spendableKeyFile{}))
		}

		// check whether wallet is encrypted
		w.encrypted = tx.Bucket(bucketWallet).Get(keyEncryptionVerification) != nil
		return nil
	})
	return err
}

// initPersist loads all of the wallet's persistence files into memory,
// creating them if they do not exist.
func (w *Wallet) initPersist() error {
	// Create a directory for the wallet without overwriting an existing
	// directory.
	err := os.MkdirAll(w.persistDir, 0700)
	if err != nil {
		return err
	}

	// Start logging.
	w.log, err = persist.NewFileLogger(filepath.Join(w.persistDir, logFile))
	if err != nil {
		return err
	}

	// Open the database.
	dbFilename := filepath.Join(w.persistDir, dbFile)
	compatFilename := filepath.Join(w.persistDir, compatFile)
	_, dbErr := os.Stat(dbFilename)
	_, compatErr := os.Stat(compatFilename)
	if dbErr != nil && compatErr == nil {
		// database does not exist, but old persist does; convert it
		err = w.convertPersistFrom112To120(dbFilename, compatFilename)
	} else {
		// either database exists or neither exists; open/create the database
		err = w.openDB(filepath.Join(w.persistDir, dbFile))
	}
	if err != nil {
		return err
	}
	w.tg.AfterStop(func() { w.db.Close() })

	return nil
}

// createBackup copies the wallet database to dst.
func (w *Wallet) createBackup(dst io.Writer) error {
	_, err := w.dbTx.WriteTo(dst)
	return err
}

// CreateBackup creates a backup file at the desired filepath.
func (w *Wallet) CreateBackup(backupFilepath string) error {
	if err := w.tg.Add(); err != nil {
		return err
	}
	defer w.tg.Done()
	w.mu.Lock()
	defer w.mu.Unlock()
	f, err := os.Create(backupFilepath)
	if err != nil {
		return err
	}
	defer f.Close()
	return w.createBackup(f)
}

// compat112Persist is the structure of the wallet.json file used in v1.1.2
type compat112Persist struct {
	UID                    uniqueID
	EncryptionVerification crypto.Ciphertext
	PrimarySeedFile        seedFile
	PrimarySeedProgress    uint64
	AuxiliarySeedFiles     []seedFile
	UnseededKeys           []spendableKeyFile
}

// compat112Meta is the metadata of the wallet.json file used in v1.1.2
var compat112Meta = persist.Metadata{
	Header:  "Wallet Settings",
	Version: "0.4.0",
}

// convertPersistFrom112To120 converts an old (pre-v1.2.0) wallet.json file to
// a wallet.db database.
func (w *Wallet) convertPersistFrom112To120(dbFilename, compatFilename string) error {
	var data compat112Persist
	err := persist.LoadFile(compat112Meta, &data, compatFilename)
	if err != nil {
		return err
	}

	w.db, err = persist.OpenDatabase(dbMetadata, dbFilename)
	if err != nil {
		return err
	}
	// initialize the database
	err = w.db.Update(func(tx *bolt.Tx) error {
		for _, b := range dbBuckets {
			_, err := tx.CreateBucket(b)
			if err != nil {
				return fmt.Errorf("could not create bucket %v: %v", string(b), err)
			}
		}
		// set UID, verification, seeds, and seed progress
		tx.Bucket(bucketWallet).Put(keyUID, data.UID[:])
		tx.Bucket(bucketWallet).Put(keyEncryptionVerification, data.EncryptionVerification)
		tx.Bucket(bucketWallet).Put(keyPrimarySeedFile, encoding.Marshal(data.PrimarySeedFile))
		tx.Bucket(bucketWallet).Put(keyAuxiliarySeedFiles, encoding.Marshal(data.AuxiliarySeedFiles))
		tx.Bucket(bucketWallet).Put(keySpendableKeyFiles, encoding.Marshal(data.UnseededKeys))
		// old wallets had a "preload depth" of 25
		dbPutPrimarySeedProgress(tx, data.PrimarySeedProgress+25)

		// set consensus height and CCID to zero so that a full rescan is
		// triggered
		dbPutConsensusHeight(tx, 0)
		dbPutConsensusChangeID(tx, modules.ConsensusChangeBeginning)
		return nil
	})
	w.encrypted = true
	return err
}

/*
// LoadBackup loads a backup file from the provided filepath. The backup file
// primary seed is loaded as an auxiliary seed.
func (w *Wallet) LoadBackup(masterKey, backupMasterKey crypto.TwofishKey, backupFilepath string) error {
	if err := w.tg.Add(); err != nil {
		return err
	}
	defer w.tg.Done()

	lockID := w.mu.Lock()
	defer w.mu.Unlock(lockID)

	// Load all of the seed files, check for duplicates, re-encrypt them (but
	// keep the UID), and add them to the walletPersist object)
	var backupPersist walletPersist
	err := persist.LoadFile(settingsMetadata, &backupPersist, backupFilepath)
	if err != nil {
		return err
	}
	backupSeeds := append(backupPersist.AuxiliarySeedFiles, backupPersist.PrimarySeedFile)
	TODO: more
}
*/
<commit_msg>migrate wallet to new persist<commit_after>package wallet

import (
	"fmt"
	"io"
	"os"
	"path/filepath"

	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/encoding"
	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/Sia/persist"
	"github.com/NebulousLabs/fastrand"

	"github.com/NebulousLabs/bolt"
)

const (
	logFile    = modules.WalletDir + ".log"
	dbFile     = modules.WalletDir + ".db"
	compatFile = modules.WalletDir + ".json"
)

var (
	dbMetadata = persist.Metadata{
		Header:  "Wallet Database",
		Version: "1.1.0",
	}
)

// spendableKeyFile stores an encrypted spendable key on disk.
type spendableKeyFile struct {
	UID                    uniqueID
	EncryptionVerification crypto.Ciphertext
	SpendableKey           crypto.Ciphertext
}

// openDB loads the set database and populates it with the necessary buckets.
func (w *Wallet) openDB(filename string) (err error) {
	w.db, err = persist.OpenDatabase(dbMetadata, filename)
	if err != nil {
		return err
	}
	// initialize the database
	err = w.db.Update(func(tx *bolt.Tx) error {
		for _, b := range dbBuckets {
			_, err := tx.CreateBucketIfNotExists(b)
			if err != nil {
				return fmt.Errorf("could not create bucket %v: %v", string(b), err)
			}
		}
		// if the wallet does not have a UID, create one
		if tx.Bucket(bucketWallet).Get(keyUID) == nil {
			uid := make([]byte, len(uniqueID{}))
			fastrand.Read(uid[:])
			tx.Bucket(bucketWallet).Put(keyUID, uid)
		}
		// if fields in bucketWallet are nil, set them to zero to prevent unmarshal errors
		wb := tx.Bucket(bucketWallet)
		if wb.Get(keyConsensusHeight) == nil {
			wb.Put(keyConsensusHeight, encoding.Marshal(uint64(0)))
		}
		if wb.Get(keyAuxiliarySeedFiles) == nil {
			wb.Put(keyAuxiliarySeedFiles, encoding.Marshal([]seedFile{}))
		}
		if wb.Get(keySpendableKeyFiles) == nil {
			wb.Put(keySpendableKeyFiles, encoding.Marshal([]spendableKeyFile{}))
		}

		// check whether wallet is encrypted
		w.encrypted = tx.Bucket(bucketWallet).Get(keyEncryptionVerification) != nil
		return nil
	})
	return err
}

// initPersist loads all of the wallet's persistence files into memory,
// creating them if they do not exist.
func (w *Wallet) initPersist() error {
	// Create a directory for the wallet without overwriting an existing
	// directory.
	err := os.MkdirAll(w.persistDir, 0700)
	if err != nil {
		return err
	}

	// Start logging.
	w.log, err = persist.NewFileLogger(filepath.Join(w.persistDir, logFile))
	if err != nil {
		return err
	}

	// Open the database.
	dbFilename := filepath.Join(w.persistDir, dbFile)
	compatFilename := filepath.Join(w.persistDir, compatFile)
	_, dbErr := os.Stat(dbFilename)
	_, compatErr := os.Stat(compatFilename)
	if dbErr != nil && compatErr == nil {
		// database does not exist, but old persist does; convert it
		err = w.convertPersistFrom112To120(dbFilename, compatFilename)
	} else {
		// either database exists or neither exists; open/create the database
		err = w.openDB(filepath.Join(w.persistDir, dbFile))
	}
	if err != nil {
		return err
	}
	w.tg.AfterStop(func() { w.db.Close() })

	return nil
}

// createBackup copies the wallet database to dst.
func (w *Wallet) createBackup(dst io.Writer) error {
	_, err := w.dbTx.WriteTo(dst)
	return err
}

// CreateBackup creates a backup file at the desired filepath.
func (w *Wallet) CreateBackup(backupFilepath string) error {
	if err := w.tg.Add(); err != nil {
		return err
	}
	defer w.tg.Done()
	w.mu.Lock()
	defer w.mu.Unlock()
	f, err := os.Create(backupFilepath)
	if err != nil {
		return err
	}
	defer f.Close()
	return w.createBackup(f)
}

// compat112Persist is the structure of the wallet.json file used in v1.1.2
type compat112Persist struct {
	UID                    uniqueID
	EncryptionVerification crypto.Ciphertext
	PrimarySeedFile        seedFile
	PrimarySeedProgress    uint64
	AuxiliarySeedFiles     []seedFile
	UnseededKeys           []spendableKeyFile
}

// compat112Meta is the metadata of the wallet.json file used in v1.1.2
var compat112Meta = persist.Metadata{
	Header:  "Wallet Settings",
	Version: "0.4.0",
}

// convertPersistFrom112To120 converts an old (pre-v1.2.0) wallet.json file to
// a wallet.db database.
func (w *Wallet) convertPersistFrom112To120(dbFilename, compatFilename string) error {
	var data compat112Persist
	err := persist.LoadJSON(compat112Meta, &data, compatFilename)
	if err != nil {
		return err
	}

	w.db, err = persist.OpenDatabase(dbMetadata, dbFilename)
	if err != nil {
		return err
	}
	// initialize the database
	err = w.db.Update(func(tx *bolt.Tx) error {
		for _, b := range dbBuckets {
			_, err := tx.CreateBucket(b)
			if err != nil {
				return fmt.Errorf("could not create bucket %v: %v", string(b), err)
			}
		}
		// set UID, verification, seeds, and seed progress
		tx.Bucket(bucketWallet).Put(keyUID, data.UID[:])
		tx.Bucket(bucketWallet).Put(keyEncryptionVerification, data.EncryptionVerification)
		tx.Bucket(bucketWallet).Put(keyPrimarySeedFile, encoding.Marshal(data.PrimarySeedFile))
		tx.Bucket(bucketWallet).Put(keyAuxiliarySeedFiles, encoding.Marshal(data.AuxiliarySeedFiles))
		tx.Bucket(bucketWallet).Put(keySpendableKeyFiles, encoding.Marshal(data.UnseededKeys))
		// old wallets had a "preload depth" of 25
		dbPutPrimarySeedProgress(tx, data.PrimarySeedProgress+25)

		// set consensus height and CCID to zero so that a full rescan is
		// triggered
		dbPutConsensusHeight(tx, 0)
		dbPutConsensusChangeID(tx, modules.ConsensusChangeBeginning)
		return nil
	})
	w.encrypted = true
	return err
}

/*
// LoadBackup loads a backup file from the provided filepath. The backup file
// primary seed is loaded as an auxiliary seed.
func (w *Wallet) LoadBackup(masterKey, backupMasterKey crypto.TwofishKey, backupFilepath string) error {
	if err := w.tg.Add(); err != nil {
		return err
	}
	defer w.tg.Done()

	lockID := w.mu.Lock()
	defer w.mu.Unlock(lockID)

	// Load all of the seed files, check for duplicates, re-encrypt them (but
	// keep the UID), and add them to the walletPersist object)
	var backupPersist walletPersist
	err := persist.LoadFile(settingsMetadata, &backupPersist, backupFilepath)
	if err != nil {
		return err
	}
	backupSeeds := append(backupPersist.AuxiliarySeedFiles, backupPersist.PrimarySeedFile)
	TODO: more
}
*/
<|endoftext|>


<commit_before>package controllers

import (
	"github.com/robfig/revel"
	"os"
	fpath "path/filepath"
	"strings"
)

type Static struct {
	*revel.Controller
}

// This method handles requests for files. The supplied prefix may be absolute
// or relative. If the prefix is relative it is assumed to be relative to the
// application directory. The filepath may either be just a file or an
// additional filepath to search for the given file. This response may return
// the following responses in the event of an error or invalid request;
//   403(Forbidden): If the prefix filepath combination results in a directory.
//   404(Not found): If the prefix and filepath combination results in a non-existent file.
//   500(Internal Server Error): There are a few edge cases that would likely indicate some configuration error outside of revel.
//
// Note that when defining routes in routes/conf the parameters must not have
// spaces around the comma.
//   Bad:  Static.Serve("public/img", "favicon.png")
//   Good: Static.Serve("public/img","favicon.png")
//
// Examples:
// Serving a directory
//   Route (conf/routes):
//     GET /public/{<.*>filepath} Static.Serve("public")
//   Request:
//     public/js/sessvars.js
//   Calls
//     Static.Serve("public","js/sessvars.js")
//
// Serving a file
//   Route (conf/routes):
//     GET /favicon.ico Static.Serve("public/img","favicon.png")
//   Request:
//     favicon.ico
//   Calls:
//     Static.Serve("public/img", "favicon.png")
func (c Static) Serve(prefix, filepath string) revel.Result {
	var basePath string

	if !fpath.IsAbs(prefix) {
		basePath = revel.BasePath
	}

	basePathPrefix := fpath.Join(basePath, fpath.FromSlash(prefix))
	fname := fpath.Join(basePathPrefix, fpath.FromSlash(filepath))
	if !strings.HasPrefix(fname, basePathPrefix) {
		revel.WARN.Printf("Attempted to read file outside of base path: %s", fname)
		return c.NotFound("")
	}

	finfo, err := os.Stat(fname)
	if err != nil {
		if os.IsNotExist(err) {
			revel.WARN.Printf("File not found (%s): %s ", fname, err)
			return c.NotFound("File not found")
		}
		revel.ERROR.Printf("Error trying to get fileinfo for '%s': %s", fname, err)
		return c.RenderError(err)
	}

	if finfo.Mode().IsDir() {
		revel.WARN.Printf("Attempted directory listing of %s", fname)
		return c.Forbidden("Directory listing not allowed")
	}

	file, err := os.Open(fname)
	if err != nil {
		if os.IsNotExist(err) {
			revel.WARN.Printf("File not found (%s): %s ", fname, err)
			return c.NotFound("File not found")
		}
		revel.ERROR.Printf("Error opening '%s': %s", fname, err)
		return c.RenderError(err)
	}
	return c.RenderFile(file, revel.Inline)
}

// This method allows modules to serve binary files. The parameters are the same
// as Static.Serve with the additional module name pre-pended to the list of
// arguments.
func (c Static) ServeModule(moduleName, prefix, filepath string) revel.Result {
	var basePath string
	for _, module := range revel.Modules {
		if module.Name == moduleName {
			basePath = module.Path
		}
	}

	absPath := fpath.Join(basePath, fpath.FromSlash(prefix))

	return c.Serve(absPath, filepath)
}
<commit_msg>#379: return 500 on not-exist public file path<commit_after>package controllers

import (
	"github.com/robfig/revel"
	"os"
	fpath "path/filepath"
	"strings"
	"syscall"
)

type Static struct {
	*revel.Controller
}

// This method handles requests for files. The supplied prefix may be absolute
// or relative. If the prefix is relative it is assumed to be relative to the
// application directory. The filepath may either be just a file or an
// additional filepath to search for the given file. This response may return
// the following responses in the event of an error or invalid request;
//   403(Forbidden): If the prefix filepath combination results in a directory.
//   404(Not found): If the prefix and filepath combination results in a non-existent file.
//   500(Internal Server Error): There are a few edge cases that would likely indicate some configuration error outside of revel.
//
// Note that when defining routes in routes/conf the parameters must not have
// spaces around the comma.
//   Bad:  Static.Serve("public/img", "favicon.png")
//   Good: Static.Serve("public/img","favicon.png")
//
// Examples:
// Serving a directory
//   Route (conf/routes):
//     GET /public/{<.*>filepath} Static.Serve("public")
//   Request:
//     public/js/sessvars.js
//   Calls
//     Static.Serve("public","js/sessvars.js")
//
// Serving a file
//   Route (conf/routes):
//     GET /favicon.ico Static.Serve("public/img","favicon.png")
//   Request:
//     favicon.ico
//   Calls:
//     Static.Serve("public/img", "favicon.png")
func (c Static) Serve(prefix, filepath string) revel.Result {
	var basePath string

	if !fpath.IsAbs(prefix) {
		basePath = revel.BasePath
	}

	basePathPrefix := fpath.Join(basePath, fpath.FromSlash(prefix))
	fname := fpath.Join(basePathPrefix, fpath.FromSlash(filepath))
	if !strings.HasPrefix(fname, basePathPrefix) {
		revel.WARN.Printf("Attempted to read file outside of base path: %s", fname)
		return c.NotFound("")
	}

	finfo, err := os.Stat(fname)
	if err != nil {
		if os.IsNotExist(err) || isNotDir(err) {
			revel.WARN.Printf("File not found (%s): %s ", fname, err)
			return c.NotFound("File not found")
		}
		revel.ERROR.Printf("Error trying to get fileinfo for '%s': %s", fname, err)
		return c.RenderError(err)
	}

	if finfo.Mode().IsDir() {
		revel.WARN.Printf("Attempted directory listing of %s", fname)
		return c.Forbidden("Directory listing not allowed")
	}

	file, err := os.Open(fname)
	if err != nil {
		if os.IsNotExist(err) {
			revel.WARN.Printf("File not found (%s): %s ", fname, err)
			return c.NotFound("File not found")
		}
		revel.ERROR.Printf("Error opening '%s': %s", fname, err)
		return c.RenderError(err)
	}
	return c.RenderFile(file, revel.Inline)
}

// This method allows modules to serve binary files. The parameters are the same
// as Static.Serve with the additional module name pre-pended to the list of
// arguments.
func (c Static) ServeModule(moduleName, prefix, filepath string) revel.Result {
	var basePath string
	for _, module := range revel.Modules {
		if module.Name == moduleName {
			basePath = module.Path
		}
	}

	absPath := fpath.Join(basePath, fpath.FromSlash(prefix))

	return c.Serve(absPath, filepath)
}

func isNotDir(err error) bool {
	switch pe := err.(type) {
	case nil:
		return false
	case *os.PathError:
		err = pe.Err
	case *os.LinkError:
		err = pe.Err
	}
	return err == syscall.ENOTDIR
}
<|endoftext|>


<commit_before>package pps

import (
	"fmt"

	. "github.com/pachyderm/pachyderm/src/client/pfs"
	ppsclient "github.com/pachyderm/pachyderm/src/client/pps"
)

func JobRepo(job *ppsclient.Job) *Repo {
	return &Repo{Name: fmt.Sprintf("job-%s", job.ID)}
}

func PipelineRepo(pipeline *ppsclient.Pipeline) *Repo {
	return &Repo{Name: pipeline.Name}
}
<commit_msg>Fix dot import<commit_after>package pps

import (
	"fmt"

	"github.com/pachyderm/pachyderm/src/client/pfs"
	ppsclient "github.com/pachyderm/pachyderm/src/client/pps"
)

func JobRepo(job *ppsclient.Job) *pfs.Repo {
	return &pfs.Repo{Name: fmt.Sprintf("job-%s", job.ID)}
}

func PipelineRepo(pipeline *ppsclient.Pipeline) *pfs.Repo {
	return &pfs.Repo{Name: pipeline.Name}
}
<|endoftext|>


<commit_before>package find_breaks

import (
	"context"
	"io/ioutil"
	"testing"
	"time"

	assert "github.com/stretchr/testify/require"

	"go.skia.org/infra/go/deepequal"
	"go.skia.org/infra/go/git"
	"go.skia.org/infra/go/git/repograph"
	git_testutils "go.skia.org/infra/go/git/testutils"
	"go.skia.org/infra/go/testutils"
)

// setupHelper is a shared function used for reducing boilerplate when setting
// up test inputs. The provided func is used to build the git repo which will
// be used by the test.
func setupHelper(t *testing.T, setup func(context.Context, *git_testutils.GitBuilder)) (*repograph.Graph, func()) {
	testutils.MediumTest(t)
	ctx := context.Background()
	gb := git_testutils.GitInit(t, ctx)
	wd, err := ioutil.TempDir("", "")
	assert.NoError(t, err)
	setup(ctx, gb)
	cleanup := func() {
		gb.Cleanup()
		testutils.RemoveAll(t, wd)
	}
	repo, err := repograph.NewGraph(ctx, gb.RepoUrl(), wd)
	assert.NoError(t, err)
	assert.NoError(t, repo.Update(ctx))
	return repo, cleanup
}

// TestCommitSlices1 uses a simple, single-branch git repo:
//
//      e
//      |
//      d
//      |
//      c
//      |
//      b
//      |
//      a
//
func TestCommitSlices1(t *testing.T) {
	now := time.Now().Round(time.Second)
	var a, b, c, d, e string
	repo, cleanup := setupHelper(t, func(ctx context.Context, gb *git_testutils.GitBuilder) {
		ts := now.Add(-30 * time.Minute)
		a = gb.CommitGenAt(ctx, "file", ts)

		ts = ts.Add(2 * time.Minute)
		b = gb.CommitGenAt(ctx, "file", ts)

		ts = ts.Add(2 * time.Minute)
		c = gb.CommitGenAt(ctx, "file", ts)

		ts = ts.Add(2 * time.Minute)
		d = gb.CommitGenAt(ctx, "file", ts)

		ts = ts.Add(2 * time.Minute)
		e = gb.CommitGenAt(ctx, "file", ts)
	})
	defer cleanup()

	// Make sure we get all of the commits in one slice.
	slices := commitSlices(repo, time.Time{}, now)
	assert.Equal(t, 1, len(slices))
	assert.Equal(t, 5, len(slices[0]))
	deepequal.AssertDeepEqual(t, []string{a, b, c, d, e}, slices[0])

	// Make sure the timestamp cutoffs work.
	end := now.Add(-22 * time.Minute)
	start := now.Add(-30 * time.Minute)
	slices = commitSlices(repo, start, end)
	assert.Equal(t, 1, len(slices))
	assert.Equal(t, 4, len(slices[0]))
	deepequal.AssertDeepEqual(t, []string{a, b, c, d}, slices[0])

	// Test the edges of the timestamp cutoffs.
	slices = commitSlices(repo, start.Add(2*time.Second), end.Add(-2*time.Second))
	assert.Equal(t, 1, len(slices))
	assert.Equal(t, 3, len(slices[0]))
	deepequal.AssertDeepEqual(t, []string{b, c, d}, slices[0])

	// We shouldn't return empty slices.
	slices = commitSlices(repo, now.Add(30*time.Minute), now.Add(60*time.Minute))
	assert.Equal(t, 0, len(slices))
}

// TestCommitSlices2 uses a git repo with two diverging branches:
//
//      d   c
//      | /
//      b
//      |
//      a
//
func TestCommitSlices2(t *testing.T) {
	var a, b, c, d string
	repo, cleanup := setupHelper(t, func(ctx context.Context, gb *git_testutils.GitBuilder) {
		ts := time.Now().Add(-30 * time.Minute)
		a = gb.CommitGenAt(ctx, "file", ts)

		ts = ts.Add(2 * time.Minute)
		b = gb.CommitGenAt(ctx, "file", ts)

		ts = ts.Add(2 * time.Minute)
		gb.CreateBranchTrackBranch(ctx, "otherBranch", "master")
		c = gb.CommitGenAt(ctx, "file", ts)

		ts = ts.Add(2 * time.Minute)
		gb.CheckoutBranch(ctx, "master")
		d = gb.CommitGenAt(ctx, "file", ts)
	})
	defer cleanup()

	// Entire repo. We should get two slices.
	slices := commitSlices(repo, time.Time{}, time.Now())
	assert.Equal(t, 2, len(slices))
	assert.Equal(t, 3, len(slices[0]))
	assert.Equal(t, 3, len(slices[1]))
	deepequal.AssertDeepEqual(t, []string{a, b, d}, slices[0])
	deepequal.AssertDeepEqual(t, []string{a, b, c}, slices[1])
}

// TestCommitSlices3 uses a git repo with two merging branches:
//
//      d
//      |
//      c
//      | \
//      a   b
//
func TestCommitSlices3(t *testing.T) {
	var a, b, c, d string
	repo, cleanup := setupHelper(t, func(ctx context.Context, gb *git_testutils.GitBuilder) {
		ts := time.Now().Add(-30 * time.Minute)
		a = gb.CommitGenAt(ctx, "file", ts)

		ts = ts.Add(2 * time.Minute)
		gb.CreateOrphanBranch(ctx, "branch2")
		gb.AddGen(ctx, "file2")
		b = gb.CommitGenAt(ctx, "file2", ts)

		ts = ts.Add(2 * time.Minute)
		gb.CheckoutBranch(ctx, "master")
		c = gb.MergeBranch(ctx, "branch2")
		_, err := git.GitDir(gb.Dir()).Git(ctx, "branch", "-D", "branch2")
		assert.NoError(t, err)

		ts = ts.Add(2 * time.Minute)
		d = gb.CommitGenAt(ctx, "file", ts)
	})
	defer cleanup()

	// Entire repo. We should get two slices.
	slices := commitSlices(repo, time.Time{}, time.Now())
	assert.Equal(t, 2, len(slices))
	assert.Equal(t, 3, len(slices[0]))
	assert.Equal(t, 3, len(slices[1]))
	deepequal.AssertDeepEqual(t, []string{a, c, d}, slices[0])
	deepequal.AssertDeepEqual(t, []string{b, c, d}, slices[1])
}

// TestCommitSlices4 uses a git repo with a branch which diverges and then
// merges again:
//
//      f
//      |
//      e
//      | \
//      |   d
//      |   |
//      c   |
//      | /
//      b
//      |
//      a
//
func TestCommitSlices4(t *testing.T) {
	var a, b, c, d, e, f string
	repo, cleanup := setupHelper(t, func(ctx context.Context, gb *git_testutils.GitBuilder) {
		ts := time.Now().Add(-30 * time.Minute)
		a = gb.CommitGenAt(ctx, "file", ts)

		ts = ts.Add(2 * time.Minute)
		b = gb.CommitGenAt(ctx, "file", ts)

		ts = ts.Add(2 * time.Minute)
		c = gb.CommitGenAt(ctx, "file", ts)

		ts = ts.Add(2 * time.Minute)
		gb.CreateBranchAtCommit(ctx, "branch2", b)
		d = gb.CommitGenAt(ctx, "file2", ts)

		ts = ts.Add(2 * time.Minute)
		gb.CheckoutBranch(ctx, "master")
		e = gb.MergeBranch(ctx, "branch2")
		_, err := git.GitDir(gb.Dir()).Git(ctx, "branch", "-D", "branch2")
		assert.NoError(t, err)

		ts = ts.Add(2 * time.Minute)
		f = gb.CommitGenAt(ctx, "file", ts)
	})
	defer cleanup()

	// Entire repo. We should get two slices.
	slices := commitSlices(repo, time.Time{}, time.Now())
	assert.Equal(t, 2, len(slices))
	assert.Equal(t, 5, len(slices[0]))
	assert.Equal(t, 5, len(slices[1]))
	deepequal.AssertDeepEqual(t, []string{a, b, c, e, f}, slices[0])
	deepequal.AssertDeepEqual(t, []string{a, b, d, e, f}, slices[1])
}
<commit_msg>Resize CommitSlices tests<commit_after>package find_breaks

import (
	"context"
	"io/ioutil"
	"testing"
	"time"

	assert "github.com/stretchr/testify/require"

	"go.skia.org/infra/go/deepequal"
	"go.skia.org/infra/go/git"
	"go.skia.org/infra/go/git/repograph"
	git_testutils "go.skia.org/infra/go/git/testutils"
	"go.skia.org/infra/go/testutils"
)

// setupHelper is a shared function used for reducing boilerplate when setting
// up test inputs. The provided func is used to build the git repo which will
// be used by the test.
func setupHelper(t *testing.T, setup func(context.Context, *git_testutils.GitBuilder)) (*repograph.Graph, func()) {
	testutils.LargeTest(t)
	ctx := context.Background()
	gb := git_testutils.GitInit(t, ctx)
	wd, err := ioutil.TempDir("", "")
	assert.NoError(t, err)
	setup(ctx, gb)
	cleanup := func() {
		gb.Cleanup()
		testutils.RemoveAll(t, wd)
	}
	repo, err := repograph.NewGraph(ctx, gb.RepoUrl(), wd)
	assert.NoError(t, err)
	assert.NoError(t, repo.Update(ctx))
	return repo, cleanup
}

// TestCommitSlices1 uses a simple, single-branch git repo:
//
//      e
//      |
//      d
//      |
//      c
//      |
//      b
//      |
//      a
//
func TestCommitSlices1(t *testing.T) {
	now := time.Now().Round(time.Second)
	var a, b, c, d, e string
	repo, cleanup := setupHelper(t, func(ctx context.Context, gb *git_testutils.GitBuilder) {
		ts := now.Add(-30 * time.Minute)
		a = gb.CommitGenAt(ctx, "file", ts)

		ts = ts.Add(2 * time.Minute)
		b = gb.CommitGenAt(ctx, "file", ts)

		ts = ts.Add(2 * time.Minute)
		c = gb.CommitGenAt(ctx, "file", ts)

		ts = ts.Add(2 * time.Minute)
		d = gb.CommitGenAt(ctx, "file", ts)

		ts = ts.Add(2 * time.Minute)
		e = gb.CommitGenAt(ctx, "file", ts)
	})
	defer cleanup()

	// Make sure we get all of the commits in one slice.
	slices := commitSlices(repo, time.Time{}, now)
	assert.Equal(t, 1, len(slices))
	assert.Equal(t, 5, len(slices[0]))
	deepequal.AssertDeepEqual(t, []string{a, b, c, d, e}, slices[0])

	// Make sure the timestamp cutoffs work.
	end := now.Add(-22 * time.Minute)
	start := now.Add(-30 * time.Minute)
	slices = commitSlices(repo, start, end)
	assert.Equal(t, 1, len(slices))
	assert.Equal(t, 4, len(slices[0]))
	deepequal.AssertDeepEqual(t, []string{a, b, c, d}, slices[0])

	// Test the edges of the timestamp cutoffs.
	slices = commitSlices(repo, start.Add(2*time.Second), end.Add(-2*time.Second))
	assert.Equal(t, 1, len(slices))
	assert.Equal(t, 3, len(slices[0]))
	deepequal.AssertDeepEqual(t, []string{b, c, d}, slices[0])

	// We shouldn't return empty slices.
	slices = commitSlices(repo, now.Add(30*time.Minute), now.Add(60*time.Minute))
	assert.Equal(t, 0, len(slices))
}

// TestCommitSlices2 uses a git repo with two diverging branches:
//
//      d   c
//      | /
//      b
//      |
//      a
//
func TestCommitSlices2(t *testing.T) {
	var a, b, c, d string
	repo, cleanup := setupHelper(t, func(ctx context.Context, gb *git_testutils.GitBuilder) {
		ts := time.Now().Add(-30 * time.Minute)
		a = gb.CommitGenAt(ctx, "file", ts)

		ts = ts.Add(2 * time.Minute)
		b = gb.CommitGenAt(ctx, "file", ts)

		ts = ts.Add(2 * time.Minute)
		gb.CreateBranchTrackBranch(ctx, "otherBranch", "master")
		c = gb.CommitGenAt(ctx, "file", ts)

		ts = ts.Add(2 * time.Minute)
		gb.CheckoutBranch(ctx, "master")
		d = gb.CommitGenAt(ctx, "file", ts)
	})
	defer cleanup()

	// Entire repo. We should get two slices.
	slices := commitSlices(repo, time.Time{}, time.Now())
	assert.Equal(t, 2, len(slices))
	assert.Equal(t, 3, len(slices[0]))
	assert.Equal(t, 3, len(slices[1]))
	deepequal.AssertDeepEqual(t, []string{a, b, d}, slices[0])
	deepequal.AssertDeepEqual(t, []string{a, b, c}, slices[1])
}

// TestCommitSlices3 uses a git repo with two merging branches:
//
//      d
//      |
//      c
//      | \
//      a   b
//
func TestCommitSlices3(t *testing.T) {
	var a, b, c, d string
	repo, cleanup := setupHelper(t, func(ctx context.Context, gb *git_testutils.GitBuilder) {
		ts := time.Now().Add(-30 * time.Minute)
		a = gb.CommitGenAt(ctx, "file", ts)

		ts = ts.Add(2 * time.Minute)
		gb.CreateOrphanBranch(ctx, "branch2")
		gb.AddGen(ctx, "file2")
		b = gb.CommitGenAt(ctx, "file2", ts)

		ts = ts.Add(2 * time.Minute)
		gb.CheckoutBranch(ctx, "master")
		c = gb.MergeBranch(ctx, "branch2")
		_, err := git.GitDir(gb.Dir()).Git(ctx, "branch", "-D", "branch2")
		assert.NoError(t, err)

		ts = ts.Add(2 * time.Minute)
		d = gb.CommitGenAt(ctx, "file", ts)
	})
	defer cleanup()

	// Entire repo. We should get two slices.
	slices := commitSlices(repo, time.Time{}, time.Now())
	assert.Equal(t, 2, len(slices))
	assert.Equal(t, 3, len(slices[0]))
	assert.Equal(t, 3, len(slices[1]))
	deepequal.AssertDeepEqual(t, []string{a, c, d}, slices[0])
	deepequal.AssertDeepEqual(t, []string{b, c, d}, slices[1])
}

// TestCommitSlices4 uses a git repo with a branch which diverges and then
// merges again:
//
//      f
//      |
//      e
//      | \
//      |   d
//      |   |
//      c   |
//      | /
//      b
//      |
//      a
//
func TestCommitSlices4(t *testing.T) {
	var a, b, c, d, e, f string
	repo, cleanup := setupHelper(t, func(ctx context.Context, gb *git_testutils.GitBuilder) {
		ts := time.Now().Add(-30 * time.Minute)
		a = gb.CommitGenAt(ctx, "file", ts)

		ts = ts.Add(2 * time.Minute)
		b = gb.CommitGenAt(ctx, "file", ts)

		ts = ts.Add(2 * time.Minute)
		c = gb.CommitGenAt(ctx, "file", ts)

		ts = ts.Add(2 * time.Minute)
		gb.CreateBranchAtCommit(ctx, "branch2", b)
		d = gb.CommitGenAt(ctx, "file2", ts)

		ts = ts.Add(2 * time.Minute)
		gb.CheckoutBranch(ctx, "master")
		e = gb.MergeBranch(ctx, "branch2")
		_, err := git.GitDir(gb.Dir()).Git(ctx, "branch", "-D", "branch2")
		assert.NoError(t, err)

		ts = ts.Add(2 * time.Minute)
		f = gb.CommitGenAt(ctx, "file", ts)
	})
	defer cleanup()

	// Entire repo. We should get two slices.
	slices := commitSlices(repo, time.Time{}, time.Now())
	assert.Equal(t, 2, len(slices))
	assert.Equal(t, 5, len(slices[0]))
	assert.Equal(t, 5, len(slices[1]))
	deepequal.AssertDeepEqual(t, []string{a, b, c, e, f}, slices[0])
	deepequal.AssertDeepEqual(t, []string{a, b, d, e, f}, slices[1])
}
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Jason Woods.
 *
 * 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.
 */

package codecs

import (
  "errors"
  "fmt"
  "lc-lib/core"
  "regexp"
  "strings"
  "sync"
  "time"
)

const (
  codecMultiline_What_Previous = 0x00000001
  codecMultiline_What_Next     = 0x00000002
)

type CodecMultilineFactory struct {
  Pattern         string        `config:"pattern"`
  What            string        `config:"what"`
  Negate          bool          `config:"negate"`
  PreviousTimeout time.Duration `config:"previous timeout"`

  matcher *regexp.Regexp
  what    int
}

type CodecMultiline struct {
  config        *CodecMultilineFactory
  last_offset   int64
  callback_func core.CodecCallbackFunc

  end_offset   int64
  start_offset int64
  line         uint64
  buffer       []string
  timer_lock   *sync.Mutex
  timer_chan   chan bool
}

func NewMultilineCodecFactory(config *core.Config, config_path string, unused map[string]interface{}, name string) (core.CodecFactory, error) {
  var err error

  result := &CodecMultilineFactory{}
  if err = config.PopulateConfig(result, config_path, unused); err != nil {
    return nil, err
  }

  if result.Pattern == "" {
    return nil, errors.New("Multiline codec pattern must be specified.")
  }

  result.matcher, err = regexp.Compile(result.Pattern)
  if err != nil {
    return nil, fmt.Errorf("Failed to compile multiline codec pattern, '%s'.", err)
  }

  if result.What == "" || result.What == "previous" {
    result.what = codecMultiline_What_Previous
  } else if result.What == "next" {
    result.what = codecMultiline_What_Next
  }

  return result, nil
}

func (f *CodecMultilineFactory) NewCodec(callback_func core.CodecCallbackFunc, offset int64) core.Codec {
  c := &CodecMultiline{
    config:        f,
    last_offset:   offset,
    callback_func: callback_func,
  }

  // TODO: Make this more performant - use similiar methodology to Go's internal network deadlines
  if f.PreviousTimeout != 0 {
    c.timer_lock = new(sync.Mutex)
    c.timer_chan = make(chan bool, 1)

    go func() {
      var active bool

      timer := time.NewTimer(0)

      for {
        select {
        case shutdown := <-c.timer_chan:
          timer.Stop()
          if shutdown {
            // Shutdown signal so end the routine
            break
          }
          timer.Reset(c.config.PreviousTimeout)
          active = true
        case <-timer.C:
          if active {
            // Surround flush in mutex to prevent data getting modified by a new line while we flush
            c.timer_lock.Lock()
            c.flush()
            c.timer_lock.Unlock()
            active = false
          }
        }
      }
    }()
  }
  return c
}

func (c *CodecMultiline) Teardown() int64 {
  return c.last_offset
}

func (c *CodecMultiline) Event(start_offset int64, end_offset int64, line uint64, text string) {
  // TODO(driskell): If we are using previous and we match on the very first line read,
  // then this is because we've started in the middle of a multiline event (the first line
  // should never match) - so we could potentially offer an option to discard this.
  // The benefit would be that when using previous_timeout, we could discard any extraneous
  // event data that did not get written in time, if the user so wants it, in order to prevent
  // odd incomplete data. It would be a signal from the user, "I will worry about the buffering
  // issues my programs may have - you just make sure to write each event either completely or
  // partially, always with the FIRST line correct (which could be the important one)."
  match_failed := c.config.Negate == c.config.matcher.MatchString(text)
  if c.config.what == codecMultiline_What_Previous {
    if c.config.PreviousTimeout != 0 {
      // Prevent a flush happening while we're modifying the stored data
      c.timer_lock.Lock()
    }
    if match_failed {
      c.flush()
    }
  }
  if len(c.buffer) == 0 {
    c.line = line
    c.start_offset = start_offset
  }
  c.end_offset = end_offset
  c.buffer = append(c.buffer, text)
  if c.config.what == codecMultiline_What_Previous {
    if c.config.PreviousTimeout != 0 {
      // Reset the timer and unlock
      c.timer_chan <- false
      c.timer_lock.Unlock()
    }
  } else if c.config.what == codecMultiline_What_Next && match_failed {
    c.flush()
  }
}

func (c *CodecMultiline) flush() {
  if len(c.buffer) == 0 {
    return
  }

  text := strings.Join(c.buffer, "\n")

  // Set last offset - this is returned in Teardown so if we're mid multiline and crash, we start this multiline again
  c.last_offset = c.end_offset
  c.buffer = nil

  c.callback_func(c.start_offset, c.end_offset, c.line, text)
}

// Register the codec
func init() {
  core.RegisterCodec("multiline", NewMultilineCodecFactory)
}
<commit_msg>Improve previous_timeout routines<commit_after>/*
 * Copyright 2014 Jason Woods.
 *
 * 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.
 */

package codecs

import (
  "errors"
  "fmt"
  "lc-lib/core"
  "regexp"
  "strings"
  "sync"
  "time"
)

const (
  codecMultiline_What_Previous = 0x00000001
  codecMultiline_What_Next     = 0x00000002
)

type CodecMultilineFactory struct {
  Pattern         string        `config:"pattern"`
  What            string        `config:"what"`
  Negate          bool          `config:"negate"`
  PreviousTimeout time.Duration `config:"previous timeout"`

  matcher *regexp.Regexp
  what    int
}

type CodecMultiline struct {
  config        *CodecMultilineFactory
  last_offset   int64
  callback_func core.CodecCallbackFunc

  end_offset     int64
  start_offset   int64
  line           uint64
  buffer         []string
  timer_lock     sync.Mutex
  timer_stop     chan interface{}
  timer_wait     sync.WaitGroup
  timer_deadline time.Time
}

func NewMultilineCodecFactory(config *core.Config, config_path string, unused map[string]interface{}, name string) (core.CodecFactory, error) {
  var err error

  result := &CodecMultilineFactory{}
  if err = config.PopulateConfig(result, config_path, unused); err != nil {
    return nil, err
  }

  if result.Pattern == "" {
    return nil, errors.New("Multiline codec pattern must be specified.")
  }

  result.matcher, err = regexp.Compile(result.Pattern)
  if err != nil {
    return nil, fmt.Errorf("Failed to compile multiline codec pattern, '%s'.", err)
  }

  if result.What == "" || result.What == "previous" {
    result.what = codecMultiline_What_Previous
  } else if result.What == "next" {
    result.what = codecMultiline_What_Next
  }

  return result, nil
}

func (f *CodecMultilineFactory) NewCodec(callback_func core.CodecCallbackFunc, offset int64) core.Codec {
  c := &CodecMultiline{
    config:        f,
    last_offset:   offset,
    callback_func: callback_func,
  }

  // Start the "previous timeout" routine that will auto flush at deadline
  if f.PreviousTimeout != 0 {
    c.timer_stop = make(chan interface{})
    c.timer_wait.Add(1)

    c.timer_deadline = time.Now().Add(f.PreviousTimeout)

    go c.deadlineRoutine()
  }
  return c
}

func (c *CodecMultiline) Teardown() int64 {
  if c.config.PreviousTimeout != 0 {
    close(c.timer_stop)
    c.timer_wait.Wait()
  }

  return c.last_offset
}

func (c *CodecMultiline) Event(start_offset int64, end_offset int64, line uint64, text string) {
  // TODO(driskell): If we are using previous and we match on the very first line read,
  // then this is because we've started in the middle of a multiline event (the first line
  // should never match) - so we could potentially offer an option to discard this.
  // The benefit would be that when using previous_timeout, we could discard any extraneous
  // event data that did not get written in time, if the user so wants it, in order to prevent
  // odd incomplete data. It would be a signal from the user, "I will worry about the buffering
  // issues my programs may have - you just make sure to write each event either completely or
  // partially, always with the FIRST line correct (which could be the important one)."
  match_failed := c.config.Negate == c.config.matcher.MatchString(text)
  if c.config.what == codecMultiline_What_Previous {
    if c.config.PreviousTimeout != 0 {
      // Prevent a flush happening while we're modifying the stored data
      c.timer_lock.Lock()
    }
    if match_failed {
      c.flush()
    }
  }
  if len(c.buffer) == 0 {
    c.line = line
    c.start_offset = start_offset
  }
  c.end_offset = end_offset
  c.buffer = append(c.buffer, text)
  if c.config.what == codecMultiline_What_Previous {
    if c.config.PreviousTimeout != 0 {
      // Reset the timer and unlock
      c.timer_deadline = time.Now().Add(c.config.PreviousTimeout)
      c.timer_lock.Unlock()
    }
  } else if c.config.what == codecMultiline_What_Next && match_failed {
    c.flush()
  }
}

func (c *CodecMultiline) flush() {
  if len(c.buffer) == 0 {
    return
  }

  text := strings.Join(c.buffer, "\n")

  // Set last offset - this is returned in Teardown so if we're mid multiline and crash, we start this multiline again
  c.last_offset = c.end_offset
  c.buffer = nil

  c.callback_func(c.start_offset, c.end_offset, c.line, text)
}

func (c *CodecMultiline) deadlineRoutine() {
  timer := time.NewTimer(0)

DeadlineLoop:
  for {
    select {
    case <-c.timer_stop:
      timer.Stop()

      // Shutdown signal so end the routine
      break DeadlineLoop
    case now := <-timer.C:
      c.timer_lock.Lock()

      // Have we reached the target time?
      if !now.After(c.timer_deadline) {
        // Deadline moved, update the timer
        timer.Reset(c.timer_deadline.Sub(now))
      }

      c.flush()

      c.timer_lock.Unlock()
    }
  }

  c.timer_wait.Done()
}

// Register the codec
func init() {
  core.RegisterCodec("multiline", NewMultilineCodecFactory)
}
<|endoftext|>


<commit_before>package daemon

import (
	"encoding/json"
	"fmt"

	"github.com/docker/docker/engine"
	"github.com/docker/docker/runconfig"
)

func (daemon *Daemon) ContainerInspect(job *engine.Job) engine.Status {
	if len(job.Args) != 1 {
		return job.Errorf("usage: %s NAME", job.Name)
	}
	name := job.Args[0]
	if container := daemon.Get(name); container != nil {
		container.Lock()
		defer container.Unlock()
		if job.GetenvBool("raw") {
			b, err := json.Marshal(&struct {
				*Container
				HostConfig *runconfig.HostConfig
			}{container, container.hostConfig})
			if err != nil {
				return job.Error(err)
			}
			job.Stdout.Write(b)
			return engine.StatusOK
		}

		out := &engine.Env{}
		out.SetJson("Id", container.ID)
		out.SetAuto("Created", container.Created)
		out.SetJson("Path", container.Path)
		out.SetList("Args", container.Args)
		out.SetJson("Config", container.Config)
		out.SetJson("State", container.State)
		out.Set("Image", container.ImageID)
		out.SetJson("NetworkSettings", container.NetworkSettings)
		out.Set("ResolvConfPath", container.ResolvConfPath)
		out.Set("HostnamePath", container.HostnamePath)
		out.Set("HostsPath", container.HostsPath)
		out.SetJson("Name", container.Name)
		out.SetInt("RestartCount", container.RestartCount)
		out.Set("Driver", container.Driver)
		out.Set("ExecDriver", container.ExecDriver)
		out.Set("MountLabel", container.MountLabel)
		out.Set("ProcessLabel", container.ProcessLabel)
		out.SetJson("Volumes", container.Volumes)
		out.SetJson("VolumesRW", container.VolumesRW)
		out.SetJson("AppArmorProfile", container.AppArmorProfile)

		out.SetList("ExecIDs", container.GetExecIDs())

		if children, err := daemon.Children(container.Name); err == nil {
			for linkAlias, child := range children {
				container.hostConfig.Links = append(container.hostConfig.Links, fmt.Sprintf("%s:%s", child.Name, linkAlias))
			}
		}

		out.SetJson("HostConfig", container.hostConfig)

		checkpoints := make([]*ContainerCheckpoint, 0, len(container.Checkpoints))
		// Make checkpoint list with ordering by creation time
		for _, checkpoint := range container.Checkpoints {
			checkpoints = append(checkpoints, checkpoint)
			for i := len(checkpoints)-1; i >= 0; i-- {
				if checkpoints[i].CreatedAt.Before(checkpoint.CreatedAt) {
					break
				}
				checkpoints[i+1], checkpoints[i] = checkpoints[i], checkpoint
			}
		}
		out.SetJson("Checkpoints", checkpoints)

		container.hostConfig.Links = nil
		if _, err := out.WriteTo(job.Stdout); err != nil {
			return job.Error(err)
		}
		return engine.StatusOK
	}
	return job.Errorf("No such container: %s", name)
}

func (daemon *Daemon) ContainerExecInspect(job *engine.Job) engine.Status {
	if len(job.Args) != 1 {
		return job.Errorf("usage: %s ID", job.Name)
	}
	id := job.Args[0]
	eConfig, err := daemon.getExecConfig(id)
	if err != nil {
		return job.Error(err)
	}

	b, err := json.Marshal(*eConfig)
	if err != nil {
		return job.Error(err)
	}
	job.Stdout.Write(b)
	return engine.StatusOK
}
<commit_msg>fix incorrect slice index<commit_after>package daemon

import (
	"encoding/json"
	"fmt"

	"github.com/docker/docker/engine"
	"github.com/docker/docker/runconfig"
)

func (daemon *Daemon) ContainerInspect(job *engine.Job) engine.Status {
	if len(job.Args) != 1 {
		return job.Errorf("usage: %s NAME", job.Name)
	}
	name := job.Args[0]
	if container := daemon.Get(name); container != nil {
		container.Lock()
		defer container.Unlock()
		if job.GetenvBool("raw") {
			b, err := json.Marshal(&struct {
				*Container
				HostConfig *runconfig.HostConfig
			}{container, container.hostConfig})
			if err != nil {
				return job.Error(err)
			}
			job.Stdout.Write(b)
			return engine.StatusOK
		}

		out := &engine.Env{}
		out.SetJson("Id", container.ID)
		out.SetAuto("Created", container.Created)
		out.SetJson("Path", container.Path)
		out.SetList("Args", container.Args)
		out.SetJson("Config", container.Config)
		out.SetJson("State", container.State)
		out.Set("Image", container.ImageID)
		out.SetJson("NetworkSettings", container.NetworkSettings)
		out.Set("ResolvConfPath", container.ResolvConfPath)
		out.Set("HostnamePath", container.HostnamePath)
		out.Set("HostsPath", container.HostsPath)
		out.SetJson("Name", container.Name)
		out.SetInt("RestartCount", container.RestartCount)
		out.Set("Driver", container.Driver)
		out.Set("ExecDriver", container.ExecDriver)
		out.Set("MountLabel", container.MountLabel)
		out.Set("ProcessLabel", container.ProcessLabel)
		out.SetJson("Volumes", container.Volumes)
		out.SetJson("VolumesRW", container.VolumesRW)
		out.SetJson("AppArmorProfile", container.AppArmorProfile)

		out.SetList("ExecIDs", container.GetExecIDs())

		if children, err := daemon.Children(container.Name); err == nil {
			for linkAlias, child := range children {
				container.hostConfig.Links = append(container.hostConfig.Links, fmt.Sprintf("%s:%s", child.Name, linkAlias))
			}
		}

		out.SetJson("HostConfig", container.hostConfig)

		checkpoints := make([]*ContainerCheckpoint, 0, len(container.Checkpoints))
		// Make checkpoint list with ordering by creation time
		for _, checkpoint := range container.Checkpoints {
			checkpoints = append(checkpoints, checkpoint)
			for i := len(checkpoints)-1; i > 0; i-- {
				if checkpoints[i-1].CreatedAt.Before(checkpoint.CreatedAt) {
					break
				}
				checkpoints[i], checkpoints[i-1] = checkpoints[i-1], checkpoint
			}
		}
		out.SetJson("Checkpoints", checkpoints)

		container.hostConfig.Links = nil
		if _, err := out.WriteTo(job.Stdout); err != nil {
			return job.Error(err)
		}
		return engine.StatusOK
	}
	return job.Errorf("No such container: %s", name)
}

func (daemon *Daemon) ContainerExecInspect(job *engine.Job) engine.Status {
	if len(job.Args) != 1 {
		return job.Errorf("usage: %s ID", job.Name)
	}
	id := job.Args[0]
	eConfig, err := daemon.getExecConfig(id)
	if err != nil {
		return job.Error(err)
	}

	b, err := json.Marshal(*eConfig)
	if err != nil {
		return job.Error(err)
	}
	job.Stdout.Write(b)
	return engine.StatusOK
}
<|endoftext|>


<commit_before>package quic

import (
	"bytes"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Public Header", func() {
	It("parses intial client header", func() {
		b := bytes.NewReader([]byte{0xd, 0xf6, 0x19, 0x86, 0x66, 0x9b, 0x9f, 0xfa, 0x4c, 0x51, 0x30, 0x33, 0x30, 0x1})
		publicHeader, err := ParsePublicHeader(b)
		Expect(err).ToNot(HaveOccurred())
		Expect(publicHeader.VersionFlag).To(BeTrue())
		Expect(publicHeader.ResetFlag).To(BeFalse())
		Expect(publicHeader.ConnectionIDLength).To(Equal(uint8(8)))
		Expect(publicHeader.ConnectionID).ToNot(BeZero())
		Expect(publicHeader.QuicVersion).To(Equal(uint32(0x51303330)))
		Expect(publicHeader.PacketNumberLength).To(Equal(uint8(1)))
		Expect(publicHeader.PacketNumber).To(Equal(uint64(1)))
	})
})
<commit_msg>improve public header tests<commit_after>package quic

import (
	"bytes"
	"encoding/binary"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Public Header", func() {
	Context("when parsing", func() {
		It("accepts a sample client header", func() {
			b := bytes.NewReader([]byte{0x0d, 0xf6, 0x19, 0x86, 0x66, 0x9b, 0x9f, 0xfa, 0x4c, 0x51, 0x30, 0x33, 0x30, 0x01})
			publicHeader, err := ParsePublicHeader(b)
			Expect(err).ToNot(HaveOccurred())
			Expect(publicHeader.VersionFlag).To(BeTrue())
			Expect(publicHeader.ResetFlag).To(BeFalse())
			Expect(publicHeader.ConnectionIDLength).To(Equal(uint8(8)))
			Expect(publicHeader.ConnectionID).To(Equal(uint64(0xf61986669b9ffa4c)))
			Expect(publicHeader.QuicVersion).To(Equal(binary.BigEndian.Uint32([]byte("Q030"))))
			Expect(publicHeader.PacketNumberLength).To(Equal(uint8(1)))
			Expect(publicHeader.PacketNumber).To(Equal(uint64(1)))
			Expect(b.Len()).To(BeZero())
		})

		It("accepts 4-byte connection IDs", func() {
			b := bytes.NewReader([]byte{0x08, 0x9b, 0x9f, 0xfa, 0x4c, 0x01})
			publicHeader, err := ParsePublicHeader(b)
			Expect(err).ToNot(HaveOccurred())
			Expect(publicHeader.VersionFlag).To(BeFalse())
			Expect(publicHeader.ConnectionIDLength).To(Equal(uint8(4)))
			Expect(publicHeader.ConnectionID).To(Equal(uint64(0x9b9ffa4c)))
			Expect(b.Len()).To(BeZero())
		})

		It("accepts 1-byte connection IDs", func() {
			b := bytes.NewReader([]byte{0x04, 0x4c, 0x01})
			publicHeader, err := ParsePublicHeader(b)
			Expect(err).ToNot(HaveOccurred())
			Expect(publicHeader.VersionFlag).To(BeFalse())
			Expect(publicHeader.ConnectionIDLength).To(Equal(uint8(1)))
			Expect(publicHeader.ConnectionID).To(Equal(uint64(0x4c)))
			Expect(b.Len()).To(BeZero())
		})

		It("accepts 0-byte connection ID", func() {
			b := bytes.NewReader([]byte{0x00, 0x01})
			publicHeader, err := ParsePublicHeader(b)
			Expect(err).ToNot(HaveOccurred())
			Expect(publicHeader.VersionFlag).To(BeFalse())
			Expect(publicHeader.ConnectionIDLength).To(Equal(uint8(0)))
			Expect(b.Len()).To(BeZero())
		})

		It("accepts 2-byte packet numbers", func() {
			b := bytes.NewReader([]byte{0x10, 0xde, 0xca})
			publicHeader, err := ParsePublicHeader(b)
			Expect(err).ToNot(HaveOccurred())
			Expect(publicHeader.PacketNumberLength).To(Equal(uint8(2)))
			Expect(publicHeader.PacketNumber).To(Equal(uint64(0xdeca)))
			Expect(b.Len()).To(BeZero())
		})

		It("accepts 4-byte packet numbers", func() {
			b := bytes.NewReader([]byte{0x20, 0xde, 0xca, 0xfb, 0xad})
			publicHeader, err := ParsePublicHeader(b)
			Expect(err).ToNot(HaveOccurred())
			Expect(publicHeader.PacketNumberLength).To(Equal(uint8(4)))
			Expect(publicHeader.PacketNumber).To(Equal(uint64(0xdecafbad)))
			Expect(b.Len()).To(BeZero())
		})

		It("accepts 6-byte packet numbers", func() {
			b := bytes.NewReader([]byte{0x30, 0xde, 0xca, 0xfb, 0xad, 0x42, 0x23})
			publicHeader, err := ParsePublicHeader(b)
			Expect(err).ToNot(HaveOccurred())
			Expect(publicHeader.PacketNumberLength).To(Equal(uint8(6)))
			Expect(publicHeader.PacketNumber).To(Equal(uint64(0xdecafbad4223)))
			Expect(b.Len()).To(BeZero())
		})
	})
})
<|endoftext|>