<commit_before>package template

import (
	"bytes"
	"gondola/mux"
	"gondola/template/config"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"path"
	"regexp"
	"strconv"
	"strings"
	"sync"
)

type ScriptType int

const (
	_ ScriptType = iota
	ScriptTypeStandard
	ScriptTypeAsync
	ScriptTypeOnload
)

var (
	commentRe = regexp.MustCompile(`(?s:\{\{\\*(.*?)\*/\}\})`)
	keyRe     = regexp.MustCompile(`(?s:\s*([\w\-_])+:)`)
)

var stylesBoilerplate = `
  {{ range _getstyles }}
    <link rel="stylesheet" type="text/css" href="{{ asset . }}">
  {{ end }}
`

var scriptsBoilerplate = `
  {{ range _getscripts }}
    {{ if .IsAsync }}

    {{ else }}

    {{ end }}
  {{ end }}
`

func StaticFilesUrl() string {
	return config.StaticFilesUrl()
}

// Sets the base url for static assets. Might be
// relative (e.g. /static/) or absolute (e.g. http://static.example.com/)
func SetStaticFilesUrl(url string) {
	config.SetStaticFilesUrl(url)
}

func Path() string {
	return config.Path()
}

// Sets the path for the template files. By default, it's
// initialized to the directory tmpl relative to the executable
func SetPath(p string) {
	config.SetPath(p)
}

type script struct {
	Name string
	Type ScriptType
}

func (s *script) IsAsync() bool {
	return s.Type == ScriptTypeAsync
}

type Template struct {
	*template.Template
	root    string
	scripts []*script
	styles  []string
	mu      *sync.Mutex
	context *mux.Context
}

func (t *Template) parseScripts(value string, st ScriptType) {
	for _, v := range strings.Split(value, ",") {
		name := strings.TrimSpace(v)
		t.scripts = append(t.scripts, &script{name, st})
	}
}

func (t *Template) Execute(w io.Writer, data interface{}) error {
	var buf bytes.Buffer
	ctx, _ := w.(*mux.Context)
	t.mu.Lock()
	t.context = ctx
	err := t.ExecuteTemplate(&buf, t.root, data)
	t.mu.Unlock()
	if err != nil {
		return err
	}
	if rw, ok := w.(http.ResponseWriter); ok {
		header := rw.Header()
		header.Set("Content-Type", "text/html; charset=utf-8")
		header.Set("Content-Length", strconv.Itoa(buf.Len()))
		rw.Write(buf.Bytes())
	}
	return nil
}

func (t *Template) MustExecute(w io.Writer, data interface{}) {
	err := t.Execute(w, data)
	if err != nil {
		if rw, ok := w.(http.ResponseWriter); ok {
			http.Error(rw, "Error", http.StatusInternalServerError)
		}
		log.Panicf("Error executing template: %s\n", err)
	}
}

func AddFunc(name string, f interface{}) {
	templateFuncs[name] = f
}

func parseComment(value string, t *Template, name string) {
	lines := strings.Split(value, "\n")
	extended := false
	for _, v := range lines {
		m := keyRe.FindStringSubmatchIndex(v)
		if m != nil && m[0] == 0 && len(m) == 4 {
			start := m[1] - m[3]
			end := start + m[2]
			key := strings.TrimSpace(v[start:end])
			value := strings.TrimSpace(v[m[1]:])
			if value != "" {
				switch strings.ToLower(key) {
				case "script", "scripts":
					t.parseScripts(value, ScriptTypeStandard)
				case "ascript", "ascripts":
					t.parseScripts(value, ScriptTypeAsync)
				case "css", "style", "styles":
					for _, v := range strings.Split(value, ",") {
						style := strings.TrimSpace(v)
						t.styles = append(t.styles, style)
					}
				case "extend", "extends":
					load(value, t)
					extended = true
				}
			}
		}
	}
	if !extended {
		t.root = name
	}
}

func getTemplatePath(name string) string {
	return path.Join(config.Path(), name)
}

func load(name string, t *Template) error {
	f := getTemplatePath(name)
	b, err := ioutil.ReadFile(f)
	if err != nil {
		return err
	}
	s := string(b)
	matches := commentRe.FindStringSubmatch(s)
	comment := ""
	if matches != nil && len(matches) > 0 {
		comment = matches[1]
	}
	parseComment(comment, t, name)
	if idx := strings.Index(s, ""); idx >= 0 {
		s = s[:idx] + "{{ template \"__styles\" }}" + s[idx:]
	}
	if idx := strings.Index(s, ""); idx >= 0 {
		s = s[:idx] + "{{ template \"__scripts\" }}" + s[idx:]
	}
	var tmpl *template.Template
	if t.Template == nil {
		t.Template = template.New(name)
		tmpl = t.Template
	} else {
		tmpl = t.Template.New(name)
	}
	tmpl = tmpl.Funcs(templateFuncs)
	tmpl = tmpl.Funcs(template.FuncMap{
		"Ctx":     makeContext(t),
		"reverse": makeReverse(t),
		"request": makeRequest(t),
	})
	tmpl, err = tmpl.Parse(s)
	if err != nil {
		return err
	}
	return nil
}

func Parse(name string) (*Template, error) {
	t := &Template{}
	t.mu = &sync.Mutex{}
	err := load(name, t)
	if err != nil {
		return nil, err
	}
	/* Add styles and scripts */
	styles := t.Template.New("__styles")
	styles.Funcs(template.FuncMap{
		"_getstyles": func() []string { return t.styles },
	})
	styles.Parse(stylesBoilerplate)
	scripts := t.Template.New("__scripts")
	scripts.Funcs(template.FuncMap{
		"_getscripts": func() []*script { return t.scripts },
	})
	scripts.Parse(scriptsBoilerplate)
	return t, nil
}

func MustParse(name string) *Template {
	t, err := Parse(name)
	if err != nil {
		log.Fatalf("Error loading template %s: %s\n", name, err)
	}
	return t
}

func Execute(name string, w io.Writer, data interface{}) error {
	t, err := Parse(name)
	if err != nil {
		return err
	}
	return t.Execute(w, data)
}

func MustExecute(name string, w io.Writer, data interface{}) {
	err := Execute(name, w, data)
	if err != nil {
		log.Panic(err)
	}
}
<commit_msg>Cache templates in Execute(), except in debug mode<commit_after>package template

import (
	"bytes"
	"gondola/mux"
	"gondola/template/config"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"path"
	"regexp"
	"strconv"
	"strings"
	"sync"
)

type ScriptType int

const (
	_ ScriptType = iota
	ScriptTypeStandard
	ScriptTypeAsync
	ScriptTypeOnload
)

var (
	commentRe = regexp.MustCompile(`(?s:\{\{\\*(.*?)\*/\}\})`)
	keyRe     = regexp.MustCompile(`(?s:\s*([\w\-_])+:)`)
	cache     = map[string]*Template{}
	cacheLock = &sync.RWMutex{}
	debug     = false
)

var stylesBoilerplate = `
  {{ range _getstyles }}
    <link rel="stylesheet" type="text/css" href="{{ asset . }}">
  {{ end }}
`

var scriptsBoilerplate = `
  {{ range _getscripts }}
    {{ if .IsAsync }}

    {{ else }}

    {{ end }}
  {{ end }}
`

func StaticFilesUrl() string {
	return config.StaticFilesUrl()
}

// Sets the base url for static assets. Might be
// relative (e.g. /static/) or absolute (e.g. http://static.example.com/)
func SetStaticFilesUrl(url string) {
	config.SetStaticFilesUrl(url)
}

func Path() string {
	return config.Path()
}

// Sets the path for the template files. By default, it's
// initialized to the directory tmpl relative to the executable
func SetPath(p string) {
	config.SetPath(p)
}

// Debug returns if the template is in debug mode
// (i.e. templates are not cached).
func Debug() bool {
	return debug
}

// SetDebug sets the debug state for the templates.
// When true, templates executed via template.Execute() or
// template.MustExecute() are recompiled every time
// they are executed. The default is false.
func SetDebug(d bool) {
	debug = d
}

type script struct {
	Name string
	Type ScriptType
}

func (s *script) IsAsync() bool {
	return s.Type == ScriptTypeAsync
}

type Template struct {
	*template.Template
	root    string
	scripts []*script
	styles  []string
	mu      *sync.Mutex
	context *mux.Context
}

func (t *Template) parseScripts(value string, st ScriptType) {
	for _, v := range strings.Split(value, ",") {
		name := strings.TrimSpace(v)
		t.scripts = append(t.scripts, &script{name, st})
	}
}

func (t *Template) Execute(w io.Writer, data interface{}) error {
	var buf bytes.Buffer
	ctx, _ := w.(*mux.Context)
	t.mu.Lock()
	t.context = ctx
	err := t.ExecuteTemplate(&buf, t.root, data)
	t.mu.Unlock()
	if err != nil {
		return err
	}
	if rw, ok := w.(http.ResponseWriter); ok {
		header := rw.Header()
		header.Set("Content-Type", "text/html; charset=utf-8")
		header.Set("Content-Length", strconv.Itoa(buf.Len()))
		rw.Write(buf.Bytes())
	}
	return nil
}

func (t *Template) MustExecute(w io.Writer, data interface{}) {
	err := t.Execute(w, data)
	if err != nil {
		if rw, ok := w.(http.ResponseWriter); ok {
			http.Error(rw, "Error", http.StatusInternalServerError)
		}
		log.Panicf("Error executing template: %s\n", err)
	}
}

func AddFunc(name string, f interface{}) {
	templateFuncs[name] = f
}

func parseComment(value string, t *Template, name string) {
	lines := strings.Split(value, "\n")
	extended := false
	for _, v := range lines {
		m := keyRe.FindStringSubmatchIndex(v)
		if m != nil && m[0] == 0 && len(m) == 4 {
			start := m[1] - m[3]
			end := start + m[2]
			key := strings.TrimSpace(v[start:end])
			value := strings.TrimSpace(v[m[1]:])
			if value != "" {
				switch strings.ToLower(key) {
				case "script", "scripts":
					t.parseScripts(value, ScriptTypeStandard)
				case "ascript", "ascripts":
					t.parseScripts(value, ScriptTypeAsync)
				case "css", "style", "styles":
					for _, v := range strings.Split(value, ",") {
						style := strings.TrimSpace(v)
						t.styles = append(t.styles, style)
					}
				case "extend", "extends":
					load(value, t)
					extended = true
				}
			}
		}
	}
	if !extended {
		t.root = name
	}
}

func getTemplatePath(name string) string {
	return path.Join(config.Path(), name)
}

func load(name string, t *Template) error {
	f := getTemplatePath(name)
	b, err := ioutil.ReadFile(f)
	if err != nil {
		return err
	}
	s := string(b)
	matches := commentRe.FindStringSubmatch(s)
	comment := ""
	if matches != nil && len(matches) > 0 {
		comment = matches[1]
	}
	parseComment(comment, t, name)
	if idx := strings.Index(s, ""); idx >= 0 {
		s = s[:idx] + "{{ template \"__styles\" }}" + s[idx:]
	}
	if idx := strings.Index(s, ""); idx >= 0 {
		s = s[:idx] + "{{ template \"__scripts\" }}" + s[idx:]
	}
	var tmpl *template.Template
	if t.Template == nil {
		t.Template = template.New(name)
		tmpl = t.Template
	} else {
		tmpl = t.Template.New(name)
	}
	tmpl = tmpl.Funcs(templateFuncs)
	tmpl = tmpl.Funcs(template.FuncMap{
		"Ctx":     makeContext(t),
		"reverse": makeReverse(t),
		"request": makeRequest(t),
	})
	tmpl, err = tmpl.Parse(s)
	if err != nil {
		return err
	}
	return nil
}

func Parse(name string) (*Template, error) {
	t := &Template{}
	t.mu = &sync.Mutex{}
	err := load(name, t)
	if err != nil {
		return nil, err
	}
	/* Add styles and scripts */
	styles := t.Template.New("__styles")
	styles.Funcs(template.FuncMap{
		"_getstyles": func() []string { return t.styles },
	})
	styles.Parse(stylesBoilerplate)
	scripts := t.Template.New("__scripts")
	scripts.Funcs(template.FuncMap{
		"_getscripts": func() []*script { return t.scripts },
	})
	scripts.Parse(scriptsBoilerplate)
	return t, nil
}

func MustParse(name string) *Template {
	t, err := Parse(name)
	if err != nil {
		log.Fatalf("Error loading template %s: %s\n", name, err)
	}
	return t
}

func Execute(name string, w io.Writer, data interface{}) error {
	cacheLock.RLock()
	t := cache[name]
	cacheLock.RUnlock()
	if t == nil {
		var err error
		t, err = Parse(name)
		if err != nil {
			return err
		}
		if !debug {
			cacheLock.Lock()
			cache[name] = t
			cacheLock.Unlock()
		}
	}
	return t.Execute(w, data)
}

