<commit_before>// Copyright (C) 2015 Nippon Telegraph and Telephone Corporation.
//
// 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 main

import (
	// "encoding/gob"
	"fmt"
	"os"

	// . "../equtils"

	"github.com/mitchellh/cli"
)

const (
	storageConfigPath string = "config.json"
)

func _init(args []string) {
	if len(args) != 2 {
		fmt.Printf("specify <config file path> <storage dir path>\n")
		os.Exit(1)
	}

	conf := args[0]
	storage := args[1]

	cfi, cerr := os.Stat(conf)
	if cerr != nil {
		fmt.Printf("failed to stat path: %s (%s)\n", conf, cerr)
		os.Exit(1)
	}

	if !cfi.Mode().IsRegular() {
		fmt.Printf("config file (%s) must be a regular file\n", conf)
		os.Exit(1)
	}

	sfi, serr := os.Stat(storage)
	if serr != nil {
		fmt.Printf("failed to stat path: %s (%s)\n", storage, serr)
		os.Exit(1)
	}

	if !sfi.Mode().IsDir() {
		fmt.Printf("storage directory (%s) must be a directory\n", storage)
		os.Exit(1)
	}

	dir, derr := os.Open(storage)
	if derr != nil {
		fmt.Printf("failed to open storage directory: %s (%s)\n", storage, derr)
		os.Exit(1)
	}

	fi, rderr := dir.Readdir(0)
	if rderr != nil {
		fmt.Printf("failed to read storage directory: %s (%s)\n", storage, rderr)
		os.Exit(1)
	}

	if len(fi) != 0 {
		fmt.Printf("directory for earthquake storage (%s) must be empty\n", storage)
		os.Exit(1)
	}

	lerr := os.Link(conf, storage + "/" + storageConfigPath)
	if lerr != nil {
		fmt.Printf("creating link of config file (%s) failed (%s)\n", conf, lerr)
		os.Exit(1)
	}

	fmt.Printf("ok\n")
}

type initCmd struct {
}

func (cmd initCmd) Help() string {
	return "init help (todo)"
}

func (cmd initCmd) Run(args []string) int {
	_init(args)
	return 0
}

func (cmd initCmd) Synopsis() string {
	return "init subcommand"
}

func initCommandFactory() (cli.Command, error) {
	return initCmd{}, nil
}
<commit_msg>init: hardlinks for materials e.g. scripts for test run<commit_after>// Copyright (C) 2015 Nippon Telegraph and Telephone Corporation.
//
// 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 main

import (
	// "encoding/gob"
	"fmt"
	"os"

	// . "../equtils"

	"github.com/mitchellh/cli"
)

const (
	storageConfigPath    string = "config.json"
	storageMaterialsPath string = "materials"
)

func recursiveHardLink(srcPath, dstPath string) {
	f, oerr := os.Open(srcPath)
	if oerr != nil {
		fmt.Printf("failed to open source path: %s (%s)\n",
			srcPath, oerr)
		os.Exit(1)
	}

	names, rerr := f.Readdirnames(0)
	if rerr != nil {
		fmt.Printf("failed to readdirnames: %s\n", rerr)
		os.Exit(1)
	}

	for _, name := range names {
		path := srcPath + "/" + name

		fi, serr := os.Stat(path)
		if serr != nil {
			fmt.Printf("failed to stat (%s): %s", path, serr)
			os.Exit(1)
		}

		if fi.Mode().IsDir() {
			dstDir := dstPath + "/" + name
			merr := os.Mkdir(dstDir, 0777)
			if merr != nil {
				fmt.Printf("failed to make directory %s: %s\n",
					dstDir, merr)
				os.Exit(1)
			}
			recursiveHardLink(path, dstDir)
		} else {
			lerr := os.Link(path, dstPath + "/" + name)
			if lerr != nil {
				fmt.Printf("failed to link (src: %s, dst: %s): %s\n",
					path, dstPath + "/" + name, lerr)
				os.Exit(1)
			}
		}
	}

}

func _init(args []string) {
	if len(args) != 3 {
		fmt.Printf("specify <config file path> <materials dir path> <storage dir path>\n")
		os.Exit(1)
	}

	conf := args[0]
	materials := args[1]
	storage := args[2]

	cfi, cerr := os.Stat(conf)
	if cerr != nil {
		fmt.Printf("failed to stat path: %s (%s)\n", conf, cerr)
		os.Exit(1)
	}

	if !cfi.Mode().IsRegular() {
		fmt.Printf("config file (%s) must be a regular file\n", conf)
		os.Exit(1)
	}

	sfi, serr := os.Stat(storage)
	if serr != nil {
		fmt.Printf("failed to stat path: %s (%s)\n", storage, serr)
		os.Exit(1)
	}

	if !sfi.Mode().IsDir() {
		fmt.Printf("storage directory (%s) must be a directory\n", storage)
		os.Exit(1)
	}

	dir, derr := os.Open(storage)
	if derr != nil {
		fmt.Printf("failed to open storage directory: %s (%s)\n", storage, derr)
		os.Exit(1)
	}

	fi, rderr := dir.Readdir(0)
	if rderr != nil {
		fmt.Printf("failed to read storage directory: %s (%s)\n", storage, rderr)
		os.Exit(1)
	}

	if len(fi) != 0 {
		fmt.Printf("directory for earthquake storage (%s) must be empty\n", storage)
		os.Exit(1)
	}

	lerr := os.Link(conf, storage+"/"+storageConfigPath)
	if lerr != nil {
		fmt.Printf("creating link of config file (%s) failed (%s)\n", conf, lerr)
		os.Exit(1)
	}

	materialDir := storage + "/" + storageMaterialsPath
	derr = os.Mkdir(materialDir, 0777)
	if derr != nil {
		fmt.Printf("creating a directory for materials (%s) failed (%s)\n",
			storage + "/" + storageMaterialsPath, derr)
		os.Exit(1)
		// TODO: cleaning conf file
	}

	recursiveHardLink(materials, materialDir)
	fmt.Printf("ok\n")
}

type initCmd struct {
}

func (cmd initCmd) Help() string {
	return "init help (todo)"
}

func (cmd initCmd) Run(args []string) int {
	_init(args)
	return 0
}

func (cmd initCmd) Synopsis() string {
	return "init subcommand"
}

func initCommandFactory() (cli.Command, error) {
	return initCmd{}, nil
}
<|endoftext|>


<commit_before>package handler

import (
	"fmt"
	"io"
	"os"
	"strings"
	"sync"

	"github.com/codegangsta/cli"
	"github.com/jrperritt/rack/auth"
	"github.com/jrperritt/rack/output"
	"github.com/jrperritt/rack/util"
	"github.com/rackspace/gophercloud"
)

// Command is the type that commands have.
type Command struct {
	Ctx *Context
}

// Context is a global context that `rack` uses.
type Context struct {
	// CLIContext is the context that the `cli` library uses. `rack` uses it to
	// access flags.
	CLIContext *cli.Context
	// ServiceClient is the Rackspace service client used to authenticate the user
	// and carry out the requests while processing the command.
	ServiceClient *gophercloud.ServiceClient
	// ServiceClientType is the type of Rackspace service client used (e.g. compute).
	ServiceClientType string
	// WaitGroup is used for synchronizing output.
	WaitGroup *sync.WaitGroup
	// Results is a channel into which commands send results. It allows for streaming
	// output.
	Results chan *Resource
}

// ListenAndReceive creates the Results channel and processes the results that
// come through it before sending them on to `Print`. It is run in a separate
// goroutine from `main`.
func (ctx *Context) ListenAndReceive() {
	ctx.Results = make(chan *Resource)
	go func() {
		for {
			select {
			case resource, ok := <-ctx.Results:
				if !ok {
					ctx.Results = nil
					continue
				}
				if resource.Err != nil {
					resource.Keys = []string{"error"}
					resource.Result = map[string]interface{}{"error": resource.Err.Error()}
					ctx.CLIContext.App.Writer = os.Stderr
				}
				ctx.Print(resource)
				if resource.ErrExit1 {
					os.Exit(1)
				}
			}
		}
	}()
}

// Print returns the output to the user
func (ctx *Context) Print(resource *Resource) {
	defer ctx.WaitGroup.Done()

	// limit the returned fields if any were given in the `fields` flag
	keys := ctx.limitFields(resource)
	w := ctx.CLIContext.App.Writer
	if ctx.CLIContext.GlobalIsSet("json") || ctx.CLIContext.IsSet("json") {
		switch resource.Result.(type) {
		case map[string]interface{}:
			m := resource.Result.(map[string]interface{})
			output.MetadataJSON(w, m, keys)
		case []map[string]interface{}:
			m := resource.Result.([]map[string]interface{})
			output.ListJSON(w, m, keys)
		case io.Reader:
			if _, ok := resource.Result.(io.ReadCloser); ok {
				defer resource.Result.(io.ReadCloser).Close()
			}
			_, err := io.Copy(w, resource.Result.(io.Reader))
			if err != nil {
				fmt.Fprintf(os.Stderr, "Error copying (io.Reader) result: %s\n", err)
			}
		default:
			output.DefaultJSON(w, resource.Result)
		}
	} else if ctx.CLIContext.GlobalIsSet("csv") || ctx.CLIContext.GlobalIsSet("csv") {
		switch resource.Result.(type) {
		case map[string]interface{}:
			m := resource.Result.(map[string]interface{})
			output.MetadataCSV(w, m, keys)
		case []map[string]interface{}:
			m := resource.Result.([]map[string]interface{})
			output.ListCSV(w, m, keys)
		case io.Reader:
			if _, ok := resource.Result.(io.ReadCloser); ok {
				defer resource.Result.(io.ReadCloser).Close()
			}
			_, err := io.Copy(w, resource.Result.(io.Reader))
			if err != nil {
				fmt.Fprintf(os.Stderr, "Error copying (io.Reader) result: %s\n", err)
			}
		default:
			fmt.Fprintf(w, "%v", resource.Result)
		}
	} else {
		switch resource.Result.(type) {
		case map[string]interface{}:
			m := resource.Result.(map[string]interface{})
			output.MetadataTable(w, m, keys)
		case []map[string]interface{}:
			m := resource.Result.([]map[string]interface{})
			output.ListTable(w, m, keys)
		case io.Reader:
			if _, ok := resource.Result.(io.ReadCloser); ok {
				defer resource.Result.(io.ReadCloser).Close()
			}
			_, err := io.Copy(w, resource.Result.(io.Reader))
			if err != nil {
				fmt.Fprintf(os.Stderr, "Error copying (io.Reader) result: %s\n", err)
			}
		default:
			fmt.Fprintf(w, "%v", resource.Result)
		}
	}
}

// limitFields returns only the fields the user specified in the `fields` flag. If
// the flag wasn't provided, all fields are returned.
func (ctx *Context) limitFields(resource *Resource) []string {
	if ctx.CLIContext.IsSet("fields") {
		fields := strings.Split(strings.ToLower(ctx.CLIContext.String("fields")), ",")
		newKeys := []string{}
		for _, key := range resource.Keys {
			if util.Contains(fields, strings.Join(strings.Split(strings.ToLower(key), " "), "-")) {
				newKeys = append(newKeys, key)
			}
		}
		return newKeys
	}
	return resource.Keys
}

// StoreCredentials caches the users auth credentials if available and the `no-cache`
// flag was not provided.
func (ctx *Context) StoreCredentials() {
	// if serviceClient is nil, the HTTP request for the command didn't get sent.
	// don't set cache if the `no-cache` flag is provided
	if ctx.ServiceClient != nil && !ctx.CLIContext.GlobalIsSet("no-cache") && !ctx.CLIContext.IsSet("no-cache") {
		newCacheValue := &auth.CacheItem{
			TokenID:         ctx.ServiceClient.TokenID,
			ServiceEndpoint: ctx.ServiceClient.Endpoint,
		}
		// get auth credentials
		ao, region, err := auth.Credentials(ctx.CLIContext)
		if err == nil {
			// form the cache key
			cacheKey := auth.CacheKey(*ao, region, ctx.ServiceClientType)
			// initialize the cache
			cache := &auth.Cache{}
			// set the cache value to the current values
			_ = cache.SetValue(cacheKey, newCacheValue)
		}
	}
}

// ErrExit1 tells `rack` to print the error and exit.
func (ctx *Context) ErrExit1(resource *Resource) {
	resource.ErrExit1 = true
	ctx.WaitGroup.Add(1)
	ctx.Results <- resource
	ctx.WaitGroup.Wait()
}

// IDOrName is a function for retrieving a resources unique identifier based on
// whether he or she passed an `id` or a `name` flag.
func (ctx *Context) IDOrName(idFromNameFunc func(*gophercloud.ServiceClient, string) (string, error)) (string, error) {
	if ctx.CLIContext.IsSet("id") {
		if ctx.CLIContext.IsSet("name") {
			return "", fmt.Errorf("Only one of either --id or --name may be provided.")
		}
		return ctx.CLIContext.String("id"), nil
	} else if ctx.CLIContext.IsSet("name") {
		name := ctx.CLIContext.String("name")
		id, err := idFromNameFunc(ctx.ServiceClient, name)
		if err != nil {
			return "", fmt.Errorf("Error converting name [%s] to ID: %s", name, err)
		}
		return id, nil
	} else {
		return "", output.ErrMissingFlag{"One of either --id or --name must be provided."}
	}
}

// CheckArgNum checks that the provided number of arguments has the same
// cardinality as the expected number of arguments.
func (ctx *Context) CheckArgNum(expected int) error {
	argsLen := len(ctx.CLIContext.Args())
	if argsLen != expected {
		return fmt.Errorf("Expected %d args but got %d\nUsage: %s", expected, argsLen, ctx.CLIContext.Command.Usage)
	}
	return nil
}

