Unverified Commit 90c723d6 authored by Hector Sanjuan's avatar Hector Sanjuan Committed by GitHub

Staticcheck fixes (#196)

* Staticcheck fixes

This fixes all staticcheck warnings for this library.
parent c3c51f79
...@@ -4,7 +4,7 @@ os: ...@@ -4,7 +4,7 @@ os:
language: go language: go
go: go:
- 1.11.x - 1.14.2
env: env:
global: global:
......
...@@ -29,12 +29,12 @@ func TestChanResponsePair(t *testing.T) { ...@@ -29,12 +29,12 @@ func TestChanResponsePair(t *testing.T) {
wg.Add(1) wg.Add(1)
go func() { go func() {
for _, v := range tc.values { for _, v := range tc.values {
v_, err := res.Next() v2, err := res.Next()
if err != nil { if err != nil {
t.Error("Next returned unexpected error:", err) t.Error("Next returned unexpected error:", err)
} }
if v != v_ { if v != v2 {
t.Errorf("Next returned unexpected value %q, expected %q", v_, v) t.Errorf("Next returned unexpected value %q, expected %q", v2, v)
} }
} }
...@@ -93,7 +93,7 @@ func TestSingle1(t *testing.T) { ...@@ -93,7 +93,7 @@ func TestSingle1(t *testing.T) {
err := re.Close() err := re.Close()
if err != ErrClosingClosedEmitter { if err != ErrClosingClosedEmitter {
t.Fatalf("expected double close error, got %v", err) t.Errorf("expected double close error, got %v", err)
} }
close(wait) close(wait)
}() }()
...@@ -127,7 +127,8 @@ func TestSingle2(t *testing.T) { ...@@ -127,7 +127,8 @@ func TestSingle2(t *testing.T) {
go func() { go func() {
err := re.Emit(Single{42}) err := re.Emit(Single{42})
if err != ErrClosedEmitter { if err != ErrClosedEmitter {
t.Fatal("expected closed emitter error, got", err) t.Error("expected closed emitter error, got", err)
return
} }
}() }()
......
...@@ -38,7 +38,7 @@ func suggestUnknownCmd(args []string, root *cmds.Command) []string { ...@@ -38,7 +38,7 @@ func suggestUnknownCmd(args []string, root *cmds.Command) []string {
var suggestions []string var suggestions []string
sortableSuggestions := make(suggestionSlice, 0) sortableSuggestions := make(suggestionSlice, 0)
var sFinal []string var sFinal []string
const MIN_LEVENSHTEIN = 3 const MinLevenshtein = 3
var options levenshtein.Options = levenshtein.Options{ var options levenshtein.Options = levenshtein.Options{
InsCost: 1, InsCost: 1,
...@@ -50,7 +50,7 @@ func suggestUnknownCmd(args []string, root *cmds.Command) []string { ...@@ -50,7 +50,7 @@ func suggestUnknownCmd(args []string, root *cmds.Command) []string {
} }
// Start with a simple strings.Contains check // Start with a simple strings.Contains check
for name, _ := range root.Subcommands { for name := range root.Subcommands {
if strings.Contains(arg, name) { if strings.Contains(arg, name) {
suggestions = append(suggestions, name) suggestions = append(suggestions, name)
} }
...@@ -61,9 +61,9 @@ func suggestUnknownCmd(args []string, root *cmds.Command) []string { ...@@ -61,9 +61,9 @@ func suggestUnknownCmd(args []string, root *cmds.Command) []string {
return suggestions return suggestions
} }
for name, _ := range root.Subcommands { for name := range root.Subcommands {
lev := levenshtein.DistanceForStrings([]rune(arg), []rune(name), options) lev := levenshtein.DistanceForStrings([]rune(arg), []rune(name), options)
if lev <= MIN_LEVENSHTEIN { if lev <= MinLevenshtein {
sortableSuggestions = append(sortableSuggestions, &suggestion{name, lev}) sortableSuggestions = append(sortableSuggestions, &suggestion{name, lev})
} }
} }
...@@ -78,11 +78,17 @@ func suggestUnknownCmd(args []string, root *cmds.Command) []string { ...@@ -78,11 +78,17 @@ func suggestUnknownCmd(args []string, root *cmds.Command) []string {
func printSuggestions(inputs []string, root *cmds.Command) (err error) { func printSuggestions(inputs []string, root *cmds.Command) (err error) {
suggestions := suggestUnknownCmd(inputs, root) suggestions := suggestUnknownCmd(inputs, root)
if len(suggestions) > 1 { if len(suggestions) > 1 {
//lint:ignore ST1005 user facing error
err = fmt.Errorf("Unknown Command \"%s\"\n\nDid you mean any of these?\n\n\t%s", inputs[0], strings.Join(suggestions, "\n\t")) err = fmt.Errorf("Unknown Command \"%s\"\n\nDid you mean any of these?\n\n\t%s", inputs[0], strings.Join(suggestions, "\n\t"))
} else if len(suggestions) > 0 { } else if len(suggestions) > 0 {
//lint:ignore ST1005 user facing error
err = fmt.Errorf("Unknown Command \"%s\"\n\nDid you mean this?\n\n\t%s", inputs[0], suggestions[0]) err = fmt.Errorf("Unknown Command \"%s\"\n\nDid you mean this?\n\n\t%s", inputs[0], suggestions[0])
} else { } else {
//lint:ignore ST1005 user facing error
err = fmt.Errorf("Unknown Command \"%s\"\n", inputs[0]) err = fmt.Errorf("Unknown Command \"%s\"\n", inputs[0])
} }
return return
......
...@@ -137,8 +137,11 @@ func init() { ...@@ -137,8 +137,11 @@ func init() {
shortHelpTemplate = template.Must(template.New("shortHelp").Parse(shortHelpFormat)) shortHelpTemplate = template.Must(template.New("shortHelp").Parse(shortHelpFormat))
} }
// ErrNoHelpRequested returns when request for help help does not include the
// short nor the long option.
var ErrNoHelpRequested = errors.New("no help requested") var ErrNoHelpRequested = errors.New("no help requested")
// HandleHelp writes help to a writer for the given request's command.
func HandleHelp(appName string, req *cmds.Request, out io.Writer) error { func HandleHelp(appName string, req *cmds.Request, out io.Writer) error {
long, _ := req.Options[cmds.OptLongHelp].(bool) long, _ := req.Options[cmds.OptLongHelp].(bool)
short, _ := req.Options[cmds.OptShortHelp].(bool) short, _ := req.Options[cmds.OptShortHelp].(bool)
...@@ -369,18 +372,15 @@ func appendWrapped(prefix, text string, width int) string { ...@@ -369,18 +372,15 @@ func appendWrapped(prefix, text string, width int) string {
func optionFlag(flag string) string { func optionFlag(flag string) string {
if len(flag) == 1 { if len(flag) == 1 {
return fmt.Sprintf(shortFlag, flag) return fmt.Sprintf(shortFlag, flag)
} else {
return fmt.Sprintf(longFlag, flag)
} }
return fmt.Sprintf(longFlag, flag)
} }
func optionText(width int, cmd ...*cmds.Command) []string { func optionText(width int, cmd ...*cmds.Command) []string {
// get a slice of the options we want to list out // get a slice of the options we want to list out
options := make([]cmds.Option, 0) options := make([]cmds.Option, 0)
for _, c := range cmd { for _, c := range cmd {
for _, opt := range c.Options { options = append(options, c.Options...)
options = append(options, opt)
}
} }
// add option names to output // add option names to output
...@@ -503,13 +503,6 @@ func align(lines []string) []string { ...@@ -503,13 +503,6 @@ func align(lines []string) []string {
return lines return lines
} }
func indent(lines []string, prefix string) []string {
for i, line := range lines {
lines[i] = prefix + indentString(line, prefix)
}
return lines
}
func indentString(line string, prefix string) string { func indentString(line string, prefix string) string {
return prefix + strings.Replace(line, "\n", "\n"+prefix, -1) return prefix + strings.Replace(line, "\n", "\n"+prefix, -1)
} }
......
...@@ -3,7 +3,6 @@ package cli ...@@ -3,7 +3,6 @@ package cli
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/ipfs/go-ipfs-files"
"io" "io"
"io/ioutil" "io/ioutil"
"net/url" "net/url"
...@@ -12,6 +11,8 @@ import ( ...@@ -12,6 +11,8 @@ import (
"strings" "strings"
"testing" "testing"
files "github.com/ipfs/go-ipfs-files"
cmds "github.com/ipfs/go-ipfs-cmds" cmds "github.com/ipfs/go-ipfs-cmds"
) )
...@@ -211,7 +212,7 @@ func TestArgumentParsing(t *testing.T) { ...@@ -211,7 +212,7 @@ func TestArgumentParsing(t *testing.T) {
test := func(cmd words, f *os.File, res words) { test := func(cmd words, f *os.File, res words) {
if f != nil { if f != nil {
if _, err := f.Seek(0, os.SEEK_SET); err != nil { if _, err := f.Seek(0, io.SeekStart); err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
...@@ -486,7 +487,7 @@ func TestBodyArgs(t *testing.T) { ...@@ -486,7 +487,7 @@ func TestBodyArgs(t *testing.T) {
for _, tc := range tcs { for _, tc := range tcs {
if tc.f != nil { if tc.f != nil {
if _, err := tc.f.Seek(0, os.SEEK_SET); err != nil { if _, err := tc.f.Seek(0, io.SeekStart); err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
......
...@@ -5,15 +5,9 @@ import ( ...@@ -5,15 +5,9 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/ipfs/go-ipfs-cmds" cmds "github.com/ipfs/go-ipfs-cmds"
) )
type writeCloser struct {
*bytes.Buffer
}
func (wc writeCloser) Close() error { return nil }
type tcCloseWithError struct { type tcCloseWithError struct {
stdout, stderr *bytes.Buffer stdout, stderr *bytes.Buffer
exStdout, exStderr string exStdout, exStderr string
......
...@@ -5,7 +5,7 @@ import ( ...@@ -5,7 +5,7 @@ import (
"context" "context"
"testing" "testing"
"github.com/ipfs/go-ipfs-cmds" cmds "github.com/ipfs/go-ipfs-cmds"
) )
func TestSingle(t *testing.T) { func TestSingle(t *testing.T) {
...@@ -25,7 +25,8 @@ func TestSingle(t *testing.T) { ...@@ -25,7 +25,8 @@ func TestSingle(t *testing.T) {
go func() { go func() {
if err := cmds.EmitOnce(re, "test"); err != nil { if err := cmds.EmitOnce(re, "test"); err != nil {
t.Fatal(err) t.Error(err)
return
} }
err := re.Emit("this should not be emitted") err := re.Emit("this should not be emitted")
......
...@@ -13,11 +13,12 @@ import ( ...@@ -13,11 +13,12 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/ipfs/go-ipfs-files" files "github.com/ipfs/go-ipfs-files"
logging "github.com/ipfs/go-log" logging "github.com/ipfs/go-log"
) )
// DefaultOutputEncoding defines the default API output encoding.
const DefaultOutputEncoding = JSON const DefaultOutputEncoding = JSON
var log = logging.Logger("cmds") var log = logging.Logger("cmds")
...@@ -93,13 +94,13 @@ type Command struct { ...@@ -93,13 +94,13 @@ type Command struct {
var ( var (
// ErrNotCallable signals a command that cannot be called. // ErrNotCallable signals a command that cannot be called.
ErrNotCallable = ClientError("This command can't be called directly. Try one of its subcommands.") ErrNotCallable = ClientError("this command cannot be called directly; try one of its subcommands.")
// ErrNoFormatter signals that the command can not be formatted. // ErrNoFormatter signals that the command can not be formatted.
ErrNoFormatter = ClientError("This command cannot be formatted to plain text") ErrNoFormatter = ClientError("this command cannot be formatted to plain text")
// ErrIncorrectType signales that the commands returned a value with unexpected type. // ErrIncorrectType signales that the commands returned a value with unexpected type.
ErrIncorrectType = errors.New("The command returned a value with a different type than expected") ErrIncorrectType = errors.New("the command returned a value with a different type than expected")
) )
// Call invokes the command for the given Request // Call invokes the command for the given Request
......
...@@ -39,7 +39,7 @@ func TestOptionValidation(t *testing.T) { ...@@ -39,7 +39,7 @@ func TestOptionValidation(t *testing.T) {
cmd.Call(req, re, nil) cmd.Call(req, re, nil)
} else { } else {
if err == nil { if err == nil {
t.Errorf("Should have failed with error %q", tc.NewRequestError) t.Errorf("should have failed with error %q", tc.NewRequestError)
} else if err.Error() != tc.NewRequestError { } else if err.Error() != tc.NewRequestError {
t.Errorf("expected error %q, got %q", tc.NewRequestError, err) t.Errorf("expected error %q, got %q", tc.NewRequestError, err)
} }
...@@ -50,7 +50,7 @@ func TestOptionValidation(t *testing.T) { ...@@ -50,7 +50,7 @@ func TestOptionValidation(t *testing.T) {
tcs := []testcase{ tcs := []testcase{
{ {
opts: map[string]interface{}{"boop": true}, opts: map[string]interface{}{"boop": true},
NewRequestError: `Option "boop" should be type "string", but got type "bool"`, NewRequestError: `option "boop" should be type "string", but got type "bool"`,
}, },
{opts: map[string]interface{}{"beep": 5}}, {opts: map[string]interface{}{"beep": 5}},
{opts: map[string]interface{}{"beep": 5, "boop": "test"}}, {opts: map[string]interface{}{"beep": 5, "boop": "test"}},
...@@ -61,10 +61,10 @@ func TestOptionValidation(t *testing.T) { ...@@ -61,10 +61,10 @@ func TestOptionValidation(t *testing.T) {
{opts: map[string]interface{}{"S": [2]string{"a", "b"}}}, {opts: map[string]interface{}{"S": [2]string{"a", "b"}}},
{ {
opts: map[string]interface{}{"S": true}, opts: map[string]interface{}{"S": true},
NewRequestError: `Option "S" should be type "array", but got type "bool"`}, NewRequestError: `option "S" should be type "array", but got type "bool"`},
{ {
opts: map[string]interface{}{"beep": ":)"}, opts: map[string]interface{}{"beep": ":)"},
NewRequestError: `Could not convert value ":)" to type "int" (for option "-beep")`, NewRequestError: `could not convert value ":)" to type "int" (for option "-beep")`,
}, },
} }
...@@ -279,7 +279,8 @@ func TestPostRun(t *testing.T) { ...@@ -279,7 +279,8 @@ func TestPostRun(t *testing.T) {
t.Log("next returned", v, err) t.Log("next returned", v, err)
if err != nil { if err != nil {
close(ch) close(ch)
t.Fatal(err) t.Error(err)
return
} }
ch <- v ch <- v
......
...@@ -8,7 +8,7 @@ import ( ...@@ -8,7 +8,7 @@ import (
"testing" "testing"
) )
var theError = errors.New("an error occurred") var errGeneric = errors.New("an error occurred")
var root = &Command{ var root = &Command{
Subcommands: map[string]*Command{ Subcommands: map[string]*Command{
...@@ -20,7 +20,7 @@ var root = &Command{ ...@@ -20,7 +20,7 @@ var root = &Command{
}, },
"testError": &Command{ "testError": &Command{
Run: func(req *Request, re ResponseEmitter, env Environment) error { Run: func(req *Request, re ResponseEmitter, env Environment) error {
err := theError err := errGeneric
if err != nil { if err != nil {
return err return err
} }
......
...@@ -170,15 +170,11 @@ func allowUserAgent(r *http.Request, cfg *ServerConfig) bool { ...@@ -170,15 +170,11 @@ func allowUserAgent(r *http.Request, cfg *ServerConfig) bool {
return true return true
} }
// Allow if the user agent does not start with Mozilla... (i.e. curl) // Allow if the user agent does not start with Mozilla... (i.e. curl).
ua := r.Header.Get("User-agent")
if !strings.HasPrefix(ua, "Mozilla") {
return true
}
// Disallow otherwise. // Disallow otherwise.
// //
// This means the request probably came from a browser and thus, it // This means the request probably came from a browser and thus, it
// should have included Origin or referer headers. // should have included Origin or referer headers.
return false ua := r.Header.Get("User-agent")
return !strings.HasPrefix(ua, "Mozilla")
} }
...@@ -5,7 +5,6 @@ import ( ...@@ -5,7 +5,6 @@ import (
"errors" "errors"
"net/http" "net/http"
"runtime/debug" "runtime/debug"
"strings"
"sync" "sync"
"time" "time"
...@@ -17,11 +16,12 @@ import ( ...@@ -17,11 +16,12 @@ import (
var log = logging.Logger("cmds/http") var log = logging.Logger("cmds/http")
var ( var (
ErrNotFound = errors.New("404 page not found") // ErrNotFound is returned when the endpoint does not exist.
errApiVersionMismatch = errors.New("api version mismatch") ErrNotFound = errors.New("404 page not found")
) )
const ( const (
// StreamErrHeader is used as trailer when stream errors happen.
StreamErrHeader = "X-Stream-Error" StreamErrHeader = "X-Stream-Error"
streamHeader = "X-Stream-Output" streamHeader = "X-Stream-Output"
channelHeader = "X-Chunked-Output" channelHeader = "X-Chunked-Output"
...@@ -32,7 +32,7 @@ const ( ...@@ -32,7 +32,7 @@ const (
transferEncodingHeader = "Transfer-Encoding" transferEncodingHeader = "Transfer-Encoding"
originHeader = "origin" originHeader = "origin"
applicationJson = "application/json" applicationJSON = "application/json"
applicationOctetStream = "application/octet-stream" applicationOctetStream = "application/octet-stream"
plainText = "text/plain" plainText = "text/plain"
) )
...@@ -57,6 +57,7 @@ type handler struct { ...@@ -57,6 +57,7 @@ type handler struct {
env cmds.Environment env cmds.Environment
} }
// NewHandler creates the http.Handler for the given commands.
func NewHandler(env cmds.Environment, root *cmds.Command, cfg *ServerConfig) http.Handler { func NewHandler(env cmds.Environment, root *cmds.Command, cfg *ServerConfig) http.Handler {
if cfg == nil { if cfg == nil {
panic("must provide a valid ServerConfig") panic("must provide a valid ServerConfig")
...@@ -190,13 +191,6 @@ func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { ...@@ -190,13 +191,6 @@ func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.root.Call(req, re, h.env) h.root.Call(req, re, h.env)
} }
func sanitizedErrStr(err error) string {
s := err.Error()
s = strings.Split(s, "\n")[0]
s = strings.Split(s, "\r")[0]
return s
}
func setAllowedHeaders(w http.ResponseWriter, allowGet bool) { func setAllowedHeaders(w http.ResponseWriter, allowGet bool) {
w.Header().Add("Allow", http.MethodHead) w.Header().Add("Allow", http.MethodHead)
w.Header().Add("Allow", http.MethodOptions) w.Header().Add("Allow", http.MethodOptions)
......
...@@ -10,9 +10,9 @@ import ( ...@@ -10,9 +10,9 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/ipfs/go-ipfs-cmds" cmds "github.com/ipfs/go-ipfs-cmds"
"github.com/ipfs/go-ipfs-files" files "github.com/ipfs/go-ipfs-files"
logging "github.com/ipfs/go-log" logging "github.com/ipfs/go-log"
) )
...@@ -133,7 +133,7 @@ func parseRequest(r *http.Request, root *cmds.Command) (*cmds.Request, error) { ...@@ -133,7 +133,7 @@ func parseRequest(r *http.Request, root *cmds.Command) (*cmds.Request, error) {
// if there is a required filearg, error if no files were provided // if there is a required filearg, error if no files were provided
if len(requiredFile) > 0 && f == nil { if len(requiredFile) > 0 && f == nil {
return nil, fmt.Errorf("File argument '%s' is required", requiredFile) return nil, fmt.Errorf("file argument '%s' is required", requiredFile)
} }
ctx := logging.ContextWithLoggable(r.Context(), uuidLoggable()) ctx := logging.ContextWithLoggable(r.Context(), uuidLoggable())
......
...@@ -47,7 +47,7 @@ func TestParse(t *testing.T) { ...@@ -47,7 +47,7 @@ func TestParse(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
req, err = parseRequest(r, root) _, err = parseRequest(r, root)
if err != ErrNotFound { if err != ErrNotFound {
t.Errorf("expected ErrNotFound, got: %v", err) t.Errorf("expected ErrNotFound, got: %v", err)
} }
......
...@@ -384,7 +384,7 @@ func TestEncoding(t *testing.T) { ...@@ -384,7 +384,7 @@ func TestEncoding(t *testing.T) {
} }
tcs := []httpTestCase{ tcs := []httpTestCase{
gtc(cmds.JSON, applicationJson), gtc(cmds.JSON, applicationJSON),
gtc(cmds.XML, "application/xml"), gtc(cmds.XML, "application/xml"),
} }
......
...@@ -8,14 +8,14 @@ import ( ...@@ -8,14 +8,14 @@ import (
"strings" "strings"
"sync" "sync"
"github.com/ipfs/go-ipfs-cmds" cmds "github.com/ipfs/go-ipfs-cmds"
) )
var ( var (
HeadRequest = fmt.Errorf("HEAD request") // AllowedExposedHeadersArr defines the default Access-Control-Expose-Headers.
AllowedExposedHeadersArr = []string{streamHeader, channelHeader, extraContentLengthHeader} AllowedExposedHeadersArr = []string{streamHeader, channelHeader, extraContentLengthHeader}
AllowedExposedHeaders = strings.Join(AllowedExposedHeadersArr, ", ") // AllowedExposedHeaders is the list of defaults Access-Control-Expose-Headers separated by comma.
AllowedExposedHeaders = strings.Join(AllowedExposedHeadersArr, ", ")
mimeTypes = map[cmds.EncodingType]string{ mimeTypes = map[cmds.EncodingType]string{
cmds.Protobuf: "application/protobuf", cmds.Protobuf: "application/protobuf",
...@@ -25,7 +25,7 @@ var ( ...@@ -25,7 +25,7 @@ var (
} }
) )
// NewResponeEmitter returns a new ResponseEmitter. // NewResponseEmitter returns a new ResponseEmitter.
func NewResponseEmitter(w http.ResponseWriter, method string, req *cmds.Request, opts ...ResponseEmitterOption) (ResponseEmitter, error) { func NewResponseEmitter(w http.ResponseWriter, method string, req *cmds.Request, opts ...ResponseEmitterOption) (ResponseEmitter, error) {
encType, enc, err := cmds.GetEncoder(req, w, cmds.JSON) encType, enc, err := cmds.GetEncoder(req, w, cmds.JSON)
if err != nil { if err != nil {
...@@ -61,6 +61,8 @@ func withRequestBodyEOFChan(ch <-chan struct{}) ResponseEmitterOption { ...@@ -61,6 +61,8 @@ func withRequestBodyEOFChan(ch <-chan struct{}) ResponseEmitterOption {
} }
} }
// ResponseEmitter interface defines the components that can care of sending
// the response to HTTP Requests.
type ResponseEmitter interface { type ResponseEmitter interface {
cmds.ResponseEmitter cmds.ResponseEmitter
http.Flusher http.Flusher
...@@ -75,7 +77,6 @@ type responseEmitter struct { ...@@ -75,7 +77,6 @@ type responseEmitter struct {
l sync.Mutex l sync.Mutex
length uint64 length uint64
err *cmds.Error
bodyEOFChan <-chan struct{} bodyEOFChan <-chan struct{}
...@@ -315,10 +316,6 @@ func (re *responseEmitter) doPreamble(value interface{}) { ...@@ -315,10 +316,6 @@ func (re *responseEmitter) doPreamble(value interface{}) {
re.w.WriteHeader(http.StatusOK) re.w.WriteHeader(http.StatusOK)
} }
type responseWriterer interface {
Lower() http.ResponseWriter
}
func flushCopy(w io.Writer, r io.Reader) error { func flushCopy(w io.Writer, r io.Reader) error {
buf := make([]byte, 4096) buf := make([]byte, 4096)
f, ok := w.(http.Flusher) f, ok := w.(http.Flusher)
......
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"time" "time"
) )
// ReqLogEntry represent a log entry for a request.
type ReqLogEntry struct { type ReqLogEntry struct {
StartTime time.Time StartTime time.Time
EndTime time.Time EndTime time.Time
...@@ -16,11 +17,13 @@ type ReqLogEntry struct { ...@@ -16,11 +17,13 @@ type ReqLogEntry struct {
ID int ID int
} }
// Copy copies a log entry and returns a pointer to the copy.
func (r *ReqLogEntry) Copy() *ReqLogEntry { func (r *ReqLogEntry) Copy() *ReqLogEntry {
out := *r out := *r
return &out return &out
} }
// ReqLog represents a request log.
type ReqLog struct { type ReqLog struct {
Requests []*ReqLogEntry Requests []*ReqLogEntry
nextID int nextID int
...@@ -28,6 +31,7 @@ type ReqLog struct { ...@@ -28,6 +31,7 @@ type ReqLog struct {
keep time.Duration keep time.Duration
} }
// Add ads an entry to the log for the given request.
func (rl *ReqLog) Add(req *Request) *ReqLogEntry { func (rl *ReqLog) Add(req *Request) *ReqLogEntry {
rle := &ReqLogEntry{ rle := &ReqLogEntry{
StartTime: time.Now(), StartTime: time.Now(),
...@@ -42,6 +46,7 @@ func (rl *ReqLog) Add(req *Request) *ReqLogEntry { ...@@ -42,6 +46,7 @@ func (rl *ReqLog) Add(req *Request) *ReqLogEntry {
return rle return rle
} }
// AddEntry adds an entry to the log.
func (rl *ReqLog) AddEntry(rle *ReqLogEntry) { func (rl *ReqLog) AddEntry(rle *ReqLogEntry) {
rl.lock.Lock() rl.lock.Lock()
defer rl.lock.Unlock() defer rl.lock.Unlock()
...@@ -52,10 +57,9 @@ func (rl *ReqLog) AddEntry(rle *ReqLogEntry) { ...@@ -52,10 +57,9 @@ func (rl *ReqLog) AddEntry(rle *ReqLogEntry) {
if rle == nil || !rle.Active { if rle == nil || !rle.Active {
rl.maybeCleanup() rl.maybeCleanup()
} }
return
} }
// ClearInactive clears any inactive requests from the log.
func (rl *ReqLog) ClearInactive() { func (rl *ReqLog) ClearInactive() {
rl.lock.Lock() rl.lock.Lock()
defer rl.lock.Unlock() defer rl.lock.Unlock()
......
...@@ -66,6 +66,7 @@ func (req *Request) BodyArgs() StdinArguments { ...@@ -66,6 +66,7 @@ func (req *Request) BodyArgs() StdinArguments {
return nil return nil
} }
// ParseBodyArgs parses arguments in the request body.
func (req *Request) ParseBodyArgs() error { func (req *Request) ParseBodyArgs() error {
s := req.BodyArgs() s := req.BodyArgs()
if s == nil { if s == nil {
...@@ -78,6 +79,7 @@ func (req *Request) ParseBodyArgs() error { ...@@ -78,6 +79,7 @@ func (req *Request) ParseBodyArgs() error {
return s.Err() return s.Err()
} }
// SetOption sets a request option.
func (req *Request) SetOption(name string, value interface{}) { func (req *Request) SetOption(name string, value interface{}) {
optDefs, err := req.Root.GetOptions(req.Path) optDefs, err := req.Root.GetOptions(req.Path)
optDef, found := optDefs[name] optDef, found := optDefs[name]
...@@ -95,8 +97,6 @@ func (req *Request) SetOption(name string, value interface{}) { ...@@ -95,8 +97,6 @@ func (req *Request) SetOption(name string, value interface{}) {
name = optDef.Name() name = optDef.Name()
req.Options[name] = value req.Options[name] = value
return
} }
func checkAndConvertOptions(root *Command, opts OptMap, path []string) (OptMap, error) { func checkAndConvertOptions(root *Command, opts OptMap, path []string) (OptMap, error) {
...@@ -125,20 +125,20 @@ func checkAndConvertOptions(root *Command, opts OptMap, path []string) (OptMap, ...@@ -125,20 +125,20 @@ func checkAndConvertOptions(root *Command, opts OptMap, path []string) (OptMap,
if len(str) == 0 { if len(str) == 0 {
value = "empty value" value = "empty value"
} }
return options, fmt.Errorf("Could not convert %s to type %q (for option %q)", return options, fmt.Errorf("could not convert %s to type %q (for option %q)",
value, opt.Type().String(), "-"+k) value, opt.Type().String(), "-"+k)
} }
options[k] = val options[k] = val
} else { } else {
return options, fmt.Errorf("Option %q should be type %q, but got type %q", return options, fmt.Errorf("option %q should be type %q, but got type %q",
k, opt.Type().String(), kind.String()) k, opt.Type().String(), kind.String())
} }
} }
for _, name := range opt.Names() { for _, name := range opt.Names() {
if _, ok := options[name]; name != k && ok { if _, ok := options[name]; name != k && ok {
return options, fmt.Errorf("Duplicate command options were provided (%q and %q)", return options, fmt.Errorf("duplicate command options were provided (%q and %q)",
k, name) k, name)
} }
} }
...@@ -162,7 +162,7 @@ func GetEncoding(req *Request, def EncodingType) EncodingType { ...@@ -162,7 +162,7 @@ func GetEncoding(req *Request, def EncodingType) EncodingType {
} }
} }
// fillDefault fills in default values if option has not been set // FillDefaults fills in default values if option has not been set.
func (req *Request) FillDefaults() error { func (req *Request) FillDefaults() error {
optDefMap, err := req.Root.GetOptions(req.Path) optDefMap, err := req.Root.GetOptions(req.Path)
if err != nil { if err != nil {
......
...@@ -12,20 +12,6 @@ type TestOutput struct { ...@@ -12,20 +12,6 @@ type TestOutput struct {
Baz int Baz int
} }
func eqStringSlice(a, b []string) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}
func TestMarshalling(t *testing.T) { func TestMarshalling(t *testing.T) {
cmd := &Command{} cmd := &Command{}
......
...@@ -19,18 +19,21 @@ func TestCopy(t *testing.T) { ...@@ -19,18 +19,21 @@ func TestCopy(t *testing.T) {
go func() { go func() {
err := Copy(re2, res1) err := Copy(re2, res1)
if err != nil { if err != nil {
t.Fatal(err) t.Error(err)
return
} }
}() }()
go func() { go func() {
err := re1.Emit("test") err := re1.Emit("test")
if err != nil { if err != nil {
t.Fatal(err) t.Error(err)
return
} }
err = re1.Close() err = re1.Close()
if err != nil { if err != nil {
t.Fatal(err) t.Error(err)
return
} }
}() }()
...@@ -64,18 +67,21 @@ func TestCopyError(t *testing.T) { ...@@ -64,18 +67,21 @@ func TestCopyError(t *testing.T) {
go func() { go func() {
err := Copy(re2, res1) err := Copy(re2, res1)
if err != nil { if err != nil {
t.Fatal(err) t.Error(err)
return
} }
}() }()
go func() { go func() {
err := re1.Emit("test") err := re1.Emit("test")
if err != nil { if err != nil {
t.Fatal(err) t.Error(err)
return
} }
err = re1.CloseWithError(fooErr) err = re1.CloseWithError(fooErr)
if err != nil { if err != nil {
t.Fatal(err) t.Error(err)
return
} }
}() }()
...@@ -106,17 +112,20 @@ func TestError(t *testing.T) { ...@@ -106,17 +112,20 @@ func TestError(t *testing.T) {
go func() { go func() {
err := re.Emit("value1") err := re.Emit("value1")
if err != nil { if err != nil {
t.Fatal(err) t.Error(err)
return
} }
err = re.Emit("value2") err = re.Emit("value2")
if err != nil { if err != nil {
t.Fatal(err) t.Error(err)
return
} }
err = re.CloseWithError(&Error{Message: "foo"}) err = re.CloseWithError(&Error{Message: "foo"})
if err != nil { if err != nil {
t.Fatal(err) t.Error(err)
return
} }
}() }()
......
...@@ -22,7 +22,8 @@ func TestSingleChan(t *testing.T) { ...@@ -22,7 +22,8 @@ func TestSingleChan(t *testing.T) {
defer wg.Done() defer wg.Done()
if err := EmitOnce(re, "test"); err != nil { if err := EmitOnce(re, "test"); err != nil {
t.Fatal(err) t.Error(err)
return
} }
err := re.Emit("test") err := re.Emit("test")
...@@ -73,7 +74,8 @@ func TestSingleWriter(t *testing.T) { ...@@ -73,7 +74,8 @@ func TestSingleWriter(t *testing.T) {
wg.Add(1) wg.Add(1)
go func() { go func() {
if err := EmitOnce(re, "test"); err != nil { if err := EmitOnce(re, "test"); err != nil {
t.Fatal(err) t.Error(err)
return
} }
err := re.Emit("this should not be sent") err := re.Emit("this should not be sent")
......
...@@ -8,6 +8,8 @@ import ( ...@@ -8,6 +8,8 @@ import (
"sync" "sync"
) )
// NewWriterResponseEmitter creates a response emitter that sends responses to
// the given WriterCloser.
func NewWriterResponseEmitter(w io.WriteCloser, req *Request) (ResponseEmitter, error) { func NewWriterResponseEmitter(w io.WriteCloser, req *Request) (ResponseEmitter, error) {
_, valEnc, err := GetEncoder(req, w, Undefined) _, valEnc, err := GetEncoder(req, w, Undefined)
if err != nil { if err != nil {
...@@ -24,6 +26,7 @@ func NewWriterResponseEmitter(w io.WriteCloser, req *Request) (ResponseEmitter, ...@@ -24,6 +26,7 @@ func NewWriterResponseEmitter(w io.WriteCloser, req *Request) (ResponseEmitter,
return re, nil return re, nil
} }
// NewReaderResponse creates a Response from the given reader.
func NewReaderResponse(r io.Reader, req *Request) (Response, error) { func NewReaderResponse(r io.Reader, req *Request) (Response, error) {
encType := GetEncoding(req, Undefined) encType := GetEncoding(req, Undefined)
dec, ok := Decoders[encType] dec, ok := Decoders[encType]
...@@ -99,7 +102,6 @@ type writerResponseEmitter struct { ...@@ -99,7 +102,6 @@ type writerResponseEmitter struct {
req *Request req *Request
length *uint64 length *uint64
err *Error
emitted bool emitted bool
closed bool closed bool
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment