<commit_before>package commands

import (
	"errors"
	"fmt"
	"io"
	"reflect"
	"strconv"

	"github.com/jbenet/go-ipfs/config"
	"github.com/jbenet/go-ipfs/core"
	u "github.com/jbenet/go-ipfs/util"
)

type optMap map[string]interface{}

type Context struct {
	ConfigRoot string

	config     *config.Config
	LoadConfig func(path string) (*config.Config, error)

	node          *core.IpfsNode
	ConstructNode func() (*core.IpfsNode, error)
}

// GetConfig returns the config of the current Command exection
// context. It may load it with the providied function.
func (c *Context) GetConfig() (*config.Config, error) {
	var err error
	if c.config == nil {
		if c.LoadConfig == nil {
			return nil, errors.New("nil LoadConfig function")
		}
		c.config, err = c.LoadConfig(c.ConfigRoot)
	}
	return c.config, err
}

// GetNode returns the node of the current Command exection
// context. It may construct it with the providied function.
func (c *Context) GetNode() (*core.IpfsNode, error) {
	var err error
	if c.node == nil {
		if c.ConstructNode == nil {
			return nil, errors.New("nil ConstructNode function")
		}
		c.node, err = c.ConstructNode()
	}
	return c.node, err
}

// NodeWithoutConstructing returns the underlying node variable
// so that clients may close it.
func (c *Context) NodeWithoutConstructing() *core.IpfsNode {
	return c.node
}

// Request represents a call to a command from a consumer
type Request interface {
	Path() []string
	Option(name string) *OptionValue
	Options() optMap
	SetOption(name string, val interface{})

	// Arguments() returns user provided arguments as declared on the Command.
	//
	// NB: `io.Reader`s returned by Arguments() are owned by the library.
	// Readers are not guaranteed to remain open after the Command's Run
	// function returns.
	Arguments() []interface{} // TODO: make argument value type instead of using interface{}
	Context() *Context
	SetContext(Context)
	Command() *Command
	Cleanup() error

	ConvertOptions() error
}

type request struct {
	path       []string
	options    optMap
	arguments  []interface{}
	cmd        *Command
	ctx        Context
	optionDefs map[string]Option
}

// Path returns the command path of this request
func (r *request) Path() []string {
	return r.path
}

// Option returns the value of the option for given name.
func (r *request) Option(name string) *OptionValue {
	val, found := r.options[name]
	if found {
		return &OptionValue{val, found}
	}

	// if a value isn't defined for that name, we will try to look it up by its aliases

	// find the option with the specified name
	option, found := r.optionDefs[name]
	if !found {
		return nil
	}

	// try all the possible names, break if we find a value
	for _, n := range option.Names {
		val, found = r.options[n]
		if found {
			return &OptionValue{val, found}
		}
	}

	// MAYBE_TODO: use default value instead of nil
	return &OptionValue{nil, false}
}

// Options returns a copy of the option map
func (r *request) Options() optMap {
	output := make(optMap)
	for k, v := range r.options {
		output[k] = v
	}
	return output
}

// SetOption sets the value of the option for given name.
func (r *request) SetOption(name string, val interface{}) {
	// find the option with the specified name
	option, found := r.optionDefs[name]
	if !found {
		return
	}

	// try all the possible names, if we already have a value then set over it
	for _, n := range option.Names {
		_, found := r.options[n]
		if found {
			r.options[n] = val
			return
		}
	}

	r.options[name] = val
}

// Arguments returns the arguments slice
func (r *request) Arguments() []interface{} {
	return r.arguments
}

func (r *request) Context() *Context {
	return &r.ctx
}

func (r *request) SetContext(ctx Context) {
	r.ctx = ctx
}

func (r *request) Command() *Command {
	return r.cmd
}

func (r *request) Cleanup() error {
	for _, arg := range r.arguments {
		closer, ok := arg.(io.Closer)
		if ok {
			err := closer.Close()
			if err != nil {
				return err
			}
		}
	}

	return nil
}

type converter func(string) (interface{}, error)

var converters = map[reflect.Kind]converter{
	Bool: func(v string) (interface{}, error) {
		if v == "" {
			return true, nil
		}
		return strconv.ParseBool(v)
	},
	Int: func(v string) (interface{}, error) {
		val, err := strconv.ParseInt(v, 0, 32)
		if err != nil {
			return nil, err
		}
		return int(val), err
	},
	Uint: func(v string) (interface{}, error) {
		val, err := strconv.ParseUint(v, 0, 32)
		if err != nil {
			return nil, err
		}
		return int(val), err
	},
	Float: func(v string) (interface{}, error) {
		return strconv.ParseFloat(v, 64)
	},
}

func (r *request) ConvertOptions() error {
	for k, v := range r.options {
		opt, ok := r.optionDefs[k]
		if !ok {
			continue
		}

		kind := reflect.TypeOf(v).Kind()
		if kind != opt.Type {
			if kind == String {
				convert := converters[opt.Type]
				str, ok := v.(string)
				if !ok {
					return u.ErrCast()
				}
				val, err := convert(str)
				if err != nil {
					return fmt.Errorf("Could not convert string value '%s' to type '%s'",
						v, opt.Type.String())
				}
				r.options[k] = val

			} else {
				return fmt.Errorf("Option '%s' should be type '%s', but got type '%s'",
					k, opt.Type.String(), kind.String())
			}
		} else {
			r.options[k] = v
		}

		for _, name := range opt.Names {
			if _, ok := r.options[name]; name != k && ok {
				return fmt.Errorf("Duplicate command options were provided ('%s' and '%s')",
					k, name)
			}
		}
	}

	return nil
}

// NewEmptyRequest initializes an empty request
func NewEmptyRequest() (Request, error) {
	return NewRequest(nil, nil, nil, nil, nil)
}

// NewRequest returns a request initialized with given arguments
func NewRequest(path []string, opts optMap, args []interface{}, cmd *Command, optDefs map[string]Option) (Request, error) {
	if path == nil {
		path = make([]string, 0)
	}
	if opts == nil {
		opts = make(map[string]interface{})
	}
	if args == nil {
		args = make([]interface{}, 0)
	}
	if optDefs == nil {
		optDefs = make(map[string]Option)
	}

	req := &request{path, opts, args, cmd, Context{}, optDefs}
	err := req.ConvertOptions()
	if err != nil {
		return nil, err
	}

	return req, nil
}
<commit_msg>commands: Improved option conversin error message<commit_after>package commands

import (
	"errors"
	"fmt"
	"io"
	"reflect"
	"strconv"

	"github.com/jbenet/go-ipfs/config"
	"github.com/jbenet/go-ipfs/core"
	u "github.com/jbenet/go-ipfs/util"
)

type optMap map[string]interface{}

type Context struct {
	ConfigRoot string

	config     *config.Config
	LoadConfig func(path string) (*config.Config, error)

	node          *core.IpfsNode
	ConstructNode func() (*core.IpfsNode, error)
}

// GetConfig returns the config of the current Command exection
// context. It may load it with the providied function.
func (c *Context) GetConfig() (*config.Config, error) {
	var err error
	if c.config == nil {
		if c.LoadConfig == nil {
			return nil, errors.New("nil LoadConfig function")
		}
		c.config, err = c.LoadConfig(c.ConfigRoot)
	}
	return c.config, err
}

// GetNode returns the node of the current Command exection
// context. It may construct it with the providied function.
func (c *Context) GetNode() (*core.IpfsNode, error) {
	var err error
	if c.node == nil {
		if c.ConstructNode == nil {
			return nil, errors.New("nil ConstructNode function")
		}
		c.node, err = c.ConstructNode()
	}
	return c.node, err
}

// NodeWithoutConstructing returns the underlying node variable
// so that clients may close it.
func (c *Context) NodeWithoutConstructing() *core.IpfsNode {
	return c.node
}

// Request represents a call to a command from a consumer
type Request interface {
	Path() []string
	Option(name string) *OptionValue
	Options() optMap
	SetOption(name string, val interface{})

	// Arguments() returns user provided arguments as declared on the Command.
	//
	// NB: `io.Reader`s returned by Arguments() are owned by the library.
	// Readers are not guaranteed to remain open after the Command's Run
	// function returns.
	Arguments() []interface{} // TODO: make argument value type instead of using interface{}
	Context() *Context
	SetContext(Context)
	Command() *Command
	Cleanup() error

	ConvertOptions() error
}

type request struct {
	path       []string
	options    optMap
	arguments  []interface{}
	cmd        *Command
	ctx        Context
	optionDefs map[string]Option
}

// Path returns the command path of this request
func (r *request) Path() []string {
	return r.path
}

// Option returns the value of the option for given name.
func (r *request) Option(name string) *OptionValue {
	val, found := r.options[name]
	if found {
		return &OptionValue{val, found}
	}

	// if a value isn't defined for that name, we will try to look it up by its aliases

	// find the option with the specified name
	option, found := r.optionDefs[name]
	if !found {
		return nil
	}

	// try all the possible names, break if we find a value
	for _, n := range option.Names {
		val, found = r.options[n]
		if found {
			return &OptionValue{val, found}
		}
	}

	// MAYBE_TODO: use default value instead of nil
	return &OptionValue{nil, false}
}

// Options returns a copy of the option map
func (r *request) Options() optMap {
	output := make(optMap)
	for k, v := range r.options {
		output[k] = v
	}
	return output
}

// SetOption sets the value of the option for given name.
func (r *request) SetOption(name string, val interface{}) {
	// find the option with the specified name
	option, found := r.optionDefs[name]
	if !found {
		return
	}

	// try all the possible names, if we already have a value then set over it
	for _, n := range option.Names {
		_, found := r.options[n]
		if found {
			r.options[n] = val
			return
		}
	}

	r.options[name] = val
}

// Arguments returns the arguments slice
func (r *request) Arguments() []interface{} {
	return r.arguments
}

func (r *request) Context() *Context {
	return &r.ctx
}

func (r *request) SetContext(ctx Context) {
	r.ctx = ctx
}

func (r *request) Command() *Command {
	return r.cmd
}

func (r *request) Cleanup() error {
	for _, arg := range r.arguments {
		closer, ok := arg.(io.Closer)
		if ok {
			err := closer.Close()
			if err != nil {
				return err
			}
		}
	}

	return nil
}

type converter func(string) (interface{}, error)

var converters = map[reflect.Kind]converter{
	Bool: func(v string) (interface{}, error) {
		if v == "" {
			return true, nil
		}
		return strconv.ParseBool(v)
	},
	Int: func(v string) (interface{}, error) {
		val, err := strconv.ParseInt(v, 0, 32)
		if err != nil {
			return nil, err
		}
		return int(val), err
	},
	Uint: func(v string) (interface{}, error) {
		val, err := strconv.ParseUint(v, 0, 32)
		if err != nil {
			return nil, err
		}
		return int(val), err
	},
	Float: func(v string) (interface{}, error) {
		return strconv.ParseFloat(v, 64)
	},
}

func (r *request) ConvertOptions() error {
	for k, v := range r.options {
		opt, ok := r.optionDefs[k]
		if !ok {
			continue
		}

		kind := reflect.TypeOf(v).Kind()
		if kind != opt.Type {
			if kind == String {
				convert := converters[opt.Type]
				str, ok := v.(string)
				if !ok {
					return u.ErrCast()
				}
				val, err := convert(str)
				if err != nil {
					value := fmt.Sprintf("value '%v'", v)
					if len(str) == 0 {
						value = "empty value"
					}
					return fmt.Errorf("Could not convert %s to type '%s' (for option '-%s')",
						value, opt.Type.String(), k)
				}
				r.options[k] = val

			} else {
				return fmt.Errorf("Option '%s' should be type '%s', but got type '%s'",
					k, opt.Type.String(), kind.String())
			}
		} else {
			r.options[k] = v
		}

		for _, name := range opt.Names {
			if _, ok := r.options[name]; name != k && ok {
				return fmt.Errorf("Duplicate command options were provided ('%s' and '%s')",
					k, name)
			}
		}
	}

	return nil
}