func MustExecute(name string, w io.Writer, data interface{}) {
	err := Execute(name, w, data)
	if err != nil {
		log.Panic(err)
	}
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package main

import (
	"testing"

	"github.com/labstack/echo"
	"github.com/labstack/echo/test"
	. "github.com/smartystreets/goconvey/convey"
)

func TestGetParamFilter(t *testing.T) {
	e := echo.New()
	req := test.NewRequest(echo.GET, "/", nil)
	rec := test.NewResponseRecorder()
	Convey("Scenario: getting an empty http context", t, func() {
		c := e.NewContext(req, rec)
		Convey("when it is converted to a query", func() {
			query := getParamFilter(c)
			Convey("the query is also empty", func() {
				So(query, ShouldNotBeNil)
				So(len(query), ShouldEqual, 0)
			})
		})
	})

	Convey("Scenario: getting an http context", t, func() {
		c := e.NewContext(req, rec)
		Convey("when it has a name paramater", func() {
			c.SetParamNames("name")
			c.SetParamValues("somename")
			Convey("and it is converted to a query", func() {
				query := getParamFilter(c)
				Convey("the query has the name and its value", func() {
					So(query, ShouldNotBeNil)
					So(len(query), ShouldEqual, 1)
					So(query["name"], ShouldEqual, "somename")
				})
			})
		})
	})

}
<commit_msg>test service to name when context and queries<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package main

import (
	"testing"

	"github.com/labstack/echo"
	"github.com/labstack/echo/test"
	. "github.com/smartystreets/goconvey/convey"
)

func TestGetParamFilter(t *testing.T) {
	e := echo.New()
	req := test.NewRequest(echo.GET, "/", nil)
	rec := test.NewResponseRecorder()
	Convey("Scenario: getting an empty http context", t, func() {
		c := e.NewContext(req, rec)
		Convey("when it is converted to a query", func() {
			query := getParamFilter(c)
			Convey("the query is also empty", func() {
				So(query, ShouldNotBeNil)
				So(len(query), ShouldEqual, 0)
			})
		})
	})

	Convey("Scenario: getting an http context", t, func() {
		c := e.NewContext(req, rec)
		Convey("when it has a name paramater", func() {
			c.SetParamNames("name")
			c.SetParamValues("somename")
			Convey("and it is converted to a query", func() {
				query := getParamFilter(c)
				Convey("the query has the name and its value", func() {
					So(query, ShouldNotBeNil)
					So(len(query), ShouldEqual, 1)
					So(query["name"], ShouldEqual, "somename")
				})
			})
		})
	})

	Convey("Scenario: getting an http context", t, func() {
		c := e.NewContext(req, rec)
		Convey("when it has a service paramater", func() {
			c.SetParamNames("service")
			c.SetParamValues("somename")
			Convey("and it is converted to a query", func() {
				query := getParamFilter(c)
				Convey("the query has the name and its value", func() {
					So(query, ShouldNotBeNil)
					So(len(query), ShouldEqual, 1)
					So(query["name"], ShouldEqual, "somename")
				})
			})
		})
	})

}
<|endoftext|>


<commit_before>package logrus

import (
	"bytes"
	"fmt"
	"runtime"
	"sort"
	"strings"
	"time"
)

const (
	nocolor = 0
	red     = 31
	green   = 32
	yellow  = 33
	blue    = 34
	gray    = 37
)

var (
	baseTimestamp time.Time
	isTerminal    bool
)

func init() {
	baseTimestamp = time.Now()
	isTerminal = IsTerminal()
}

func miniTS() int {
	return int(time.Since(baseTimestamp) / time.Second)
}

type TextFormatter struct {
	// Set to true to bypass checking for a TTY before outputting colors.
	ForceColors bool

	// Force disabling colors.
	DisableColors bool

	// Disable timestamp logging. useful when output is redirected to logging
	// system that already adds timestamps.
	DisableTimestamp bool

	// Enable logging the full timestamp when a TTY is attached instead of just
	// the time passed since beginning of execution.
	FullTimestamp bool

	// TimestampFormat to use for display when a full timestamp is printed
	TimestampFormat string

	// The fields are sorted by default for a consistent output. For applications
	// that log extremely frequently and don't use the JSON formatter this may not
	// be desired.
	DisableSorting bool
}

func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
	var keys []string = make([]string, 0, len(entry.Data))
	for k := range entry.Data {
		keys = append(keys, k)
	}

	if !f.DisableSorting {
		sort.Strings(keys)
	}

	b := &bytes.Buffer{}

	prefixFieldClashes(entry.Data)

	isColorTerminal := isTerminal && (runtime.GOOS != "windows")
	isColored := (f.ForceColors || isColorTerminal) && !f.DisableColors

	if f.TimestampFormat == "" {
		f.TimestampFormat = DefaultTimestampFormat
	}
	if isColored {
		f.printColored(b, entry, keys)
	} else {
		if !f.DisableTimestamp {
			f.appendKeyValue(b, "time", entry.Time.Format(f.TimestampFormat))
		}
		f.appendKeyValue(b, "level", entry.Level.String())
		f.appendKeyValue(b, "msg", entry.Message)
		for _, key := range keys {
			f.appendKeyValue(b, key, entry.Data[key])
		}
	}

	b.WriteByte('\n')
	return b.Bytes(), nil
}

func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string) {
	var levelColor int
	switch entry.Level {
	case DebugLevel:
		levelColor = gray
	case WarnLevel:
		levelColor = yellow
	case ErrorLevel, FatalLevel, PanicLevel:
		levelColor = red
	default:
		levelColor = blue
	}

	levelText := strings.ToUpper(entry.Level.String())[0:4]

	if !f.FullTimestamp {
		fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, miniTS(), entry.Message)
	} else {
		fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(f.TimestampFormat), entry.Message)
	}
	for _, k := range keys {
		v := entry.Data[k]
		fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=%v", levelColor, k, v)
	}
}

func needsQuoting(text string) bool {
	for _, ch := range text {
		if !((ch >= 'a' && ch <= 'z') ||
			(ch >= 'A' && ch <= 'Z') ||
			(ch >= '0' && ch <= '9') ||
			ch == '-' || ch == '.') {
			return false
		}
	}
	return true
}

func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) {

	b.WriteString(key)
	b.WriteByte('=')

	switch value := value.(type) {
	case string:
		if needsQuoting(value) {
			b.WriteString(value)
		} else {
			fmt.Fprintf(b, "%q", value)
		}
	case error:
		errmsg := value.Error()
		if needsQuoting(errmsg) {
			b.WriteString(errmsg)
		} else {
			fmt.Fprintf(b, "%q", value)
		}
	default:
		fmt.Fprint(b, value)
	}

	b.WriteByte(' ')
}
<commit_msg>Print struct keys for struct log fields<commit_after>package logrus

import (
	"bytes"
	"fmt"
	"runtime"
	"sort"
	"strings"
	"time"
)

const (
	nocolor = 0
	red     = 31
	green   = 32
	yellow  = 33
	blue    = 34
	gray    = 37
)

var (
	baseTimestamp time.Time
	isTerminal    bool
)

func init() {
	baseTimestamp = time.Now()
	isTerminal = IsTerminal()
}

func miniTS() int {
	return int(time.Since(baseTimestamp) / time.Second)
}

type TextFormatter struct {
	// Set to true to bypass checking for a TTY before outputting colors.
	ForceColors bool

	// Force disabling colors.
	DisableColors bool

	// Disable timestamp logging. useful when output is redirected to logging
	// system that already adds timestamps.
	DisableTimestamp bool

	// Enable logging the full timestamp when a TTY is attached instead of just
	// the time passed since beginning of execution.
	FullTimestamp bool

	// TimestampFormat to use for display when a full timestamp is printed
	TimestampFormat string

	// The fields are sorted by default for a consistent output. For applications
	// that log extremely frequently and don't use the JSON formatter this may not
	// be desired.
	DisableSorting bool
}

func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
	var keys []string = make([]string, 0, len(entry.Data))
	for k := range entry.Data {
		keys = append(keys, k)
	}

	if !f.DisableSorting {
		sort.Strings(keys)
	}

	b := &bytes.Buffer{}

	prefixFieldClashes(entry.Data)

	isColorTerminal := isTerminal && (runtime.GOOS != "windows")
	isColored := (f.ForceColors || isColorTerminal) && !f.DisableColors

	if f.TimestampFormat == "" {
		f.TimestampFormat = DefaultTimestampFormat
	}
	if isColored {
		f.printColored(b, entry, keys)
	} else {
		if !f.DisableTimestamp {
			f.appendKeyValue(b, "time", entry.Time.Format(f.TimestampFormat))
		}
		f.appendKeyValue(b, "level", entry.Level.String())
		f.appendKeyValue(b, "msg", entry.Message)
		for _, key := range keys {
			f.appendKeyValue(b, key, entry.Data[key])
		}
	}

	b.WriteByte('\n')
	return b.Bytes(), nil
}

func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string) {
	var levelColor int
	switch entry.Level {
	case DebugLevel:
		levelColor = gray
	case WarnLevel:
		levelColor = yellow
	case ErrorLevel, FatalLevel, PanicLevel:
		levelColor = red
	default:
		levelColor = blue
	}

	levelText := strings.ToUpper(entry.Level.String())[0:4]

	if !f.FullTimestamp {
		fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, miniTS(), entry.Message)
	} else {
		fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(f.TimestampFormat), entry.Message)
	}
	for _, k := range keys {
		v := entry.Data[k]
		fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=%+v", levelColor, k, v)
	}
}

func needsQuoting(text string) bool {
	for _, ch := range text {
		if !((ch >= 'a' && ch <= 'z') ||
			(ch >= 'A' && ch <= 'Z') ||
			(ch >= '0' && ch <= '9') ||
			ch == '-' || ch == '.') {
			return false
		}
	}
	return true
}

func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) {

	b.WriteString(key)
	b.WriteByte('=')

	switch value := value.(type) {
	case string:
		if needsQuoting(value) {
			b.WriteString(value)
		} else {
			fmt.Fprintf(b, "%q", value)
		}
	case error:
		errmsg := value.Error()
		if needsQuoting(errmsg) {
			b.WriteString(errmsg)
		} else {
			fmt.Fprintf(b, "%q", value)
		}
	default:
		fmt.Fprint(b, value)
	}

	b.WriteByte(' ')
}
<|endoftext|>


<commit_before>// Copyright (C) 2014 Daniel Harrison

package hfile

import "bytes"
import "encoding/binary"
import "errors"
import "github.com/edsrzf/mmap-go"
import "os"
import "github.com/golang/snappy"

type Reader struct {
	mmap      mmap.MMap
	version   Version
	header    Header
	dataIndex DataIndex
}

func NewReader(file *os.File) (Reader, error) {
	hfile := Reader{}
	var err error
	hfile.mmap, err = mmap.Map(file, mmap.RDONLY, 0)
	if err != nil {
		return hfile, err
	}

	versionIndex := len(hfile.mmap) - 4
	hfile.version, err = newVersion(bytes.NewReader(hfile.mmap[versionIndex:]))
	if err != nil {
		return hfile, err
	}
	hfile.header, err = hfile.version.newHeader(hfile.mmap)
	if err != nil {
		return hfile, err
	}
	hfile.dataIndex, err = hfile.header.newDataIndex(hfile.mmap)
	if err != nil {
		return hfile, err
	}

	return hfile, nil
}
func (hfile *Reader) String() string {
	return "hfile"
}
func getDataBlock(key []byte, blocks *[]DataBlock) (*DataBlock, error) {
	// TODO(dan): Binary search instead.
	for i := len(*blocks) - 1; i >= 0; i-- {
		block := (*blocks)[i]
		if cmp := bytes.Compare(key, block.firstKeyBytes); cmp == 0 || cmp == 1 {
			return &block, nil
		}
	}
	return nil, errors.New("key not found")
}
func (hfile *Reader) Get(key []byte) ([]byte, error) {
	dataBlock, err := getDataBlock(key, &hfile.dataIndex.dataBlocks)
	if err != nil {
		return key, err
	}
	return dataBlock.get(key)
}

type Version struct {
	buf          *bytes.Reader
	majorVersion uint32
	minorVersion uint32
}

func newVersion(versionBuf *bytes.Reader) (Version, error) {
	version := Version{buf: versionBuf}
	var rawByte uint32
	binary.Read(version.buf, binary.BigEndian, &rawByte)
	version.majorVersion = rawByte & 0x00ffffff
	version.minorVersion = rawByte >> 24
	return version, nil
}
func (version *Version) newHeader(mmap mmap.MMap) (Header, error) {
	header := Header{}

	if version.majorVersion != 1 || version.minorVersion != 0 {
		return header, errors.New("wrong version")
	}

	header.index = len(mmap) - 60
	header.buf = bytes.NewReader(mmap[header.index:])
	headerMagic := make([]byte, 8)
	header.buf.Read(headerMagic)
	if bytes.Compare(headerMagic, []byte("TRABLK\"$")) != 0 {
		return header, errors.New("bad header magic")
	}

	binary.Read(header.buf, binary.BigEndian, &header.fileInfoOffset)
	binary.Read(header.buf, binary.BigEndian, &header.dataIndexOffset)
	binary.Read(header.buf, binary.BigEndian, &header.dataIndexCount)
	binary.Read(header.buf, binary.BigEndian, &header.metaIndexOffset)
	binary.Read(header.buf, binary.BigEndian, &header.metaIndexCount)
	binary.Read(header.buf, binary.BigEndian, &header.totalUncompressedDataBytes)
	binary.Read(header.buf, binary.BigEndian, &header.entryCount)
	binary.Read(header.buf, binary.BigEndian, &header.compressionCodec)
	return header, nil
}

type Header struct {
	buf   *bytes.Reader
	index int

	fileInfoOffset             uint64
	dataIndexOffset            uint64
	dataIndexCount             uint32
	metaIndexOffset            uint64
	metaIndexCount             uint32
	totalUncompressedDataBytes uint64
	entryCount                 uint32
	compressionCodec           uint32
}

func (header *Header) newDataIndex(mmap mmap.MMap) (DataIndex, error) {
	dataIndex := DataIndex{}
	dataIndexEnd := header.metaIndexOffset
	if header.metaIndexOffset == 0 {
		dataIndexEnd = uint64(header.index)
	}
	dataIndex.buf = bytes.NewReader(mmap[header.dataIndexOffset:dataIndexEnd])

	dataIndexMagic := make([]byte, 8)
	dataIndex.buf.Read(dataIndexMagic)
	if bytes.Compare(dataIndexMagic, []byte("IDXBLK)+")) != 0 {
		return dataIndex, errors.New("bad data index magic")
	}

	for dataIndex.buf.Len() > 0 {
		dataBlock := DataBlock{}

		binary.Read(dataIndex.buf, binary.BigEndian, &dataBlock.offset)
		binary.Read(dataIndex.buf, binary.BigEndian, &dataBlock.size)

		switch {
		case header.compressionCodec == 2: // No compression
			dataBlock.buf = bytes.NewReader(mmap[dataBlock.offset : dataBlock.offset+uint64(dataBlock.size)])
		case header.compressionCodec == 3: // Snappy
			uncompressedByteSize := binary.BigEndian.Uint32(mmap[dataBlock.offset : dataBlock.offset+4])
			if uncompressedByteSize != dataBlock.size {
				return dataIndex, errors.New("mismatched uncompressed block size")
			}
			compressedByteSize := binary.BigEndian.Uint32(mmap[dataBlock.offset+4 : dataBlock.offset+8])
			compressedBytes := mmap[dataBlock.offset+8 : dataBlock.offset+8+uint64(compressedByteSize)]
			uncompressedBytes, err := snappy.Decode(nil, compressedBytes)
			if err != nil {
				return dataIndex, err
			}
			dataBlock.buf = bytes.NewReader(uncompressedBytes)
		default:
			return dataIndex, errors.New("Unsupported compression codec " + string(header.compressionCodec))
		}

		dataBlockMagic := make([]byte, 8)
		dataBlock.buf.Read(dataBlockMagic)
		if bytes.Compare(dataBlockMagic, []byte("DATABLK*")) != 0 {
			return dataIndex, errors.New("bad data block magic")
		}

		firstKeyLen, _ := binary.ReadUvarint(dataIndex.buf)
		dataBlock.firstKeyBytes = make([]byte, firstKeyLen)
		dataIndex.buf.Read(dataBlock.firstKeyBytes)

		dataIndex.dataBlocks = append(dataIndex.dataBlocks, dataBlock)
	}

	return dataIndex, nil
}

type DataIndex struct {
	buf        *bytes.Reader
	dataBlocks []DataBlock
}

type DataBlock struct {
	buf           *bytes.Reader
	offset        uint64
	size          uint32
	firstKeyBytes []byte
}

func (dataBlock *DataBlock) reset() {
	dataBlock.buf.Seek(8, 0)
}
func (dataBlock *DataBlock) get(key []byte) ([]byte, error) {
	dataBlock.reset()
	for dataBlock.buf.Len() > 0 {
		var keyLen, valLen uint32
		binary.Read(dataBlock.buf, binary.BigEndian, &keyLen)
		binary.Read(dataBlock.buf, binary.BigEndian, &valLen)
		keyBytes := make([]byte, keyLen)
		valBytes := make([]byte, valLen)
		dataBlock.buf.Read(keyBytes)
		dataBlock.buf.Read(valBytes)
		if bytes.Compare(key, keyBytes) == 0 {
			return valBytes, nil
		}
	}
	return key, errors.New("key not found")
}
<commit_msg>add printing of debug summary of reader<commit_after>// Copyright (C) 2014 Daniel Harrison

package hfile

import (
	"bytes"
	"fmt"
	"io"
)
import "encoding/binary"
import "errors"
import "github.com/edsrzf/mmap-go"
import "os"
import "github.com/golang/snappy"

type Reader struct {
	mmap      mmap.MMap
	version   Version
	header    Header
	dataIndex DataIndex
}

func NewReader(file *os.File) (Reader, error) {
	hfile := Reader{}
	var err error
	hfile.mmap, err = mmap.Map(file, mmap.RDONLY, 0)
	if err != nil {
		return hfile, err
	}

	versionIndex := len(hfile.mmap) - 4
	hfile.version, err = newVersion(bytes.NewReader(hfile.mmap[versionIndex:]))
	if err != nil {
		return hfile, err
	}
	hfile.header, err = hfile.version.newHeader(hfile.mmap)
	if err != nil {
		return hfile, err
	}
	hfile.dataIndex, err = hfile.header.newDataIndex(hfile.mmap)
	if err != nil {
		return hfile, err
	}

	return hfile, nil
}
func (hfile *Reader) String() string {
	return "hfile"
}
func getDataBlock(key []byte, blocks *[]DataBlock) (*DataBlock, error) {
	// TODO(dan): Binary search instead.
	for i := len(*blocks) - 1; i >= 0; i-- {
		block := (*blocks)[i]
		if cmp := bytes.Compare(key, block.firstKeyBytes); cmp == 0 || cmp == 1 {
			return &block, nil
		}
	}
	return nil, errors.New("key not found")
}
func (hfile *Reader) Get(key []byte) ([]byte, error) {
	dataBlock, err := getDataBlock(key, &hfile.dataIndex.dataBlocks)
	if err != nil {
		return key, err
	}
	return dataBlock.get(key)
}

func (r *Reader) PrintDebugInfo(out io.Writer) {
	fmt.Fprintln(out, "entries: ", r.header.entryCount)
	fmt.Fprintln(out, "blocks: ", len(r.dataIndex.dataBlocks))
	for i, blk := range r.dataIndex.dataBlocks {
		fmt.Fprintf(out, "\t#%d: %s (%v)\n", i, blk.firstKeyBytes, blk.firstKeyBytes)
	}
}

type Version struct {
	buf          *bytes.Reader
	majorVersion uint32
	minorVersion uint32
}

func newVersion(versionBuf *bytes.Reader) (Version, error) {
	version := Version{buf: versionBuf}
	var rawByte uint32
	binary.Read(version.buf, binary.BigEndian, &rawByte)
	version.majorVersion = rawByte & 0x00ffffff
	version.minorVersion = rawByte >> 24
	return version, nil
}
func (version *Version) newHeader(mmap mmap.MMap) (Header, error) {
	header := Header{}

	if version.majorVersion != 1 || version.minorVersion != 0 {
		return header, errors.New("wrong version")
	}

	header.index = len(mmap) - 60
	header.buf = bytes.NewReader(mmap[header.index:])
	headerMagic := make([]byte, 8)
	header.buf.Read(headerMagic)
	if bytes.Compare(headerMagic, []byte("TRABLK\"$")) != 0 {
		return header, errors.New("bad header magic")
	}

	binary.Read(header.buf, binary.BigEndian, &header.fileInfoOffset)
	binary.Read(header.buf, binary.BigEndian, &header.dataIndexOffset)
	binary.Read(header.buf, binary.BigEndian, &header.dataIndexCount)
	binary.Read(header.buf, binary.BigEndian, &header.metaIndexOffset)
	binary.Read(header.buf, binary.BigEndian, &header.metaIndexCount)
	binary.Read(header.buf, binary.BigEndian, &header.totalUncompressedDataBytes)
	binary.Read(header.buf, binary.BigEndian, &header.entryCount)
	binary.Read(header.buf, binary.BigEndian, &header.compressionCodec)
	return header, nil
}

type Header struct {
	buf   *bytes.Reader
	index int

	fileInfoOffset             uint64
	dataIndexOffset            uint64
	dataIndexCount             uint32
	metaIndexOffset            uint64
	metaIndexCount             uint32
	totalUncompressedDataBytes uint64
	entryCount                 uint32
	compressionCodec           uint32
}

func (header *Header) newDataIndex(mmap mmap.MMap) (DataIndex, error) {
	dataIndex := DataIndex{}
	dataIndexEnd := header.metaIndexOffset
	if header.metaIndexOffset == 0 {
		dataIndexEnd = uint64(header.index)
	}
	dataIndex.buf = bytes.NewReader(mmap[header.dataIndexOffset:dataIndexEnd])

	dataIndexMagic := make([]byte, 8)
	dataIndex.buf.Read(dataIndexMagic)
	if bytes.Compare(dataIndexMagic, []byte("IDXBLK)+")) != 0 {
		return dataIndex, errors.New("bad data index magic")
	}

	for dataIndex.buf.Len() > 0 {
		dataBlock := DataBlock{}

		binary.Read(dataIndex.buf, binary.BigEndian, &dataBlock.offset)
		binary.Read(dataIndex.buf, binary.BigEndian, &dataBlock.size)

		switch {
		case header.compressionCodec == 2: // No compression
			dataBlock.buf = bytes.NewReader(mmap[dataBlock.offset : dataBlock.offset+uint64(dataBlock.size)])
		case header.compressionCodec == 3: // Snappy
			uncompressedByteSize := binary.BigEndian.Uint32(mmap[dataBlock.offset : dataBlock.offset+4])
			if uncompressedByteSize != dataBlock.size {
				return dataIndex, errors.New("mismatched uncompressed block size")
			}
			compressedByteSize := binary.BigEndian.Uint32(mmap[dataBlock.offset+4 : dataBlock.offset+8])
			compressedBytes := mmap[dataBlock.offset+8 : dataBlock.offset+8+uint64(compressedByteSize)]
			uncompressedBytes, err := snappy.Decode(nil, compressedBytes)
			if err != nil {
				return dataIndex, err
			}
			dataBlock.buf = bytes.NewReader(uncompressedBytes)
		default:
			return dataIndex, errors.New("Unsupported compression codec " + string(header.compressionCodec))
		}

		dataBlockMagic := make([]byte, 8)
		dataBlock.buf.Read(dataBlockMagic)
		if bytes.Compare(dataBlockMagic, []byte("DATABLK*")) != 0 {
			return dataIndex, errors.New("bad data block magic")
		}

		firstKeyLen, _ := binary.ReadUvarint(dataIndex.buf)
		dataBlock.firstKeyBytes = make([]byte, firstKeyLen)
		dataIndex.buf.Read(dataBlock.firstKeyBytes)

		dataIndex.dataBlocks = append(dataIndex.dataBlocks, dataBlock)
	}

	return dataIndex, nil
}

type DataIndex struct {
	buf        *bytes.Reader
	dataBlocks []DataBlock
}

type DataBlock struct {
	buf           *bytes.Reader
	offset        uint64
	size          uint32
	firstKeyBytes []byte
}

func (dataBlock *DataBlock) reset() {
	dataBlock.buf.Seek(8, 0)
}
func (dataBlock *DataBlock) get(key []byte) ([]byte, error) {
	dataBlock.reset()
	for dataBlock.buf.Len() > 0 {
		var keyLen, valLen uint32
		binary.Read(dataBlock.buf, binary.BigEndian, &keyLen)
		binary.Read(dataBlock.buf, binary.BigEndian, &valLen)
		keyBytes := make([]byte, keyLen)
		valBytes := make([]byte, valLen)
		dataBlock.buf.Read(keyBytes)
		dataBlock.buf.Read(valBytes)
		if bytes.Compare(key, keyBytes) == 0 {
			return valBytes, nil
		}
	}
	return key, errors.New("key not found")
}
<|endoftext|>


<commit_before>// Copyright (c) 2017-2021 Tigera, Inc. All rights reserved.
//
// 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 infrastructure

import (
	"context"
	"fmt"
	"regexp"
	"sync"
	"time"

	"github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	log "github.com/sirupsen/logrus"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	api "github.com/projectcalico/libcalico-go/lib/apis/v3"
	client "github.com/projectcalico/libcalico-go/lib/clientv3"
	"github.com/projectcalico/libcalico-go/lib/errors"
	"github.com/projectcalico/libcalico-go/lib/options"
	"github.com/projectcalico/libcalico-go/lib/resources"

	"github.com/projectcalico/felix/fv/containers"
)

type TopologyOptions struct {
	FelixLogSeverity          string
	EnableIPv6                bool
	ExtraEnvVars              map[string]string
	ExtraVolumes              map[string]string
	WithTypha                 bool
	WithFelixTyphaTLS         bool
	TestManagesBPF            bool
	TyphaLogSeverity          string
	IPIPEnabled               bool
	IPIPRoutesEnabled         bool
	VXLANMode                 api.VXLANMode
	WireguardEnabled          bool
	InitialFelixConfiguration *api.FelixConfiguration
	NATOutgoingEnabled        bool
	DelayFelixStart           bool
	AutoHEPsEnabled           bool
	TriggerDelayedFelixStart  bool
	FelixStopGraceful         bool
	ExternalIPs               bool
	UseIPPools                bool
	NeedNodeIP                bool
}

func DefaultTopologyOptions() TopologyOptions {
	return TopologyOptions{
		FelixLogSeverity:  "info",
		EnableIPv6:        true,
		ExtraEnvVars:      map[string]string{},
		ExtraVolumes:      map[string]string{},
		WithTypha:         false,
		WithFelixTyphaTLS: false,
		TyphaLogSeverity:  "info",
		IPIPEnabled:       true,
		IPIPRoutesEnabled: true,
		UseIPPools:        true,
	}
}

// StartSingleNodeEtcdTopology starts an etcd container and a single Felix container; it initialises
// the datastore and installs a Node resource for the Felix node.
func StartSingleNodeEtcdTopology(options TopologyOptions) (felix *Felix, etcd *containers.Container, calicoClient client.Interface, infra DatastoreInfra) {
	felixes, etcd, calicoClient, infra := StartNNodeEtcdTopology(1, options)
	felix = felixes[0]
	return
}

// StartNNodeEtcdTopology starts an etcd container and a set of Felix hosts.  If n > 1, sets
// up IPIP, otherwise this is skipped.
//
// - Configures an IPAM pool for 10.65.0.0/16 (so that Felix programs the all-IPAM blocks IP set)
//   but (for simplicity) we don't actually use IPAM to assign IPs.
// - Configures routes between the hosts, giving each host 10.65.x.0/24, where x is the
//   index in the returned array.  When creating workloads, use IPs from the relevant block.
// - Configures the Tunnel IP for each host as 10.65.x.1.
func StartNNodeEtcdTopology(n int, opts TopologyOptions) (felixes []*Felix, etcd *containers.Container, client client.Interface, infra DatastoreInfra) {
	log.Infof("Starting a %d-node etcd topology.", n)

	eds, err := GetEtcdDatastoreInfra()
	Expect(err).ToNot(HaveOccurred())
	etcd = eds.etcdContainer
	infra = eds

	felixes, client = StartNNodeTopology(n, opts, eds)

	return
}