// CheckFlagsSet checks that the given flag names are set for the command.
func (ctx *Context) CheckFlagsSet(flagNames []string) error {
	for _, flagName := range flagNames {
		if !ctx.CLIContext.IsSet(flagName) {
			return output.ErrMissingFlag{fmt.Sprintf("--%s is required.", flagName)}
		}
	}
	return nil
}

// CheckKVFlag is a function used for verifying the format of a key-value flag.
func (ctx *Context) CheckKVFlag(flagName string) (map[string]string, error) {
	kv := make(map[string]string)
	kvStrings := strings.Split(ctx.CLIContext.String(flagName), ",")
	for _, kvString := range kvStrings {
		temp := strings.Split(kvString, "=")
		if len(temp) != 2 {
			return nil, output.ErrFlagFormatting{fmt.Sprintf("Expected key1=value1,key2=value2 format but got %s for --%s.\n", kvString, flagName)}
		}
		kv[temp[0]] = temp[1]
	}
	return kv, nil
}
<commit_msg>check for csv flag in command flags<commit_after>package handler

import (
	"fmt"
	"io"
	"os"
	"strings"
	"sync"

	"github.com/codegangsta/cli"
	"github.com/jrperritt/rack/auth"
	"github.com/jrperritt/rack/output"
	"github.com/jrperritt/rack/util"
	"github.com/rackspace/gophercloud"
)

// Command is the type that commands have.
type Command struct {
	Ctx *Context
}

// Context is a global context that `rack` uses.
type Context struct {
	// CLIContext is the context that the `cli` library uses. `rack` uses it to
	// access flags.
	CLIContext *cli.Context
	// ServiceClient is the Rackspace service client used to authenticate the user
	// and carry out the requests while processing the command.
	ServiceClient *gophercloud.ServiceClient
	// ServiceClientType is the type of Rackspace service client used (e.g. compute).
	ServiceClientType string
	// WaitGroup is used for synchronizing output.
	WaitGroup *sync.WaitGroup
	// Results is a channel into which commands send results. It allows for streaming
	// output.
	Results chan *Resource
}

// ListenAndReceive creates the Results channel and processes the results that
// come through it before sending them on to `Print`. It is run in a separate
// goroutine from `main`.
func (ctx *Context) ListenAndReceive() {
	ctx.Results = make(chan *Resource)
	go func() {
		for {
			select {
			case resource, ok := <-ctx.Results:
				if !ok {
					ctx.Results = nil
					continue
				}
				if resource.Err != nil {
					resource.Keys = []string{"error"}
					resource.Result = map[string]interface{}{"error": resource.Err.Error()}
					ctx.CLIContext.App.Writer = os.Stderr
				}
				ctx.Print(resource)
				if resource.ErrExit1 {
					os.Exit(1)
				}
			}
		}
	}()
}

// Print returns the output to the user
func (ctx *Context) Print(resource *Resource) {
	defer ctx.WaitGroup.Done()

	// limit the returned fields if any were given in the `fields` flag
	keys := ctx.limitFields(resource)
	w := ctx.CLIContext.App.Writer
	if ctx.CLIContext.GlobalIsSet("json") || ctx.CLIContext.IsSet("json") {
		switch resource.Result.(type) {
		case map[string]interface{}:
			m := resource.Result.(map[string]interface{})
			output.MetadataJSON(w, m, keys)
		case []map[string]interface{}:
			m := resource.Result.([]map[string]interface{})
			output.ListJSON(w, m, keys)
		case io.Reader:
			if _, ok := resource.Result.(io.ReadCloser); ok {
				defer resource.Result.(io.ReadCloser).Close()
			}
			_, err := io.Copy(w, resource.Result.(io.Reader))
			if err != nil {
				fmt.Fprintf(os.Stderr, "Error copying (io.Reader) result: %s\n", err)
			}
		default:
			output.DefaultJSON(w, resource.Result)
		}
	} else if ctx.CLIContext.GlobalIsSet("csv") || ctx.CLIContext.IsSet("csv") {
		switch resource.Result.(type) {
		case map[string]interface{}:
			m := resource.Result.(map[string]interface{})
			output.MetadataCSV(w, m, keys)
		case []map[string]interface{}:
			m := resource.Result.([]map[string]interface{})
			output.ListCSV(w, m, keys)
		case io.Reader:
			if _, ok := resource.Result.(io.ReadCloser); ok {
				defer resource.Result.(io.ReadCloser).Close()
			}
			_, err := io.Copy(w, resource.Result.(io.Reader))
			if err != nil {
				fmt.Fprintf(os.Stderr, "Error copying (io.Reader) result: %s\n", err)
			}
		default:
			fmt.Fprintf(w, "%v", resource.Result)
		}
	} else {
		switch resource.Result.(type) {
		case map[string]interface{}:
			m := resource.Result.(map[string]interface{})
			output.MetadataTable(w, m, keys)
		case []map[string]interface{}:
			m := resource.Result.([]map[string]interface{})
			output.ListTable(w, m, keys)
		case io.Reader:
			if _, ok := resource.Result.(io.ReadCloser); ok {
				defer resource.Result.(io.ReadCloser).Close()
			}
			_, err := io.Copy(w, resource.Result.(io.Reader))
			if err != nil {
				fmt.Fprintf(os.Stderr, "Error copying (io.Reader) result: %s\n", err)
			}
		default:
			fmt.Fprintf(w, "%v", resource.Result)
		}
	}
}

// limitFields returns only the fields the user specified in the `fields` flag. If
// the flag wasn't provided, all fields are returned.
func (ctx *Context) limitFields(resource *Resource) []string {
	if ctx.CLIContext.IsSet("fields") {
		fields := strings.Split(strings.ToLower(ctx.CLIContext.String("fields")), ",")
		newKeys := []string{}
		for _, key := range resource.Keys {
			if util.Contains(fields, strings.Join(strings.Split(strings.ToLower(key), " "), "-")) {
				newKeys = append(newKeys, key)
			}
		}
		return newKeys
	}
	return resource.Keys
}

// StoreCredentials caches the users auth credentials if available and the `no-cache`
// flag was not provided.
func (ctx *Context) StoreCredentials() {
	// if serviceClient is nil, the HTTP request for the command didn't get sent.
	// don't set cache if the `no-cache` flag is provided
	if ctx.ServiceClient != nil && !ctx.CLIContext.GlobalIsSet("no-cache") && !ctx.CLIContext.IsSet("no-cache") {
		newCacheValue := &auth.CacheItem{
			TokenID:         ctx.ServiceClient.TokenID,
			ServiceEndpoint: ctx.ServiceClient.Endpoint,
		}
		// get auth credentials
		ao, region, err := auth.Credentials(ctx.CLIContext)
		if err == nil {
			// form the cache key
			cacheKey := auth.CacheKey(*ao, region, ctx.ServiceClientType)
			// initialize the cache
			cache := &auth.Cache{}
			// set the cache value to the current values
			_ = cache.SetValue(cacheKey, newCacheValue)
		}
	}
}

// ErrExit1 tells `rack` to print the error and exit.
func (ctx *Context) ErrExit1(resource *Resource) {
	resource.ErrExit1 = true
	ctx.WaitGroup.Add(1)
	ctx.Results <- resource
	ctx.WaitGroup.Wait()
}

// IDOrName is a function for retrieving a resources unique identifier based on
// whether he or she passed an `id` or a `name` flag.
func (ctx *Context) IDOrName(idFromNameFunc func(*gophercloud.ServiceClient, string) (string, error)) (string, error) {
	if ctx.CLIContext.IsSet("id") {
		if ctx.CLIContext.IsSet("name") {
			return "", fmt.Errorf("Only one of either --id or --name may be provided.")
		}
		return ctx.CLIContext.String("id"), nil
	} else if ctx.CLIContext.IsSet("name") {
		name := ctx.CLIContext.String("name")
		id, err := idFromNameFunc(ctx.ServiceClient, name)
		if err != nil {
			return "", fmt.Errorf("Error converting name [%s] to ID: %s", name, err)
		}
		return id, nil
	} else {
		return "", output.ErrMissingFlag{"One of either --id or --name must be provided."}
	}
}

// CheckArgNum checks that the provided number of arguments has the same
// cardinality as the expected number of arguments.
func (ctx *Context) CheckArgNum(expected int) error {
	argsLen := len(ctx.CLIContext.Args())
	if argsLen != expected {
		return fmt.Errorf("Expected %d args but got %d\nUsage: %s", expected, argsLen, ctx.CLIContext.Command.Usage)
	}
	return nil
}

// CheckFlagsSet checks that the given flag names are set for the command.
func (ctx *Context) CheckFlagsSet(flagNames []string) error {
	for _, flagName := range flagNames {
		if !ctx.CLIContext.IsSet(flagName) {
			return output.ErrMissingFlag{fmt.Sprintf("--%s is required.", flagName)}
		}
	}
	return nil
}

// CheckKVFlag is a function used for verifying the format of a key-value flag.
func (ctx *Context) CheckKVFlag(flagName string) (map[string]string, error) {
	kv := make(map[string]string)
	kvStrings := strings.Split(ctx.CLIContext.String(flagName), ",")
	for _, kvString := range kvStrings {
		temp := strings.Split(kvString, "=")
		if len(temp) != 2 {
			return nil, output.ErrFlagFormatting{fmt.Sprintf("Expected key1=value1,key2=value2 format but got %s for --%s.\n", kvString, flagName)}
		}
		kv[temp[0]] = temp[1]
	}
	return kv, nil
}
<|endoftext|>


<commit_before>package handler

// Contains common methods used for writing appengine apps.

import (
	"crypto/md5"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"html/template"
	"io"
	"net/http"
	"net/url"
	"path/filepath"
	"strings"
	"time"

	"golang.org/x/net/context"
	"google.golang.org/appengine"
	"google.golang.org/appengine/log"
)

type handlerError struct {
	AppVersion string   `json:"appVersion"`
	URL        *url.URL `json:"url"`
	Method     string   `json:"method"`
	StatusCode int      `json:"statusCode"`
	InstanceID string   `json:"instanceId"`
	VersionID  string   `json:"versionId"`
	RequestID  string   `json:"requestId"`
	ModuleName string   `json:"moduleName"`
	Err        string   `json:"message"`
}

func (e *handlerError) Error() string {
	b, err := json.MarshalIndent(e, "", "  ")
	if err != nil {
		return err.Error()
	}
	return string(b)
}

// Base struct designed to be extended by more specific url handlers
type Base struct {
	Ctx context.Context
	Req *http.Request
	Res http.ResponseWriter

	config          Config
	templates       map[string]*template.Template
	templateHelpers map[string]interface{}
}

// Config contains the custom handler configuration settings
type Config struct {
	DefaultLayout    string
	LayoutPath       string
	ViewPath         string
	ParentLayoutName string
}

var defaultConfig = Config{
	DefaultLayout:    "application.html",
	LayoutPath:       "layouts",
	ViewPath:         "views",
	ParentLayoutName: "layout",
}

// New allows one to override the default configuration settings.
//  func NewRootHandler() rootHandler {
//  	return rootHandler{Base: handler.New(&handler.Config{
//  		LayoutPath: "layouts/admin.html",
//  	})}
//  }
func New(c *Config) Base {
	b := Base{config: *c} // copy the passed in pointer
	b.templates = make(map[string]*template.Template)
	return b
}

// Default uses the default config settings
//  func NewRootHandler() rootHandler {
//  	return rootHandler{Base: handler.Default()}
//  }
func Default() Base {
	return New(&defaultConfig)
}

// AddHelpers sets the html.template functions for the handler. This method should be
// called once to intialize the handler with a set of common template helpers used
// throughout the app.
func (b *Base) AddHelpers(helpers map[string]interface{}) {
	dup := make(map[string]interface{})
	for k, v := range helpers {
		dup[k] = v
	}
	b.templateHelpers = dup
}

// AddHelper allows one to add additional helpers to a handler. Use this when a handler
// needs a less common helper.
func (b *Base) AddHelper(name string, fn interface{}) {
	if b.templateHelpers == nil {
		b.templateHelpers = make(map[string]interface{})
	}
	b.templateHelpers[name] = fn
}

// OriginMiddleware returns a middleware function that validates the origin
// header within the request matches the allowed values
func OriginMiddleware(allowed []string) func(context.Context, http.ResponseWriter, *http.Request) context.Context {
	return func(c context.Context, w http.ResponseWriter, r *http.Request) context.Context {
		origin := r.Header.Get("Origin")
		if len(origin) == 0 {
			return c
		}
		ok := validateOrigin(origin, allowed)
		if !ok {
			c2, cancel := context.WithCancel(c)
			cancel()
			return c2
		}

		w.Header().Add("Access-Control-Allow-Headers", "Content-Type, Authorization")
		w.Header().Add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS")
		w.Header().Add("Access-Control-Allow-Origin", origin)

		return c
	}
}

// ValidateOrigin is a helper method called within the ServeHTTP method on
// OPTION requests to validate the allowed origins
func (b *Base) ValidateOrigin(allowed []string) {
	origin := b.Req.Header.Get("Origin")
	ok := validateOrigin(origin, allowed)
	if !ok {
		_, cancel := context.WithCancel(b.Ctx)
		cancel()
	}
}

func validateOrigin(origin string, allowed []string) bool {
	if allowed == nil || len(allowed) == 0 {
		return true
	}
	if len(origin) == 0 {
		return false
	}
	for _, allowedOrigin := range allowed {
		if origin == allowedOrigin {
			return true
		}
	}
	return false
}

// ToJSON encodes an interface into the response writer with a default http
// status code of 200
func (b *Base) ToJSON(data interface{}) {
	b.Res.Header().Add("Content-Type", "application/json")
	err := json.NewEncoder(b.Res).Encode(data)
	if err != nil {
		b.Abort(http.StatusInternalServerError, fmt.Errorf("Decoding JSON: %v", err))
	}
}

// ToJSONWithStatus json encodes an interface into the response writer with a
// custom http status code
func (b *Base) ToJSONWithStatus(data interface{}, status int) {
	b.Res.Header().Add("Content-Type", "application/json")
	b.Res.WriteHeader(status)
	b.ToJSON(data)
}

// SendStatus writes the passed in status to the response without any data
func (b *Base) SendStatus(status int) {
	b.Res.WriteHeader(status)
}

// Bind must be called at the beginning of every request to set the required references
func (b *Base) Bind(c context.Context, w http.ResponseWriter, r *http.Request) {
	b.Ctx, b.Res, b.Req = c, w, r
}

// Header gets the request header value
func (b *Base) Header(name string) string {
	return b.Req.Header.Get(name)
}

// SetHeader sets a response header value
func (b *Base) SetHeader(name, value string) {
	b.Res.Header().Set(name, value)
}

// Abort is called when pre-maturally exiting from a handler function due to an
// error. A detailed error is delivered to the client and logged to provide the
// details required to identify the issue.
func (b *Base) Abort(statusCode int, err error) {
	c, cancel := context.WithCancel(b.Ctx)
	defer cancel()

	// testapp is the name given to all apps when being tested
	var isTest = appengine.AppID(c) == "testapp"

	hErr := &handlerError{
		URL:        b.Req.URL,
		Method:     b.Req.Method,
		StatusCode: statusCode,
		AppVersion: appengine.AppID(c),
		RequestID:  appengine.RequestID(c),
	}
	if err != nil {
		hErr.Err = err.Error()
	}

	if !isTest {
		hErr.InstanceID = appengine.InstanceID()
		hErr.VersionID = appengine.VersionID(c)
		hErr.ModuleName = appengine.ModuleName(c)
	}

	// log method to appengine log
	log.Errorf(c, hErr.Error())

	b.Res.WriteHeader(statusCode)
	if strings.Index(b.Req.Header.Get("Accept"), "application/json") >= 0 {
		json.NewEncoder(b.Res).Encode(hErr)
	}
}

// Redirect is a simple wrapper around the core http method
func (b *Base) Redirect(str string, args ...interface{}) {
	http.Redirect(b.Res, b.Req, fmt.Sprintf(str, args...), 303)
}

// Render pre-caches and renders template.
func (b *Base) Render(path string, data interface{}) {
	b.RenderTemplate(path, data, RenderOptions{
		Name:    b.config.ParentLayoutName,
		FuncMap: b.templateHelpers,
		Parents: []string{filepath.Join(b.config.LayoutPath, b.config.DefaultLayout)},
	})
}

// RenderOptions contain the optional data items for rendering
type RenderOptions struct {
	// http status to return in the response
	Status int

	// template functions
	FuncMap template.FuncMap

	// parent layout paths to render the defined view within
	Parents []string

	// the defined *name* to render
	// 	{{define "layout"}}...{{end}}
	Name string
}

// RenderTemplate renders the template without any layout
func (b *Base) RenderTemplate(tmplPath string, data interface{}, opts *RenderOptions) {
	name := strings.TrimPrefix(tmplPath, "/")
	tmpl := b.templates[name]
	if tmpl == nil {
		t := template.New(name)
		if opts != nil && opts.FuncMap != nil {
			t.Funcs(opts.FuncMap)
		}
		var views []string
		if opts != nil && opts.Parents != nil {
			for _, p := range opts.Parents {
				views = append(views, b.fileNameWithExt(p))
			}
		} else {
			views = make([]string, 0)
		}

		views = append(views, filepath.Join(b.config.ViewPath, b.fileNameWithExt(name)))
		tmpl = template.Must(t.ParseFiles(views...))
		b.templates[name] = tmpl
	}
	if opts != nil && opts.Status != 0 {
		b.Res.WriteHeader(opts.Status)
	} else {
		b.Res.WriteHeader(http.StatusOK)
	}

	var renderErr error
	if opts != nil && opts.Name != "" {
		renderErr = tmpl.ExecuteTemplate(b.Res, opts.Name, data)
	} else {
		renderErr = tmpl.Execute(b.Res, data)
	}
	if renderErr != nil {
		panic(renderErr)
	}
}

// SetLastModified sets the Last-Modified header in the RFC1123 time format
func (b *Base) SetLastModified(t time.Time) {
	b.Res.Header().Set("Last-Modified", t.Format(time.RFC1123))
}

// SetETag sets the etag with the md5 value
func (b *Base) SetETag(val interface{}) {
	var str string
	switch val.(type) {
	case string:
		str = val.(string)
	case time.Time:
		str = val.(time.Time).Format(time.RFC1123)
	case fmt.Stringer:
		str = val.(fmt.Stringer).String()
	default:
		str = fmt.Sprintf("%v", val)
	}

	h := md5.New()
	io.WriteString(h, str)
	etag := base64.StdEncoding.EncodeToString(h.Sum(nil))
	b.Res.Header().Set("ETag", etag)
}

func (b *Base) SetExpires(t time.Time) {
	b.Res.Header().Set("Expires", t.Format(time.RFC1123))
}

func (b *Base) SetExpiresIn(d time.Duration) {
	b.Res.Header().Set("Expires", time.Now().Add(d).Format(time.RFC1123))
}

func (b *Base) fileNameWithExt(name string) string {
	var ext string
	if strings.Index(name, ".") > 0 {
		ext = ""
	} else {
		ext = ".html"
	}
	return fmt.Sprintf("%s%s", name, ext)
}
<commit_msg>use RenderOptions copy instead of pointer<commit_after>package handler

// Contains common methods used for writing appengine apps.

import (
	"crypto/md5"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"html/template"
	"io"
	"net/http"
	"net/url"
	"path/filepath"
	"strings"
	"time"

	"golang.org/x/net/context"
	"google.golang.org/appengine"
	"google.golang.org/appengine/log"
)

type handlerError struct {
	AppVersion string   `json:"appVersion"`
	URL        *url.URL `json:"url"`
	Method     string   `json:"method"`
	StatusCode int      `json:"statusCode"`
	InstanceID string   `json:"instanceId"`
	VersionID  string   `json:"versionId"`
	RequestID  string   `json:"requestId"`
	ModuleName string   `json:"moduleName"`
	Err        string   `json:"message"`
}

func (e *handlerError) Error() string {
	b, err := json.MarshalIndent(e, "", "  ")
	if err != nil {
		return err.Error()
	}
	return string(b)
}

// Base struct designed to be extended by more specific url handlers
type Base struct {
	Ctx context.Context
	Req *http.Request
	Res http.ResponseWriter

	config          Config
	templates       map[string]*template.Template
	templateHelpers map[string]interface{}
}

// Config contains the custom handler configuration settings
type Config struct {
	DefaultLayout    string
	LayoutPath       string
	ViewPath         string
	ParentLayoutName string
}

var defaultConfig = Config{
	DefaultLayout:    "application.html",
	LayoutPath:       "layouts",
	ViewPath:         "views",
	ParentLayoutName: "layout",
}

// New allows one to override the default configuration settings.
//  func NewRootHandler() rootHandler {
//  	return rootHandler{Base: handler.New(&handler.Config{
//  		LayoutPath: "layouts/admin.html",
//  	})}
//  }
func New(c *Config) Base {
	b := Base{config: *c} // copy the passed in pointer
	b.templates = make(map[string]*template.Template)
	return b
}

// Default uses the default config settings
//  func NewRootHandler() rootHandler {
//  	return rootHandler{Base: handler.Default()}
//  }
func Default() Base {
	return New(&defaultConfig)
}

// AddHelpers sets the html.template functions for the handler. This method should be
// called once to intialize the handler with a set of common template helpers used
// throughout the app.
func (b *Base) AddHelpers(helpers map[string]interface{}) {
	dup := make(map[string]interface{})
	for k, v := range helpers {
		dup[k] = v
	}
	b.templateHelpers = dup
}

// AddHelper allows one to add additional helpers to a handler. Use this when a handler
// needs a less common helper.
func (b *Base) AddHelper(name string, fn interface{}) {
	if b.templateHelpers == nil {
		b.templateHelpers = make(map[string]interface{})
	}
	b.templateHelpers[name] = fn
}

// OriginMiddleware returns a middleware function that validates the origin
// header within the request matches the allowed values
func OriginMiddleware(allowed []string) func(context.Context, http.ResponseWriter, *http.Request) context.Context {
	return func(c context.Context, w http.ResponseWriter, r *http.Request) context.Context {
		origin := r.Header.Get("Origin")
		if len(origin) == 0 {
			return c
		}
		ok := validateOrigin(origin, allowed)
		if !ok {
			c2, cancel := context.WithCancel(c)
			cancel()
			return c2
		}

		w.Header().Add("Access-Control-Allow-Headers", "Content-Type, Authorization")
		w.Header().Add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS")
		w.Header().Add("Access-Control-Allow-Origin", origin)

		return c
	}
}

// ValidateOrigin is a helper method called within the ServeHTTP method on
// OPTION requests to validate the allowed origins
func (b *Base) ValidateOrigin(allowed []string) {
	origin := b.Req.Header.Get("Origin")
	ok := validateOrigin(origin, allowed)
	if !ok {
		_, cancel := context.WithCancel(b.Ctx)
		cancel()
	}
}

func validateOrigin(origin string, allowed []string) bool {
	if allowed == nil || len(allowed) == 0 {
		return true
	}
	if len(origin) == 0 {
		return false
	}
	for _, allowedOrigin := range allowed {
		if origin == allowedOrigin {
			return true
		}
	}
	return false
}

// ToJSON encodes an interface into the response writer with a default http
// status code of 200
func (b *Base) ToJSON(data interface{}) {
	b.Res.Header().Add("Content-Type", "application/json")
	err := json.NewEncoder(b.Res).Encode(data)
	if err != nil {
		b.Abort(http.StatusInternalServerError, fmt.Errorf("Decoding JSON: %v", err))
	}
}

// ToJSONWithStatus json encodes an interface into the response writer with a
// custom http status code
func (b *Base) ToJSONWithStatus(data interface{}, status int) {
	b.Res.Header().Add("Content-Type", "application/json")
	b.Res.WriteHeader(status)
	b.ToJSON(data)
}

// SendStatus writes the passed in status to the response without any data
func (b *Base) SendStatus(status int) {
	b.Res.WriteHeader(status)
}

// Bind must be called at the beginning of every request to set the required references
func (b *Base) Bind(c context.Context, w http.ResponseWriter, r *http.Request) {
	b.Ctx, b.Res, b.Req = c, w, r
}

// Header gets the request header value
func (b *Base) Header(name string) string {
	return b.Req.Header.Get(name)
}

// SetHeader sets a response header value
func (b *Base) SetHeader(name, value string) {
	b.Res.Header().Set(name, value)
}

// Abort is called when pre-maturally exiting from a handler function due to an
// error. A detailed error is delivered to the client and logged to provide the
// details required to identify the issue.
func (b *Base) Abort(statusCode int, err error) {
	c, cancel := context.WithCancel(b.Ctx)
	defer cancel()

	// testapp is the name given to all apps when being tested
	var isTest = appengine.AppID(c) == "testapp"

	hErr := &handlerError{
		URL:        b.Req.URL,
		Method:     b.Req.Method,
		StatusCode: statusCode,
		AppVersion: appengine.AppID(c),
		RequestID:  appengine.RequestID(c),
	}
	if err != nil {
		hErr.Err = err.Error()
	}

	if !isTest {
		hErr.InstanceID = appengine.InstanceID()
		hErr.VersionID = appengine.VersionID(c)
		hErr.ModuleName = appengine.ModuleName(c)
	}

	// log method to appengine log
	log.Errorf(c, hErr.Error())

	b.Res.WriteHeader(statusCode)
	if strings.Index(b.Req.Header.Get("Accept"), "application/json") >= 0 {
		json.NewEncoder(b.Res).Encode(hErr)
	}
}

// Redirect is a simple wrapper around the core http method
func (b *Base) Redirect(str string, args ...interface{}) {
	http.Redirect(b.Res, b.Req, fmt.Sprintf(str, args...), 303)
}

// Render pre-caches and renders template.
func (b *Base) Render(path string, data interface{}) {
	b.RenderTemplate(path, data, RenderOptions{
		Name:    b.config.ParentLayoutName,
		FuncMap: b.templateHelpers,
		Parents: []string{filepath.Join(b.config.LayoutPath, b.config.DefaultLayout)},
	})
}

// RenderOptions contain the optional data items for rendering
type RenderOptions struct {
	// http status to return in the response
	Status int

	// template functions
	FuncMap template.FuncMap

	// parent layout paths to render the defined view within
	Parents []string

	// the defined *name* to render
	// 	{{define "layout"}}...{{end}}
	Name string
}

// RenderTemplate renders the template without any layout
func (b *Base) RenderTemplate(tmplPath string, data interface{}, opts RenderOptions) {
	name := strings.TrimPrefix(tmplPath, "/")
	tmpl := b.templates[name]
	if tmpl == nil {
		t := template.New(name)
		if opts.FuncMap != nil {
			t.Funcs(opts.FuncMap)
		}
		var views []string
		if opts.Parents != nil {
			for _, p := range opts.Parents {
				views = append(views, b.fileNameWithExt(p))
			}
		} else {
			views = make([]string, 0)
		}

		views = append(views, filepath.Join(b.config.ViewPath, b.fileNameWithExt(name)))
		tmpl = template.Must(t.ParseFiles(views...))
		b.templates[name] = tmpl
	}
	if opts.Status != 0 {
		b.Res.WriteHeader(opts.Status)
	} else {
		b.Res.WriteHeader(http.StatusOK)
	}

	var renderErr error
	if opts.Name != "" {
		renderErr = tmpl.ExecuteTemplate(b.Res, opts.Name, data)
	} else {
		renderErr = tmpl.Execute(b.Res, data)
	}
	if renderErr != nil {
		panic(renderErr)
	}
}

// SetLastModified sets the Last-Modified header in the RFC1123 time format
func (b *Base) SetLastModified(t time.Time) {
	b.Res.Header().Set("Last-Modified", t.Format(time.RFC1123))
}

// SetETag sets the etag with the md5 value
func (b *Base) SetETag(val interface{}) {
	var str string
	switch val.(type) {
	case string:
		str = val.(string)
	case time.Time:
		str = val.(time.Time).Format(time.RFC1123)
	case fmt.Stringer:
		str = val.(fmt.Stringer).String()
	default:
		str = fmt.Sprintf("%v", val)
	}

	h := md5.New()
	io.WriteString(h, str)
	etag := base64.StdEncoding.EncodeToString(h.Sum(nil))
	b.Res.Header().Set("ETag", etag)
}

func (b *Base) SetExpires(t time.Time) {
	b.Res.Header().Set("Expires", t.Format(time.RFC1123))
}

func (b *Base) SetExpiresIn(d time.Duration) {
	b.Res.Header().Set("Expires", time.Now().Add(d).Format(time.RFC1123))
}

func (b *Base) fileNameWithExt(name string) string {
	var ext string
	if strings.Index(name, ".") > 0 {
		ext = ""
	} else {
		ext = ".html"
	}
	return fmt.Sprintf("%s%s", name, ext)
}
<|endoftext|>


<commit_before>package yiigo

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
)

// AESCBCEncrypt AES CBC encrypt with PKCS#7 padding
func AESCBCEncrypt(plainText, key []byte, iv ...byte) ([]byte, error) {
	block, err := aes.NewCipher(key)

	if err != nil {
		return nil, err
	}

	plainText = PKCS7Padding(plainText, len(key))

	cipherText := make([]byte, len(plainText))

	if len(iv) == 0 {
		iv = key[:block.BlockSize()]
	}

	blockMode := cipher.NewCBCEncrypter(block, iv)
	blockMode.CryptBlocks(cipherText, plainText)

	return cipherText, nil
}

// AESCBCDecrypt AES CBC decrypt with PKCS#7 unpadding
func AESCBCDecrypt(cipherText, key []byte, iv ...byte) ([]byte, error) {
	block, err := aes.NewCipher(key)

	if err != nil {
		return nil, err
	}

	plainText := make([]byte, len(cipherText))

	if len(iv) == 0 {
		iv = key[:block.BlockSize()]
	}

	blockMode := cipher.NewCBCDecrypter(block, iv)
	blockMode.CryptBlocks(plainText, cipherText)

	return PKCS7UnPadding(plainText), nil
}

// PKCS7Padding PKCS7 padding
func PKCS7Padding(cipherText []byte, blockSize int) []byte {
	padding := blockSize - len(cipherText)%blockSize
	padText := bytes.Repeat([]byte{byte(padding)}, padding)

	return append(cipherText, padText...)
}

// PKCS7UnPadding PKCS7 unpadding
func PKCS7UnPadding(decryptedData []byte) []byte {
	l := len(decryptedData)
	unpadding := int(decryptedData[l-1])

	return decryptedData[:(l - unpadding)]
}
<commit_msg>update PKCS#7<commit_after>package yiigo

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
)

// AESCBCEncrypt AES CBC encrypt with PKCS#7 padding
func AESCBCEncrypt(plainText, key []byte, iv ...byte) ([]byte, error) {
	block, err := aes.NewCipher(key)

	if err != nil {
		return nil, err
	}

	plainText = PKCS7Padding(plainText, len(key))

	cipherText := make([]byte, len(plainText))

	if len(iv) == 0 {
		iv = key[:block.BlockSize()]
	}

	blockMode := cipher.NewCBCEncrypter(block, iv)
	blockMode.CryptBlocks(cipherText, plainText)

	return cipherText, nil
}

// AESCBCDecrypt AES CBC decrypt with PKCS#7 unpadding
func AESCBCDecrypt(cipherText, key []byte, iv ...byte) ([]byte, error) {
	block, err := aes.NewCipher(key)

	if err != nil {
		return nil, err
	}

	plainText := make([]byte, len(cipherText))

	if len(iv) == 0 {
		iv = key[:block.BlockSize()]
	}

	blockMode := cipher.NewCBCDecrypter(block, iv)
	blockMode.CryptBlocks(plainText, cipherText)

	return PKCS7UnPadding(plainText, len(key)), nil
}

// PKCS7Padding PKCS7 padding
func PKCS7Padding(cipherText []byte, blockSize int) []byte {
	padding := blockSize - len(cipherText)%blockSize

	if padding == 0 {
		padding = blockSize
	}

	padText := bytes.Repeat([]byte{byte(padding)}, padding)

	return append(cipherText, padText...)
}

// PKCS7UnPadding PKCS7 unpadding
func PKCS7UnPadding(plainText []byte, blockSize int) []byte {
	l := len(plainText)
	unpadding := int(plainText[l-1])

	if unpadding < 1 || unpadding > blockSize {
		unpadding = 0
	}

	return plainText[:(l - unpadding)]
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/hex"
	"errors"
	"flag"
	"math/rand"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/replaygaming/consumer"
	"github.com/replaygaming/eventsource"
)

var (
	topicName = flag.String("topic",
		fromEnvWithDefault("ES_TOPIC", "eventsource"),
		"Topic name")

	subscriptionName = flag.String("subscription",
		fromEnvWithDefault("ES_SUBSCRIPTION", "eventsource_"+generateSubId()),
		"Subscription name")

	port = flag.String("port",
		fromEnvWithDefault("ES_PORT", "80"),
		"Eventsource port")

	useMetrics = flag.Bool("metrics", os.Getenv("ES_METRICS") == "true", "Enable metrics")

	metricsPrefix = flag.String("metrics-prefix",
		fromEnvWithDefault("ES_METRICS_PREFIX", "production"),
		"Metrics prefix")

	metricsProvider = flag.String("metrics-provider",
		fromEnvWithDefault("ES_METRICS_PROVIDER", "log"),
		"Metrics provider. Available ones are: stackdriver and log")

	compress = flag.Bool("compression", os.Getenv("ES_COMPRESSION") == "true", "Enable zlib compression of data")

	verbose = flag.Bool("verbose", os.Getenv("ES_VERBOSE") == "true", "Enable verbose output")
)

func init() {
	flag.Parse()
}

// Create a new eventsource server, optionally with metrics
func newServerWithMetrics() *eventsource.Eventsource {
	server := &eventsource.Eventsource{
		ChannelSubscriber: eventsource.QueryStringChannels{Name: "channels"},
	}

	if *useMetrics {
		metrics, err := newMetrics()
		if err != nil {
			Fatal("Could not instantiate metrics", err)
		}
		server.Metrics = metrics
	}
	server.Start()
	return server
}

func newMetrics() (eventsource.Metrics, error) {
	Info("Instantiating " + *metricsProvider + " metrics")
	switch *metricsProvider {
	case "stackdriver":
		return NewStackdriverMetrics(*metricsPrefix, *subscriptionName)
	case "log":
		return NewLogMetrics(*metricsPrefix)
	default:
		return nil, errors.New("Don't know how to instantiate metrics provider: " + *metricsProvider)
	}
}

// Create new message consumer
func newConsumer() consumer.Consumer {
	return consumer.NewConsumer(*topicName, *subscriptionName)
}

// Create the channel that we'll receive messages
func consume(c consumer.Consumer) <-chan consumer.Message {
	messages, err := c.Consume()
	if err != nil {
		Fatal("Failed to consume messages", err)
	}
	return messages
}

// Pulls out messages from the channel
func messageLoop(messages <-chan consumer.Message, server *eventsource.Eventsource, c consumer.Consumer) {
	for m := range messages {
		messageData := m.Data()
		if *verbose {
			Debug("Got message: %s", string(messageData))
		}
		data, channels, err := parseMessage(messageData)
		if err != nil {
			Warn("json conversion failed %s", err)
		} else {
			e := eventsource.DefaultEvent{
				Message:  data,
				Channels: channels,
				Compress: *compress,
			}
			server.Send(e)
		}
		m.Done(true)
	}
}

// Handle GET /
func heartbeat(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(200)
}

// Start HTTP server
func startServing(server *eventsource.Eventsource) {
	http.HandleFunc("/", heartbeat)
	http.Handle("/subscribe", server)

	Info("EventSource server started")
	Info("Configuration: port=%s subscription=%s topic=%s"+
		" compression=%t metrics=%t", *port, *subscriptionName,
		*topicName, *compress, *useMetrics)
	if *useMetrics {
		Info("Metrics configuration: metrics-prefix=%s", *metricsPrefix)
	}
	err := http.ListenAndServe(":"+*port, nil)
	if err != nil {
		Fatal("Error starting HTTP server: %v", err)
	}
}

func main() {
	server := newServerWithMetrics()
	c := newConsumer()
	messages := consume(c)

	setupSignalHandlers(c)

	go errorLoop(server)
	go messageLoop(messages, server, c)

	startServing(server)
}

func errorLoop(server *eventsource.Eventsource) {
	for err := range server.Errors() {
		Error("Error: %v", err)
	}
}

var shuttingDown = false

// Catch signals to perform a graceful shutdown
func setupSignalHandlers(consumer consumer.Consumer) {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
	go func() {
		<-c
		if shuttingDown {
			os.Exit(1)
		}
		Info("Shutting down gracefully. Repeat signal to force shutdown")
		shuttingDown = true
		Info("Removing consumer")
		err := consumer.Remove()
		if err != nil {
			Fatal("Could not remove subscription %s: %v", *subscriptionName, err)
		}
		Info("Consumer removed successfully. Exiting")
		os.Exit(0)
	}()
}

// Generates a random hexadecimal string
func generateSubId() string {
	id := make([]byte, 4)
	todo := len(id)
	offset := 0
	source := rand.NewSource(time.Now().UnixNano())
	for {
		val := int64(source.Int63())
		for i := 0; i < 8; i++ {
			id[offset] = byte(val & 0xff)
			todo--
			if todo == 0 {
				return hex.EncodeToString(id)
			}
			offset++
			val >>= 8
		}
	}
}

// Attempts to get a value from the environment with a default
func fromEnvWithDefault(varName string, defaultValue string) string {
	value := os.Getenv(varName)
	if value != "" {
		return value
	} else {
		return defaultValue
	}
}
<commit_msg>Only log errors channel if verbose is given<commit_after>package main

import (
	"encoding/hex"
	"errors"
	"flag"
	"math/rand"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/replaygaming/consumer"
	"github.com/replaygaming/eventsource"
)

var (
	topicName = flag.String("topic",
		fromEnvWithDefault("ES_TOPIC", "eventsource"),
		"Topic name")

	subscriptionName = flag.String("subscription",
		fromEnvWithDefault("ES_SUBSCRIPTION", "eventsource_"+generateSubId()),
		"Subscription name")

	port = flag.String("port",
		fromEnvWithDefault("ES_PORT", "80"),
		"Eventsource port")

	useMetrics = flag.Bool("metrics", os.Getenv("ES_METRICS") == "true", "Enable metrics")

	metricsPrefix = flag.String("metrics-prefix",
		fromEnvWithDefault("ES_METRICS_PREFIX", "production"),
		"Metrics prefix")

	metricsProvider = flag.String("metrics-provider",
		fromEnvWithDefault("ES_METRICS_PROVIDER", "log"),
		"Metrics provider. Available ones are: stackdriver and log")

	compress = flag.Bool("compression", os.Getenv("ES_COMPRESSION") == "true", "Enable zlib compression of data")

	verbose = flag.Bool("verbose", os.Getenv("ES_VERBOSE") == "true", "Enable verbose output")
)

func init() {
	flag.Parse()
}

// Create a new eventsource server, optionally with metrics
func newServerWithMetrics() *eventsource.Eventsource {
	server := &eventsource.Eventsource{
		ChannelSubscriber: eventsource.QueryStringChannels{Name: "channels"},
	}

	if *useMetrics {
		metrics, err := newMetrics()
		if err != nil {
			Fatal("Could not instantiate metrics", err)
		}
		server.Metrics = metrics
	}
	server.Start()
	return server
}

func newMetrics() (eventsource.Metrics, error) {
	Info("Instantiating " + *metricsProvider + " metrics")
	switch *metricsProvider {
	case "stackdriver":
		return NewStackdriverMetrics(*metricsPrefix, *subscriptionName)
	case "log":
		return NewLogMetrics(*metricsPrefix)
	default:
		return nil, errors.New("Don't know how to instantiate metrics provider: " + *metricsProvider)
	}
}

// Create new message consumer
func newConsumer() consumer.Consumer {
	return consumer.NewConsumer(*topicName, *subscriptionName)
}

// Create the channel that we'll receive messages
func consume(c consumer.Consumer) <-chan consumer.Message {
	messages, err := c.Consume()
	if err != nil {
		Fatal("Failed to consume messages", err)
	}
	return messages
}

// Pulls out messages from the channel
func messageLoop(messages <-chan consumer.Message, server *eventsource.Eventsource, c consumer.Consumer) {
	for m := range messages {
		messageData := m.Data()
		if *verbose {
			Debug("Got message: %s", string(messageData))
		}
		data, channels, err := parseMessage(messageData)
		if err != nil {
			Warn("json conversion failed %s", err)
		} else {
			e := eventsource.DefaultEvent{
				Message:  data,
				Channels: channels,
				Compress: *compress,
			}
			server.Send(e)
		}
		m.Done(true)
	}
}

// Handle GET /
func heartbeat(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(200)
}

// Start HTTP server
func startServing(server *eventsource.Eventsource) {
	http.HandleFunc("/", heartbeat)
	http.Handle("/subscribe", server)

	Info("EventSource server started")
	Info("Configuration: port=%s subscription=%s topic=%s"+
		" compression=%t metrics=%t", *port, *subscriptionName,
		*topicName, *compress, *useMetrics)
	if *useMetrics {
		Info("Metrics configuration: metrics-prefix=%s", *metricsPrefix)
	}
	err := http.ListenAndServe(":"+*port, nil)
	if err != nil {
		Fatal("Error starting HTTP server: %v", err)
	}
}

func main() {
	server := newServerWithMetrics()
	c := newConsumer()
	messages := consume(c)

	setupSignalHandlers(c)

	if *verbose {
		go errorLoop(server)
	}
	go messageLoop(messages, server, c)

	startServing(server)
}

func errorLoop(server *eventsource.Eventsource) {
	for err := range server.Errors() {
		Error("Error: %v", err)
	}
}

var shuttingDown = false

// Catch signals to perform a graceful shutdown
func setupSignalHandlers(consumer consumer.Consumer) {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
	go func() {
		<-c
		if shuttingDown {
			os.Exit(1)
		}
		Info("Shutting down gracefully. Repeat signal to force shutdown")
		shuttingDown = true
		Info("Removing consumer")
		err := consumer.Remove()
		if err != nil {
			Fatal("Could not remove subscription %s: %v", *subscriptionName, err)
		}
		Info("Consumer removed successfully. Exiting")
		os.Exit(0)
	}()
}

// Generates a random hexadecimal string
func generateSubId() string {
	id := make([]byte, 4)
	todo := len(id)
	offset := 0
	source := rand.NewSource(time.Now().UnixNano())
	for {
		val := int64(source.Int63())
		for i := 0; i < 8; i++ {
			id[offset] = byte(val & 0xff)
			todo--
			if todo == 0 {
				return hex.EncodeToString(id)
			}
			offset++
			val >>= 8
		}
	}
}

// Attempts to get a value from the environment with a default
func fromEnvWithDefault(varName string, defaultValue string) string {
	value := os.Getenv(varName)
	if value != "" {
		return value
	} else {
		return defaultValue
	}
}
<|endoftext|>


<commit_before>package gubled

import (
	"os"
	"testing"

	"github.com/stretchr/testify/assert"

	"fmt"
	"time"

	"io/ioutil"
	"log"

	"github.com/smancke/guble/client"
	"github.com/smancke/guble/gubled/config"
	"github.com/smancke/guble/protocol"
	"github.com/smancke/guble/testutil"
)

type testgroup struct {
	t                   *testing.T
	groupID             int
	addr                string
	done                chan bool
	messagesToSend      int
	consumer, publisher client.Client
	topic               string
}

func newTestgroup(t *testing.T, groupID int, addr string, messagesToSend int) *testgroup {
	return &testgroup{
		t:              t,
		groupID:        groupID,
		addr:           addr,
		done:           make(chan bool),
		messagesToSend: messagesToSend,
	}
}

func TestThroughput(t *testing.T) {
	// defer testutil.EnableDebugForMethod()()
	defer testutil.ResetDefaultRegistryHealthCheck()

	dir, _ := ioutil.TempDir("", "guble_benchmarking_test")

	*config.HttpListen = "localhost:0"
	*config.KVS = "memory"
	*config.MS = "file"
	*config.StoragePath = dir

	service := StartService()

	testgroupCount := 1
	messagesPerGroup := 100
	log.Printf("init the %v testgroups", testgroupCount)
	testgroups := make([]*testgroup, testgroupCount, testgroupCount)
	for i := range testgroups {
		testgroups[i] = newTestgroup(t, i, service.WebServer().GetAddr(), messagesPerGroup)
	}

	// init test
	log.Print("init the testgroups")
	for i := range testgroups {
		testgroups[i].Init()
	}

	defer func() {
		// cleanup tests
		log.Print("cleanup the testgroups")
		for i := range testgroups {
			testgroups[i].Clean()
		}

		service.Stop()

		os.RemoveAll(dir)
	}()

	// start test
	log.Print("start the testgroups")
	start := time.Now()
	for i := range testgroups {
		go testgroups[i].Start()
	}

	log.Print("wait for finishing")
	for i, test := range testgroups {
		select {
		case successFlag := <-test.done:
			if !successFlag {
				t.Logf("testgroup %v returned with error", i)
				t.FailNow()
				return
			}
		case <-time.After(time.Second * 20):
			t.Log("timeout. testgroups not ready before timeout")
			t.Fail()
			return
		}
	}

	end := time.Now()
	totalMessages := testgroupCount * messagesPerGroup
	throughput := float64(totalMessages) / end.Sub(start).Seconds()
	log.Printf("finished! Throughput: %v/sec (%v message in %v)", int(throughput), totalMessages, end.Sub(start))

	time.Sleep(time.Second * 1)
}

func (tg *testgroup) Init() {
	tg.topic = fmt.Sprintf("/%v-foo", tg.groupID)
	var err error
	location := "ws://" + tg.addr + "/stream/user/xy"
	//location := "ws://gathermon.mancke.net:8080/stream/"
	//location := "ws://127.0.0.1:8080/stream/"
	tg.consumer, err = client.Open(location, "http://localhost/", 10, false)
	if err != nil {
		panic(err)
	}
	tg.publisher, err = client.Open(location, "http://localhost/", 10, false)
	if err != nil {
		panic(err)
	}

	tg.expectStatusMessage(protocol.SUCCESS_CONNECTED, "You are connected to the server.")

	tg.consumer.Subscribe(tg.topic)
	time.Sleep(time.Millisecond * 1)
	//test.expectStatusMessage(protocol.SUCCESS_SUBSCRIBED_TO, test.topic)
}

func (tg *testgroup) expectStatusMessage(name string, arg string) {
	select {
	case notify := <-tg.consumer.StatusMessages():
		assert.Equal(tg.t, name, notify.Name)
		assert.Equal(tg.t, arg, notify.Arg)
	case <-time.After(time.Second * 1):
		tg.t.Logf("[%v] no notification of type %s until timeout", tg.groupID, name)
		tg.done <- false
		tg.t.Fail()
		return
	}
}

func (tg *testgroup) Start() {
	go func() {
		for i := 0; i < tg.messagesToSend; i++ {
			body := fmt.Sprintf("Hallo-%d", i)
			tg.publisher.Send(tg.topic, body, "")
		}
	}()

	for i := 0; i < tg.messagesToSend; i++ {
		body := fmt.Sprintf("Hallo-%d", i)

		select {
		case msg := <-tg.consumer.Messages():
			assert.Equal(tg.t, tg.topic, string(msg.Path))
			if !assert.Equal(tg.t, body, msg.BodyAsString()) {
				tg.t.FailNow()
				tg.done <- false
			}
		case msg := <-tg.consumer.Errors():
			tg.t.Logf("[%v] received error: %v", tg.groupID, msg)
			tg.done <- false
			tg.t.Fail()
			return
		case <-time.After(time.Second * 5):
			tg.t.Logf("[%v] no message received until timeout, expected message %v", tg.groupID, i)
			tg.done <- false
			tg.t.Fail()
			return
		}
	}
	tg.done <- true
}

func (tg *testgroup) Clean() {
	tg.consumer.Close()
	tg.publisher.Close()
}
<commit_msg>Reverted test leftover<commit_after>package gubled

import (
	"os"
	"testing"

	"github.com/stretchr/testify/assert"

	"fmt"
	"time"

	"io/ioutil"
	"log"

	"github.com/smancke/guble/client"
	"github.com/smancke/guble/gubled/config"
	"github.com/smancke/guble/protocol"
	"github.com/smancke/guble/testutil"
)

type testgroup struct {
	t                   *testing.T
	groupID             int
	addr                string
	done                chan bool
	messagesToSend      int
	consumer, publisher client.Client
	topic               string
}

func newTestgroup(t *testing.T, groupID int, addr string, messagesToSend int) *testgroup {
	return &testgroup{
		t:              t,
		groupID:        groupID,
		addr:           addr,
		done:           make(chan bool),
		messagesToSend: messagesToSend,
	}
}

func TestThroughput(t *testing.T) {
	// defer testutil.EnableDebugForMethod()()
	defer testutil.ResetDefaultRegistryHealthCheck()

	dir, _ := ioutil.TempDir("", "guble_benchmarking_test")

	*config.HttpListen = "localhost:0"
	*config.KVS = "memory"
	*config.MS = "file"
	*config.StoragePath = dir

	service := StartService()

	testgroupCount := 4
	messagesPerGroup := 100
	log.Printf("init the %v testgroups", testgroupCount)
	testgroups := make([]*testgroup, testgroupCount, testgroupCount)
	for i := range testgroups {
		testgroups[i] = newTestgroup(t, i, service.WebServer().GetAddr(), messagesPerGroup)
	}

	// init test
	log.Print("init the testgroups")
	for i := range testgroups {
		testgroups[i].Init()
	}

	defer func() {
		// cleanup tests
		log.Print("cleanup the testgroups")
		for i := range testgroups {
			testgroups[i].Clean()
		}

		service.Stop()

		os.RemoveAll(dir)
	}()

	// start test
	log.Print("start the testgroups")
	start := time.Now()
	for i := range testgroups {
		go testgroups[i].Start()
	}

	log.Print("wait for finishing")
	for i, test := range testgroups {
		select {
		case successFlag := <-test.done:
			if !successFlag {
				t.Logf("testgroup %v returned with error", i)
				t.FailNow()
				return
			}
		case <-time.After(time.Second * 20):
			t.Log("timeout. testgroups not ready before timeout")
			t.Fail()
			return
		}
	}

	end := time.Now()
	totalMessages := testgroupCount * messagesPerGroup
	throughput := float64(totalMessages) / end.Sub(start).Seconds()
	log.Printf("finished! Throughput: %v/sec (%v message in %v)", int(throughput), totalMessages, end.Sub(start))

	time.Sleep(time.Second * 1)
}

func (tg *testgroup) Init() {
	tg.topic = fmt.Sprintf("/%v-foo", tg.groupID)
	var err error
	location := "ws://" + tg.addr + "/stream/user/xy"
	//location := "ws://gathermon.mancke.net:8080/stream/"
	//location := "ws://127.0.0.1:8080/stream/"
	tg.consumer, err = client.Open(location, "http://localhost/", 10, false)
	if err != nil {
		panic(err)
	}
	tg.publisher, err = client.Open(location, "http://localhost/", 10, false)
	if err != nil {
		panic(err)
	}

	tg.expectStatusMessage(protocol.SUCCESS_CONNECTED, "You are connected to the server.")

	tg.consumer.Subscribe(tg.topic)
	time.Sleep(time.Millisecond * 1)
	//test.expectStatusMessage(protocol.SUCCESS_SUBSCRIBED_TO, test.topic)
}

func (tg *testgroup) expectStatusMessage(name string, arg string) {
	select {
	case notify := <-tg.consumer.StatusMessages():
		assert.Equal(tg.t, name, notify.Name)
		assert.Equal(tg.t, arg, notify.Arg)
	case <-time.After(time.Second * 1):
		tg.t.Logf("[%v] no notification of type %s until timeout", tg.groupID, name)
		tg.done <- false
		tg.t.Fail()
		return
	}
}

func (tg *testgroup) Start() {
	go func() {
		for i := 0; i < tg.messagesToSend; i++ {
			body := fmt.Sprintf("Hallo-%d", i)
			tg.publisher.Send(tg.topic, body, "")
		}
	}()

	for i := 0; i < tg.messagesToSend; i++ {
		body := fmt.Sprintf("Hallo-%d", i)

		select {
		case msg := <-tg.consumer.Messages():
			assert.Equal(tg.t, tg.topic, string(msg.Path))
			if !assert.Equal(tg.t, body, msg.BodyAsString()) {
				tg.t.FailNow()
				tg.done <- false
			}
		case msg := <-tg.consumer.Errors():
			tg.t.Logf("[%v] received error: %v", tg.groupID, msg)
			tg.done <- false
			tg.t.Fail()
			return
		case <-time.After(time.Second * 5):
			tg.t.Logf("[%v] no message received until timeout, expected message %v", tg.groupID, i)
			tg.done <- false
			tg.t.Fail()
			return
		}
	}
	tg.done <- true
}

func (tg *testgroup) Clean() {
	tg.consumer.Close()
	tg.publisher.Close()
}
<|endoftext|>


<commit_before>// Copyright 2014 Igor Dolzhikov. All rights reserved.
// Use of this source code is governed by
// license that can be found in the LICENSE file.

/*
Package daemon 0.1.3 for use with Go (golang) services.

Package daemon provides primitives for daemonization of golang services.
This package is not provide implementation of user daemon,
accordingly must have root rights to install/remove service.
In the current implementation is only supported Linux and Mac Os X daemon.

Example:

	//Example of the daemon with echo service
	package main

	import (
		"fmt"
		"log"
		"net"
		"os"
		"os/signal"
		"syscall"

		"github.com/takama/daemon"
	)

	const (

		// name of the service, match with executable file name
		name        = "myservice"
		description = "My Echo Service"

		// port which daemon should be listen
		port = ":9977"
	)

	type Service struct {
		daemon.Daemon
	}

	func (service *Service) Manage() (string, error) {

		usage := "Usage: myservice install | remove | start | stop | status"

		// if received any kind of command, do it
		if len(os.Args) > 1 {
			command := os.Args[1]
			switch command {
			case "install":
				return service.Install()
			case "remove":
				return service.Remove()
			case "start":
				return service.Start()
			case "stop":
				return service.Stop()
			case "status":
				return service.Status()
			default:
				return usage, nil
			}
		}

		// Do something, call your goroutines, etc

		// Set up channel on which to send signal notifications.
		// We must use a buffered channel or risk missing the signal
		// if we're not ready to receive when the signal is sent.
		interrupt := make(chan os.Signal, 1)
		signal.Notify(interrupt, os.Interrupt, os.Kill, syscall.SIGTERM)

		// Set up listener for defined host and port
		listener, err := net.Listen("tcp", port)
		if err != nil {
			return "Possibly was a problem with the port binding", err
		}

		// set up channel on which to send accepted connections
		listen := make(chan net.Conn, 100)
		go acceptConnection(listener, listen)

		// loop work cycle with accept connections or interrupt
		// by system signal
		for {
			select {
			case conn := <-listen:
				go handleClient(conn)
			case killSignal := <-interrupt:
				log.Println("Got signal:", killSignal)
				log.Println("Stoping listening on ", listener.Addr())
				listener.Close()
				if killSignal == os.Interrupt {
					return "Daemon was interruped by system signal", nil
				}
				return "Daemon was killed", nil
			}
		}

		// never happen, but need to complete code
		return usage, nil
	}

	// Accept a client connection and collect it in a channel
	func acceptConnection(listener net.Listener, listen chan<- net.Conn) {
		for {
			conn, err := listener.Accept()
			if err != nil {
				continue
			}
			listen <- conn
		}
	}

	func handleClient(client net.Conn) {
		for {
			buf := make([]byte, 4096)
			numbytes, err := client.Read(buf)
			if numbytes == 0 || err != nil {
				return
			}
			client.Write(buf)
		}
	}

	func main() {
		srv, err := daemon.New(name, description)
		if err != nil {
			fmt.Println("Error: ", err)
			os.Exit(1)
		}
		service := &Service{srv}
		status, err := service.Manage()
		if err != nil {
			fmt.Println(status, "\nError: ", err)
			os.Exit(1)
		}
		fmt.Println(status)
	}

Go daemon
*/
package daemon

// Daemon interface has standard set of a methods/commands
type Daemon interface {

	// Install the service into the system
	Install() (string, error)

	// Remove the service and all corresponded files from the system
	Remove() (string, error)

	// Start the service
	Start() (string, error)

	// Stop the service
	Stop() (string, error)

	// Status - check the service status
	Status() (string, error)
}

// New - Create a new daemon
//
// name: name of the service, match with executable file name;
// description: any explanation, what is the service, its purpose
func New(name, description string) (Daemon, error) {
	return newDaemon(name, description)
}
<commit_msg>Bumped version number to 0.1.4<commit_after>// Copyright 2014 Igor Dolzhikov. All rights reserved.
// Use of this source code is governed by
// license that can be found in the LICENSE file.

/*
Package daemon 0.1.4 for use with Go (golang) services.

Package daemon provides primitives for daemonization of golang services.
This package is not provide implementation of user daemon,
accordingly must have root rights to install/remove service.
In the current implementation is only supported Linux and Mac Os X daemon.

Example:

	//Example of the daemon with echo service
	package main

	import (
		"fmt"
		"log"
		"net"
		"os"
		"os/signal"
		"syscall"

		"github.com/takama/daemon"
	)

	const (

		// name of the service, match with executable file name
		name        = "myservice"
		description = "My Echo Service"

		// port which daemon should be listen
		port = ":9977"
	)

	type Service struct {
		daemon.Daemon
	}

	func (service *Service) Manage() (string, error) {

		usage := "Usage: myservice install | remove | start | stop | status"

		// if received any kind of command, do it
		if len(os.Args) > 1 {
			command := os.Args[1]
			switch command {
			case "install":
				return service.Install()
			case "remove":
				return service.Remove()
			case "start":
				return service.Start()
			case "stop":
				return service.Stop()
			case "status":
				return service.Status()
			default:
				return usage, nil
			}
		}

		// Do something, call your goroutines, etc

		// Set up channel on which to send signal notifications.
		// We must use a buffered channel or risk missing the signal
		// if we're not ready to receive when the signal is sent.
		interrupt := make(chan os.Signal, 1)
		signal.Notify(interrupt, os.Interrupt, os.Kill, syscall.SIGTERM)

		// Set up listener for defined host and port
		listener, err := net.Listen("tcp", port)
		if err != nil {
			return "Possibly was a problem with the port binding", err
		}

		// set up channel on which to send accepted connections
		listen := make(chan net.Conn, 100)
		go acceptConnection(listener, listen)

		// loop work cycle with accept connections or interrupt
		// by system signal
		for {
			select {
			case conn := <-listen:
				go handleClient(conn)
			case killSignal := <-interrupt:
				log.Println("Got signal:", killSignal)
				log.Println("Stoping listening on ", listener.Addr())
				listener.Close()
				if killSignal == os.Interrupt {
					return "Daemon was interruped by system signal", nil
				}
				return "Daemon was killed", nil
			}
		}

		// never happen, but need to complete code
		return usage, nil
	}

	// Accept a client connection and collect it in a channel
	func acceptConnection(listener net.Listener, listen chan<- net.Conn) {
		for {
			conn, err := listener.Accept()
			if err != nil {
				continue
			}
			listen <- conn
		}
	}

	func handleClient(client net.Conn) {
		for {
			buf := make([]byte, 4096)
			numbytes, err := client.Read(buf)
			if numbytes == 0 || err != nil {
				return
			}
			client.Write(buf)
		}
	}

	func main() {
		srv, err := daemon.New(name, description)
		if err != nil {
			fmt.Println("Error: ", err)
			os.Exit(1)
		}
		service := &Service{srv}
		status, err := service.Manage()
		if err != nil {
			fmt.Println(status, "\nError: ", err)
			os.Exit(1)
		}
		fmt.Println(status)
	}

Go daemon
*/
package daemon

// Daemon interface has standard set of a methods/commands
type Daemon interface {

	// Install the service into the system
	Install() (string, error)

	// Remove the service and all corresponded files from the system
	Remove() (string, error)

	// Start the service
	Start() (string, error)

	// Stop the service
	Stop() (string, error)

	// Status - check the service status
	Status() (string, error)
}

// New - Create a new daemon
//
// name: name of the service, match with executable file name;
// description: any explanation, what is the service, its purpose
func New(name, description string) (Daemon, error) {
	return newDaemon(name, description)
}
<|endoftext|>


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

package time_test

import (
	"fmt"
	"time"
)

func expensiveCall() {}

func ExampleDuration() {
	t0 := time.Now()
	expensiveCall()
	t1 := time.Now()
	fmt.Printf("The call took %v to run.\n", t1.Sub(t0))
}

var c chan int

func handle(int) {}

func ExampleAfter() {
	select {
	case m := <-c:
		handle(m)
	case <-time.After(5 * time.Minute):
		fmt.Println("timed out")
	}
}

func ExampleSleep() {
	time.Sleep(100 * time.Millisecond)
}

func statusUpdate() string { return "" }

func ExampleTick() {
	c := time.Tick(1 * time.Minute)
	for now := range c {
		fmt.Printf("%v %s\n", now, statusUpdate())
	}
}

func ExampleMonth() {
	_, month, day := time.Now().Date()
	if month == time.November && day == 10 {
		fmt.Println("Happy Go day!")
	}
}

func ExampleDate() {
	t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
	fmt.Printf("Go launched at %s\n", t.Local())
	// Output: Go launched at 2009-11-10 15:00:00 -0800 PST
}

func ExampleTime_Format() {
	// Parse a time value from a string in the standard Unix format.
	t, err := time.Parse(time.UnixDate, "Sat Mar  7 11:06:39 PST 2015")
	if err != nil { // Always check errors even if they should not happen.
		panic(err)
	}

	// time.Time's Stringer method is useful without any format.
	fmt.Println("default format:", t)

	// Predefined constants in the package implement common layouts.
	fmt.Println("Unix format:", t.Format(time.UnixDate))

	// The time zone attached to the time value affects its output.
	fmt.Println("Same, in UTC:", t.UTC().Format(time.UnixDate))

	// The rest of this function demonstrates the properties of the
	// layout string used in the format.

	// The layout string used by the Parse function and Format method
	// shows by example how the reference time should be represented.
	// We stress that one must show how the reference time is formatted,
	// not a time of the user's choosing. Thus each layout string is a
	// representation of the time stamp,
	//	Jan 2 15:04:05 2006 MST
	// An easy way to remember this value is that it holds, when presented
	// in this order, the values (lined up with the elements above):
	//	  1 2  3  4  5    6  -7
	// There are some wrinkles illustrated below.

	// Most uses of Format and Parse use constant layout strings such as
	// the ones defined in this package, but the interface is flexible,
	// as these examples show.

	// Define a helper function to make the examples' output look nice.
	do := func(name, layout, want string) {
		got := t.Format(layout)
		if want != got {
			fmt.Printf("error: for %q got %q; expected %q\n", layout, got, want)
			return
		}
		fmt.Printf("%-15s %q gives %q\n", name, layout, got)
	}

	// Print a header in our output.
	fmt.Printf("\nFormats:\n\n")

	// A simple starter example.
	do("Basic", "Mon Jan 2 15:04:05 MST 2006", "Sat Mar 7 11:06:39 PST 2015")

	// For fixed-width printing of values, such as the date, that may be one or
	// two characters (7 vs. 07), use an _ instead of a space in the layout string.
	// Here we print just the day, which is 2 in our layout string and 7 in our
	// value.
	do("No pad", "<2>", "<7>")

	// An underscore represents a zero pad, if required.
	do("Spaces", "<_2>", "< 7>")

	// Similarly, a 0 indicates zero padding.
	do("Zeros", "<02>", "<07>")

	// If the value is already the right width, padding is not used.
	// For instance, the second (05 in the reference time) in our value is 39,
	// so it doesn't need padding, but the minutes (04, 06) does.
	do("Suppressed pad", "04:05", "06:39")

	// The predefined constant Unix uses an underscore to pad the day.
	// Compare with our simple starter example.
	do("Unix", time.UnixDate, "Sat Mar  7 11:06:39 PST 2015")

	// The hour of the reference time is 15, or 3PM. The layout can express
	// it either way, and since our value is the morning we should see it as
	// an AM time. We show both in one format string. Lower case too.
	do("AM/PM", "3PM==3pm==15h", "11AM==11am==11h")

	// When parsing, if the seconds value is followed by a decimal point
	// and some digits, that is taken as a fraction of a second even if
	// the layout string does not represent the fractional second.
	// Here we add a fractional second to our time value used above.
	t, err = time.Parse(time.UnixDate, "Sat Mar  7 11:06:39.1234 PST 2015")
	if err != nil {
		panic(err)
	}
	// It does not appear in the output if the layout string does not contain
	// a representation of the fractional second.
	do("No fraction", time.UnixDate, "Sat Mar  7 11:06:39 PST 2015")

	// Fractional seconds can be printed by adding a run of 0s or 9s after
	// a decimal point in the seconds value in the layout string.
	// If the layout digits are 0s, the fractional second is of the specified
	// width. Note that the output has a trailing zero.
	do("0s for fraction", "15:04:05.00000", "11:06:39.12340")

	// If the fraction in the layout is 9s, trailing zeros are dropped.
	do("9s for fraction", "15:04:05.99999999", "11:06:39.1234")

	// Output:
	// default format: 2015-03-07 11:06:39 -0800 PST
	// Unix format: Sat Mar  7 11:06:39 PST 2015
	// Same, in UTC: Sat Mar  7 19:06:39 UTC 2015
	//
	// Formats:
	//
	// Basic           "Mon Jan 2 15:04:05 MST 2006" gives "Sat Mar 7 11:06:39 PST 2015"
	// No pad          "<2>" gives "<7>"
	// Spaces          "<_2>" gives "< 7>"
	// Zeros           "<02>" gives "<07>"
	// Suppressed pad  "04:05" gives "06:39"
	// Unix            "Mon Jan _2 15:04:05 MST 2006" gives "Sat Mar  7 11:06:39 PST 2015"
	// AM/PM           "3PM==3pm==15h" gives "11AM==11am==11h"
	// No fraction     "Mon Jan _2 15:04:05 MST 2006" gives "Sat Mar  7 11:06:39 PST 2015"
	// 0s for fraction "15:04:05.00000" gives "11:06:39.12340"
	// 9s for fraction "15:04:05.99999999" gives "11:06:39.1234"

}

func ExampleParse() {
	// See the example for time.Format for a thorough description of how
	// to define the layout string to parse a time.Time value; Parse and
	// Format use the same model to describe their input and output.

	// longForm shows by example how the reference time would be represented in
	// the desired layout.
	const longForm = "Jan 2, 2006 at 3:04pm (MST)"
	t, _ := time.Parse(longForm, "Feb 3, 2013 at 7:54pm (PST)")
	fmt.Println(t)

	// shortForm is another way the reference time would be represented
	// in the desired layout; it has no time zone present.
	// Note: without explicit zone, returns time in UTC.
	const shortForm = "2006-Jan-02"
	t, _ = time.Parse(shortForm, "2013-Feb-03")
	fmt.Println(t)

	// Output:
	// 2013-02-03 19:54:00 -0800 PST
	// 2013-02-03 00:00:00 +0000 UTC
}

func ExampleParseInLocation() {
	loc, _ := time.LoadLocation("Europe/Berlin")

	const longForm = "Jan 2, 2006 at 3:04pm (MST)"
	t, _ := time.ParseInLocation(longForm, "Jul 9, 2012 at 5:02am (CEST)", loc)
	fmt.Println(t)

	// Note: without explicit zone, returns time in given location.
	const shortForm = "2006-Jan-02"
	t, _ = time.ParseInLocation(shortForm, "2012-Jul-09", loc)
	fmt.Println(t)

	// Output:
	// 2012-07-09 05:02:00 +0200 CEST
	// 2012-07-09 00:00:00 +0200 CEST
}

func ExampleTime_Round() {
	t := time.Date(0, 0, 0, 12, 15, 30, 918273645, time.UTC)
	round := []time.Duration{
		time.Nanosecond,
		time.Microsecond,
		time.Millisecond,
		time.Second,
		2 * time.Second,
		time.Minute,
		10 * time.Minute,
		time.Hour,
	}

	for _, d := range round {
		fmt.Printf("t.Round(%6s) = %s\n", d, t.Round(d).Format("15:04:05.999999999"))
	}
	// Output:
	// t.Round(   1ns) = 12:15:30.918273645
	// t.Round(   1µs) = 12:15:30.918274
	// t.Round(   1ms) = 12:15:30.918
	// t.Round(    1s) = 12:15:31
	// t.Round(    2s) = 12:15:30
	// t.Round(  1m0s) = 12:16:00
	// t.Round( 10m0s) = 12:20:00
	// t.Round(1h0m0s) = 12:00:00
}

func ExampleTime_Truncate() {
	t, _ := time.Parse("2006 Jan 02 15:04:05", "2012 Dec 07 12:15:30.918273645")
	trunc := []time.Duration{
		time.Nanosecond,
		time.Microsecond,
		time.Millisecond,
		time.Second,
		2 * time.Second,
		time.Minute,
		10 * time.Minute,
	}

	for _, d := range trunc {
		fmt.Printf("t.Truncate(%5s) = %s\n", d, t.Truncate(d).Format("15:04:05.999999999"))
	}

	// Output:
	// t.Truncate(  1ns) = 12:15:30.918273645
	// t.Truncate(  1µs) = 12:15:30.918273
	// t.Truncate(  1ms) = 12:15:30.918
	// t.Truncate(   1s) = 12:15:30
	// t.Truncate(   2s) = 12:15:30
	// t.Truncate( 1m0s) = 12:15:00
	// t.Truncate(10m0s) = 12:10:00
}
<commit_msg>time: show how to get midnight on the current day<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package time_test

import (
	"fmt"
	"time"
)

func expensiveCall() {}

func ExampleDuration() {
	t0 := time.Now()
	expensiveCall()
	t1 := time.Now()
	fmt.Printf("The call took %v to run.\n", t1.Sub(t0))
}

var c chan int

func handle(int) {}

func ExampleAfter() {
	select {
	case m := <-c:
		handle(m)
	case <-time.After(5 * time.Minute):
		fmt.Println("timed out")
	}
}

func ExampleSleep() {
	time.Sleep(100 * time.Millisecond)
}

func statusUpdate() string { return "" }

func ExampleTick() {
	c := time.Tick(1 * time.Minute)
	for now := range c {
		fmt.Printf("%v %s\n", now, statusUpdate())
	}
}

func ExampleMonth() {
	_, month, day := time.Now().Date()
	if month == time.November && day == 10 {
		fmt.Println("Happy Go day!")
	}
}

func ExampleDate() {
	t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
	fmt.Printf("Go launched at %s\n", t.Local())
	// Output: Go launched at 2009-11-10 15:00:00 -0800 PST
}

func ExampleTime_Format() {
	// Parse a time value from a string in the standard Unix format.
	t, err := time.Parse(time.UnixDate, "Sat Mar  7 11:06:39 PST 2015")
	if err != nil { // Always check errors even if they should not happen.
		panic(err)
	}

	// time.Time's Stringer method is useful without any format.
	fmt.Println("default format:", t)

	// Predefined constants in the package implement common layouts.
	fmt.Println("Unix format:", t.Format(time.UnixDate))

	// The time zone attached to the time value affects its output.
	fmt.Println("Same, in UTC:", t.UTC().Format(time.UnixDate))

	// The rest of this function demonstrates the properties of the
	// layout string used in the format.

	// The layout string used by the Parse function and Format method
	// shows by example how the reference time should be represented.
	// We stress that one must show how the reference time is formatted,
	// not a time of the user's choosing. Thus each layout string is a
	// representation of the time stamp,
	//	Jan 2 15:04:05 2006 MST
	// An easy way to remember this value is that it holds, when presented
	// in this order, the values (lined up with the elements above):
	//	  1 2  3  4  5    6  -7
	// There are some wrinkles illustrated below.

	// Most uses of Format and Parse use constant layout strings such as
	// the ones defined in this package, but the interface is flexible,
	// as these examples show.

	// Define a helper function to make the examples' output look nice.
	do := func(name, layout, want string) {
		got := t.Format(layout)
		if want != got {
			fmt.Printf("error: for %q got %q; expected %q\n", layout, got, want)
			return
		}
		fmt.Printf("%-15s %q gives %q\n", name, layout, got)
	}

	// Print a header in our output.
	fmt.Printf("\nFormats:\n\n")

	// A simple starter example.
	do("Basic", "Mon Jan 2 15:04:05 MST 2006", "Sat Mar 7 11:06:39 PST 2015")

	// For fixed-width printing of values, such as the date, that may be one or
	// two characters (7 vs. 07), use an _ instead of a space in the layout string.
	// Here we print just the day, which is 2 in our layout string and 7 in our
	// value.
	do("No pad", "<2>", "<7>")

	// An underscore represents a zero pad, if required.
	do("Spaces", "<_2>", "< 7>")

	// Similarly, a 0 indicates zero padding.
	do("Zeros", "<02>", "<07>")

	// If the value is already the right width, padding is not used.
	// For instance, the second (05 in the reference time) in our value is 39,
	// so it doesn't need padding, but the minutes (04, 06) does.
	do("Suppressed pad", "04:05", "06:39")

	// The predefined constant Unix uses an underscore to pad the day.
	// Compare with our simple starter example.
	do("Unix", time.UnixDate, "Sat Mar  7 11:06:39 PST 2015")

	// The hour of the reference time is 15, or 3PM. The layout can express
	// it either way, and since our value is the morning we should see it as
	// an AM time. We show both in one format string. Lower case too.
	do("AM/PM", "3PM==3pm==15h", "11AM==11am==11h")

	// When parsing, if the seconds value is followed by a decimal point
	// and some digits, that is taken as a fraction of a second even if
	// the layout string does not represent the fractional second.
	// Here we add a fractional second to our time value used above.
	t, err = time.Parse(time.UnixDate, "Sat Mar  7 11:06:39.1234 PST 2015")
	if err != nil {
		panic(err)
	}
	// It does not appear in the output if the layout string does not contain
	// a representation of the fractional second.
	do("No fraction", time.UnixDate, "Sat Mar  7 11:06:39 PST 2015")

	// Fractional seconds can be printed by adding a run of 0s or 9s after
	// a decimal point in the seconds value in the layout string.
	// If the layout digits are 0s, the fractional second is of the specified
	// width. Note that the output has a trailing zero.
	do("0s for fraction", "15:04:05.00000", "11:06:39.12340")

	// If the fraction in the layout is 9s, trailing zeros are dropped.
	do("9s for fraction", "15:04:05.99999999", "11:06:39.1234")

	// Output:
	// default format: 2015-03-07 11:06:39 -0800 PST
	// Unix format: Sat Mar  7 11:06:39 PST 2015
	// Same, in UTC: Sat Mar  7 19:06:39 UTC 2015
	//
	// Formats:
	//
	// Basic           "Mon Jan 2 15:04:05 MST 2006" gives "Sat Mar 7 11:06:39 PST 2015"
	// No pad          "<2>" gives "<7>"
	// Spaces          "<_2>" gives "< 7>"
	// Zeros           "<02>" gives "<07>"
	// Suppressed pad  "04:05" gives "06:39"
	// Unix            "Mon Jan _2 15:04:05 MST 2006" gives "Sat Mar  7 11:06:39 PST 2015"
	// AM/PM           "3PM==3pm==15h" gives "11AM==11am==11h"
	// No fraction     "Mon Jan _2 15:04:05 MST 2006" gives "Sat Mar  7 11:06:39 PST 2015"
	// 0s for fraction "15:04:05.00000" gives "11:06:39.12340"
	// 9s for fraction "15:04:05.99999999" gives "11:06:39.1234"

}

func ExampleParse() {
	// See the example for time.Format for a thorough description of how
	// to define the layout string to parse a time.Time value; Parse and
	// Format use the same model to describe their input and output.

	// longForm shows by example how the reference time would be represented in
	// the desired layout.
	const longForm = "Jan 2, 2006 at 3:04pm (MST)"
	t, _ := time.Parse(longForm, "Feb 3, 2013 at 7:54pm (PST)")
	fmt.Println(t)

	// shortForm is another way the reference time would be represented
	// in the desired layout; it has no time zone present.
	// Note: without explicit zone, returns time in UTC.
	const shortForm = "2006-Jan-02"
	t, _ = time.Parse(shortForm, "2013-Feb-03")
	fmt.Println(t)

	// Output:
	// 2013-02-03 19:54:00 -0800 PST
	// 2013-02-03 00:00:00 +0000 UTC
}

func ExampleParseInLocation() {
	loc, _ := time.LoadLocation("Europe/Berlin")

	const longForm = "Jan 2, 2006 at 3:04pm (MST)"
	t, _ := time.ParseInLocation(longForm, "Jul 9, 2012 at 5:02am (CEST)", loc)
	fmt.Println(t)

	// Note: without explicit zone, returns time in given location.
	const shortForm = "2006-Jan-02"
	t, _ = time.ParseInLocation(shortForm, "2012-Jul-09", loc)
	fmt.Println(t)

	// Output:
	// 2012-07-09 05:02:00 +0200 CEST
	// 2012-07-09 00:00:00 +0200 CEST
}

func ExampleTime_Round() {
	t := time.Date(0, 0, 0, 12, 15, 30, 918273645, time.UTC)
	round := []time.Duration{
		time.Nanosecond,
		time.Microsecond,
		time.Millisecond,
		time.Second,
		2 * time.Second,
		time.Minute,
		10 * time.Minute,
		time.Hour,
	}

	for _, d := range round {
		fmt.Printf("t.Round(%6s) = %s\n", d, t.Round(d).Format("15:04:05.999999999"))
	}
	// Output:
	// t.Round(   1ns) = 12:15:30.918273645
	// t.Round(   1µs) = 12:15:30.918274
	// t.Round(   1ms) = 12:15:30.918
	// t.Round(    1s) = 12:15:31
	// t.Round(    2s) = 12:15:30
	// t.Round(  1m0s) = 12:16:00
	// t.Round( 10m0s) = 12:20:00
	// t.Round(1h0m0s) = 12:00:00
}

func ExampleTime_Truncate() {
	t, _ := time.Parse("2006 Jan 02 15:04:05", "2012 Dec 07 12:15:30.918273645")
	trunc := []time.Duration{
		time.Nanosecond,
		time.Microsecond,
		time.Millisecond,
		time.Second,
		2 * time.Second,
		time.Minute,
		10 * time.Minute,
	}

	for _, d := range trunc {
		fmt.Printf("t.Truncate(%5s) = %s\n", d, t.Truncate(d).Format("15:04:05.999999999"))
	}
	// To round to the last midnight in the local timezone, create a new Date.
	midnight := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.Local)
	_ = midnight

	// Output:
	// t.Truncate(  1ns) = 12:15:30.918273645
	// t.Truncate(  1µs) = 12:15:30.918273
	// t.Truncate(  1ms) = 12:15:30.918
	// t.Truncate(   1s) = 12:15:30
	// t.Truncate(   2s) = 12:15:30
	// t.Truncate( 1m0s) = 12:15:00
	// t.Truncate(10m0s) = 12:10:00
}
<|endoftext|>


<commit_before>package linreg

import "testing"

func TestNewLinearRegression(t *testing.T) {
	if lr := NewLinearRegression(); lr == nil {
		t.Errorf("got nil linear regression")
	}
}

func TestInitialize(t *testing.T) {
	lr := NewLinearRegression()

	lr.Initialize()

	if len(lr.Xn) != len(lr.Yn) {
		t.Errorf("got different size of vectors Xn Yn, wants same size")
	}

	if len(lr.Xn[0]) != len(lr.Wn) {
		t.Errorf("got different size of vectors Xn Wn, wants same size")
	}

	if len(lr.Xn) != lr.TrainingPoints {
		t.Errorf("got different size of vectors Xn and training points, wants same number")
	}

	for i := 0; i < len(lr.Xn); i++ {
		for j := 0; j < len(lr.Xn[0]); j++ {
			if lr.Xn[i][j] < lr.Interval.Min ||
				lr.Xn[i][j] > lr.Interval.Max {
				t.Errorf("got value of Xn[%d][%d] = %v, want it between %v and %v", i, j, lr.Xn[i][j], lr.Interval.Min, lr.Interval.Max)
			}
		}
	}

	for i := 0; i < len(lr.Yn); i++ {
		if lr.Yn[i] != float64(-1) && lr.Yn[i] != float64(1) {
			t.Errorf("got value of Yn[%v] = %v, want it equal to -1 or 1", i, lr.Yn[i])
		}
	}

}

func TestFlip(t *testing.T) {
	lr := NewLinearRegression()
	lr.Noise = 0
	for i := 0; i < 100; i++ {
		if v := lr.flip(); v != float64(1) {
			t.Errorf("got flip value = -1 wants 1")
		}
	}
	lr.Noise = 1
	for i := 0; i < 100; i++ {
		if v := lr.flip(); v != float64(-1) {
			t.Errorf("got flip value = 1 wants -1")
		}
	}

	lr.Noise = 0.5
	for i := 0; i < 100; i++ {
		if v := lr.flip(); v != float64(-1) && v != float64(1) {
			t.Errorf("got flip value = %v wants value equal to 1 or -1", v)
		}
	}
}

func TestInitializeFromFile(t *testing.T) {
	// todo(santiaago): make this test.
}

func TestInitializeFromData(t *testing.T) {
	data := [][]float64{
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
	}
	lr := NewLinearRegression()
	if err := lr.InitializeFromData(data); err != nil {
		t.Errorf("%v", err)
	}
	if len(lr.Xn) != len(data) || len(lr.Yn) != len(data) {
		t.Errorf("got difference in size of Xn or Yn and data")
	}

	if len(lr.Xn) != lr.TrainingPoints {
		t.Errorf("got difference in size of Xn or TrainingPoints and data")
	}

	if len(lr.Xn[0]) != len(lr.Wn) {
		t.Errorf("got different size of vectors Xn Wn, wants same size")
	}

	if len(lr.Xn[0]) != lr.VectorSize || len(data[0]) != lr.VectorSize {
		t.Errorf("got difference in size of Xn[0] or data[0] with VectorSize")
	}
}

func TestInitializeValidationFromData(t *testing.T) {
	//todo(santiaago): test this
}

func TestApplyTransformation(t *testing.T) {

	tf := func(a []float64) []float64 {
		for i := 1; i < len(a); i++ {
			a[i] = -a[i]
		}
		return a
	}

	data := [][]float64{
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
	}

	lr := NewLinearRegression()
	lr.InitializeFromData(data)
	lr.TransformFunction = tf
	lr.ApplyTransformation()

	for i := 0; i < lr.TrainingPoints; i++ {
		for j := 1; j < len(lr.Xn[i]); j++ {
			if lr.Xn[i][j] != -1 {
				t.Errorf("got %v wants -1", lr.Xn[i][j])
			}
		}
		if lr.Yn[i] != 1 {
			t.Errorf("got Yn[%v] = %v wants %v", i, lr.Yn[i], 1)
		}
	}

}

func TestApplyTransformationOnValidation(t *testing.T) {
	// todo(santiaago): test this
}

func TestLearn(t *testing.T) {
	lr := NewLinearRegression()
	data := [][]float64{
		{0.1, 1, 1},
		{0.2, 1, 1},
		{0.3, 1, 1},
		{1, 0.5, -1},
		{1, 0.6, -1},
		{1, 0.7, -1},
	}

	lr.InitializeFromData(data)
	lr.Learn()
	expectedWn := []float64{0.393, -1.967, 0.983}
	if !equal(expectedWn, lr.Wn) {
		t.Errorf("Weight vector is not correct: got %v, want %v", lr.Wn, expectedWn)
	}
}

func TestSetWeight(t *testing.T) {

	lr := NewLinearRegression()
	lr.VectorSize = 5
	lr.Yn = []float64{-1, -1, -1}
	lr.TrainingPoints = 5
	d := [][]float64{
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
	}

	lr.setWeight(d)

	expectedWn := []float64{-3, -3, -3, -3, -3}
	if !equal(expectedWn, lr.Wn) {
		t.Errorf("Weight vector is not correct: got %v, want %v", lr.Wn, expectedWn)
	}
}

func TestSetWeightReg(t *testing.T) {

	lr := NewLinearRegression()
	lr.VectorSize = 5
	lr.Yn = []float64{-1, -1, -1}
	lr.TrainingPoints = 5
	d := [][]float64{
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
	}

	lr.setWeightReg(d)

	expectedWReg := []float64{-3, -3, -3, -3, -3}
	if !equal(expectedWReg, lr.WReg) {
		t.Errorf("Weight vector is not correct: got %v, want %v", lr.WReg, expectedWReg)
	}
}

func TestEin(t *testing.T) {
	lr := NewLinearRegression()
	lr.Xn = [][]float64{
		{1, 0.1, 0.1},
		{1, 0.2, 0.2},
		{1, 0.3, 0.3},
		{1, 0.4, 0.4},
		{1, 0.5, 0.5},
		{1, 0.6, 0.6},
	}

	tests := []struct {
		Y           []float64
		Wn          []float64
		expectedEin float64
	}{
		{
			[]float64{1, 1, 1, -1, -1, -1},
			[]float64{-1, 0, 0},
			0.5,
		},
		{
			[]float64{-1, -1, -1, -1, -1, -1},
			[]float64{-1, 0, 0},
			0,
		},
		{
			[]float64{-1, -1, -1, -1, -1, -1},
			[]float64{1, 0, 0},
			1.0,
		},
	}

	for _, tt := range tests {
		lr.Yn = tt.Y
		lr.Wn = tt.Wn
		got := lr.Ein()
		want := tt.expectedEin
		if got != want {
			t.Errorf("Ein is not correct, got %v, want %v", got, want)
		}
	}
}

const epsilon float64 = 0.001

func equal(a, b []float64) bool {
	if len(a) != len(b) {
		return false
	}
	for i := range a {
		if (a[i] - b[i]) > epsilon {
			return false
		}
	}
	return true
}
<commit_msg>add tests to EAugIn and EValIn<commit_after>package linreg

import "testing"

func TestNewLinearRegression(t *testing.T) {
	if lr := NewLinearRegression(); lr == nil {
		t.Errorf("got nil linear regression")
	}
}

func TestInitialize(t *testing.T) {
	lr := NewLinearRegression()

	lr.Initialize()

	if len(lr.Xn) != len(lr.Yn) {
		t.Errorf("got different size of vectors Xn Yn, wants same size")
	}

	if len(lr.Xn[0]) != len(lr.Wn) {
		t.Errorf("got different size of vectors Xn Wn, wants same size")
	}

	if len(lr.Xn) != lr.TrainingPoints {
		t.Errorf("got different size of vectors Xn and training points, wants same number")
	}

	for i := 0; i < len(lr.Xn); i++ {
		for j := 0; j < len(lr.Xn[0]); j++ {
			if lr.Xn[i][j] < lr.Interval.Min ||
				lr.Xn[i][j] > lr.Interval.Max {
				t.Errorf("got value of Xn[%d][%d] = %v, want it between %v and %v", i, j, lr.Xn[i][j], lr.Interval.Min, lr.Interval.Max)
			}
		}
	}

	for i := 0; i < len(lr.Yn); i++ {
		if lr.Yn[i] != float64(-1) && lr.Yn[i] != float64(1) {
			t.Errorf("got value of Yn[%v] = %v, want it equal to -1 or 1", i, lr.Yn[i])
		}
	}

}

func TestFlip(t *testing.T) {
	lr := NewLinearRegression()
	lr.Noise = 0
	for i := 0; i < 100; i++ {
		if v := lr.flip(); v != float64(1) {
			t.Errorf("got flip value = -1 wants 1")
		}
	}
	lr.Noise = 1
	for i := 0; i < 100; i++ {
		if v := lr.flip(); v != float64(-1) {
			t.Errorf("got flip value = 1 wants -1")
		}
	}

	lr.Noise = 0.5
	for i := 0; i < 100; i++ {
		if v := lr.flip(); v != float64(-1) && v != float64(1) {
			t.Errorf("got flip value = %v wants value equal to 1 or -1", v)
		}
	}
}

func TestInitializeFromFile(t *testing.T) {
	// todo(santiaago): make this test.
}

func TestInitializeFromData(t *testing.T) {
	data := [][]float64{
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
	}
	lr := NewLinearRegression()
	if err := lr.InitializeFromData(data); err != nil {
		t.Errorf("%v", err)
	}
	if len(lr.Xn) != len(data) || len(lr.Yn) != len(data) {
		t.Errorf("got difference in size of Xn or Yn and data")
	}

	if len(lr.Xn) != lr.TrainingPoints {
		t.Errorf("got difference in size of Xn or TrainingPoints and data")
	}

	if len(lr.Xn[0]) != len(lr.Wn) {
		t.Errorf("got different size of vectors Xn Wn, wants same size")
	}

	if len(lr.Xn[0]) != lr.VectorSize || len(data[0]) != lr.VectorSize {
		t.Errorf("got difference in size of Xn[0] or data[0] with VectorSize")
	}
}

func TestInitializeValidationFromData(t *testing.T) {
	//todo(santiaago): test this
}

func TestApplyTransformation(t *testing.T) {

	tf := func(a []float64) []float64 {
		for i := 1; i < len(a); i++ {
			a[i] = -a[i]
		}
		return a
	}

	data := [][]float64{
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
	}

	lr := NewLinearRegression()
	lr.InitializeFromData(data)
	lr.TransformFunction = tf
	lr.ApplyTransformation()

	for i := 0; i < lr.TrainingPoints; i++ {
		for j := 1; j < len(lr.Xn[i]); j++ {
			if lr.Xn[i][j] != -1 {
				t.Errorf("got %v wants -1", lr.Xn[i][j])
			}
		}
		if lr.Yn[i] != 1 {
			t.Errorf("got Yn[%v] = %v wants %v", i, lr.Yn[i], 1)
		}
	}

}

func TestApplyTransformationOnValidation(t *testing.T) {
	// todo(santiaago): test this
}

func TestLearn(t *testing.T) {
	lr := NewLinearRegression()
	data := [][]float64{
		{0.1, 1, 1},
		{0.2, 1, 1},
		{0.3, 1, 1},
		{1, 0.5, -1},
		{1, 0.6, -1},
		{1, 0.7, -1},
	}

	lr.InitializeFromData(data)
	lr.Learn()
	expectedWn := []float64{0.393, -1.967, 0.983}
	if !equal(expectedWn, lr.Wn) {
		t.Errorf("Weight vector is not correct: got %v, want %v", lr.Wn, expectedWn)
	}
}

func TestSetWeight(t *testing.T) {

	lr := NewLinearRegression()
	lr.VectorSize = 5
	lr.Yn = []float64{-1, -1, -1}
	lr.TrainingPoints = 5
	d := [][]float64{
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
	}

	lr.setWeight(d)

	expectedWn := []float64{-3, -3, -3, -3, -3}
	if !equal(expectedWn, lr.Wn) {
		t.Errorf("Weight vector is not correct: got %v, want %v", lr.Wn, expectedWn)
	}
}

func TestSetWeightReg(t *testing.T) {

	lr := NewLinearRegression()
	lr.VectorSize = 5
	lr.Yn = []float64{-1, -1, -1}
	lr.TrainingPoints = 5
	d := [][]float64{
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
		{1, 1, 1},
	}

	lr.setWeightReg(d)

	expectedWReg := []float64{-3, -3, -3, -3, -3}
	if !equal(expectedWReg, lr.WReg) {
		t.Errorf("Weight vector is not correct: got %v, want %v", lr.WReg, expectedWReg)
	}
}

func TestEin(t *testing.T) {
	lr := NewLinearRegression()
	lr.Xn = [][]float64{
		{1, 0.1, 0.1},
		{1, 0.2, 0.2},
		{1, 0.3, 0.3},
		{1, 0.4, 0.4},
		{1, 0.5, 0.5},
		{1, 0.6, 0.6},
	}

	tests := []struct {
		Y           []float64
		Wn          []float64
		expectedEin float64
	}{
		{
			[]float64{1, 1, 1, -1, -1, -1},
			[]float64{-1, 0, 0},
			0.5,
		},
		{
			[]float64{-1, -1, -1, -1, -1, -1},
			[]float64{-1, 0, 0},
			0,
		},
		{
			[]float64{-1, -1, -1, -1, -1, -1},
			[]float64{1, 0, 0},
			1.0,
		},
	}

	for _, tt := range tests {
		lr.Yn = tt.Y
		lr.Wn = tt.Wn
		got := lr.Ein()
		want := tt.expectedEin
		if got != want {
			t.Errorf("Ein is not correct, got %v, want %v", got, want)
		}
	}
}

func TestEAugIn(t *testing.T) {
	lr := NewLinearRegression()
	lr.Xn = [][]float64{
		{1, 0.1, 0.1},
		{1, 0.2, 0.2},
		{1, 0.3, 0.3},
		{1, 0.4, 0.4},
		{1, 0.5, 0.5},
		{1, 0.6, 0.6},
	}

	tests := []struct {
		Y              []float64
		WReg           []float64
		expectedEAugIn float64
	}{
		{
			[]float64{1, 1, 1, -1, -1, -1},
			[]float64{-1, 0, 0},
			0.5,
		},
		{
			[]float64{-1, -1, -1, -1, -1, -1},
			[]float64{-1, 0, 0},
			0,
		},
		{
			[]float64{-1, -1, -1, -1, -1, -1},
			[]float64{1, 0, 0},
			1.0,
		},
	}

	for _, tt := range tests {
		lr.Yn = tt.Y
		lr.WReg = tt.WReg
		got := lr.EAugIn()
		want := tt.expectedEAugIn
		if got != want {
			t.Errorf("Ein is not correct, got %v, want %v", got, want)
		}
	}
}

func TestEValIn(t *testing.T) {
	lr := NewLinearRegression()
	lr.XVal = [][]float64{
		{1, 0.1, 0.1},
		{1, 0.2, 0.2},
		{1, 0.3, 0.3},
		{1, 0.4, 0.4},
		{1, 0.5, 0.5},
		{1, 0.6, 0.6},
	}

	tests := []struct {
		YVal           []float64
		Wn             []float64
		expectedEValIn float64
	}{
		{
			[]float64{1, 1, 1, -1, -1, -1},
			[]float64{-1, 0, 0},
			0.5,
		},
		{
			[]float64{-1, -1, -1, -1, -1, -1},
			[]float64{-1, 0, 0},
			0,
		},
		{
			[]float64{-1, -1, -1, -1, -1, -1},
			[]float64{1, 0, 0},
			1.0,
		},
	}

	for _, tt := range tests {
		lr.YVal = tt.YVal
		lr.Wn = tt.Wn
		got := lr.EValIn()
		want := tt.expectedEValIn
		if got != want {
			t.Errorf("Ein is not correct, got %v, want %v", got, want)
		}
	}
}

const epsilon float64 = 0.001

func equal(a, b []float64) bool {
	if len(a) != len(b) {
		return false
	}
	for i := range a {
		if (a[i] - b[i]) > epsilon {
			return false
		}
	}
	return true
}
<|endoftext|>