// NewEmptyRequest initializes an empty request
func NewEmptyRequest() (Request, error) {
	return NewRequest(nil, nil, nil, nil, nil)
}

// NewRequest returns a request initialized with given arguments
func NewRequest(path []string, opts optMap, args []interface{}, cmd *Command, optDefs map[string]Option) (Request, error) {
	if path == nil {
		path = make([]string, 0)
	}
	if opts == nil {
		opts = make(map[string]interface{})
	}
	if args == nil {
		args = make([]interface{}, 0)
	}
	if optDefs == nil {
		optDefs = make(map[string]Option)
	}

	req := &request{path, opts, args, cmd, Context{}, optDefs}
	err := req.ConvertOptions()
	if err != nil {
		return nil, err
	}

	return req, nil
}
<|endoftext|>


<commit_before>package google

import "fmt"

func GetProjectIamPolicyCaiObject(d TerraformResourceData, config *Config) (Asset, error) {
	return newProjectIamAsset(d, config, expandIamPolicyBindings)
}

func GetProjectIamBindingCaiObject(d TerraformResourceData, config *Config) (Asset, error) {
	return newProjectIamAsset(d, config, expandIamRoleBindings)
}

func GetProjectIamMemberCaiObject(d TerraformResourceData, config *Config) (Asset, error) {
	return newProjectIamAsset(d, config, expandIamMemberBindings)
}

func MergeProjectIamPolicy(existing, incoming Asset) Asset {
	existing.IAMPolicy = incoming.IAMPolicy
	return existing
}

func MergeProjectIamBinding(existing, incoming Asset) Asset {
	return mergeIamAssets(existing, incoming, mergeAuthoritativeBindings)
}

func MergeProjectIamMember(existing, incoming Asset) Asset {
	return mergeIamAssets(existing, incoming, mergeAdditiveBindings)
}

func newProjectIamAsset(
	d TerraformResourceData,
	config *Config,
	expandBindings func(d TerraformResourceData) ([]IAMBinding, error),
) (Asset, error) {
	bindings, err := expandBindings(d)
	if err != nil {
		return Asset{}, fmt.Errorf("expanding bindings: %v", err)
	}

	// Ideally we should use project_number, but since that is generated server-side,
	// we substitute project_id.
	name, err := assetName(d, config, "//cloudresourcemanager.googleapis.com/projects/{{project}}")
	if err != nil {
		return Asset{}, err
	}

	return Asset{
		Name: name,
		Type: "cloudresourcemanager.googleapis.com/Project",
		IAMPolicy: &IAMPolicy{
			Bindings: bindings,
		},
	}, nil
}
<commit_msg>Added mergeDelete and fetch functions for Project IAM<commit_after>package google

import "fmt"

func GetProjectIamPolicyCaiObject(d TerraformResourceData, config *Config) (Asset, error) {
	return newProjectIamAsset(d, config, expandIamPolicyBindings)
}

func GetProjectIamBindingCaiObject(d TerraformResourceData, config *Config) (Asset, error) {
	return newProjectIamAsset(d, config, expandIamRoleBindings)
}

func GetProjectIamMemberCaiObject(d TerraformResourceData, config *Config) (Asset, error) {
	return newProjectIamAsset(d, config, expandIamMemberBindings)
}

func MergeProjectIamPolicy(existing, incoming Asset) Asset {
	existing.IAMPolicy = incoming.IAMPolicy
	return existing
}

func MergeProjectIamBinding(existing, incoming Asset) Asset {
	return mergeIamAssets(existing, incoming, mergeAuthoritativeBindings)
}

func MergeProjectIamBindingDelete(existing, incoming Asset) Asset {
	return mergeDeleteIamAssets(existing, incoming, mergeDeleteAuthoritativeBindings)
}

func MergeProjectIamMember(existing, incoming Asset) Asset {
	return mergeIamAssets(existing, incoming, mergeAdditiveBindings)
}

func MergeProjectIamMemberDelete(existing, incoming Asset) Asset {
	return mergeDeleteIamAssets(existing, incoming, mergeDeleteAdditiveBindings)
}

func newProjectIamAsset(
	d TerraformResourceData,
	config *Config,
	expandBindings func(d TerraformResourceData) ([]IAMBinding, error),
) (Asset, error) {
	bindings, err := expandBindings(d)
	if err != nil {
		return Asset{}, fmt.Errorf("expanding bindings: %v", err)
	}

	// Ideally we should use project_number, but since that is generated server-side,
	// we substitute project_id.
	name, err := assetName(d, config, "//cloudresourcemanager.googleapis.com/projects/{{project}}")
	if err != nil {
		return Asset{}, err
	}

	return Asset{
		Name: name,
		Type: "cloudresourcemanager.googleapis.com/Project",
		IAMPolicy: &IAMPolicy{
			Bindings: bindings,
		},
	}, nil
}

func FetchProjectIamPolicy(d TerraformResourceData, config *Config) (Asset, error) {
	updater, err := NewProjectIamUpdater(d, config)
	if err != nil {
		return Asset{}, err
	}

	iamPolicy, err := updater.GetResourceIamPolicy()
	if err != nil {
		return Asset{}, err
	}

	var bindings []IAMBinding
	for _, b := range iamPolicy.Bindings {
		bindings = append(
			bindings,
			IAMBinding{
				Role:    b.Role,
				Members: b.Members,
			},
		)
	}

	// We use project_id to be consistent with newProjectIamAsset.
	name, err := assetName(d, config, "//cloudresourcemanager.googleapis.com/projects/{{project}}")

	return Asset{
		Name: name,
		Type: "cloudresourcemanager.googleapis.com/Project",
		IAMPolicy: &IAMPolicy{
			Bindings: bindings,
		},
	}, nil
}
<|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.

// +build appengine

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"net/http"

	"appengine"
	"appengine/urlfetch"
)

const runUrl = "http://golang.org/compile"

func init() {
	http.HandleFunc("/", rootHandler)
	http.HandleFunc("/compile", compileHandler)
	err := serveScripts("js", "playground.js")
	if err != nil {
		panic(err)
	}
	if err := initTour("."); err != nil {
		panic(err)
	}
}

func rootHandler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	if err := renderTour(w); err != nil {
		c.Criticalf("template render: %v", err)
	}
}

func compileHandler(w http.ResponseWriter, r *http.Request) {
	if err := passThru(w, r); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprintln(w, "Compile server error.")
	}
}

func passThru(w io.Writer, req *http.Request) error {
	c := appengine.NewContext(req)
	client := urlfetch.Client(c)
	defer req.Body.Close()
	r, err := client.Post(runUrl, req.Header.Get("Content-type"), req.Body)
	if err != nil {
		c.Errorf("making POST request:", err)
		return err
	}
	defer r.Body.Close()
	if _, err := io.Copy(w, r.Body); err != nil {
		c.Errorf("copying response Body:", err)
		return err
	}
	return nil
}

// prepContent returns a Reader that produces the content from the given
// Reader, but strips the prefix "#appengine: " from each line. It also drops
// any non-blank like that follows a series of 1 or more lines with the prefix.
func prepContent(in io.Reader) io.Reader {
	var prefix = []byte("#appengine: ")
	out, w := io.Pipe()
	go func() {
		r := bufio.NewReader(in)
		drop := false
		for {
			b, err := r.ReadBytes('\n')
			if err != nil && err != io.EOF {
				w.CloseWithError(err)
				return
			}
			if bytes.HasPrefix(b, prefix) {
				b = b[len(prefix):]
				drop = true
			} else if drop {
				if len(b) > 1 {
					b = nil
				}
				drop = false
			}
			if len(b) > 0 {
				w.Write(b)
			}
			if err == io.EOF {
				w.Close()
				return
			}
		}
	}()
	return out
}

// socketAddr returns the WebSocket handler address.
// The App Engine version does not provide a WebSocket handler.
func socketAddr() string { return "" }
<commit_msg>Apply codereview.appspot.com/8839044<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.

// +build appengine

package main

import (
	"bufio"
	"bytes"
	"io"
	"net/http"

	"appengine"

	_ "code.google.com/p/go.talks/pkg/playground"
)

const runUrl = "http://golang.org/compile"

func init() {
	http.HandleFunc("/", rootHandler)
	err := serveScripts("js", "playground.js")
	if err != nil {
		panic(err)
	}
	if err := initTour("."); err != nil {
		panic(err)
	}
}

func rootHandler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	if err := renderTour(w); err != nil {
		c.Criticalf("template render: %v", err)
	}
}

// prepContent returns a Reader that produces the content from the given
// Reader, but strips the prefix "#appengine: " from each line. It also drops
// any non-blank like that follows a series of 1 or more lines with the prefix.
func prepContent(in io.Reader) io.Reader {
	var prefix = []byte("#appengine: ")
	out, w := io.Pipe()
	go func() {
		r := bufio.NewReader(in)
		drop := false
		for {
			b, err := r.ReadBytes('\n')
			if err != nil && err != io.EOF {
				w.CloseWithError(err)
				return
			}
			if bytes.HasPrefix(b, prefix) {
				b = b[len(prefix):]
				drop = true
			} else if drop {
				if len(b) > 1 {
					b = nil
				}
				drop = false
			}
			if len(b) > 0 {
				w.Write(b)
			}
			if err == io.EOF {
				w.Close()
				return
			}
		}
	}()
	return out
}

// socketAddr returns the WebSocket handler address.
// The App Engine version does not provide a WebSocket handler.
func socketAddr() string { return "" }
<|endoftext|>


<commit_before>package goage

import (
	"testing"
	"time"
)

type AgeTestCandidate struct {
	BirthDate    time.Time
	CheckingTime time.Time
	ExpectedAge  int
}

var AgeTestCandidates = []AgeTestCandidate{
	{time.Date(2000, 3, 14, 0, 0, 0, 0, time.UTC), time.Date(2010, 3, 14, 0, 0, 0, 0, time.UTC), 10},
	{time.Date(2001, 3, 14, 0, 0, 0, 0, time.UTC), time.Date(2009, 3, 14, 0, 0, 0, 0, time.UTC), 8},
	{time.Date(2004, 6, 18, 0, 0, 0, 0, time.UTC), time.Date(2005, 5, 12, 0, 0, 0, 0, time.UTC), 0},
}

func TestPlayerAge(t *testing.T) {
	for _, candidate := range AgeTestCandidates {
		gotAge := AgeAt(candidate.BirthDate, candidate.CheckingTime)
		if gotAge != candidate.ExpectedAge {
			t.Error(
				"For", candidate.BirthDate,
				"Expected", candidate.ExpectedAge,
				"Got", gotAge,
			)
		}
	}
}
<commit_msg>Changed misnamed test.<commit_after>package goage

import (
	"testing"
	"time"
)

type AgeTestCandidate struct {
	BirthDate    time.Time
	CheckingTime time.Time
	ExpectedAge  int
}

var AgeTestCandidates = []AgeTestCandidate{
	{time.Date(2000, 3, 14, 0, 0, 0, 0, time.UTC), time.Date(2010, 3, 14, 0, 0, 0, 0, time.UTC), 10},
	{time.Date(2001, 3, 14, 0, 0, 0, 0, time.UTC), time.Date(2009, 3, 14, 0, 0, 0, 0, time.UTC), 8},
	{time.Date(2004, 6, 18, 0, 0, 0, 0, time.UTC), time.Date(2005, 5, 12, 0, 0, 0, 0, time.UTC), 0},
}

func TestAgeAt(t *testing.T) {
	for _, candidate := range AgeTestCandidates {
		gotAge := AgeAt(candidate.BirthDate, candidate.CheckingTime)
		if gotAge != candidate.ExpectedAge {
			t.Error(
				"For", candidate.BirthDate,
				"Expected", candidate.ExpectedAge,
				"Got", gotAge,
			)
		}
	}
}
<|endoftext|>


<commit_before>/*--------------------------------------------------------*\
|                                                          |
|                          hprose                          |
|                                                          |
| Official WebSite: https://hprose.com                     |
|                                                          |
| rpc/http/handler.go                                      |
|                                                          |
| LastModified: May 5, 2021                                |
| Author: Ma Bingyao <andot@hprose.com>                    |
|                                                          |
\*________________________________________________________*/

package http

import (
	"context"
	"io/ioutil"
	"math/rand"
	"net"
	"net/http"
	"reflect"
	"strconv"
	"strings"
	"time"

	"github.com/hprose/hprose-golang/v3/rpc/core"
)

type Handler struct {
	Service                      *core.Service
	OnError                      func(error)
	P3P                          bool
	GET                          bool
	CrossDomain                  bool
	Header                       http.Header
	AccessControlAllowOrigins    map[string]bool
	LastModified                 string
	Etag                         string
	crossDomainXMLFile           string
	crossDomainXMLContent        []byte
	clientAccessPolicyXMLFile    string
	clientAccessPolicyXMLContent []byte
}

func (h *Handler) onError(err error) {
	if h.OnError != nil {
		h.OnError(err)
	}
}

// AddAccessControlAllowOrigin add access control allow origin.
func (h *Handler) AddAccessControlAllowOrigin(origins ...string) {
	for _, origin := range origins {
		h.AccessControlAllowOrigins[origin] = true
	}
}

// RemoveAccessControlAllowOrigin remove access control allow origin.
func (h *Handler) RemoveAccessControlAllowOrigin(origins ...string) {
	for _, origin := range origins {
		delete(h.AccessControlAllowOrigins, origin)
	}
}

// CrossDomainXMLFile return the cross domain xml file.
func (h *Handler) CrossDomainXMLFile() string {
	return h.crossDomainXMLFile
}

// CrossDomainXMLContent return the cross domain xml content.
func (h *Handler) CrossDomainXMLContent() []byte {
	return h.crossDomainXMLContent
}

// ClientAccessPolicyXMLFile return the client access policy xml file.
func (h *Handler) ClientAccessPolicyXMLFile() string {
	return h.clientAccessPolicyXMLFile
}

// ClientAccessPolicyXMLContent return the client access policy xml content.
func (h *Handler) ClientAccessPolicyXMLContent() []byte {
	return h.clientAccessPolicyXMLContent
}

// SetCrossDomainXMLFile set the cross domain xml file.
func (h *Handler) SetCrossDomainXMLFile(filename string) {
	h.crossDomainXMLFile = filename
	h.crossDomainXMLContent, _ = ioutil.ReadFile(filename)
}

// SetClientAccessPolicyXMLFile set the client access policy xml file.
func (h *Handler) SetClientAccessPolicyXMLFile(filename string) {
	h.clientAccessPolicyXMLFile = filename
	h.clientAccessPolicyXMLContent, _ = ioutil.ReadFile(filename)
}

// SetCrossDomainXMLContent set the cross domain xml content.
func (h *Handler) SetCrossDomainXMLContent(content []byte) {
	h.crossDomainXMLFile = ""
	h.crossDomainXMLContent = content
}

// SetClientAccessPolicyXMLContent set the client access policy xml content.
func (h *Handler) SetClientAccessPolicyXMLContent(content []byte) {
	h.clientAccessPolicyXMLFile = ""
	h.clientAccessPolicyXMLContent = content
}

// BindContext to the http server.
func (h *Handler) BindContext(ctx context.Context, server core.Server) {
	s := server.(*http.Server)
	s.Handler = h
	s.BaseContext = func(l net.Listener) context.Context {
		return ctx
	}
}

// ServeHTTP implements the http.Handler interface.
func (h *Handler) ServeHTTP(response http.ResponseWriter, request *http.Request) {
	if request.ContentLength > int64(h.Service.MaxRequestLength) {
		response.WriteHeader(http.StatusRequestEntityTooLarge)
		return
	}
	if request.Method == "GET" {
		if h.clientAccessPolicyXMLHandler(response, request) ||
			h.crossDomainXMLHandler(response, request) {
			return
		}
		if !h.GET {
			response.WriteHeader(http.StatusForbidden)
			return
		}
	}
	data, err := readAll(request.Body, request.ContentLength)
	if err != nil {
		h.onError(err)
	}
	if err = request.Body.Close(); err != nil {
		h.onError(err)
	}
	serviceContext := h.getServiceContext(response, request)
	ctx := core.WithContext(request.Context(), serviceContext)
	result, err := h.Service.Handle(ctx, data)
	if err != nil {
		h.onError(err)
	}
	response.Header().Set("Content-Length", strconv.Itoa(len(result)))
	h.sendHeader(serviceContext, response, request)
	_, err = response.Write(result)
	if err != nil {
		h.onError(err)
	}
}

func (h *Handler) xmlFileHandler(response http.ResponseWriter, request *http.Request, path string, content []byte) bool {
	if content == nil || strings.ToLower(request.URL.Path) != path {
		return false
	}
	if request.Header.Get("if-modified-since") == h.LastModified &&
		request.Header.Get("if-none-match") == h.Etag {
		response.WriteHeader(304)
	} else {
		contentLength := len(content)
		header := response.Header()
		header.Set("Last-Modified", h.LastModified)
		header.Set("Etag", h.Etag)
		header.Set("Content-Type", "text/xml")
		header.Set("Content-Length", strconv.Itoa(contentLength))
		_, _ = response.Write(content)
	}
	return true
}

func (h *Handler) crossDomainXMLHandler(response http.ResponseWriter, request *http.Request) bool {
	return h.xmlFileHandler(response, request, "/crossdomain.xml", h.crossDomainXMLContent)
}

func (h *Handler) clientAccessPolicyXMLHandler(response http.ResponseWriter, request *http.Request) bool {
	return h.xmlFileHandler(response, request, "/clientaccesspolicy.xml", h.clientAccessPolicyXMLContent)
}

func (h *Handler) sendHeader(serviceContext *core.ServiceContext, response http.ResponseWriter, request *http.Request) {
	responseHeader := response.Header()
	responseHeader.Set("Content-Type", "text/plain")
	if h.P3P {
		responseHeader.Set("P3P",
			`CP="CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi `+
				`CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL `+
				`UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV"`)
	}
	if h.CrossDomain {
		origin := request.Header.Get("origin")
		if origin != "" && origin != "null" {
			if len(h.AccessControlAllowOrigins) == 0 ||
				h.AccessControlAllowOrigins[origin] {
				responseHeader.Set("Access-Control-Allow-Origin", origin)
				responseHeader.Set("Access-Control-Allow-Credentials", "true")
			}
		} else {
			responseHeader.Set("Access-Control-Allow-Origin", "*")
		}
	}
	if h.Header != nil {
		addHeader(responseHeader, h.Header)
	}
	if header, ok := serviceContext.Items().Get("httpResponseHeaders"); ok {
		if header, ok := header.(http.Header); ok {
			addHeader(responseHeader, header)
		}
	}
	if code := serviceContext.Items().GetInt("httpStatusCode"); code != 0 {
		response.WriteHeader(code)
	}
}

func (h *Handler) getServiceContext(response http.ResponseWriter, request *http.Request) *core.ServiceContext {
	serviceContext := core.NewServiceContext(h.Service)
	serviceContext.Items().Set("request", request)
	serviceContext.Items().Set("response", response)
	serviceContext.Items().Set("httpRequestHeaders", request.Header)
	serviceContext.LocalAddr, _ = net.ResolveTCPAddr("tcp", request.Host)
	serviceContext.RemoteAddr, _ = net.ResolveTCPAddr("tcp", request.RemoteAddr)
	serviceContext.Handler = h
	return serviceContext
}

type handlerFactory struct {
	serverTypes []reflect.Type
}

func (factory handlerFactory) ServerTypes() []reflect.Type {
	return factory.serverTypes
}

func (factory handlerFactory) New(service *core.Service) core.Handler {
	return &Handler{
		Service:                   service,
		P3P:                       true,
		GET:                       true,
		CrossDomain:               true,
		AccessControlAllowOrigins: make(map[string]bool),
		LastModified:              time.Now().UTC().Format(time.RFC1123),
		Etag:                      `"` + strconv.FormatInt(rand.Int63(), 16) + `"`,
	}
}

func RegisterHandler() {
	core.RegisterHandler("http", handlerFactory{
		[]reflect.Type{
			reflect.TypeOf((*http.Server)(nil)),
		},
	})
}
<commit_msg>use http.StatusNotModified instead of 304<commit_after>/*--------------------------------------------------------*\
|                                                          |
|                          hprose                          |
|                                                          |
| Official WebSite: https://hprose.com                     |
|                                                          |
| rpc/http/handler.go                                      |
|                                                          |
| LastModified: May 5, 2021                                |
| Author: Ma Bingyao <andot@hprose.com>                    |
|                                                          |
\*________________________________________________________*/

package http

import (
	"context"
	"io/ioutil"
	"math/rand"
	"net"
	"net/http"
	"reflect"
	"strconv"
	"strings"
	"time"

	"github.com/hprose/hprose-golang/v3/rpc/core"
)

type Handler struct {
	Service                      *core.Service
	OnError                      func(error)
	P3P                          bool
	GET                          bool
	CrossDomain                  bool
	Header                       http.Header
	AccessControlAllowOrigins    map[string]bool
	LastModified                 string
	Etag                         string
	crossDomainXMLFile           string
	crossDomainXMLContent        []byte
	clientAccessPolicyXMLFile    string
	clientAccessPolicyXMLContent []byte
}

func (h *Handler) onError(err error) {
	if h.OnError != nil {
		h.OnError(err)
	}
}

// AddAccessControlAllowOrigin add access control allow origin.
func (h *Handler) AddAccessControlAllowOrigin(origins ...string) {
	for _, origin := range origins {
		h.AccessControlAllowOrigins[origin] = true
	}
}

// RemoveAccessControlAllowOrigin remove access control allow origin.
func (h *Handler) RemoveAccessControlAllowOrigin(origins ...string) {
	for _, origin := range origins {
		delete(h.AccessControlAllowOrigins, origin)
	}
}

// CrossDomainXMLFile return the cross domain xml file.
func (h *Handler) CrossDomainXMLFile() string {
	return h.crossDomainXMLFile
}

// CrossDomainXMLContent return the cross domain xml content.
func (h *Handler) CrossDomainXMLContent() []byte {
	return h.crossDomainXMLContent
}

// ClientAccessPolicyXMLFile return the client access policy xml file.
func (h *Handler) ClientAccessPolicyXMLFile() string {
	return h.clientAccessPolicyXMLFile
}

// ClientAccessPolicyXMLContent return the client access policy xml content.
func (h *Handler) ClientAccessPolicyXMLContent() []byte {
	return h.clientAccessPolicyXMLContent
}

// SetCrossDomainXMLFile set the cross domain xml file.
func (h *Handler) SetCrossDomainXMLFile(filename string) {
	h.crossDomainXMLFile = filename
	h.crossDomainXMLContent, _ = ioutil.ReadFile(filename)
}

// SetClientAccessPolicyXMLFile set the client access policy xml file.
func (h *Handler) SetClientAccessPolicyXMLFile(filename string) {
	h.clientAccessPolicyXMLFile = filename
	h.clientAccessPolicyXMLContent, _ = ioutil.ReadFile(filename)
}

// SetCrossDomainXMLContent set the cross domain xml content.
func (h *Handler) SetCrossDomainXMLContent(content []byte) {
	h.crossDomainXMLFile = ""
	h.crossDomainXMLContent = content
}

// SetClientAccessPolicyXMLContent set the client access policy xml content.
func (h *Handler) SetClientAccessPolicyXMLContent(content []byte) {
	h.clientAccessPolicyXMLFile = ""
	h.clientAccessPolicyXMLContent = content
}

// BindContext to the http server.
func (h *Handler) BindContext(ctx context.Context, server core.Server) {
	s := server.(*http.Server)
	s.Handler = h
	s.BaseContext = func(l net.Listener) context.Context {
		return ctx
	}
}

// ServeHTTP implements the http.Handler interface.
func (h *Handler) ServeHTTP(response http.ResponseWriter, request *http.Request) {
	if request.ContentLength > int64(h.Service.MaxRequestLength) {
		response.WriteHeader(http.StatusRequestEntityTooLarge)
		return
	}
	if request.Method == "GET" {
		if h.clientAccessPolicyXMLHandler(response, request) ||
			h.crossDomainXMLHandler(response, request) {
			return
		}
		if !h.GET {
			response.WriteHeader(http.StatusForbidden)
			return
		}
	}
	data, err := readAll(request.Body, request.ContentLength)
	if err != nil {
		h.onError(err)
	}
	if err = request.Body.Close(); err != nil {
		h.onError(err)
	}
	serviceContext := h.getServiceContext(response, request)
	ctx := core.WithContext(request.Context(), serviceContext)
	result, err := h.Service.Handle(ctx, data)
	if err != nil {
		h.onError(err)
	}
	response.Header().Set("Content-Length", strconv.Itoa(len(result)))
	h.sendHeader(serviceContext, response, request)
	_, err = response.Write(result)
	if err != nil {
		h.onError(err)
	}
}

func (h *Handler) xmlFileHandler(response http.ResponseWriter, request *http.Request, path string, content []byte) bool {
	if content == nil || strings.ToLower(request.URL.Path) != path {
		return false
	}
	if request.Header.Get("if-modified-since") == h.LastModified &&
		request.Header.Get("if-none-match") == h.Etag {
		response.WriteHeader(http.StatusNotModified)
	} else {
		contentLength := len(content)
		header := response.Header()
		header.Set("Last-Modified", h.LastModified)
		header.Set("Etag", h.Etag)
		header.Set("Content-Type", "text/xml")
		header.Set("Content-Length", strconv.Itoa(contentLength))
		_, _ = response.Write(content)
	}
	return true
}

func (h *Handler) crossDomainXMLHandler(response http.ResponseWriter, request *http.Request) bool {
	return h.xmlFileHandler(response, request, "/crossdomain.xml", h.crossDomainXMLContent)
}

func (h *Handler) clientAccessPolicyXMLHandler(response http.ResponseWriter, request *http.Request) bool {
	return h.xmlFileHandler(response, request, "/clientaccesspolicy.xml", h.clientAccessPolicyXMLContent)
}

func (h *Handler) sendHeader(serviceContext *core.ServiceContext, response http.ResponseWriter, request *http.Request) {
	responseHeader := response.Header()
	responseHeader.Set("Content-Type", "text/plain")
	if h.P3P {
		responseHeader.Set("P3P",
			`CP="CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi `+
				`CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL `+
				`UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV"`)
	}
	if h.CrossDomain {
		origin := request.Header.Get("origin")
		if origin != "" && origin != "null" {
			if len(h.AccessControlAllowOrigins) == 0 ||
				h.AccessControlAllowOrigins[origin] {
				responseHeader.Set("Access-Control-Allow-Origin", origin)
				responseHeader.Set("Access-Control-Allow-Credentials", "true")
			}
		} else {
			responseHeader.Set("Access-Control-Allow-Origin", "*")
		}
	}
	if h.Header != nil {
		addHeader(responseHeader, h.Header)
	}
	if header, ok := serviceContext.Items().Get("httpResponseHeaders"); ok {
		if header, ok := header.(http.Header); ok {
			addHeader(responseHeader, header)
		}
	}
	if code := serviceContext.Items().GetInt("httpStatusCode"); code != 0 {
		response.WriteHeader(code)
	}
}

func (h *Handler) getServiceContext(response http.ResponseWriter, request *http.Request) *core.ServiceContext {
	serviceContext := core.NewServiceContext(h.Service)
	serviceContext.Items().Set("request", request)
	serviceContext.Items().Set("response", response)
	serviceContext.Items().Set("httpRequestHeaders", request.Header)
	serviceContext.LocalAddr, _ = net.ResolveTCPAddr("tcp", request.Host)
	serviceContext.RemoteAddr, _ = net.ResolveTCPAddr("tcp", request.RemoteAddr)
	serviceContext.Handler = h
	return serviceContext
}

type handlerFactory struct {
	serverTypes []reflect.Type
}

func (factory handlerFactory) ServerTypes() []reflect.Type {
	return factory.serverTypes
}

func (factory handlerFactory) New(service *core.Service) core.Handler {
	return &Handler{
		Service:                   service,
		P3P:                       true,
		GET:                       true,
		CrossDomain:               true,
		AccessControlAllowOrigins: make(map[string]bool),
		LastModified:              time.Now().UTC().Format(time.RFC1123),
		Etag:                      `"` + strconv.FormatInt(rand.Int63(), 16) + `"`,
	}
}

func RegisterHandler() {
	core.RegisterHandler("http", handlerFactory{
		[]reflect.Type{
			reflect.TypeOf((*http.Server)(nil)),
		},
	})
}
<|endoftext|>


<commit_before>package gobls

import (
	"bytes"
	"testing"
)

func TestNoEOF(t *testing.T) {
	bb := bytes.NewBufferString("")
	s := NewScanner(bb)
	for s.Scan() {
		t.Errorf("Actual: scan returned true; Expected: false")
	}
	if s.Err() != nil {
		t.Errorf("Actual: %#v; Expected: %#v", s.Err(), nil)
	}
}

func TestSequencesThroughEntireBuffer(t *testing.T) {
	bb := bytes.NewBufferString("flubber\nblubber\nfoo")
	s := NewScanner(bb)
	expectedLines := []string{"flubber", "blubber", "foo"}
	actualLines := make([]string, 0)
	for s.Scan() {
		actualLines = append(actualLines, s.String())
	}
	if s.Err() != nil {
		t.Errorf("Actual: %#v; Expected: %#v", s.Err(), nil)
	}
	if len(actualLines) != len(expectedLines) {
		t.Fatalf("Actual: %#v; Expected: %#v", len(actualLines), len(expectedLines))
	}
	for i := 0; i < len(expectedLines); i++ {
		if actualLines[i] != expectedLines[i] {
			t.Errorf("Actual: %#v; Expected: %#v",
				actualLines[i], expectedLines[i])
		}
	}
}

func TestHandlesVeryLargeLines(t *testing.T) {
	line := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
	bb := bytes.NewBufferString(line)
	s := NewScanner(bb)
	lines := make([]string, 0)
	for s.Scan() {
		lines = append(lines, s.String())
	}
	if s.Err() != nil {
		t.Errorf("Actual: %#v; Expected: %#v", s.Err(), nil)
	}
	if len(lines) != 1 {
		t.Fatalf("Actual: %#v; Expected: %#v", len(lines), 1)
	}
	if lines[0] != line {
		t.Errorf("Actual: %#v; Expected: %#v", lines[0], line)
	}
}
<commit_msg>test can process lines longer that bufio.MaxScanTokenSize<commit_after>package gobls

import (
	"bufio"
	"bytes"
	"testing"
)

const (
	lineCount  = 100
	lineLength = 4096
)

func makeBuffer(lineCount, lineLength int) *bytes.Buffer {
	buf := make([]byte, 0, lineCount*(lineLength+2))
	bb := bytes.NewBuffer(buf)
	for line := 0; line < lineCount; line++ {
		for i := 0; i < lineLength; i++ {
			bb.WriteByte('a')
		}
		bb.WriteString("\r\n")
	}
	return bb
}

func TestNoEOF(t *testing.T) {
	bb := bytes.NewBufferString("")
	s := NewScanner(bb)
	for s.Scan() {
		t.Errorf("Actual: scan returned true; Expected: false")
	}
	if s.Err() != nil {
		t.Errorf("Actual: %#v; Expected: %#v", s.Err(), nil)
	}
}

func TestSequencesThroughEntireBuffer(t *testing.T) {
	bb := bytes.NewBufferString("flubber\nblubber\nfoo")
	s := NewScanner(bb)
	expectedLines := []string{"flubber", "blubber", "foo"}
	actualLines := make([]string, 0)
	for s.Scan() {
		actualLines = append(actualLines, s.String())
	}
	if s.Err() != nil {
		t.Errorf("Actual: %#v; Expected: %#v", s.Err(), nil)
	}
	if len(actualLines) != len(expectedLines) {
		t.Fatalf("Actual: %#v; Expected: %#v", len(actualLines), len(expectedLines))
	}
	for i := 0; i < len(expectedLines); i++ {
		if actualLines[i] != expectedLines[i] {
			t.Errorf("Actual: %#v; Expected: %#v",
				actualLines[i], expectedLines[i])
		}
	}
}

func TestVeryLargeLinesRequireSingleInvocation(t *testing.T) {
	r := makeBuffer(1, bufio.MaxScanTokenSize+5)
	line := r.String()
	line = line[:len(line)-2] // trim CRLF

	s := NewScanner(r)
	lines := make([]string, 0, 1)
	for s.Scan() {
		lines = append(lines, s.String())
	}
	if s.Err() != nil {
		t.Errorf("Actual: %#v; Expected: %#v", s.Err(), nil)
	}
	if len(lines) != 1 {
		t.Fatalf("Actual: %#v; Expected: %#v", len(lines), 1)
	}
	if lines[0] != line {
		t.Errorf("Actual: %#v; Expected: %#v", lines[0], line)
	}
}

func BenchmarkBufioScanner(b *testing.B) {
	master := makeBuffer(lineCount, lineLength)
	initial := master.Bytes()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		s := bufio.NewScanner(bytes.NewBuffer(initial))
		for s.Scan() {
			_ = s.Text()
		}
	}
}

func BenchmarkGobls(b *testing.B) {
	master := makeBuffer(lineCount, lineLength)
	initial := master.Bytes()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		s := NewScanner(bytes.NewBuffer(initial))
		for s.Scan() {
			_ = s.String()
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2011, Bryan Matsuo. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
/*
*  File: gonew_main.go
*  Author: Bryan Matsuo [bmatsuo@soe.ucsc.edu]
*  Created: Sat Jul  2 19:17:53 PDT 2011
*  Usage: gonew [options]
 */
import (
    "os"
    //"io"
    "log"
    "fmt"
    "flag"
    //"bufio"
    //"io/ioutil"
    //"path/filepath"
    //"github.com/hoisie/mustache.go"
    //"github.com/kr/pretty.go"
)

func ArgumentError(msg string) {
    fmt.Fprintf(os.Stderr, "%s\n", msg)
    fmt.Fprint(os.Stderr, "Try `gonew -help`\n")
}

var (
    usage          = `
gonew [options] cmd NAME
gonew [options] pkg NAME
gonew [options] lib NAME PKG
`
    printUsageHead = func() { fmt.Fprint(os.Stderr, usage, "\n") }
    userepo        = true
    VERBOSE        = false
    DEBUG          = false
    DEBUG_LEVEL    = -1
    name           string
    ptype          string
    repo           string
    host           string
    user           string
    target         string
    license        string
    remote         string
    help           bool
)

func Debug(level int, msg string) {
    if DEBUG && DEBUG_LEVEL >= level {
        log.Print(msg)
    }
}

func Verbose(msg string) {
    if DEBUG || VERBOSE {
        fmt.Print(msg)
    }
}

func setupFlags() *flag.FlagSet {
    var fs = flag.NewFlagSet("gonew", flag.ExitOnError)
    fs.StringVar(&repo,
        "repo", "git", "Repository type (e.g. 'git').")
    fs.StringVar(&host,
        "host", "", "Repository host if any (e.g. 'github').")
    fs.StringVar(&user,
        "user", "", "Repo host username.")
    fs.StringVar(&remote,
        "remote", "", "Remote repository url to initialize and push to.")
    fs.StringVar(&target,
        "target", "", "Makefile target. Default based on NAME.")
    fs.StringVar(&license,
        "license", "", "Project license (e.g. 'newbsd').")
    fs.BoolVar(&(AppConfig.MakeTest),
        "test", AppConfig.MakeTest, "Produce test files with Go files.")
    fs.BoolVar(&(userepo), "userepo", true, "Create a local repository.")
    fs.BoolVar(&VERBOSE,
        "v", false, "Verbose output.")
    fs.IntVar(&DEBUG_LEVEL,
        "debug", -1, "Change the amout of debug output.")
    fs.BoolVar(&help,
        "help", false, "Show this message.")
    var usageTemp = fs.Usage
    fs.Usage = func() {
        printUsageHead()
        usageTemp()
    }
    return fs
}

type Request int

const (
    NilRequest Request = iota
    ProjectRequest
    LibraryRequest
)

var RequestedFile File
var RequestedProject Project

func parseArgs() Request {
    var fs = setupFlags()
    fs.Parse(os.Args[1:])
    if DEBUG_LEVEL >= 0 {
        DEBUG = true
    }
    if help {
        fs.Usage()
        os.Exit(0)
    }
    var narg = fs.NArg()
    if narg < 1 {
        ArgumentError("Missing TYPE argument")
        os.Exit(1)
    }
    if narg < 2 {
        ArgumentError("Missing NAME argument")
        os.Exit(1)
    }
    ptype = fs.Arg(0)
    name = fs.Arg(1)

    if target == "" {
        target = DefaultTarget(name)
    }
    var (
        file = File{
            Name: name, Pkg: "main",
            Repo: AppConfig.Repo, License: AppConfig.License,
            User: AppConfig.HostUser, Host: AppConfig.Host}
        project = Project{
            Name: name, Target: target,
            Type: NilProjectType, License: AppConfig.License, Remote: remote,
            Host: AppConfig.Host, User: AppConfig.HostUser,
            Repo: AppConfig.Repo}
        produceProject = true
        licObj         = NilLicenseType
        repoObj        = NilRepoType
        hostObj        = NilRepoHost
    )
    switch ptype {
    case "cmd":
        project.Type = CmdType
    case "pkg":
        project.Type = PkgType
    case "lib":
        produceProject = false
    default:
        fmt.Fprintf(os.Stderr, "Unknown TYPE %s\n", ptype)
        os.Exit(1)
    }
    switch license {
    case "":
        break
    case "newbsd":
        licObj = NewBSD
    default:
        fmt.Fprintf(os.Stderr, "Unknown TYPE %s\n", ptype)
        os.Exit(1)
    }
    switch repo {
    case "":
        break
    case "git":
        repoObj = GitType
    case "mercurial":
        repoObj = HgType
    default:
        fmt.Fprintf(os.Stderr, "Unknown REPO %s\n", repo)
        os.Exit(1)
    }
    switch host {
    case "":
        break
    case "github":
        hostObj = GitHubHost
        repoObj = GitType
    /*
       case "googlecode":
           hostObj = GoogleCodeType
           repoObj = HgType
    */
    default:
        fmt.Fprintf(os.Stderr, "Unknown HOST %s\n", host)
        os.Exit(1)
    }
    if produceProject {
        // TODO check target for improper characters.
        if user != "" {
            project.User = user
        }
        if licObj != NilLicenseType {
            project.License = licObj
        }
        if hostObj != NilRepoHost {
            project.Host = hostObj
        }
        if repoObj != NilRepoType {
            project.Repo = repoObj
        }
        RequestedProject = project
        return ProjectRequest
    } else {
        if narg < 3 {
            ArgumentError("Missing PKG argument")
            os.Exit(1)
        }
        file.Pkg = fs.Arg(2)
        if user != "" {
            file.User = user
        }
        if licObj != NilLicenseType {
            file.License = licObj
        }
        if hostObj != NilRepoHost {
            file.Host = hostObj
        }
        if repoObj != NilRepoType {
            file.Repo = repoObj
        }
        RequestedFile = file
        return LibraryRequest
    }
    return NilRequest
}

func main() {
    if err := TouchConfig(); err != nil {
        fmt.Fprint(os.Stderr, err.String(), "\n")
        os.Exit(1)
    }
    Verbose("Parsing config file.\n")
    ReadConfig()
    switch request := parseArgs(); request {
    case ProjectRequest:
        if DEBUG {
            fmt.Printf("Project requested %v\n", RequestedProject)
        } else if VERBOSE {
            fmt.Printf("Generating project %s\n", RequestedProject.Name)
        }
        if err := RequestedProject.Create(); err != nil {
            fmt.Fprint(os.Stderr, err.String(), "\n")
            os.Exit(1)
        }
    case LibraryRequest:
        if DEBUG {
            fmt.Printf("Library requested %v\n", RequestedFile)
        } else if VERBOSE {
            fmt.Printf("Generating library %s (package %s)\n",
                RequestedFile.Name+".go", RequestedFile.Pkg)
        }
        if err := RequestedFile.Create(); err != nil {
            fmt.Fprint(os.Stderr, err.String(), "\n")
            os.Exit(1)
        }
    }
}
<commit_msg>Print option help message when an argument error occurs.<commit_after>// Copyright 2011, Bryan Matsuo. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
/*
*  File: gonew_main.go
*  Author: Bryan Matsuo [bmatsuo@soe.ucsc.edu]
*  Created: Sat Jul  2 19:17:53 PDT 2011
*  Usage: gonew [options]
 */
import (
    "os"
    //"io"
    "log"
    "fmt"
    "flag"
    //"bufio"
    //"io/ioutil"
    //"path/filepath"
    //"github.com/hoisie/mustache.go"
    //"github.com/kr/pretty.go"
)

func ArgumentError(msg string) {
    fmt.Fprintf(os.Stderr, "%s\n", msg)
    fs := setupFlags()
    fs.Usage()
}

var (
    usage          = `
gonew [options] cmd NAME
gonew [options] pkg NAME
gonew [options] lib NAME PKG
`
    printUsageHead = func() { fmt.Fprint(os.Stderr, usage, "\n") }
    userepo        = true
    VERBOSE        = false
    DEBUG          = false
    DEBUG_LEVEL    = -1
    name           string
    ptype          string
    repo           string
    host           string
    user           string
    target         string
    license        string
    remote         string
    help           bool
)

func Debug(level int, msg string) {
    if DEBUG && DEBUG_LEVEL >= level {
        log.Print(msg)
    }
}

func Verbose(msg string) {
    if DEBUG || VERBOSE {
        fmt.Print(msg)
    }
}

func setupFlags() *flag.FlagSet {
    var fs = flag.NewFlagSet("gonew", flag.ExitOnError)
    fs.StringVar(&repo,
        "repo", "git", "Repository type (e.g. 'git').")
    fs.StringVar(&host,
        "host", "", "Repository host if any (e.g. 'github').")
    fs.StringVar(&user,
        "user", "", "Repo host username.")
    fs.StringVar(&remote,
        "remote", "", "Remote repository url to initialize and push to.")
    fs.StringVar(&target,
        "target", "", "Makefile target. Default based on NAME.")
    fs.StringVar(&license,
        "license", "", "Project license (e.g. 'newbsd').")
    fs.BoolVar(&(AppConfig.MakeTest),
        "test", AppConfig.MakeTest, "Produce test files with Go files.")
    fs.BoolVar(&(userepo), "userepo", true, "Create a local repository.")
    fs.BoolVar(&VERBOSE,
        "v", false, "Verbose output.")
    fs.IntVar(&DEBUG_LEVEL,
        "debug", -1, "Change the amout of debug output.")
    fs.BoolVar(&help,
        "help", false, "Show this message.")
    var usageTemp = fs.Usage
    fs.Usage = func() {
        printUsageHead()
        usageTemp()
    }
    return fs
}

type Request int

const (
    NilRequest Request = iota
    ProjectRequest
    LibraryRequest
)

var RequestedFile File
var RequestedProject Project

func parseArgs() Request {
    var fs = setupFlags()
    fs.Parse(os.Args[1:])
    if DEBUG_LEVEL >= 0 {
        DEBUG = true
    }
    if help {
        fs.Usage()
        os.Exit(0)
    }
    var narg = fs.NArg()
    if narg < 1 {
        ArgumentError("Missing TYPE argument")
        os.Exit(1)
    }
    if narg < 2 {
        ArgumentError("Missing NAME argument")
        os.Exit(1)
    }
    ptype = fs.Arg(0)
    name = fs.Arg(1)

    if target == "" {
        target = DefaultTarget(name)
    }
    var (
        file = File{
            Name: name, Pkg: "main",
            Repo: AppConfig.Repo, License: AppConfig.License,
            User: AppConfig.HostUser, Host: AppConfig.Host}
        project = Project{
            Name: name, Target: target,
            Type: NilProjectType, License: AppConfig.License, Remote: remote,
            Host: AppConfig.Host, User: AppConfig.HostUser,
            Repo: AppConfig.Repo}
        produceProject = true
        licObj         = NilLicenseType
        repoObj        = NilRepoType
        hostObj        = NilRepoHost
    )
    switch ptype {
    case "cmd":
        project.Type = CmdType
    case "pkg":
        project.Type = PkgType
    case "lib":
        produceProject = false
    default:
        fmt.Fprintf(os.Stderr, "Unknown TYPE %s\n", ptype)
        os.Exit(1)
    }
    switch license {
    case "":
        break
    case "newbsd":
        licObj = NewBSD
    default:
        fmt.Fprintf(os.Stderr, "Unknown TYPE %s\n", ptype)
        os.Exit(1)
    }
    switch repo {
    case "":
        break
    case "git":
        repoObj = GitType
    case "mercurial":
        repoObj = HgType
    default:
        fmt.Fprintf(os.Stderr, "Unknown REPO %s\n", repo)
        os.Exit(1)
    }
    switch host {
    case "":
        break
    case "github":
        hostObj = GitHubHost
        repoObj = GitType
    /*
       case "googlecode":
           hostObj = GoogleCodeType
           repoObj = HgType
    */
    default:
        fmt.Fprintf(os.Stderr, "Unknown HOST %s\n", host)
        os.Exit(1)
    }
    if produceProject {
        // TODO check target for improper characters.
        if user != "" {
            project.User = user
        }
        if licObj != NilLicenseType {
            project.License = licObj
        }
        if hostObj != NilRepoHost {
            project.Host = hostObj
        }
        if repoObj != NilRepoType {
            project.Repo = repoObj
        }
        RequestedProject = project
        return ProjectRequest
    } else {
        if narg < 3 {
            ArgumentError("Missing PKG argument")
            os.Exit(1)
        }
        file.Pkg = fs.Arg(2)
        if user != "" {
            file.User = user
        }
        if licObj != NilLicenseType {
            file.License = licObj
        }
        if hostObj != NilRepoHost {
            file.Host = hostObj
        }
        if repoObj != NilRepoType {
            file.Repo = repoObj
        }
        RequestedFile = file
        return LibraryRequest
    }
    return NilRequest
}

func main() {
    if err := TouchConfig(); err != nil {
        fmt.Fprint(os.Stderr, err.String(), "\n")
        os.Exit(1)
    }
    Verbose("Parsing config file.\n")
    ReadConfig()
    switch request := parseArgs(); request {
    case ProjectRequest:
        if DEBUG {
            fmt.Printf("Project requested %v\n", RequestedProject)
        } else if VERBOSE {
            fmt.Printf("Generating project %s\n", RequestedProject.Name)
        }
        if err := RequestedProject.Create(); err != nil {
            fmt.Fprint(os.Stderr, err.String(), "\n")
            os.Exit(1)
        }
    case LibraryRequest:
        if DEBUG {
            fmt.Printf("Library requested %v\n", RequestedFile)
        } else if VERBOSE {
            fmt.Printf("Generating library %s (package %s)\n",
                RequestedFile.Name+".go", RequestedFile.Pkg)
        }
        if err := RequestedFile.Create(); err != nil {
            fmt.Fprint(os.Stderr, err.String(), "\n")
            os.Exit(1)
        }
    }
}
<|endoftext|>


<commit_before>package gospy_test

import (
	. "github.com/cfmobile/gospy"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

const (
	kOriginalStringReturn = "original string value"
	kOriginalFloatReturn = float64(123.45)
)

var _ = Describe("GoSpy", func() {
	var subject *GoSpy

	var functionToSpy func(string, int, bool) (string, float64)
	var panicked bool

	BeforeEach(func() {
	    subject = nil
		panicked = false
		functionToSpy = func(string, int, bool) (string, float64) {
			return kOriginalStringReturn, kOriginalFloatReturn
		}
	})

	panicRecover := func() {
		panicked = recover() != nil
	}

	Describe("Constructors", func() {

	    Describe("Spy", func() {

	        Context("when calling Spy with a valid function pointer", func() {
				BeforeEach(func() {
					defer panicRecover()
				    subject = Spy(&functionToSpy)
				})

				It("should not have panicked", func() {
				    Expect(panicked).To(BeFalse())
				})

				It("should have returned a valid *GoSpy object", func() {
				    Expect(subject).NotTo(BeNil())
				})

				It("should not affect the function's behaviour", func() {
					stringResult, floatResult := functionToSpy("something", 10, false)
					Expect(stringResult).To(Equal(kOriginalStringReturn))
					Expect(floatResult).To(Equal(kOriginalFloatReturn))
				})
	        })
	    })
	})

	Context("when a valid GoSpy object is created", func() {

		BeforeEach(func() {
			subject = Spy(&functionToSpy)
		})

		It("Called() should indicate that the function hasn't been called yet", func() {
		    Expect(subject.Called()).To(BeFalse())
		})

		It("CallCount() should indicate a call count of zero", func() {
		    Expect(subject.CallCount()).To(BeZero())
		})

		It("Calls() should indicate a nil call list", func() {
		    Expect(subject.Calls()).To(BeNil())
		})

		Context("when ArgsForCall() is called with no calls in the Spy", func() {
			BeforeEach(func() {
			    defer panicRecover()
				subject.ArgsForCall(0)
			})

			It("should panic", func() {
				Expect(panicked).To(BeTrue())
			})
		})

		goSpyResetTests := func() {
			Context("when Reset() is called", func() {
				BeforeEach(func() {
					subject.Reset()
				})

				It("should zero the call count", func() {
					Expect(subject.CallCount()).To(BeZero())
				})

				It("should return a nil call list", func() {
					Expect(subject.Calls()).To(BeNil())
				})

				It("should have reset the call indicator", func() {
					Expect(subject.Called()).To(BeFalse())
				})
			})
		}

		goSpyRestoreTests := func(existingCallCount int, existingCallList CallList) {
			Context("when Restore() is called", func() {
				BeforeEach(func() {
				    subject.Restore()
				})

				It("should not have affected the existing call count", func() {
				    Expect(subject.CallCount()).To(Equal(existingCallCount))
				})

				It("should not have affected the call list", func() {
				    Expect(subject.Calls()).To(Equal(existingCallList))
				})

				It("should no longer monitor subsequent calls to the function", func() {
				    Expect(subject.CallCount()).To(Equal(existingCallCount))

					functionToSpy("another call", 101, true)

					Expect(subject.CallCount()).To(Equal(existingCallCount))
					Expect(subject.Calls()).NotTo(ContainElement(ArgList{"another call", 101, true}))
				})
			})
		}

		Context("and the monitored function is called once", func() {
			kFirstArg, kSecondArg, kThirdArg := "test value", 101, true

			BeforeEach(func() {
			    functionToSpy(kFirstArg, kSecondArg, kThirdArg)
			})

			It("Called() should indicate that the function was called", func() {
				Expect(subject.Called()).To(BeTrue())
			})

			It("CallCount() should indicate that a call was made", func() {
				Expect(subject.CallCount()).To(Equal(1))
			})

			It("Calls() should return a valid call list", func() {
			    Expect(subject.Calls()).NotTo(BeNil())
			})

			It("ArgsForCall() should return the arguments that were used in the call", func() {
			    Expect(subject.ArgsForCall(0)).To(Equal(ArgList{kFirstArg, kSecondArg, kThirdArg}))
			})

			goSpyResetTests()

			goSpyRestoreTests(1, CallList{
				{kFirstArg, kSecondArg, kThirdArg},
			})
		})

		Context("and the monitored function is called several times", func() {
			BeforeEach(func() {
			    functionToSpy("call 1", 1, true)
				functionToSpy("call 2", 2, false)
				functionToSpy("call 3", 3, true)
			})

			It("CallCount() should reflect the right number of calls", func() {
			    Expect(subject.CallCount()).To(Equal(3))
			})

			It("Calls() should return the arguments for each call in the order they were made", func() {
				expectedCallList := CallList{
					{"call 1", 1, true},
					{"call 2", 2, false},
					{"call 3", 3, true},
				}

				Expect(subject.Calls()).To(Equal(expectedCallList))
			})

			It("ArgsForCall(n) should return the arguments for the n-th call (0-based index) ", func() {
			    Expect(subject.ArgsForCall(0)).To(Equal(ArgList{"call 1", 1, true}))
			    Expect(subject.ArgsForCall(1)).To(Equal(ArgList{"call 2", 2, false}))
			    Expect(subject.ArgsForCall(2)).To(Equal(ArgList{"call 3", 3, true}))
			})

			goSpyResetTests()

			goSpyRestoreTests(3, CallList{
				{"call 1", 1, true},
				{"call 2", 2, false},
				{"call 3", 3, true},
			})
		})
	})
})
<commit_msg>RS - Generalized the tests for GoSpy’s methods and reused them in different scenarios.<commit_after>package gospy_test

import (
	. "github.com/cfmobile/gospy"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"fmt"
)

const (
	kOriginalStringReturn = "original string value"
	kOriginalFloatReturn = float64(123.45)
)

var _ = Describe("GoSpy", func() {
	var subject *GoSpy

	var functionToSpy func(string, int, bool) (string, float64)
	var panicked bool

	BeforeEach(func() {
	    subject = nil
		panicked = false
		functionToSpy = func(string, int, bool) (string, float64) {
			return kOriginalStringReturn, kOriginalFloatReturn
		}
	})

	panicRecover := func() {
		panicked = recover() != nil
	}

	Describe("Constructors", func() {

	    Describe("Spy", func() {

	        Context("when calling Spy with a valid function pointer", func() {
				BeforeEach(func() {
					defer panicRecover()
				    subject = Spy(&functionToSpy)
				})

				It("should not have panicked", func() {
				    Expect(panicked).To(BeFalse())
				})

				It("should have returned a valid *GoSpy object", func() {
				    Expect(subject).NotTo(BeNil())
				})

				It("should not affect the function's behaviour", func() {
					stringResult, floatResult := functionToSpy("something", 10, false)
					Expect(stringResult).To(Equal(kOriginalStringReturn))
					Expect(floatResult).To(Equal(kOriginalFloatReturn))
				})
	        })
	    })
	})

	Context("when a valid GoSpy object is created", func() {
		var expectedCalledState bool
		var expectedCallCount int
		var expectedCallList CallList

		// Definition of common tests for each scenario
		var goSpyResetTests = func() {
			Context("when Reset() is called", func() {
				BeforeEach(func() {
					subject.Reset()
				})

				It("should zero the call count", func() {
					Expect(subject.CallCount()).To(BeZero())
				})

				It("should return a nil call list", func() {
					Expect(subject.Calls()).To(BeNil())
				})

				It("should have reset the call indicator", func() {
					Expect(subject.Called()).To(BeFalse())
				})
			})
		}

		var goSpyRestoreTests = func(existingCallCount int, existingCallList CallList) {
			Context("when Restore() is called", func() {
				BeforeEach(func() {
					subject.Restore()
				})

				It("should not have affected the existing call count", func() {
					Expect(subject.CallCount()).To(Equal(existingCallCount))
				})

				It("should not have affected the call list", func() {
					Expect(subject.Calls()).To(Equal(existingCallList))
				})

				It("should no longer monitor subsequent calls to the function", func() {
					Expect(subject.CallCount()).To(Equal(existingCallCount))

					functionToSpy("another call", 101, true)

					Expect(subject.CallCount()).To(Equal(existingCallCount))
					Expect(subject.Calls()).NotTo(ContainElement(ArgList{"another call", 101, true}))
				})
			})
		}

		var goSpyCalledTest = func(expectedCalledState bool) {
			wasCalled := "was"
			if !expectedCalledState {
				wasCalled = "was not"
			}

			It(fmt.Sprintf("should indicate that the function %s Called()", wasCalled), func() {
				Expect(subject.Called()).To(Equal(expectedCalledState))
			})
		}

		var goSpyCallCountTest = func(expectedCallCount int) {
			It(fmt.Sprintf("should indicate a CallCount() of %d", expectedCallCount), func() {
				Expect(subject.CallCount()).To(Equal(expectedCallCount))
			})
		}

		var goSpyCallsTest = func(expectedCallList CallList) {
			msg := "an expected and ordered"
			if expectedCallList == nil {
				msg = "a nil"
			}

			It(fmt.Sprintf("should contain %s list of Calls()", msg), func() {
			    Expect(subject.Calls()).To(Equal(expectedCallList))
			})
		}

		BeforeEach(func() {
			subject = Spy(&functionToSpy)
		})

		Context("as soon as it's created", func() {
			expectedCalledState = false
		    expectedCallCount = 0
			expectedCallList = nil

			goSpyCalledTest(expectedCalledState)

			goSpyCallCountTest(expectedCallCount)

			goSpyCallsTest(expectedCallList)

			goSpyResetTests()

			goSpyRestoreTests(expectedCallCount, expectedCallList)

			Context("when ArgsForCall() is called with no calls in the Spy", func() {
				BeforeEach(func() {
					defer panicRecover()
					subject.ArgsForCall(0)
				})

				It("should panic", func() {
					Expect(panicked).To(BeTrue())
				})
			})
		})

		Context("and the monitored function is called once", func() {
			expectedCalledState = true
			expectedCallCount = 1
			expectedArgList := ArgList{"test value", 101, true}
			expectedCallList = CallList{expectedArgList}

			BeforeEach(func() {
			    functionToSpy("test value", 101, true)
			})

			goSpyCalledTest(expectedCalledState)

			goSpyCallCountTest(expectedCallCount)

			goSpyCallsTest(expectedCallList)

			goSpyResetTests()

			goSpyRestoreTests(expectedCallCount, expectedCallList)

			It("ArgsForCall() should return the arguments that were used in the call", func() {
			    Expect(subject.ArgsForCall(0)).To(Equal(expectedArgList))
			})
		})

		Context("and the monitored function is called several times", func() {
			expectedCalledState = true
			expectedCallCount = 3
			expectedCallList = CallList{
				{"call 1", 1, true},
				{"call 2", 2, false},
				{"call 3", 3, true},
			}

			BeforeEach(func() {
			    functionToSpy("call 1", 1, true)
				functionToSpy("call 2", 2, false)
				functionToSpy("call 3", 3, true)
			})

			goSpyCalledTest(expectedCalledState)

			goSpyCallCountTest(expectedCallCount)

			goSpyCallsTest(expectedCallList)

			goSpyResetTests()

			goSpyRestoreTests(expectedCallCount, expectedCallList)

			It("ArgsForCall(n) should return the arguments for the n-th call (0-based index) ", func() {
			    Expect(subject.ArgsForCall(0)).To(Equal(expectedCallList[0]))
			    Expect(subject.ArgsForCall(1)).To(Equal(expectedCallList[1]))
			    Expect(subject.ArgsForCall(2)).To(Equal(expectedCallList[2]))
			})
		})
	})
})
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2017 AlexRuzin (stan.ruzin@gmail.com)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package govfs

import (
    "testing"
    "time"
    "os"
    "io"
    _"bytes"
    "bytes"
    "runtime"
)

const FS_DATABASE_FILE string = "test_db"

func TestFSWriter(t *testing.T) {
    /*
     * This test will generate the raw fs stream file, along with some contents
     *  that will be later loaded by the TestFSReader() method
     */
    out("[+] Running Standard I/O Sanity Test...")

    /* Remove the test database if it exists */
    var filename = gen_raw_filename(FS_DATABASE_FILE)
    if _, err := os.Stat(filename); os.IsExist(err) {
        os.Remove(filename)
    }

    var header, err = CreateDatabase(filename, FLAG_DB_CREATE)
    if header == nil || err != nil {
        drive_fail(err.Error(), t)
    }
    if err := header.StartIOController(); err != nil {
        drive_fail("TEST1.1: Failed to start IOController", t)
    }
    out("[+] Test 1 PASS")

    // The root file "/" must at least exist
    if file, err := header.Create("/"); file != nil && err == nil {
        drive_fail("TEST2: Failed to return root handle", t)
    }
    out("[+] Test 2 PASS")

    /*
     * Try to delete the root file "/"
     */
    if header.Delete("/") == nil {
        drive_fail("TEST3: Cannot delete root -- critical", t)
    }
    out("[+] Test 3 PASS")

    /*
     * Attempt to write to a nonexistant file
     */
    var data = []byte{ 1, 2 }
    if header.Write("/folder5/folder5/file5", data) == nil {
        drive_fail("TEST4: Cannot write to a nonexistant file", t)
    }
    out("[+] Test 4 PASS")

    /*
     * Create empty file file9
     */
    if file, err := header.Create("/folder5/folder4/folder2/file9"); file == nil || err != nil {
        drive_fail("TEST4.1: file9 cannot be created", t)
    }
    out("[+] Test 4.1 PASS")

    /*
     * Attempt to create a new file0
     */
    if file, err := header.Create("/folder0/folder0/file0"); file == nil || err != nil {
        drive_fail("TEST5.0: file0 cannot be created", t)
    }
    out("[+] Test 5.0 PASS")

    /*
     * Attempt to create a new file0, this will fail since it should already exist
     */
    if file, err := header.Create("/folder0/folder0/file0"); file != nil && err == nil {
        drive_fail("TEST5.1: file0 cannot be created twice", t)
    }
    out("[+] Test 5.1 PASS")

    /*
     * Write some data into file0
     */
    data = []byte{ 1, 2, 3, 4 }
    if header.Write("/folder0/folder0/file0", data) != nil {
        drive_fail("TEST6: Failed to write data in file0", t)
    }
    out("[+] Test 6 PASS")

    /*
     * Check that the size of file0 is 4
     */
    if k, _ := header.get_file_size("/folder0/folder0/file0"); k != uint(len(data)) {
        drive_fail("TEST6.1: The size of data does not match", t)
    }
    out("[+] Test 6.1 PASS")

    /*
     * Attempt to create a new file3
     */
    if file, err := header.Create("/folder1/folder0/file3"); file == nil || err != nil {
        drive_fail("TEST7: file3 cannot be created", t)
    }
    out("[+] Test 7 PASS")

    /*
     * Write some data into file3
     */
    var data2 = []byte{ 1, 2, 3, 4, 5, 6, 7 }
    if header.Write("/folder1/folder0/file3", data2) != nil {
        drive_fail("TEST8: Failed to write data in file3", t)
    }
    out("[+] Test 8 PASS")

    /*
     * Write some data into file3
     */
    if header.Write("/folder1/folder0/file3", data2) != nil {
        drive_fail("TEST8.1: Failed to write data in file3", t)
    }
    out("[+] Test 8.1 PASS")

    /*
     * Read the written data from file0 and compare
     */
    output_data, _ := header.Read("/folder0/folder0/file0")
    if output_data == nil || len(output_data) != len(data) || header.t_size - 7 /* len(file3) */ != uint(len(data)) {
        drive_fail("TEST9: Failed to read data from file0", t)
    }
    out("[+] Test 9 PASS")

    /*
     * Read the written data from file3 and compare
     */
    output_data, _ = header.Read("/folder1/folder0/file3")
    if output_data == nil || len(output_data) != len(data2) || header.t_size - 4 /* len(file0) */ != uint(len(data2)) {
        drive_fail("TEST10: Failed to read data from file3", t)
    }
    out("[+] Test 10 PASS")

    /*
     * Write other data to file0
     */
    data = []byte{ 1, 2, 3 }
    if header.Write("/folder0/folder0/file0", data) != nil {
        drive_fail("TEST11: Failed to write data in file1", t)
    }
    out("[+] Test 11 PASS")

    /*
     * Read the new data from file0
     */
    output_data, _ = header.Read("/folder0/folder0/file0")
    if output_data == nil || len(output_data) != len(data) {
        drive_fail("TEST12: Failed to read data from file1", t)
    }
    out("[+] Test 12 PASS")

    /*
     * Attempt to create a new file5. This will be a blank file
     */
    if file, err := header.Create("/folder2/file7"); file == nil || err != nil {
        drive_fail("TEST13: file3 cannot be created", t)
    }
    out("[+] Test 13 PASS")

    /*
     * Delete file0 -- complete this
     */
    // FIXME/ADDME

    /*
     * Create just a folder
     */
    if file, err := header.Create("/folder2/file5/"); file == nil || err != nil {
        drive_fail("TEST15: folder file5 cannot be created", t)
    }
    out("[+] Test 15 PASS")

    /*
     * Tests the Reader interface
     */
    reader, err := header.NewReader("/folder0/folder0/file0")
    if err != nil {
        drive_fail("TEST15.1: Failed to create Reader", t)
    }

    file0data := make([]byte, 3)
    data_read, err := reader.Read(file0data)
    if data_read != len(data) || err != io.EOF || bytes.Compare(file0data, data) != 0 {
        drive_fail("TEST15.2: Failed to read from NewReader", t)
    }

    /* Test the reader interface again */
    file0data = make([]byte, 1)
    data_read, err = reader.Read(file0data)
    if data_read != 1 || err != nil || file0data[0] != 1 {
        drive_fail("TEST15.3: Invalid Reader interface behaviour", t)
    }
    out("[+] Test 15.1, 15.2, 15.3 PASS -- Reader interface")

    /*
     * Tests the Writer interface
     */
    file0data = []byte{1, 2, 3, 4, 5, 6, 7, 8}
    writer, err := header.NewWriter("/folder0/folder0/file0")
    if writer == nil || err != nil {
        drive_fail("TEST15.4: Invalid Writer object", t)
    }

    written, err := writer.Write(file0data)
    if written != len(file0data) || err != io.EOF {
        drive_fail("TEST15.4: Invalid Writer response", t)
    }

    file0data = make([]byte, 8)
    data_read, err = reader.Read(file0data)
    if data_read != 8 || err != io.EOF || file0data[0] != 1 || file0data[1] != 2 {
        drive_fail("TEST15.5: Invalid Reader data",t )
    }
    out("[+] Test 15.4, 15.5 PASS -- Writer interface")

    /*
     * Print out files
     */
    file_list := header.get_file_list()
    for _, e := range file_list {
        out(e)
    }

    /*
     * Unmount/commit database to file
     */
    if err := header.UnmountDB(); err != nil {
        drive_fail("TEST16: Failed to commit database", t)
    }
    out("[+] Test 16 PASS. Raw FS stream written to: " + header.filename)

    time.Sleep(10000)
}

func TestFSReader(t *testing.T) {
    /*
     * Read in FS_DATABASE_FILE and do basic tests
     */
    var filename = gen_raw_filename(FS_DATABASE_FILE)
    out("[+] Loading Raw FS stream file: " + filename)

    /* Remove the test database if it exists */
    if _, err := os.Stat(filename); os.IsNotExist(err) {
        drive_fail("error: Standard raw fs stream " + filename + " does not exist", t)
    }

    header, err := CreateDatabase(filename, FLAG_DB_LOAD)
    if header == nil || err != nil {
        drive_fail("TEST1: Failed to obtain header", t)
    }

    if err := header.StartIOController(); err != nil {
        drive_fail("TEST1.1: Failed to start IOController", t)
    }
    out("[+] Test 1 PASS (Loaded FS stream)")
}

func gen_raw_filename(suffix string) string {
    if runtime.GOOS == "windows" {
        return os.Getenv("TEMP") + "\\" + suffix + ".db"
    }

    if runtime.GOOS == "linux" {
        return suffix + ".db"
    }

    return suffix + ".db"
}

func drive_fail(output string, t *testing.T) {
    t.Errorf(output)
    t.FailNow()
}
<commit_msg>Added Reader test 2. Serializer/Deserializer works!<commit_after>/*
 * Copyright (c) 2017 AlexRuzin (stan.ruzin@gmail.com)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package govfs

import (
    "testing"
    "time"
    "os"
    "io"
    _"bytes"
    "bytes"
    "runtime"
)

const FS_DATABASE_FILE string = "test_db"

func TestFSWriter(t *testing.T) {
    /*
     * This test will generate the raw fs stream file, along with some contents
     *  that will be later loaded by the TestFSReader() method
     */
    out("[+] Running Standard I/O Sanity Test...")

    /* Remove the test database if it exists */
    var filename = gen_raw_filename(FS_DATABASE_FILE)
    if _, err := os.Stat(filename); os.IsExist(err) {
        os.Remove(filename)
    }

    var header, err = CreateDatabase(filename, FLAG_DB_CREATE)
    if header == nil || err != nil {
        drive_fail(err.Error(), t)
    }
    if err := header.StartIOController(); err != nil {
        drive_fail("TEST1.1: Failed to start IOController", t)
    }
    out("[+] Test 1 PASS")

    // The root file "/" must at least exist
    if file, err := header.Create("/"); file != nil && err == nil {
        drive_fail("TEST2: Failed to return root handle", t)
    }
    out("[+] Test 2 PASS")

    /*
     * Try to delete the root file "/"
     */
    if header.Delete("/") == nil {
        drive_fail("TEST3: Cannot delete root -- critical", t)
    }
    out("[+] Test 3 PASS")

    /*
     * Attempt to write to a nonexistant file
     */
    var data = []byte{ 1, 2 }
    if header.Write("/folder5/folder5/file5", data) == nil {
        drive_fail("TEST4: Cannot write to a nonexistant file", t)
    }
    out("[+] Test 4 PASS")

    /*
     * Create empty file file9
     */
    if file, err := header.Create("/folder5/folder4/folder2/file9"); file == nil || err != nil {
        drive_fail("TEST4.1: file9 cannot be created", t)
    }
    out("[+] Test 4.1 PASS")

    /*
     * Attempt to create a new file0
     */
    if file, err := header.Create("/folder0/folder0/file0"); file == nil || err != nil {
        drive_fail("TEST5.0: file0 cannot be created", t)
    }
    out("[+] Test 5.0 PASS")

    /*
     * Attempt to create a new file0, this will fail since it should already exist
     */
    if file, err := header.Create("/folder0/folder0/file0"); file != nil && err == nil {
        drive_fail("TEST5.1: file0 cannot be created twice", t)
    }
    out("[+] Test 5.1 PASS")

    /*
     * Write some data into file0
     */
    data = []byte{ 1, 2, 3, 4 }
    if header.Write("/folder0/folder0/file0", data) != nil {
        drive_fail("TEST6: Failed to write data in file0", t)
    }
    out("[+] Test 6 PASS")

    /*
     * Check that the size of file0 is 4
     */
    if k, _ := header.get_file_size("/folder0/folder0/file0"); k != uint(len(data)) {
        drive_fail("TEST6.1: The size of data does not match", t)
    }
    out("[+] Test 6.1 PASS")

    /*
     * Attempt to create a new file3
     */
    if file, err := header.Create("/folder1/folder0/file3"); file == nil || err != nil {
        drive_fail("TEST7: file3 cannot be created", t)
    }
    out("[+] Test 7 PASS")

    /*
     * Write some data into file3
     */
    var data2 = []byte{ 1, 2, 3, 4, 5, 6, 7 }
    if header.Write("/folder1/folder0/file3", data2) != nil {
        drive_fail("TEST8: Failed to write data in file3", t)
    }
    out("[+] Test 8 PASS")

    /*
     * Write some data into file3
     */
    if header.Write("/folder1/folder0/file3", data2) != nil {
        drive_fail("TEST8.1: Failed to write data in file3", t)
    }
    out("[+] Test 8.1 PASS")

    /*
     * Read the written data from file0 and compare
     */
    output_data, _ := header.Read("/folder0/folder0/file0")
    if output_data == nil || len(output_data) != len(data) || header.t_size - 7 /* len(file3) */ != uint(len(data)) {
        drive_fail("TEST9: Failed to read data from file0", t)
    }
    out("[+] Test 9 PASS")

    /*
     * Read the written data from file3 and compare
     */
    output_data, _ = header.Read("/folder1/folder0/file3")
    if output_data == nil || len(output_data) != len(data2) || header.t_size - 4 /* len(file0) */ != uint(len(data2)) {
        drive_fail("TEST10: Failed to read data from file3", t)
    }
    out("[+] Test 10 PASS")

    /*
     * Write other data to file0
     */
    data = []byte{ 1, 2, 3 }
    if header.Write("/folder0/folder0/file0", data) != nil {
        drive_fail("TEST11: Failed to write data in file1", t)
    }
    out("[+] Test 11 PASS")

    /*
     * Read the new data from file0
     */
    output_data, _ = header.Read("/folder0/folder0/file0")
    if output_data == nil || len(output_data) != len(data) {
        drive_fail("TEST12: Failed to read data from file1", t)
    }
    out("[+] Test 12 PASS")

    /*
     * Attempt to create a new file5. This will be a blank file
     */
    if file, err := header.Create("/folder2/file7"); file == nil || err != nil {
        drive_fail("TEST13: file3 cannot be created", t)
    }
    out("[+] Test 13 PASS")

    /*
     * Delete file0 -- complete this
     */
    // FIXME/ADDME

    /*
     * Create just a folder
     */
    if file, err := header.Create("/folder2/file5/"); file == nil || err != nil {
        drive_fail("TEST15: folder file5 cannot be created", t)
    }
    out("[+] Test 15 PASS")

    /*
     * Tests the Reader interface
     */
    reader, err := header.NewReader("/folder0/folder0/file0")
    if err != nil {
        drive_fail("TEST15.1: Failed to create Reader", t)
    }

    file0data := make([]byte, 3)
    data_read, err := reader.Read(file0data)
    if data_read != len(data) || err != io.EOF || bytes.Compare(file0data, data) != 0 {
        drive_fail("TEST15.2: Failed to read from NewReader", t)
    }

    /* Test the reader interface again */
    file0data = make([]byte, 1)
    data_read, err = reader.Read(file0data)
    if data_read != 1 || err != nil || file0data[0] != 1 {
        drive_fail("TEST15.3: Invalid Reader interface behaviour", t)
    }
    out("[+] Test 15.1, 15.2, 15.3 PASS -- Reader interface")

    /*
     * Tests the Writer interface
     */
    file0data = []byte{1, 2, 3, 4, 5, 6, 7, 8}
    writer, err := header.NewWriter("/folder0/folder0/file0")
    if writer == nil || err != nil {
        drive_fail("TEST15.4: Invalid Writer object", t)
    }

    written, err := writer.Write(file0data)
    if written != len(file0data) || err != io.EOF {
        drive_fail("TEST15.4: Invalid Writer response", t)
    }

    file0data = make([]byte, 8)
    data_read, err = reader.Read(file0data)
    if data_read != 8 || err != io.EOF || file0data[0] != 1 || file0data[1] != 2 {
        drive_fail("TEST15.5: Invalid Reader data",t )
    }
    out("[+] Test 15.4, 15.5 PASS -- Writer interface")

    /*
     * Print out files
     */
    file_list := header.get_file_list()
    for _, e := range file_list {
        out(e)
    }

    /*
     * Unmount/commit database to file
     */
    if err := header.UnmountDB(0 /*FLAG_COMPRESS_FILES*/); err != nil {
        drive_fail("TEST16: Failed to commit database", t)
    }
    out("[+] Test 16 PASS. Raw FS stream written to: " + header.filename)
    out("Total File Content Size: " + string(header.get_total_filesizes()))

    time.Sleep(10000)
}

func TestFSReader(t *testing.T) {
    /*
     * Read in FS_DATABASE_FILE and do basic tests
     */
    var filename = gen_raw_filename(FS_DATABASE_FILE)
    out("[+] Loading Raw FS stream file: " + filename)

    /* Remove the test database if it exists */
    if _, err := os.Stat(filename); os.IsNotExist(err) {
        drive_fail("error: Standard raw fs stream " + filename + " does not exist", t)
    }

    header, err := CreateDatabase(filename, FLAG_DB_LOAD)
    if header == nil || err != nil {
        drive_fail("TEST1: Failed to obtain header", t)
    }

    if err := header.StartIOController(); err != nil {
        drive_fail("TEST1.1: Failed to start IOController", t)
    }
    out("[+] Test 1 PASS (Loaded FS stream)")

    /*
     * Tests the Writer interface
     */
    if file, err := header.Create("/NewestFolder/Subdirectory/GoodBoy.bin"); file == nil || err != nil {
        drive_fail("TEST2.1: folder file5 cannot be created", t)
    }

    file0data := []byte("whattttttt")
    writer, err := header.NewWriter("/NewestFolder/Subdirectory/GoodBoy.bin")
    if writer == nil || err != nil {
        drive_fail("TEST2.2: Invalid Writer object", t)
    }

    written, err := writer.Write(file0data)
    if written != len(file0data) || err != io.EOF {
        drive_fail("TEST2.3: Invalid Writer response", t)
    }
    out("[+] Test 2 PASS")

    /*
     * Print out files
     */
    file_list := header.get_file_list()
    for _, e := range file_list {
        out(e)
    }

    out("Total File Content Size: " + string(header.get_total_filesizes()))
}

func gen_raw_filename(suffix string) string {
    if runtime.GOOS == "windows" {
        return os.Getenv("TEMP") + "\\" + suffix + ".db"
    }

    if runtime.GOOS == "linux" {
        return suffix + ".db"
    }

    return suffix + ".db"
}

func drive_fail(output string, t *testing.T) {
    t.Errorf(output)
    t.FailNow()
}
<|endoftext|>


<commit_before>package restapi

import (
	"net/http"

	"github.com/creativesoftwarefdn/weaviate/restapi/batch"
	"github.com/creativesoftwarefdn/weaviate/restapi/operations"
	"github.com/go-openapi/errors"
	"github.com/go-openapi/runtime"
)

func configureAPI(api *operations.WeaviateAPI) http.Handler {
	api.ServeError = errors.ServeError

	api.JSONConsumer = runtime.JSONConsumer()

	api.OidcAuth = appState.OIDC.ValidateAndExtract

	setupSchemaHandlers(api)
	setupThingsHandlers(api)
	setupActionsHandlers(api)
	setupBatchHandlers(api)
	setupC11yHandlers(api)
	setupGraphQLHandlers(api)
	setupMiscHandlers(api)

	api.ServerShutdown = func() {}

	return setupGlobalMiddleware(api.Serve(setupMiddlewares))
}

func setupBatchHandlers(api *operations.WeaviateAPI) {
	batchAPI := batch.New(appState)

	api.WeaviateBatchingThingsCreateHandler = operations.
		WeaviateBatchingThingsCreateHandlerFunc(batchAPI.ThingsCreate)
	api.WeaviateBatchingActionsCreateHandler = operations.
		WeaviateBatchingActionsCreateHandlerFunc(batchAPI.ActionsCreate)
	api.WeaviateBatchingReferencesCreateHandler = operations.
		WeaviateBatchingReferencesCreateHandlerFunc(batchAPI.References)
}
<commit_msg>gh-801: set OidcAuth to anonymous closure<commit_after>package restapi

import (
	"net/http"

	"github.com/creativesoftwarefdn/weaviate/models"
	"github.com/creativesoftwarefdn/weaviate/restapi/batch"
	"github.com/creativesoftwarefdn/weaviate/restapi/operations"
	"github.com/go-openapi/errors"
	"github.com/go-openapi/runtime"
)

func configureAPI(api *operations.WeaviateAPI) http.Handler {
	api.ServeError = errors.ServeError

	api.JSONConsumer = runtime.JSONConsumer()

	api.OidcAuth = func(token string, scopes []string) (*models.Principal, error) {
		return appState.OIDC.ValidateAndExtract(token, scopes)
	}

	setupSchemaHandlers(api)
	setupThingsHandlers(api)
	setupActionsHandlers(api)
	setupBatchHandlers(api)
	setupC11yHandlers(api)
	setupGraphQLHandlers(api)
	setupMiscHandlers(api)

	api.ServerShutdown = func() {}

	return setupGlobalMiddleware(api.Serve(setupMiddlewares))
}

func setupBatchHandlers(api *operations.WeaviateAPI) {
	batchAPI := batch.New(appState)

	api.WeaviateBatchingThingsCreateHandler = operations.
		WeaviateBatchingThingsCreateHandlerFunc(batchAPI.ThingsCreate)
	api.WeaviateBatchingActionsCreateHandler = operations.
		WeaviateBatchingActionsCreateHandlerFunc(batchAPI.ActionsCreate)
	api.WeaviateBatchingReferencesCreateHandler = operations.
		WeaviateBatchingReferencesCreateHandlerFunc(batchAPI.References)
}
<|endoftext|>