// StartSingleNodeEtcdTopology starts an etcd container and a single Felix container; it initialises
// the datastore and installs a Node resource for the Felix node.
func StartSingleNodeTopology(options TopologyOptions, infra DatastoreInfra) (felix *Felix, calicoClient client.Interface) {
	felixes, calicoClient := StartNNodeTopology(1, options, infra)
	felix = felixes[0]
	return
}

// StartNNodeEtcdTopology starts an etcd container and a set of Felix hosts.  If n > 1, sets
// up IPIP, otherwise this is skipped.
//
// - Configures an IPAM pool for 10.65.0.0/16 (so that Felix programs the all-IPAM blocks IP set)
//   but (for simplicity) we don't actually use IPAM to assign IPs.
// - Configures routes between the hosts, giving each host 10.65.x.0/24, where x is the
//   index in the returned array.  When creating workloads, use IPs from the relevant block.
// - Configures the Tunnel IP for each host as 10.65.x.1.
func StartNNodeTopology(n int, opts TopologyOptions, infra DatastoreInfra) (felixes []*Felix, client client.Interface) {
	log.Infof("Starting a %d-node topology.", n)
	success := false
	var err error
	startTime := time.Now()
	defer func() {
		if !success {
			log.WithError(err).Error("Failed to start topology, tearing down containers")
			for _, felix := range felixes {
				felix.Stop()
			}
			infra.Stop()
			return
		}
		log.WithField("time", time.Since(startTime)).Info("Started topology.")
	}()

	if opts.VXLANMode == "" {
		opts.VXLANMode = api.VXLANModeNever
	}
	// Get client.
	client = infra.GetCalicoClient()
	mustInitDatastore(client)

	// If asked to, pre-create a felix configuration.  We do this before enabling IPIP because IPIP set-up can
	// create/update a FelixConfiguration as a side-effect.
	if opts.InitialFelixConfiguration != nil {
		log.WithField("config", opts.InitialFelixConfiguration).Info(
			"Installing initial FelixConfiguration")
		Eventually(func() error {
			ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
			defer cancel()
			_, err = client.FelixConfigurations().Create(ctx, opts.InitialFelixConfiguration, options.SetOptions{})
			if _, ok := err.(errors.ErrorResourceAlreadyExists); ok {
				// Try to delete the unexpected config, then, if there's still time in the Eventually loop,
				// we'll try to recreate
				_, _ = client.FelixConfigurations().Delete(ctx, "default", options.DeleteOptions{})
			}
			return err
		}, "10s").ShouldNot(HaveOccurred())
	}

	if n > 1 {
		Eventually(func() error {
			ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
			defer cancel()
			if opts.UseIPPools {
				ipPool := api.NewIPPool()
				ipPool.Name = "test-pool"
				ipPool.Spec.CIDR = "10.65.0.0/16"
				ipPool.Spec.NATOutgoing = opts.NATOutgoingEnabled
				if opts.IPIPEnabled {
					ipPool.Spec.IPIPMode = api.IPIPModeAlways
				} else {
					ipPool.Spec.IPIPMode = api.IPIPModeNever
				}

				ipPool.Spec.VXLANMode = opts.VXLANMode

				_, err = client.IPPools().Create(ctx, ipPool, options.SetOptions{})
			}
			return err
		}).ShouldNot(HaveOccurred())
	}

	typhaIP := ""
	if opts.WithTypha {
		typha := RunTypha(infra, opts)
		opts.ExtraEnvVars["FELIX_TYPHAADDR"] = typha.IP + ":5473"
		typhaIP = typha.IP
	}

	felixes = make([]*Felix, n)
	var wg sync.WaitGroup
	for i := 0; i < n; i++ {
		// Then start Felix and create a node for it.
		opts.ExtraEnvVars["BPF_LOG_PFX"] = fmt.Sprintf("%d-", i)
		// Arrange for only the first Felix to enable the BPF connect-time load balancer, as
		// we get unpredictable behaviour if more than one Felix enables it on the same
		// host.
		optsFirstFelix := opts
		opts.ExtraEnvVars = map[string]string{}
		for k, v := range optsFirstFelix.ExtraEnvVars {
			opts.ExtraEnvVars[k] = v
		}
		opts.ExtraEnvVars["FELIX_BPFConnectTimeLoadBalancingEnabled"] = "false"
		opts.ExtraEnvVars["FELIX_DebugSkipCTLBCleanup"] = "true"
		wg.Add(1)
		go func(i int) {
			defer wg.Done()
			defer ginkgo.GinkgoRecover()
			if i == 0 {
				felixes[i] = RunFelix(infra, i, optsFirstFelix)
			} else {
				felixes[i] = RunFelix(infra, i, opts)
			}
		}(i)
	}
	wg.Wait()

	for i := 0; i < n; i++ {
		opts.ExtraEnvVars["BPF_LOG_PFX"] = ""
		felix := felixes[i]
		felix.TyphaIP = typhaIP

		expectedIPs := []string{felix.IP}

		if kdd, ok := infra.(*K8sDatastoreInfra); ok && opts.ExternalIPs {
			kdd.SetExternalIP(felix, i)
			expectedIPs = append(expectedIPs, felix.ExternalIP)
		}
		if opts.IPIPEnabled {
			infra.SetExpectedIPIPTunnelAddr(felix, i, bool(n > 1))
			expectedIPs = append(expectedIPs, felix.ExpectedIPIPTunnelAddr)
		}
		if opts.VXLANMode != api.VXLANModeNever {
			infra.SetExpectedVXLANTunnelAddr(felix, i, bool(n > 1))
			expectedIPs = append(expectedIPs, felix.ExpectedVXLANTunnelAddr)
		}
		if opts.WireguardEnabled {
			infra.SetExpectedWireguardTunnelAddr(felix, i, bool(n > 1))
			expectedIPs = append(expectedIPs, felix.ExpectedWireguardTunnelAddr)
		}

		var w chan struct{}
		if !opts.DelayFelixStart && felix.ExpectedIPIPTunnelAddr != "" {
			// If felix has an IPIP tunnel address defined, Felix may restart after loading its config.
			// Handle that here by monitoring the log and waiting for the correct tunnel IP to show up
			// before we return.
			w = felix.WatchStdoutFor(regexp.MustCompile(
				`"IpInIpTunnelAddr":"` + regexp.QuoteMeta(felix.ExpectedIPIPTunnelAddr) + `"`))
		} else if opts.NeedNodeIP {
			w = felix.WatchStdoutFor(regexp.MustCompile(
				`Host config update for this host|Host IP changed`))
		}
		infra.AddNode(felix, i, bool(n > 1 || opts.NeedNodeIP))
		if w != nil {
			// Wait for any Felix restart...
			log.Info("Wait for Felix to restart")
			Eventually(w, "10s").Should(BeClosed(),
				fmt.Sprintf("Timed out waiting for %s to restart", felix.Name))
		}

		if opts.AutoHEPsEnabled {
			hep := &api.HostEndpoint{
				ObjectMeta: metav1.ObjectMeta{
					Name: fmt.Sprintf("%s-auto-hep", felix.Name),
					Labels: map[string]string{
						"projectcalico.org/created-by": "calico-kube-controllers",
						"node":                         felix.Name,
						"ep-type":                      "host",
					},
				},
				Spec: api.HostEndpointSpec{
					Node:          felix.Name,
					InterfaceName: "*",
					ExpectedIPs:   expectedIPs,
					Profiles:      []string{resources.DefaultAllowProfileName},
				},
			}
			_, err := client.HostEndpoints().Create(context.Background(), hep, options.SetOptions{})
			Expect(err).ToNot(HaveOccurred())
		}

		if opts.TriggerDelayedFelixStart {
			felix.TriggerDelayedStart()
		}

	}

	// Set up routes between the hosts, note: we're not using BGP here but we set up similar
	// CIDR-based routes.
	for i, iFelix := range felixes {
		for j, jFelix := range felixes {
			if i == j {
				continue
			}
			wg.Add(1)
			go func(i, j int, iFelix, jFelix *Felix) {
				defer wg.Done()
				defer ginkgo.GinkgoRecover()
				jBlock := fmt.Sprintf("10.65.%d.0/24", j)
				if opts.IPIPEnabled && opts.IPIPRoutesEnabled {
					// Can get "Nexthop device is not up" error here if tunl0 device is
					// not ready yet, which can happen especially if Felix start was
					// delayed.
					Eventually(func() error {
						return iFelix.ExecMayFail("ip", "route", "add", jBlock, "via", jFelix.IP, "dev", "tunl0", "onlink")
					}, "10s", "1s").ShouldNot(HaveOccurred())
				} else if opts.VXLANMode == api.VXLANModeNever {
					// If VXLAN is enabled, Felix will program these routes itself.
					err := iFelix.ExecMayFail("ip", "route", "add", jBlock, "via", jFelix.IP, "dev", "eth0")
					Expect(err).ToNot(HaveOccurred())
				}
			}(i, j, iFelix, jFelix)
		}
	}
	wg.Wait()
	success = true
	return
}

func mustInitDatastore(client client.Interface) {
	Eventually(func() error {
		log.Info("Initializing the datastore...")
		ctx, cancelFun := context.WithTimeout(context.Background(), 10*time.Second)
		defer cancelFun()
		err := client.EnsureInitialized(
			ctx,
			"v3.0.0-test",
			"felix-fv",
		)
		log.WithError(err).Info("EnsureInitialized result")
		return err
	}).ShouldNot(HaveOccurred(), "mustInitDatastore failed")
}
<commit_msg>FV: Make a separate copy of TopologyOptions for each Felix<commit_after>// Copyright (c) 2017-2021 Tigera, Inc. All rights reserved.
//
// 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 infrastructure

import (
	"context"
	"fmt"
	"regexp"
	"sync"
	"time"

	"github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	log "github.com/sirupsen/logrus"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	api "github.com/projectcalico/libcalico-go/lib/apis/v3"
	client "github.com/projectcalico/libcalico-go/lib/clientv3"
	"github.com/projectcalico/libcalico-go/lib/errors"
	"github.com/projectcalico/libcalico-go/lib/options"
	"github.com/projectcalico/libcalico-go/lib/resources"

	"github.com/projectcalico/felix/fv/containers"
)

type TopologyOptions struct {
	FelixLogSeverity          string
	EnableIPv6                bool
	ExtraEnvVars              map[string]string
	ExtraVolumes              map[string]string
	WithTypha                 bool
	WithFelixTyphaTLS         bool
	TestManagesBPF            bool
	TyphaLogSeverity          string
	IPIPEnabled               bool
	IPIPRoutesEnabled         bool
	VXLANMode                 api.VXLANMode
	WireguardEnabled          bool
	InitialFelixConfiguration *api.FelixConfiguration
	NATOutgoingEnabled        bool
	DelayFelixStart           bool
	AutoHEPsEnabled           bool
	TriggerDelayedFelixStart  bool
	FelixStopGraceful         bool
	ExternalIPs               bool
	UseIPPools                bool
	NeedNodeIP                bool
}

func DefaultTopologyOptions() TopologyOptions {
	return TopologyOptions{
		FelixLogSeverity:  "info",
		EnableIPv6:        true,
		ExtraEnvVars:      map[string]string{},
		ExtraVolumes:      map[string]string{},
		WithTypha:         false,
		WithFelixTyphaTLS: false,
		TyphaLogSeverity:  "info",
		IPIPEnabled:       true,
		IPIPRoutesEnabled: true,
		UseIPPools:        true,
	}
}

// StartSingleNodeEtcdTopology starts an etcd container and a single Felix container; it initialises
// the datastore and installs a Node resource for the Felix node.
func StartSingleNodeEtcdTopology(options TopologyOptions) (felix *Felix, etcd *containers.Container, calicoClient client.Interface, infra DatastoreInfra) {
	felixes, etcd, calicoClient, infra := StartNNodeEtcdTopology(1, options)
	felix = felixes[0]
	return
}

// StartNNodeEtcdTopology starts an etcd container and a set of Felix hosts.  If n > 1, sets
// up IPIP, otherwise this is skipped.
//
// - Configures an IPAM pool for 10.65.0.0/16 (so that Felix programs the all-IPAM blocks IP set)
//   but (for simplicity) we don't actually use IPAM to assign IPs.
// - Configures routes between the hosts, giving each host 10.65.x.0/24, where x is the
//   index in the returned array.  When creating workloads, use IPs from the relevant block.
// - Configures the Tunnel IP for each host as 10.65.x.1.
func StartNNodeEtcdTopology(n int, opts TopologyOptions) (felixes []*Felix, etcd *containers.Container, client client.Interface, infra DatastoreInfra) {
	log.Infof("Starting a %d-node etcd topology.", n)

	eds, err := GetEtcdDatastoreInfra()
	Expect(err).ToNot(HaveOccurred())
	etcd = eds.etcdContainer
	infra = eds

	felixes, client = StartNNodeTopology(n, opts, eds)

	return
}

// StartSingleNodeEtcdTopology starts an etcd container and a single Felix container; it initialises
// the datastore and installs a Node resource for the Felix node.
func StartSingleNodeTopology(options TopologyOptions, infra DatastoreInfra) (felix *Felix, calicoClient client.Interface) {
	felixes, calicoClient := StartNNodeTopology(1, options, infra)
	felix = felixes[0]
	return
}

// StartNNodeEtcdTopology starts an etcd container and a set of Felix hosts.  If n > 1, sets
// up IPIP, otherwise this is skipped.
//
// - Configures an IPAM pool for 10.65.0.0/16 (so that Felix programs the all-IPAM blocks IP set)
//   but (for simplicity) we don't actually use IPAM to assign IPs.
// - Configures routes between the hosts, giving each host 10.65.x.0/24, where x is the
//   index in the returned array.  When creating workloads, use IPs from the relevant block.
// - Configures the Tunnel IP for each host as 10.65.x.1.
func StartNNodeTopology(n int, opts TopologyOptions, infra DatastoreInfra) (felixes []*Felix, client client.Interface) {
	log.Infof("Starting a %d-node topology.", n)
	success := false
	var err error
	startTime := time.Now()
	defer func() {
		if !success {
			log.WithError(err).Error("Failed to start topology, tearing down containers")
			for _, felix := range felixes {
				felix.Stop()
			}
			infra.Stop()
			return
		}
		log.WithField("time", time.Since(startTime)).Info("Started topology.")
	}()

	if opts.VXLANMode == "" {
		opts.VXLANMode = api.VXLANModeNever
	}
	// Get client.
	client = infra.GetCalicoClient()
	mustInitDatastore(client)

	// If asked to, pre-create a felix configuration.  We do this before enabling IPIP because IPIP set-up can
	// create/update a FelixConfiguration as a side-effect.
	if opts.InitialFelixConfiguration != nil {
		log.WithField("config", opts.InitialFelixConfiguration).Info(
			"Installing initial FelixConfiguration")
		Eventually(func() error {
			ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
			defer cancel()
			_, err = client.FelixConfigurations().Create(ctx, opts.InitialFelixConfiguration, options.SetOptions{})
			if _, ok := err.(errors.ErrorResourceAlreadyExists); ok {
				// Try to delete the unexpected config, then, if there's still time in the Eventually loop,
				// we'll try to recreate
				_, _ = client.FelixConfigurations().Delete(ctx, "default", options.DeleteOptions{})
			}
			return err
		}, "10s").ShouldNot(HaveOccurred())
	}

	if n > 1 {
		Eventually(func() error {
			ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
			defer cancel()
			if opts.UseIPPools {
				ipPool := api.NewIPPool()
				ipPool.Name = "test-pool"
				ipPool.Spec.CIDR = "10.65.0.0/16"
				ipPool.Spec.NATOutgoing = opts.NATOutgoingEnabled
				if opts.IPIPEnabled {
					ipPool.Spec.IPIPMode = api.IPIPModeAlways
				} else {
					ipPool.Spec.IPIPMode = api.IPIPModeNever
				}

				ipPool.Spec.VXLANMode = opts.VXLANMode

				_, err = client.IPPools().Create(ctx, ipPool, options.SetOptions{})
			}
			return err
		}).ShouldNot(HaveOccurred())
	}

	typhaIP := ""
	if opts.WithTypha {
		typha := RunTypha(infra, opts)
		opts.ExtraEnvVars["FELIX_TYPHAADDR"] = typha.IP + ":5473"
		typhaIP = typha.IP
	}

	felixes = make([]*Felix, n)
	var wg sync.WaitGroup

	// Make a separate copy of TopologyOptions for each Felix that we will run.  This
	// is because we need to modify ExtraEnvVars for some of them.  If we kept using
	// the same copy, while starting Felixes, we could hit a concurrent map read/write
	// problem.
	optsPerFelix := make([]TopologyOptions, n)
	for i := 0; i < n; i++ {
		optsPerFelix[i] = opts
		optsPerFelix[i].ExtraEnvVars = map[string]string{}
		for k, v := range opts.ExtraEnvVars {
			optsPerFelix[i].ExtraEnvVars[k] = v
		}

		// Different log prefix for each Felix.
		optsPerFelix[i].ExtraEnvVars["BPF_LOG_PFX"] = fmt.Sprintf("%d-", i)

		// Only the first Felix enables the BPF connect-time load balancer, as
		// we get unpredictable behaviour if more than one Felix enables it on the same
		// host.  So, disable CTLB handling for subsequent Felixes.
		if i > 0 {
			optsPerFelix[i].ExtraEnvVars["FELIX_BPFConnectTimeLoadBalancingEnabled"] = "false"
			optsPerFelix[i].ExtraEnvVars["FELIX_DebugSkipCTLBCleanup"] = "true"
		}
	}

	// Now start the Felixes.
	for i := 0; i < n; i++ {
		wg.Add(1)
		go func(i int) {
			defer wg.Done()
			defer ginkgo.GinkgoRecover()
			felixes[i] = RunFelix(infra, i, optsPerFelix[i])
		}(i)
	}
	wg.Wait()

	for i := 0; i < n; i++ {
		opts.ExtraEnvVars["BPF_LOG_PFX"] = ""
		felix := felixes[i]
		felix.TyphaIP = typhaIP

		expectedIPs := []string{felix.IP}

		if kdd, ok := infra.(*K8sDatastoreInfra); ok && opts.ExternalIPs {
			kdd.SetExternalIP(felix, i)
			expectedIPs = append(expectedIPs, felix.ExternalIP)
		}
		if opts.IPIPEnabled {
			infra.SetExpectedIPIPTunnelAddr(felix, i, bool(n > 1))
			expectedIPs = append(expectedIPs, felix.ExpectedIPIPTunnelAddr)
		}
		if opts.VXLANMode != api.VXLANModeNever {
			infra.SetExpectedVXLANTunnelAddr(felix, i, bool(n > 1))
			expectedIPs = append(expectedIPs, felix.ExpectedVXLANTunnelAddr)
		}
		if opts.WireguardEnabled {
			infra.SetExpectedWireguardTunnelAddr(felix, i, bool(n > 1))
			expectedIPs = append(expectedIPs, felix.ExpectedWireguardTunnelAddr)
		}

		var w chan struct{}
		if !opts.DelayFelixStart && felix.ExpectedIPIPTunnelAddr != "" {
			// If felix has an IPIP tunnel address defined, Felix may restart after loading its config.
			// Handle that here by monitoring the log and waiting for the correct tunnel IP to show up
			// before we return.
			w = felix.WatchStdoutFor(regexp.MustCompile(
				`"IpInIpTunnelAddr":"` + regexp.QuoteMeta(felix.ExpectedIPIPTunnelAddr) + `"`))
		} else if opts.NeedNodeIP {
			w = felix.WatchStdoutFor(regexp.MustCompile(
				`Host config update for this host|Host IP changed`))
		}
		infra.AddNode(felix, i, bool(n > 1 || opts.NeedNodeIP))
		if w != nil {
			// Wait for any Felix restart...
			log.Info("Wait for Felix to restart")
			Eventually(w, "10s").Should(BeClosed(),
				fmt.Sprintf("Timed out waiting for %s to restart", felix.Name))
		}

		if opts.AutoHEPsEnabled {
			hep := &api.HostEndpoint{
				ObjectMeta: metav1.ObjectMeta{
					Name: fmt.Sprintf("%s-auto-hep", felix.Name),
					Labels: map[string]string{
						"projectcalico.org/created-by": "calico-kube-controllers",
						"node":                         felix.Name,
						"ep-type":                      "host",
					},
				},
				Spec: api.HostEndpointSpec{
					Node:          felix.Name,
					InterfaceName: "*",
					ExpectedIPs:   expectedIPs,
					Profiles:      []string{resources.DefaultAllowProfileName},
				},
			}
			_, err := client.HostEndpoints().Create(context.Background(), hep, options.SetOptions{})
			Expect(err).ToNot(HaveOccurred())
		}

		if opts.TriggerDelayedFelixStart {
			felix.TriggerDelayedStart()
		}

	}

	// Set up routes between the hosts, note: we're not using BGP here but we set up similar
	// CIDR-based routes.
	for i, iFelix := range felixes {
		for j, jFelix := range felixes {
			if i == j {
				continue
			}
			wg.Add(1)
			go func(i, j int, iFelix, jFelix *Felix) {
				defer wg.Done()
				defer ginkgo.GinkgoRecover()
				jBlock := fmt.Sprintf("10.65.%d.0/24", j)
				if opts.IPIPEnabled && opts.IPIPRoutesEnabled {
					// Can get "Nexthop device is not up" error here if tunl0 device is
					// not ready yet, which can happen especially if Felix start was
					// delayed.
					Eventually(func() error {
						return iFelix.ExecMayFail("ip", "route", "add", jBlock, "via", jFelix.IP, "dev", "tunl0", "onlink")
					}, "10s", "1s").ShouldNot(HaveOccurred())
				} else if opts.VXLANMode == api.VXLANModeNever {
					// If VXLAN is enabled, Felix will program these routes itself.
					err := iFelix.ExecMayFail("ip", "route", "add", jBlock, "via", jFelix.IP, "dev", "eth0")
					Expect(err).ToNot(HaveOccurred())
				}
			}(i, j, iFelix, jFelix)
		}
	}
	wg.Wait()
	success = true
	return
}

func mustInitDatastore(client client.Interface) {
	Eventually(func() error {
		log.Info("Initializing the datastore...")
		ctx, cancelFun := context.WithTimeout(context.Background(), 10*time.Second)
		defer cancelFun()
		err := client.EnsureInitialized(
			ctx,
			"v3.0.0-test",
			"felix-fv",
		)
		log.WithError(err).Info("EnsureInitialized result")
		return err
	}).ShouldNot(HaveOccurred(), "mustInitDatastore failed")
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"os"

	"github.com/jsgoecke/tesla"
)

func main() {
	client, err := tesla.NewClient(
		&tesla.Auth{
			ClientID:     os.Getenv("TESLA_CLIENT_ID"),
			ClientSecret: os.Getenv("TESLA_CLIENT_SECRET"),
			Email:        os.Getenv("TESLA_USERNAME"),
			Password:     os.Getenv("TESLA_PASSWORD"),
		})
	if err != nil {
		panic(err)
	}

	vehicles, err := client.Vehicles()
	if err != nil {
		panic(err)
	}
	vehicle := vehicles[0]
	status, err := vehicle.MobileEnabled()

	if err != nil {
		panic(err)
	}

	fmt.Println(status)
	fmt.Println(vehicle.ChargeState())
	fmt.Println(vehicle.ClimateState())
	fmt.Println(vehicle.DriveState())
	fmt.Println(vehicle.GuiSettings())
	fmt.Println(vehicle.VehicleState())
	fmt.Println(vehicle.HonkHorn())
	fmt.Println(vehicle.FlashLights())
	fmt.Println(vehicle.Wakeup())
	fmt.Println(vehicle.OpenChargePort())
	fmt.Println(vehicle.ResetValetPIN())
	fmt.Println(vehicle.SetChargeLimitStandard())
	fmt.Println(vehicle.SetChargeLimit(50))
	fmt.Println(vehicle.StartCharging())
	fmt.Println(vehicle.StopCharging())
	fmt.Println(vehicle.SetChargeLimitMax())
	fmt.Println(vehicle.StartAirConditioning())
	fmt.Println(vehicle.StopAirConditioning())
	fmt.Println(vehicle.UnlockDoors())
	fmt.Println(vehicle.LockDoors())
	fmt.Println(vehicle.SetTemprature(72.0, 72.0))
	fmt.Println(vehicle.Start(os.Getenv("TESLA_PASSWORD")))
	fmt.Println(vehicle.OpenTrunk("rear"))
	fmt.Println(vehicle.OpenTrunk("front"))
	fmt.Println(vehicle.MovePanoRoof("vent", 0))
	fmt.Println(vehicle.MovePanoRoof("open", 0))
	fmt.Println(vehicle.MovePanoRoof("move", 50))
	fmt.Println(vehicle.MovePanoRoof("close", 0))
	fmt.Println(vehicle.TriggerHomeLink())

	// Take care with these, as the car will move
	fmt.Println(vehicle.AutoparkForward())
	fmt.Println(vehicle.AutoparkReverse())
	// Take care with these, as the car will move

	// Stream vehicle events
	eventChan, err := vehicle.Stream()
	if err != nil {
		for {
			event := <-eventChan
			if event != nil {
				eventJSON, _ := json.Marshal(event)
				fmt.Println(string(eventJSON))
			} else {
				fmt.Println("HTTP Stream timeout!")
				break
			}
		}
	}
}
<commit_msg>Fixed casing issue in example<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"os"

	"github.com/jsgoecke/tesla"
)

func main() {
	client, err := tesla.NewClient(
		&tesla.Auth{
			ClientID:     os.Getenv("TESLA_CLIENT_ID"),
			ClientSecret: os.Getenv("TESLA_CLIENT_SECRET"),
			Email:        os.Getenv("TESLA_USERNAME"),
			Password:     os.Getenv("TESLA_PASSWORD"),
		})
	if err != nil {
		panic(err)
	}

	vehicles, err := client.Vehicles()
	if err != nil {
		panic(err)
	}
	vehicle := vehicles[0]
	status, err := vehicle.MobileEnabled()

	if err != nil {
		panic(err)
	}

	fmt.Println(status)
	fmt.Println(vehicle.ChargeState())
	fmt.Println(vehicle.ClimateState())
	fmt.Println(vehicle.DriveState())
	fmt.Println(vehicle.GuiSettings())
	fmt.Println(vehicle.VehicleState())
	fmt.Println(vehicle.HonkHorn())
	fmt.Println(vehicle.FlashLights())
	fmt.Println(vehicle.Wakeup())
	fmt.Println(vehicle.OpenChargePort())
	fmt.Println(vehicle.ResetValetPIN())
	fmt.Println(vehicle.SetChargeLimitStandard())
	fmt.Println(vehicle.SetChargeLimit(50))
	fmt.Println(vehicle.StartCharging())
	fmt.Println(vehicle.StopCharging())
	fmt.Println(vehicle.SetChargeLimitMax())
	fmt.Println(vehicle.StartAirConditioning())
	fmt.Println(vehicle.StopAirConditioning())
	fmt.Println(vehicle.UnlockDoors())
	fmt.Println(vehicle.LockDoors())
	fmt.Println(vehicle.SetTemprature(72.0, 72.0))
	fmt.Println(vehicle.Start(os.Getenv("TESLA_PASSWORD")))
	fmt.Println(vehicle.OpenTrunk("rear"))
	fmt.Println(vehicle.OpenTrunk("front"))
	fmt.Println(vehicle.MovePanoRoof("vent", 0))
	fmt.Println(vehicle.MovePanoRoof("open", 0))
	fmt.Println(vehicle.MovePanoRoof("move", 50))
	fmt.Println(vehicle.MovePanoRoof("close", 0))
	fmt.Println(vehicle.TriggerHomelink())

	// Take care with these, as the car will move
	fmt.Println(vehicle.AutoparkForward())
	fmt.Println(vehicle.AutoparkReverse())
	// Take care with these, as the car will move

	// Stream vehicle events
	eventChan, err := vehicle.Stream()
	if err != nil {
		for {
			event := <-eventChan
			if event != nil {
				eventJSON, _ := json.Marshal(event)
				fmt.Println(string(eventJSON))
			} else {
				fmt.Println("HTTP Stream timeout!")
				break
			}
		}
	}
}
<|endoftext|>


<commit_before>package gaussian

import (
	"errors"

	"github.com/alex-ant/gomath/rational"
)

// SolveGaussian solves the system of linear equations via The Gaussian Elimination.
func SolveGaussian(eqM [][]rational.Rational) (res [][]rational.Rational, err error) {
	if len(eqM) > len(eqM[0]) {
		err = errors.New("the number of equations can not be greater than the number of variables")
		return
	}

	for i := 0; i < len(eqM)-1; i++ {
		eqM = sortMatrix(eqM, i)

		var varC rational.Rational
		for k := i; k < len(eqM); k++ {
			if k == i {
				varC = eqM[k][i]
			} else {
				multipliedLine := make([]rational.Rational, len(eqM[i]))
				for z, zv := range eqM[i] {
					multipliedLine[z] = zv.Multiply(eqM[k][i].Divide(varC)).MultiplyByNum(-1)
				}
				newLine := make([]rational.Rational, len(eqM[k]))
				for z, zv := range eqM[k] {
					newLine[z] = zv.Add(multipliedLine[z])
				}
				eqM[k] = newLine
			}
		}
	}

	// Removing empty lines.
	var resultEqM [][]rational.Rational
	for i := len(eqM) - 1; i >= 0; i-- {
		if !rational.RationalsAreNull(eqM[i]) {
			resultEqM = append(resultEqM, eqM[i])
		}
	}

	firstNonZeroIndex := func(sl []rational.Rational) (index int) {
		for i, v := range sl {
			if v.GetNumerator() != 0 {
				index = i
				return
			}
		}
		return
	}

	// Back substitution.
	for z := 0; z < len(resultEqM)-1; z++ {
		var processIndex int
		var firstLine []rational.Rational
		for i := z; i < len(resultEqM); i++ {
			v := resultEqM[i]
			if i == z {
				processIndex = firstNonZeroIndex(v)
				firstLine = v
			} else {
				mult := v[processIndex].Divide(firstLine[processIndex]).MultiplyByNum(-1)
				for j, jv := range v {
					resultEqM[i][j] = firstLine[j].Multiply(mult).Add(jv)
				}
			}
		}
	}

	// Calculating variables.
	res = make([][]rational.Rational, len(eqM[0])-1)
	if firstNonZeroIndex(resultEqM[0]) == len(resultEqM[0])-2 {
		// All the variables have been found.
		for i, iv := range resultEqM {
			index := len(res) - 1 - i
			res[index] = append(res[index], iv[len(iv)-1].Divide(iv[len(resultEqM)-1-i]))
		}
	} else {
		// Some variables remained unknown.
		var unknownStart, unknownEnd int
		for i, iv := range resultEqM {
			fnz := firstNonZeroIndex(iv)
			var firstRes []rational.Rational
			firstRes = append(firstRes, iv[len(iv)-1].Divide(iv[fnz]))
			if i == 0 {
				unknownStart = fnz + 1
				unknownEnd = len(iv) - 2
				for j := unknownEnd; j >= unknownStart; j-- {
					res[j] = []rational.Rational{rational.New(0, 0)}
					firstRes = append(firstRes, iv[j].Divide(iv[fnz]))
				}
			} else {
				for j := unknownEnd; j >= unknownStart; j-- {
					firstRes = append(firstRes, iv[j].Divide(iv[fnz]))
				}
			}
			res[fnz] = firstRes
		}
	}

	return
}

func sortMatrix(m [][]rational.Rational, initRow int) (m2 [][]rational.Rational) {
	indexed := make(map[int]bool)

	for i := 0; i < initRow; i++ {
		m2 = append(m2, m[i])
		indexed[i] = true
	}

	greaterThanMax := func(rr1, rr2 []rational.Rational) (greater bool) {
		for i := 0; i < len(rr1); i++ {
			if rr1[i].GetModule().GreaterThan(rr2[i].GetModule()) {
				greater = true
				return
			} else if rr1[i].GetModule().LessThan(rr2[i].GetModule()) {
				return
			}
		}
		return
	}

	type maxStruct struct {
		index   int
		element []rational.Rational
	}

	for i := initRow; i < len(m); i++ {
		max := maxStruct{-1, make([]rational.Rational, len(m[i]))}
		var firstNotIndexed int
		for k, kv := range m {
			if !indexed[k] {
				firstNotIndexed = k
				if greaterThanMax(kv, max.element) {
					max.index = k
					max.element = kv
				}
			}
		}
		if max.index != -1 {
			m2 = append(m2, max.element)
			indexed[max.index] = true
		} else {
			m2 = append(m2, m[firstNotIndexed])
			indexed[firstNotIndexed] = true
		}
	}

	return
}
<commit_msg>printing triangle matrix for testing purposes<commit_after>package gaussian

import (
	"errors"

	"github.com/alex-ant/gomath/rational"
)

// SolveGaussian solves the system of linear equations via The Gaussian Elimination.
func SolveGaussian(eqM [][]rational.Rational) (res [][]rational.Rational, err error) {
	if len(eqM) > len(eqM[0]) {
		err = errors.New("the number of equations can not be greater than the number of variables")
		return
	}

	for i := 0; i < len(eqM)-1; i++ {
		eqM = sortMatrix(eqM, i)

		var varC rational.Rational
		for k := i; k < len(eqM); k++ {
			if k == i {
				varC = eqM[k][i]
			} else {
				multipliedLine := make([]rational.Rational, len(eqM[i]))
				for z, zv := range eqM[i] {
					multipliedLine[z] = zv.Multiply(eqM[k][i].Divide(varC)).MultiplyByNum(-1)
				}
				newLine := make([]rational.Rational, len(eqM[k]))
				for z, zv := range eqM[k] {
					newLine[z] = zv.Add(multipliedLine[z])
				}
				eqM[k] = newLine
			}
		}
	}

	// Removing empty lines.
	var resultEqM [][]rational.Rational
	for i := len(eqM) - 1; i >= 0; i-- {
		if !rational.RationalsAreNull(eqM[i]) {
			resultEqM = append(resultEqM, eqM[i])
		}
	}

	firstNonZeroIndex := func(sl []rational.Rational) (index int) {
		for i, v := range sl {
			if v.GetNumerator() != 0 {
				index = i
				return
			}
		}
		return
	}

	// Back substitution.
	for z := 0; z < len(resultEqM)-1; z++ {
		var processIndex int
		var firstLine []rational.Rational
		for i := z; i < len(resultEqM); i++ {
			v := resultEqM[i]
			if i == z {
				processIndex = firstNonZeroIndex(v)
				firstLine = v
			} else {
				mult := v[processIndex].Divide(firstLine[processIndex]).MultiplyByNum(-1)
				for j, jv := range v {
					resultEqM[i][j] = firstLine[j].Multiply(mult).Add(jv)
				}
			}
		}
	}

	/*for i := len(resultEqM) - 1; i >= 0; i-- {
		var str string
		for _, jv := range resultEqM[i] {
			str += strconv.FormatFloat(jv.Float64(), 'f', 2, 64) + ","
		}
		str = str[:len(str)-1]
		fmt.Println(str)
	}*/

	// Calculating variables.
	res = make([][]rational.Rational, len(eqM[0])-1)
	if firstNonZeroIndex(resultEqM[0]) == len(resultEqM[0])-2 {
		// All the variables have been found.
		for i, iv := range resultEqM {
			index := len(res) - 1 - i
			res[index] = append(res[index], iv[len(iv)-1].Divide(iv[len(resultEqM)-1-i]))
		}
	} else {
		// Some variables remained unknown.
		var unknownStart, unknownEnd int
		for i, iv := range resultEqM {
			fnz := firstNonZeroIndex(iv)
			var firstRes []rational.Rational
			firstRes = append(firstRes, iv[len(iv)-1].Divide(iv[fnz]))
			if i == 0 {
				unknownStart = fnz + 1
				unknownEnd = len(iv) - 2
				for j := unknownEnd; j >= unknownStart; j-- {
					res[j] = []rational.Rational{rational.New(0, 0)}
					firstRes = append(firstRes, iv[j].Divide(iv[fnz]))
				}
			} else {
				for j := unknownEnd; j >= unknownStart; j-- {
					firstRes = append(firstRes, iv[j].Divide(iv[fnz]))
				}
			}
			res[fnz] = firstRes
		}
	}

	return
}

func sortMatrix(m [][]rational.Rational, initRow int) (m2 [][]rational.Rational) {
	indexed := make(map[int]bool)

	for i := 0; i < initRow; i++ {
		m2 = append(m2, m[i])
		indexed[i] = true
	}

	greaterThanMax := func(rr1, rr2 []rational.Rational) (greater bool) {
		for i := 0; i < len(rr1); i++ {
			if rr1[i].GetModule().GreaterThan(rr2[i].GetModule()) {
				greater = true
				return
			} else if rr1[i].GetModule().LessThan(rr2[i].GetModule()) {
				return
			}
		}
		return
	}

	type maxStruct struct {
		index   int
		element []rational.Rational
	}

	for i := initRow; i < len(m); i++ {
		max := maxStruct{-1, make([]rational.Rational, len(m[i]))}
		var firstNotIndexed int
		for k, kv := range m {
			if !indexed[k] {
				firstNotIndexed = k
				if greaterThanMax(kv, max.element) {
					max.index = k
					max.element = kv
				}
			}
		}
		if max.index != -1 {
			m2 = append(m2, max.element)
			indexed[max.index] = true
		} else {
			m2 = append(m2, m[firstNotIndexed])
			indexed[firstNotIndexed] = true
		}
	}

	return
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math/rand"
)

func main() {
	distance := 56000000
	speed := rand.Intn(16) + 15
	days := (distance / speed) / 86164
	//days := rand.Intn(16) + 15
	//price := days / 2
	fmt.Printf("%-18v %4v %v %7v\n", "Spaceline", "Days", "Round-trip", "Price")
	fmt.Println("===============================================")
	fmt.Println(distance / speed, days)
	/*spaceline := {
		switch rand.Intn(2) {
		case 0:
			"Virgin Galactic"
		case 1:
			"SpaceX"
		case 2:
			"Space Adventures"
		}
	}*/
	/*for count :=0; count < 10; count++ {
		fmt.Printf("%-18v %4v %v $%4v\n", spaceline, days, "Round trip", 22)
	}*/
}
<commit_msg>Cleaning things up a little, putting in empty company variable<commit_after>package main

import (
	"fmt"
	"math/rand"
)

func main() {
	distance := 57600000
	company := ""
	speed := rand.Intn(16) + 15
	days := (distance / speed) / 86164

	fmt.Printf("%-18v %4v %v %7v\n", "Spaceline", "Days", "Round-trip", "Price")
	fmt.Println("===============================================")
	fmt.Println(distance / speed, days)
	for count :=0; count < 10; count++ {

		fmt.Printf("%-18v %4v %v $%4v\n", company, days, "Round trip", 22)
	}
}
<|endoftext|>


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

package kv_test

import (
	"bytes"
	"errors"
	"fmt"
	"path/filepath"
	"sync/atomic"
	"testing"

	"golang.org/x/net/context"

	"github.com/cockroachdb/cockroach/pkg/base"
	"github.com/cockroachdb/cockroach/pkg/internal/client"
	"github.com/cockroachdb/cockroach/pkg/roachpb"
	"github.com/cockroachdb/cockroach/pkg/rpc"
	"github.com/cockroachdb/cockroach/pkg/security"
	"github.com/cockroachdb/cockroach/pkg/storage"
	"github.com/cockroachdb/cockroach/pkg/storage/engine/enginepb"
	"github.com/cockroachdb/cockroach/pkg/storage/storagebase"
	"github.com/cockroachdb/cockroach/pkg/testutils"
	"github.com/cockroachdb/cockroach/pkg/testutils/serverutils"
	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
	"github.com/cockroachdb/cockroach/pkg/util/stop"
)

func createTestClient(t *testing.T, stopper *stop.Stopper, addr string) *client.DB {
	return createTestClientForUser(t, stopper, addr, security.NodeUser)
}

func createTestClientForUser(t *testing.T, stopper *stop.Stopper, addr, user string) *client.DB {
	var ctx base.Config
	ctx.InitDefaults()
	ctx.User = user
	ctx.SSLCA = filepath.Join(security.EmbeddedCertsDir, security.EmbeddedCACert)
	ctx.SSLCert = filepath.Join(security.EmbeddedCertsDir, fmt.Sprintf("%s.crt", user))
	ctx.SSLCertKey = filepath.Join(security.EmbeddedCertsDir, fmt.Sprintf("%s.key", user))
	sender, err := client.NewSender(rpc.NewContext(context.TODO(), &ctx, nil, stopper), addr)
	if err != nil {
		t.Fatal(err)
	}
	return client.NewDB(sender)
}

// TestKVDBCoverage verifies that all methods may be invoked on the
// key value database.
func TestKVDBCoverage(t *testing.T) {
	defer leaktest.AfterTest(t)()
	s, _, _ := serverutils.StartServer(t, base.TestServerArgs{})
	defer s.Stopper().Stop()
	ctx := context.TODO()

	db := createTestClient(t, s.Stopper(), s.ServingAddr())
	key := roachpb.Key("a")
	value1 := []byte("value1")
	value2 := []byte("value2")
	value3 := []byte("value3")

	// Put first value at key.
	if pErr := db.Put(context.TODO(), key, value1); pErr != nil {
		t.Fatal(pErr)
	}

	// Verify put.
	if gr, pErr := db.Get(ctx, key); pErr != nil {
		t.Fatal(pErr)
	} else if !gr.Exists() {
		t.Error("expected key to exist")
	}

	// Conditional put should succeed, changing value1 to value2.
	if pErr := db.CPut(context.TODO(), key, value2, value1); pErr != nil {
		t.Fatal(pErr)
	}

	// Verify get by looking up conditional put value.
	if gr, pErr := db.Get(ctx, key); pErr != nil {
		t.Fatal(pErr)
	} else if !bytes.Equal(gr.ValueBytes(), value2) {
		t.Errorf("expected get to return %q; got %q", value2, gr.ValueBytes())
	}

	// Increment.
	if ir, pErr := db.Inc(ctx, "i", 10); pErr != nil {
		t.Fatal(pErr)
	} else if ir.ValueInt() != 10 {
		t.Errorf("expected increment new value of %d; got %d", 10, ir.ValueInt())
	}

	// Delete conditional put value.
	if pErr := db.Del(ctx, key); pErr != nil {
		t.Fatal(pErr)
	}
	if gr, pErr := db.Get(ctx, key); pErr != nil {
		t.Fatal(pErr)
	} else if gr.Exists() {
		t.Error("expected key to not exist after delete")
	}

	// Put values in anticipation of scan & delete range.
	keyValues := []roachpb.KeyValue{
		{Key: roachpb.Key("a"), Value: roachpb.MakeValueFromBytes(value1)},
		{Key: roachpb.Key("b"), Value: roachpb.MakeValueFromBytes(value2)},
		{Key: roachpb.Key("c"), Value: roachpb.MakeValueFromBytes(value3)},
	}
	for _, kv := range keyValues {
		valueBytes, pErr := kv.Value.GetBytes()
		if pErr != nil {
			t.Fatal(pErr)
		}
		if pErr := db.Put(context.TODO(), kv.Key, valueBytes); pErr != nil {
			t.Fatal(pErr)
		}
	}
	if rows, pErr := db.Scan(context.TODO(), "a", "d", 0); pErr != nil {
		t.Fatal(pErr)
	} else if len(rows) != len(keyValues) {
		t.Fatalf("expected %d rows in scan; got %d", len(keyValues), len(rows))
	} else {
		for i, kv := range keyValues {
			valueBytes, pErr := kv.Value.GetBytes()
			if pErr != nil {
				t.Fatal(pErr)
			}
			if !bytes.Equal(rows[i].ValueBytes(), valueBytes) {
				t.Errorf("%d: key %q, values %q != %q", i, kv.Key, rows[i].ValueBytes(), valueBytes)
			}
		}
	}

	// Test reverse scan.
	if rows, pErr := db.ReverseScan(context.TODO(), "a", "d", 0); pErr != nil {
		t.Fatal(pErr)
	} else if len(rows) != len(keyValues) {
		t.Fatalf("expected %d rows in scan; got %d", len(keyValues), len(rows))
	} else {
		for i, kv := range keyValues {
			valueBytes, pErr := kv.Value.GetBytes()
			if pErr != nil {
				t.Fatal(pErr)
			}
			if !bytes.Equal(rows[len(keyValues)-1-i].ValueBytes(), valueBytes) {
				t.Errorf("%d: key %q, values %q != %q", i, kv.Key, rows[len(keyValues)-i].ValueBytes(), valueBytes)
			}
		}
	}

	if pErr := db.DelRange(context.TODO(), "a", "c"); pErr != nil {
		t.Fatal(pErr)
	}
}

func TestKVDBInternalMethods(t *testing.T) {
	defer leaktest.AfterTest(t)()
	s, _, _ := serverutils.StartServer(t, base.TestServerArgs{})
	defer s.Stopper().Stop()

	testCases := []roachpb.Request{
		&roachpb.HeartbeatTxnRequest{},
		&roachpb.GCRequest{},
		&roachpb.PushTxnRequest{},
		&roachpb.ResolveIntentRequest{},
		&roachpb.ResolveIntentRangeRequest{},
		&roachpb.MergeRequest{},
		&roachpb.TruncateLogRequest{},
		&roachpb.RequestLeaseRequest{},

		&roachpb.EndTransactionRequest{
			InternalCommitTrigger: &roachpb.InternalCommitTrigger{},
		},
	}
	// Verify internal methods experience bad request errors.
	db := createTestClient(t, s.Stopper(), s.ServingAddr())
	for i, args := range testCases {
		{
			header := args.Header()
			header.Key = roachpb.Key("a")
			args.SetHeader(header)
		}
		if roachpb.IsRange(args) {
			header := args.Header()
			header.EndKey = args.Header().Key.Next()
			args.SetHeader(header)
		}
		b := &client.Batch{}
		b.AddRawRequest(args)
		err := db.Run(context.TODO(), b)
		if !testutils.IsError(err, "contains an internal request|contains commit trigger") {
			t.Errorf("%d: unexpected error for %s: %v", i, args.Method(), err)
		}
	}
}

// TestKVDBTransaction verifies that transactions work properly over
// the KV DB endpoint.
func TestKVDBTransaction(t *testing.T) {
	defer leaktest.AfterTest(t)()
	s, _, _ := serverutils.StartServer(t, base.TestServerArgs{})
	defer s.Stopper().Stop()

	db := createTestClient(t, s.Stopper(), s.ServingAddr())

	key := roachpb.Key("db-txn-test")
	value := []byte("value")
	err := db.Txn(context.TODO(), func(txn *client.Txn) error {
		// Use snapshot isolation so non-transactional read can always push.
		if err := txn.SetIsolation(enginepb.SNAPSHOT); err != nil {
			return err
		}

		if err := txn.Put(key, value); err != nil {
			t.Fatal(err)
		}

		// Attempt to read outside of txn.
		if gr, err := db.Get(context.TODO(), key); err != nil {
			t.Fatal(err)
		} else if gr.Exists() {
			t.Errorf("expected nil value; got %+v", gr.Value)
		}

		// Read within the transaction.
		if gr, err := txn.Get(key); err != nil {
			t.Fatal(err)
		} else if !gr.Exists() || !bytes.Equal(gr.ValueBytes(), value) {
			t.Errorf("expected value %q; got %q", value, gr.ValueBytes())
		}
		return nil
	})
	if err != nil {
		t.Errorf("expected success on commit; got %s", err)
	}

	// Verify the value is now visible after commit.
	if gr, err := db.Get(context.TODO(), key); err != nil {
		t.Errorf("expected success reading value; got %s", err)
	} else if !gr.Exists() || !bytes.Equal(gr.ValueBytes(), value) {
		t.Errorf("expected value %q; got %q", value, gr.ValueBytes())
	}
}

// TestAuthentication tests authentication for the KV endpoint.
func TestAuthentication(t *testing.T) {
	defer leaktest.AfterTest(t)()
	s, _, _ := serverutils.StartServer(t, base.TestServerArgs{})
	defer s.Stopper().Stop()

	b1 := &client.Batch{}
	b1.Put("a", "b")

	// Create a node user client and call Run() on it which lets us build our own
	// request, specifying the user.
	db1 := createTestClientForUser(t, s.Stopper(), s.ServingAddr(), security.NodeUser)
	if err := db1.Run(context.TODO(), b1); err != nil {
		t.Fatal(err)
	}

	b2 := &client.Batch{}
	b2.Put("c", "d")

	// Try again, but this time with certs for a non-node user (even the root
	// user has no KV permissions).
	db2 := createTestClientForUser(t, s.Stopper(), s.ServingAddr(), security.RootUser)
	if err := db2.Run(context.TODO(), b2); !testutils.IsError(err, "is not allowed") {
		t.Fatal(err)
	}
}

// TestTxnDelRangeIntentResolutionCounts ensures that intents left behind by a
// DelRange with a MaxSpanRequestKeys limit are resolved correctly and by
// using the minimal span of keys.
func TestTxnDelRangeIntentResolutionCounts(t *testing.T) {
	defer leaktest.AfterTest(t)()
	var intentResolutionCount int64
	var resolveIntentCount int64
	params := base.TestServerArgs{
		Knobs: base.TestingKnobs{
			Store: &storage.StoreTestingKnobs{
				NumKeysEvaluatedForRangeIntentResolution: &intentResolutionCount,
				TestingCommandFilter: func(filterArgs storagebase.FilterArgs) *roachpb.Error {
					_, ok := filterArgs.Req.(*roachpb.ResolveIntentRequest)
					if ok {
						atomic.AddInt64(&resolveIntentCount, 1)
					}
					return nil
				},
			},
		},
	}
	s, _, db := serverutils.StartServer(t, params)
	defer s.Stopper().Stop()

	for _, abortTxn := range []bool{false, true} {
		spanSize := int64(10)
		prefixes := []string{"a", "b", "c"}
		for i := int64(0); i < spanSize; i++ {
			for _, prefix := range prefixes {
				if err := db.Put(context.TODO(), fmt.Sprintf("%s%d", prefix, i), "v"); err != nil {
					t.Fatal(err)
				}
			}
		}
		totalNumKeys := int64(len(prefixes)) * spanSize

		atomic.StoreInt64(&intentResolutionCount, 0)
		limit := totalNumKeys / 2
		if err := db.Txn(context.TODO(), func(txn *client.Txn) error {
			var b client.Batch
			// Fully deleted.
			b.DelRange("a", "b", false)
			// Partially deleted.
			b.DelRange("b", "c", false)
			// Not deleted.
			b.DelRange("c", "d", false)
			b.Header.MaxSpanRequestKeys = limit
			if err := txn.Run(&b); err != nil {
				return err
			}
			if abortTxn {
				return errors.New("aborting txn")
			}
			return nil
		}); err != nil && !abortTxn {
			t.Fatal(err)
		}

		// Ensure that the correct number of keys were evaluated for intents.
		if numKeys := atomic.LoadInt64(&intentResolutionCount); numKeys != limit {
			t.Fatalf("abortTxn: %v, resolved %d keys, expected %d", abortTxn, numKeys, limit)
		}

		// Ensure no intents are left behind. Scan the entire span to resolve
		// any intents that were left behind.
		atomic.StoreInt64(&resolveIntentCount, 0)
		kvs, err := db.Scan(context.TODO(), "a", "d", totalNumKeys)
		if err != nil {
			t.Fatal(err)
		}
		if c := atomic.LoadInt64(&resolveIntentCount); c != 0 {
			t.Errorf("abortTxn: %v, %d intents left over", abortTxn, c)
		}
		expectedNumKeys := totalNumKeys / 2
		if abortTxn {
			expectedNumKeys = totalNumKeys
		}
		if int64(len(kvs)) != expectedNumKeys {
			t.Errorf("abortTxn: %v, %d keys left behind, expected=%d",
				abortTxn, len(kvs), expectedNumKeys)
		}
	}
}
<commit_msg>kv: fix TestTxnDelRangeIntentResolutionCounts<commit_after>// Copyright 2014 The Cockroach Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
//
// Author: Spencer Kimball (spencer.kimball@gmail.com)

package kv_test

import (
	"bytes"
	"errors"
	"fmt"
	"path/filepath"
	"sync/atomic"
	"testing"

	"golang.org/x/net/context"

	"github.com/cockroachdb/cockroach/pkg/base"
	"github.com/cockroachdb/cockroach/pkg/internal/client"
	"github.com/cockroachdb/cockroach/pkg/roachpb"
	"github.com/cockroachdb/cockroach/pkg/rpc"
	"github.com/cockroachdb/cockroach/pkg/security"
	"github.com/cockroachdb/cockroach/pkg/storage"
	"github.com/cockroachdb/cockroach/pkg/storage/engine/enginepb"
	"github.com/cockroachdb/cockroach/pkg/storage/storagebase"
	"github.com/cockroachdb/cockroach/pkg/testutils"
	"github.com/cockroachdb/cockroach/pkg/testutils/serverutils"
	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
	"github.com/cockroachdb/cockroach/pkg/util/stop"
)

func createTestClient(t *testing.T, stopper *stop.Stopper, addr string) *client.DB {
	return createTestClientForUser(t, stopper, addr, security.NodeUser)
}

func createTestClientForUser(t *testing.T, stopper *stop.Stopper, addr, user string) *client.DB {
	var ctx base.Config
	ctx.InitDefaults()
	ctx.User = user
	ctx.SSLCA = filepath.Join(security.EmbeddedCertsDir, security.EmbeddedCACert)
	ctx.SSLCert = filepath.Join(security.EmbeddedCertsDir, fmt.Sprintf("%s.crt", user))
	ctx.SSLCertKey = filepath.Join(security.EmbeddedCertsDir, fmt.Sprintf("%s.key", user))
	sender, err := client.NewSender(rpc.NewContext(context.TODO(), &ctx, nil, stopper), addr)
	if err != nil {
		t.Fatal(err)
	}
	return client.NewDB(sender)
}

// TestKVDBCoverage verifies that all methods may be invoked on the
// key value database.
func TestKVDBCoverage(t *testing.T) {
	defer leaktest.AfterTest(t)()
	s, _, _ := serverutils.StartServer(t, base.TestServerArgs{})
	defer s.Stopper().Stop()
	ctx := context.TODO()

	db := createTestClient(t, s.Stopper(), s.ServingAddr())
	key := roachpb.Key("a")
	value1 := []byte("value1")
	value2 := []byte("value2")
	value3 := []byte("value3")

	// Put first value at key.
	if pErr := db.Put(context.TODO(), key, value1); pErr != nil {
		t.Fatal(pErr)
	}

	// Verify put.
	if gr, pErr := db.Get(ctx, key); pErr != nil {
		t.Fatal(pErr)
	} else if !gr.Exists() {
		t.Error("expected key to exist")
	}

	// Conditional put should succeed, changing value1 to value2.
	if pErr := db.CPut(context.TODO(), key, value2, value1); pErr != nil {
		t.Fatal(pErr)
	}

	// Verify get by looking up conditional put value.
	if gr, pErr := db.Get(ctx, key); pErr != nil {
		t.Fatal(pErr)
	} else if !bytes.Equal(gr.ValueBytes(), value2) {
		t.Errorf("expected get to return %q; got %q", value2, gr.ValueBytes())
	}

	// Increment.
	if ir, pErr := db.Inc(ctx, "i", 10); pErr != nil {
		t.Fatal(pErr)
	} else if ir.ValueInt() != 10 {
		t.Errorf("expected increment new value of %d; got %d", 10, ir.ValueInt())
	}

	// Delete conditional put value.
	if pErr := db.Del(ctx, key); pErr != nil {
		t.Fatal(pErr)
	}
	if gr, pErr := db.Get(ctx, key); pErr != nil {
		t.Fatal(pErr)
	} else if gr.Exists() {
		t.Error("expected key to not exist after delete")
	}

	// Put values in anticipation of scan & delete range.
	keyValues := []roachpb.KeyValue{
		{Key: roachpb.Key("a"), Value: roachpb.MakeValueFromBytes(value1)},
		{Key: roachpb.Key("b"), Value: roachpb.MakeValueFromBytes(value2)},
		{Key: roachpb.Key("c"), Value: roachpb.MakeValueFromBytes(value3)},
	}
	for _, kv := range keyValues {
		valueBytes, pErr := kv.Value.GetBytes()
		if pErr != nil {
			t.Fatal(pErr)
		}
		if pErr := db.Put(context.TODO(), kv.Key, valueBytes); pErr != nil {
			t.Fatal(pErr)
		}
	}
	if rows, pErr := db.Scan(context.TODO(), "a", "d", 0); pErr != nil {
		t.Fatal(pErr)
	} else if len(rows) != len(keyValues) {
		t.Fatalf("expected %d rows in scan; got %d", len(keyValues), len(rows))
	} else {
		for i, kv := range keyValues {
			valueBytes, pErr := kv.Value.GetBytes()
			if pErr != nil {
				t.Fatal(pErr)
			}
			if !bytes.Equal(rows[i].ValueBytes(), valueBytes) {
				t.Errorf("%d: key %q, values %q != %q", i, kv.Key, rows[i].ValueBytes(), valueBytes)
			}
		}
	}

	// Test reverse scan.
	if rows, pErr := db.ReverseScan(context.TODO(), "a", "d", 0); pErr != nil {
		t.Fatal(pErr)
	} else if len(rows) != len(keyValues) {
		t.Fatalf("expected %d rows in scan; got %d", len(keyValues), len(rows))
	} else {
		for i, kv := range keyValues {
			valueBytes, pErr := kv.Value.GetBytes()
			if pErr != nil {
				t.Fatal(pErr)
			}
			if !bytes.Equal(rows[len(keyValues)-1-i].ValueBytes(), valueBytes) {
				t.Errorf("%d: key %q, values %q != %q", i, kv.Key, rows[len(keyValues)-i].ValueBytes(), valueBytes)
			}
		}
	}

	if pErr := db.DelRange(context.TODO(), "a", "c"); pErr != nil {
		t.Fatal(pErr)
	}
}

func TestKVDBInternalMethods(t *testing.T) {
	defer leaktest.AfterTest(t)()
	s, _, _ := serverutils.StartServer(t, base.TestServerArgs{})
	defer s.Stopper().Stop()

	testCases := []roachpb.Request{
		&roachpb.HeartbeatTxnRequest{},
		&roachpb.GCRequest{},
		&roachpb.PushTxnRequest{},
		&roachpb.ResolveIntentRequest{},
		&roachpb.ResolveIntentRangeRequest{},
		&roachpb.MergeRequest{},
		&roachpb.TruncateLogRequest{},
		&roachpb.RequestLeaseRequest{},

		&roachpb.EndTransactionRequest{
			InternalCommitTrigger: &roachpb.InternalCommitTrigger{},
		},
	}
	// Verify internal methods experience bad request errors.
	db := createTestClient(t, s.Stopper(), s.ServingAddr())
	for i, args := range testCases {
		{
			header := args.Header()
			header.Key = roachpb.Key("a")
			args.SetHeader(header)
		}
		if roachpb.IsRange(args) {
			header := args.Header()
			header.EndKey = args.Header().Key.Next()
			args.SetHeader(header)
		}
		b := &client.Batch{}
		b.AddRawRequest(args)
		err := db.Run(context.TODO(), b)
		if !testutils.IsError(err, "contains an internal request|contains commit trigger") {
			t.Errorf("%d: unexpected error for %s: %v", i, args.Method(), err)
		}
	}
}

// TestKVDBTransaction verifies that transactions work properly over
// the KV DB endpoint.
func TestKVDBTransaction(t *testing.T) {
	defer leaktest.AfterTest(t)()
	s, _, _ := serverutils.StartServer(t, base.TestServerArgs{})
	defer s.Stopper().Stop()

	db := createTestClient(t, s.Stopper(), s.ServingAddr())

	key := roachpb.Key("db-txn-test")
	value := []byte("value")
	err := db.Txn(context.TODO(), func(txn *client.Txn) error {
		// Use snapshot isolation so non-transactional read can always push.
		if err := txn.SetIsolation(enginepb.SNAPSHOT); err != nil {
			return err
		}

		if err := txn.Put(key, value); err != nil {
			t.Fatal(err)
		}

		// Attempt to read outside of txn.
		if gr, err := db.Get(context.TODO(), key); err != nil {
			t.Fatal(err)
		} else if gr.Exists() {
			t.Errorf("expected nil value; got %+v", gr.Value)
		}

		// Read within the transaction.
		if gr, err := txn.Get(key); err != nil {
			t.Fatal(err)
		} else if !gr.Exists() || !bytes.Equal(gr.ValueBytes(), value) {
			t.Errorf("expected value %q; got %q", value, gr.ValueBytes())
		}
		return nil
	})
	if err != nil {
		t.Errorf("expected success on commit; got %s", err)
	}

	// Verify the value is now visible after commit.
	if gr, err := db.Get(context.TODO(), key); err != nil {
		t.Errorf("expected success reading value; got %s", err)
	} else if !gr.Exists() || !bytes.Equal(gr.ValueBytes(), value) {
		t.Errorf("expected value %q; got %q", value, gr.ValueBytes())
	}
}

// TestAuthentication tests authentication for the KV endpoint.
func TestAuthentication(t *testing.T) {
	defer leaktest.AfterTest(t)()
	s, _, _ := serverutils.StartServer(t, base.TestServerArgs{})
	defer s.Stopper().Stop()

	b1 := &client.Batch{}
	b1.Put("a", "b")

	// Create a node user client and call Run() on it which lets us build our own
	// request, specifying the user.
	db1 := createTestClientForUser(t, s.Stopper(), s.ServingAddr(), security.NodeUser)
	if err := db1.Run(context.TODO(), b1); err != nil {
		t.Fatal(err)
	}

	b2 := &client.Batch{}
	b2.Put("c", "d")

	// Try again, but this time with certs for a non-node user (even the root
	// user has no KV permissions).
	db2 := createTestClientForUser(t, s.Stopper(), s.ServingAddr(), security.RootUser)
	if err := db2.Run(context.TODO(), b2); !testutils.IsError(err, "is not allowed") {
		t.Fatal(err)
	}
}

// TestTxnDelRangeIntentResolutionCounts ensures that intents left behind by a
// DelRange with a MaxSpanRequestKeys limit are resolved correctly and by
// using the minimal span of keys.
func TestTxnDelRangeIntentResolutionCounts(t *testing.T) {
	defer leaktest.AfterTest(t)()
	var intentResolutionCount int64
	params := base.TestServerArgs{
		Knobs: base.TestingKnobs{
			Store: &storage.StoreTestingKnobs{
				NumKeysEvaluatedForRangeIntentResolution: &intentResolutionCount,
				TestingCommandFilter: func(filterArgs storagebase.FilterArgs) *roachpb.Error {
					req, ok := filterArgs.Req.(*roachpb.ResolveIntentRequest)
					if ok {
						key := req.Header().Key.String()
						// Check if the intent is from the range being
						// scanned below.
						if key >= "a" && key < "d" {
							t.Errorf("resolving intent on key %s", key)
						}
					}
					return nil
				},
			},
		},
	}
	s, _, db := serverutils.StartServer(t, params)
	defer s.Stopper().Stop()

	for _, abortTxn := range []bool{false, true} {
		spanSize := int64(10)
		prefixes := []string{"a", "b", "c"}
		for i := int64(0); i < spanSize; i++ {
			for _, prefix := range prefixes {
				if err := db.Put(context.TODO(), fmt.Sprintf("%s%d", prefix, i), "v"); err != nil {
					t.Fatal(err)
				}
			}
		}
		totalNumKeys := int64(len(prefixes)) * spanSize

		atomic.StoreInt64(&intentResolutionCount, 0)
		limit := totalNumKeys / 2
		if err := db.Txn(context.TODO(), func(txn *client.Txn) error {
			var b client.Batch
			// Fully deleted.
			b.DelRange("a", "b", false)
			// Partially deleted.
			b.DelRange("b", "c", false)
			// Not deleted.
			b.DelRange("c", "d", false)
			b.Header.MaxSpanRequestKeys = limit
			if err := txn.Run(&b); err != nil {
				return err
			}
			if abortTxn {
				return errors.New("aborting txn")
			}
			return nil
		}); err != nil && !abortTxn {
			t.Fatal(err)
		}

		// Ensure that the correct number of keys were evaluated for intents.
		if numKeys := atomic.LoadInt64(&intentResolutionCount); numKeys != limit {
			t.Fatalf("abortTxn: %v, resolved %d keys, expected %d", abortTxn, numKeys, limit)
		}

		// Ensure no intents are left behind. Scan the entire span to resolve
		// any intents that were left behind; intents are resolved internally
		// through ResolveIntentRequest(s).
		kvs, err := db.Scan(context.TODO(), "a", "d", totalNumKeys)
		if err != nil {
			t.Fatal(err)
		}
		expectedNumKeys := totalNumKeys / 2
		if abortTxn {
			expectedNumKeys = totalNumKeys
		}
		if int64(len(kvs)) != expectedNumKeys {
			t.Errorf("abortTxn: %v, %d keys left behind, expected=%d",
				abortTxn, len(kvs), expectedNumKeys)
		}
	}
}
<|endoftext|>


<commit_before>// Package plugin introduces plugins for Aptomi engine, which are responsible for component instantiation
// and management on different cloud providers (e.g. deployment plugin, such as k8s/helm) and also configuration of
// underlying cloud infrastructure components (e.g. istio plugin).
package plugin
<commit_msg>Better package doc for plugins<commit_after>// Package plugin introduces plugins for Aptomi engine such as cluster (kubernetes) and code (helm) plugins.
//
// Cluster plugins responsible for working with different cloud providers, such as kubernetes. Separated instance of
// the cluster plugins is created for each lang.Cluster, so, it could safely cache data.
//
// Code plugins responsible for handling deployment into the cloud providers, such as helm. Separated instance of the
// code plugin is created for each pair of the lang.Cluster and code type, for example, cluster "test-1" and code
// type "helm".
//
// PostProcess plugins has access to all data across all cloud providers and executed as a last step.
//
// All plugins created for single enforcement cycle or API call using plugin registry.
package plugin
<|endoftext|>


<commit_before>package sync

import (
	"strings"

	"github.com/pkg/errors"
)

// Apply applies a series of changes to a base entry. This function ignores the
// Old value for changes and it assumes all changes are valid to apply against
// the base.
func Apply(base *Entry, changes []*Change) (*Entry, error) {
	// Create a mutable copy of base.
	result := base.Copy()

	// Apply changes.
	for _, c := range changes {
		// Handle the special case of a root path.
		if c.Path == "" {
			result = c.New
			continue
		}

		// Crawl down the tree until there is only one component remaining - the
		// parent of the target location.
		parent := result
		components := strings.Split(c.Path, "/")
		for len(components) > 1 {
			child, ok := parent.Contents[components[0]]
			if !ok {
				return nil, errors.New("unable to resolve parent path")
			}
			parent = child
			components = components[1:]
		}

		// Depending on the new value, either set or remove the entry.
		if c.New == nil {
			delete(parent.Contents, components[0])
		} else {
			if parent.Contents == nil {
				parent.Contents = make(map[string]*Entry)
			}
			parent.Contents[components[0]] = c.New
		}
	}

	// Done.
	return result, nil
}
<commit_msg>Clarified confusing/misleading comment in sync.Apply code.<commit_after>package sync

import (
	"strings"

	"github.com/pkg/errors"
)

// Apply applies a series of changes to a base entry. This function ignores the
// Old value for changes and it assumes all changes are valid to apply against
// the base.
func Apply(base *Entry, changes []*Change) (*Entry, error) {
	// Create a mutable copy of base.
	result := base.Copy()

	// Apply changes.
	for _, c := range changes {
		// Handle the special case of a root path.
		if c.Path == "" {
			result = c.New
			continue
		}

		// Crawl down the tree until we reach the parent of the target location.
		parent := result
		components := strings.Split(c.Path, "/")
		for len(components) > 1 {
			child, ok := parent.Contents[components[0]]
			if !ok {
				return nil, errors.New("unable to resolve parent path")
			}
			parent = child
			components = components[1:]
		}

		// Depending on the new value, either set or remove the entry.
		if c.New == nil {
			delete(parent.Contents, components[0])
		} else {
			if parent.Contents == nil {
				parent.Contents = make(map[string]*Entry)
			}
			parent.Contents[components[0]] = c.New
		}
	}

	// Done.
	return result, nil
}
<|endoftext|>