Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
dms3
go-unixfs
Commits
43670971
Commit
43670971
authored
10 years ago
by
Matt Bell
Committed by
Juan Batiz-Benet
10 years ago
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
commands: Formatted code
parent
94ca2642
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
314 additions
and
310 deletions
+314
-310
commands/command.go
commands/command.go
+98
-98
commands/command_test.go
commands/command_test.go
+115
-115
commands/option.go
commands/option.go
+14
-13
commands/request.go
commands/request.go
+13
-13
commands/response.go
commands/response.go
+43
-40
commands/response_test.go
commands/response_test.go
+31
-31
No files found.
commands/command.go
View file @
43670971
package
commands
import
(
"fmt"
"strings
"
"reflect
"
"fmt"
"reflect
"
"strings
"
)
type
Command
struct
{
Help
string
Options
[]
Option
f
func
(
*
Request
,
*
Response
)
subcommands
map
[
string
]
*
Command
Help
string
Options
[]
Option
f
func
(
*
Request
,
*
Response
)
subcommands
map
[
string
]
*
Command
}
// Register adds a subcommand
func
(
c
*
Command
)
Register
(
id
string
,
sub
*
Command
)
error
{
if
c
.
subcommands
==
nil
{
c
.
subcommands
=
make
(
map
[
string
]
*
Command
)
}
// check for duplicate option names (only checks downwards)
names
:=
make
(
map
[
string
]
bool
)
globalCommand
.
checkOptions
(
names
)
c
.
checkOptions
(
names
)
err
:=
sub
.
checkOptions
(
names
)
if
err
!=
nil
{
return
err
}
if
_
,
ok
:=
c
.
subcommands
[
id
];
ok
{
return
fmt
.
Errorf
(
"There is already a subcommand registered with id '%s'"
,
id
)
}
c
.
subcommands
[
id
]
=
sub
return
nil
if
c
.
subcommands
==
nil
{
c
.
subcommands
=
make
(
map
[
string
]
*
Command
)
}
// check for duplicate option names (only checks downwards)
names
:=
make
(
map
[
string
]
bool
)
globalCommand
.
checkOptions
(
names
)
c
.
checkOptions
(
names
)
err
:=
sub
.
checkOptions
(
names
)
if
err
!=
nil
{
return
err
}
if
_
,
ok
:=
c
.
subcommands
[
id
];
ok
{
return
fmt
.
Errorf
(
"There is already a subcommand registered with id '%s'"
,
id
)
}
c
.
subcommands
[
id
]
=
sub
return
nil
}
// Call invokes the command at the given subcommand path
func
(
c
*
Command
)
Call
(
path
[]
string
,
req
*
Request
)
*
Response
{
options
:=
make
([]
Option
,
len
(
c
.
Options
))
copy
(
options
,
c
.
Options
)
options
=
append
(
options
,
globalOptions
...
)
cmd
:=
c
res
:=
&
Response
{
req
:
req
}
if
path
!=
nil
{
for
i
,
id
:=
range
path
{
cmd
=
c
.
Sub
(
id
)
if
cmd
==
nil
{
pathS
:=
strings
.
Join
(
path
[
0
:
i
],
"/"
)
res
.
SetError
(
fmt
.
Errorf
(
"Undefined command: '%s'"
,
pathS
),
Client
)
return
res
}
options
=
append
(
options
,
cmd
.
Options
...
)
}
}
optionsMap
:=
make
(
map
[
string
]
Option
)
for
_
,
opt
:=
range
options
{
for
_
,
name
:=
range
opt
.
Names
{
optionsMap
[
name
]
=
opt
}
}
for
k
,
v
:=
range
req
.
options
{
opt
,
ok
:=
optionsMap
[
k
]
if
!
ok
{
res
.
SetError
(
fmt
.
Errorf
(
"Unrecognized command option: '%s'"
,
k
),
Client
)
return
res
}
for
_
,
name
:=
range
opt
.
Names
{
if
_
,
ok
=
req
.
options
[
name
];
name
!=
k
&&
ok
{
res
.
SetError
(
fmt
.
Errorf
(
"Duplicate command options were provided ('%s' and '%s')"
,
k
,
name
),
Client
)
return
res
}
}
kind
:=
reflect
.
TypeOf
(
v
)
.
Kind
()
if
kind
!=
opt
.
Type
{
res
.
SetError
(
fmt
.
Errorf
(
"Option '%s' should be type '%s', but got type '%s'"
,
k
,
opt
.
Type
.
String
(),
kind
.
String
()),
Client
)
return
res
}
}
cmd
.
f
(
req
,
res
)
return
res
options
:=
make
([]
Option
,
len
(
c
.
Options
))
copy
(
options
,
c
.
Options
)
options
=
append
(
options
,
globalOptions
...
)
cmd
:=
c
res
:=
&
Response
{
req
:
req
}
if
path
!=
nil
{
for
i
,
id
:=
range
path
{
cmd
=
c
.
Sub
(
id
)
if
cmd
==
nil
{
pathS
:=
strings
.
Join
(
path
[
0
:
i
],
"/"
)
res
.
SetError
(
fmt
.
Errorf
(
"Undefined command: '%s'"
,
pathS
),
Client
)
return
res
}
options
=
append
(
options
,
cmd
.
Options
...
)
}
}
optionsMap
:=
make
(
map
[
string
]
Option
)
for
_
,
opt
:=
range
options
{
for
_
,
name
:=
range
opt
.
Names
{
optionsMap
[
name
]
=
opt
}
}
for
k
,
v
:=
range
req
.
options
{
opt
,
ok
:=
optionsMap
[
k
]
if
!
ok
{
res
.
SetError
(
fmt
.
Errorf
(
"Unrecognized command option: '%s'"
,
k
),
Client
)
return
res
}
for
_
,
name
:=
range
opt
.
Names
{
if
_
,
ok
=
req
.
options
[
name
];
name
!=
k
&&
ok
{
res
.
SetError
(
fmt
.
Errorf
(
"Duplicate command options were provided ('%s' and '%s')"
,
k
,
name
),
Client
)
return
res
}
}
kind
:=
reflect
.
TypeOf
(
v
)
.
Kind
()
if
kind
!=
opt
.
Type
{
res
.
SetError
(
fmt
.
Errorf
(
"Option '%s' should be type '%s', but got type '%s'"
,
k
,
opt
.
Type
.
String
(),
kind
.
String
()),
Client
)
return
res
}
}
cmd
.
f
(
req
,
res
)
return
res
}
// Sub returns the subcommand with the given id
func
(
c
*
Command
)
Sub
(
id
string
)
*
Command
{
return
c
.
subcommands
[
id
]
return
c
.
subcommands
[
id
]
}
func
(
c
*
Command
)
checkOptions
(
names
map
[
string
]
bool
)
error
{
for
_
,
opt
:=
range
c
.
Options
{
for
_
,
name
:=
range
opt
.
Names
{
if
_
,
ok
:=
names
[
name
];
ok
{
return
fmt
.
Errorf
(
"Multiple options are using the same name ('%s')"
,
name
)
}
names
[
name
]
=
true
}
}
for
_
,
cmd
:=
range
c
.
subcommands
{
err
:=
cmd
.
checkOptions
(
names
)
if
err
!=
nil
{
return
err
}
}
return
nil
for
_
,
opt
:=
range
c
.
Options
{
for
_
,
name
:=
range
opt
.
Names
{
if
_
,
ok
:=
names
[
name
];
ok
{
return
fmt
.
Errorf
(
"Multiple options are using the same name ('%s')"
,
name
)
}
names
[
name
]
=
true
}
}
for
_
,
cmd
:=
range
c
.
subcommands
{
err
:=
cmd
.
checkOptions
(
names
)
if
err
!=
nil
{
return
err
}
}
return
nil
}
This diff is collapsed.
Click to expand it.
commands/command_test.go
View file @
43670971
...
...
@@ -3,122 +3,122 @@ package commands
import
"testing"
func
TestOptionValidation
(
t
*
testing
.
T
)
{
cmd
:=
Command
{
Options
:
[]
Option
{
Option
{
[]
string
{
"b"
,
"beep"
},
Int
},
Option
{
[]
string
{
"B"
,
"boop"
},
String
},
},
f
:
func
(
req
*
Request
,
res
*
Response
)
{},
}
req
:=
NewRequest
()
req
.
options
[
"foo"
]
=
5
res
:=
cmd
.
Call
(
nil
,
req
)
if
res
.
Error
==
nil
{
t
.
Error
(
"Should have failed (unrecognized command)"
)
}
req
=
NewRequest
()
req
.
options
[
"beep"
]
=
5
req
.
options
[
"b"
]
=
10
res
=
cmd
.
Call
(
nil
,
req
)
if
res
.
Error
==
nil
{
t
.
Error
(
"Should have failed (duplicate options)"
)
}
req
=
NewRequest
()
req
.
options
[
"beep"
]
=
"foo"
res
=
cmd
.
Call
(
nil
,
req
)
if
res
.
Error
==
nil
{
t
.
Error
(
"Should have failed (incorrect type)"
)
}
req
=
NewRequest
()
req
.
options
[
"beep"
]
=
5
res
=
cmd
.
Call
(
nil
,
req
)
if
res
.
Error
!=
nil
{
t
.
Error
(
"Should have passed"
)
}
req
=
NewRequest
()
req
.
options
[
"beep"
]
=
5
req
.
options
[
"boop"
]
=
"test"
res
=
cmd
.
Call
(
nil
,
req
)
if
res
.
Error
!=
nil
{
t
.
Error
(
"Should have passed"
)
}
req
=
NewRequest
()
req
.
options
[
"b"
]
=
5
req
.
options
[
"B"
]
=
"test"
res
=
cmd
.
Call
(
nil
,
req
)
if
res
.
Error
!=
nil
{
t
.
Error
(
"Should have passed"
)
}
req
=
NewRequest
()
req
.
options
[
"enc"
]
=
"json"
res
=
cmd
.
Call
(
nil
,
req
)
if
res
.
Error
!=
nil
{
t
.
Error
(
"Should have passed"
)
}
cmd
:=
Command
{
Options
:
[]
Option
{
Option
{[]
string
{
"b"
,
"beep"
},
Int
},
Option
{[]
string
{
"B"
,
"boop"
},
String
},
},
f
:
func
(
req
*
Request
,
res
*
Response
)
{},
}
req
:=
NewRequest
()
req
.
options
[
"foo"
]
=
5
res
:=
cmd
.
Call
(
nil
,
req
)
if
res
.
Error
==
nil
{
t
.
Error
(
"Should have failed (unrecognized command)"
)
}
req
=
NewRequest
()
req
.
options
[
"beep"
]
=
5
req
.
options
[
"b"
]
=
10
res
=
cmd
.
Call
(
nil
,
req
)
if
res
.
Error
==
nil
{
t
.
Error
(
"Should have failed (duplicate options)"
)
}
req
=
NewRequest
()
req
.
options
[
"beep"
]
=
"foo"
res
=
cmd
.
Call
(
nil
,
req
)
if
res
.
Error
==
nil
{
t
.
Error
(
"Should have failed (incorrect type)"
)
}
req
=
NewRequest
()
req
.
options
[
"beep"
]
=
5
res
=
cmd
.
Call
(
nil
,
req
)
if
res
.
Error
!=
nil
{
t
.
Error
(
"Should have passed"
)
}
req
=
NewRequest
()
req
.
options
[
"beep"
]
=
5
req
.
options
[
"boop"
]
=
"test"
res
=
cmd
.
Call
(
nil
,
req
)
if
res
.
Error
!=
nil
{
t
.
Error
(
"Should have passed"
)
}
req
=
NewRequest
()
req
.
options
[
"b"
]
=
5
req
.
options
[
"B"
]
=
"test"
res
=
cmd
.
Call
(
nil
,
req
)
if
res
.
Error
!=
nil
{
t
.
Error
(
"Should have passed"
)
}
req
=
NewRequest
()
req
.
options
[
"enc"
]
=
"json"
res
=
cmd
.
Call
(
nil
,
req
)
if
res
.
Error
!=
nil
{
t
.
Error
(
"Should have passed"
)
}
}
func
TestRegistration
(
t
*
testing
.
T
)
{
cmds
:=
[]
*
Command
{
&
Command
{
Options
:
[]
Option
{
Option
{
[]
string
{
"beep"
},
Int
},
},
f
:
func
(
req
*
Request
,
res
*
Response
)
{},
},
&
Command
{
Options
:
[]
Option
{
Option
{
[]
string
{
"boop"
},
Int
},
},
f
:
func
(
req
*
Request
,
res
*
Response
)
{},
},
&
Command
{
Options
:
[]
Option
{
Option
{
[]
string
{
"boop"
},
String
},
},
f
:
func
(
req
*
Request
,
res
*
Response
)
{},
},
&
Command
{
Options
:
[]
Option
{
Option
{
[]
string
{
"bop"
},
String
},
},
f
:
func
(
req
*
Request
,
res
*
Response
)
{},
},
&
Command
{
Options
:
[]
Option
{
Option
{
[]
string
{
"enc"
},
String
},
},
f
:
func
(
req
*
Request
,
res
*
Response
)
{},
},
}
err
:=
cmds
[
0
]
.
Register
(
"foo"
,
cmds
[
1
])
if
err
!=
nil
{
t
.
Error
(
"Should have passed"
)
}
err
=
cmds
[
0
]
.
Register
(
"bar"
,
cmds
[
2
])
if
err
==
nil
{
t
.
Error
(
"Should have failed (option name collision)"
)
}
err
=
cmds
[
0
]
.
Register
(
"foo"
,
cmds
[
3
])
if
err
==
nil
{
t
.
Error
(
"Should have failed (subcommand name collision)"
)
}
err
=
cmds
[
0
]
.
Register
(
"baz"
,
cmds
[
4
])
if
err
==
nil
{
t
.
Error
(
"Should have failed (option name collision with global options)"
)
}
cmds
:=
[]
*
Command
{
&
Command
{
Options
:
[]
Option
{
Option
{[]
string
{
"beep"
},
Int
},
},
f
:
func
(
req
*
Request
,
res
*
Response
)
{},
},
&
Command
{
Options
:
[]
Option
{
Option
{[]
string
{
"boop"
},
Int
},
},
f
:
func
(
req
*
Request
,
res
*
Response
)
{},
},
&
Command
{
Options
:
[]
Option
{
Option
{[]
string
{
"boop"
},
String
},
},
f
:
func
(
req
*
Request
,
res
*
Response
)
{},
},
&
Command
{
Options
:
[]
Option
{
Option
{[]
string
{
"bop"
},
String
},
},
f
:
func
(
req
*
Request
,
res
*
Response
)
{},
},
&
Command
{
Options
:
[]
Option
{
Option
{[]
string
{
"enc"
},
String
},
},
f
:
func
(
req
*
Request
,
res
*
Response
)
{},
},
}
err
:=
cmds
[
0
]
.
Register
(
"foo"
,
cmds
[
1
])
if
err
!=
nil
{
t
.
Error
(
"Should have passed"
)
}
err
=
cmds
[
0
]
.
Register
(
"bar"
,
cmds
[
2
])
if
err
==
nil
{
t
.
Error
(
"Should have failed (option name collision)"
)
}
err
=
cmds
[
0
]
.
Register
(
"foo"
,
cmds
[
3
])
if
err
==
nil
{
t
.
Error
(
"Should have failed (subcommand name collision)"
)
}
err
=
cmds
[
0
]
.
Register
(
"baz"
,
cmds
[
4
])
if
err
==
nil
{
t
.
Error
(
"Should have failed (option name collision with global options)"
)
}
}
This diff is collapsed.
Click to expand it.
commands/option.go
View file @
43670971
...
...
@@ -3,29 +3,30 @@ package commands
import
"reflect"
const
(
Invalid
=
reflect
.
Invalid
Bool
=
reflect
.
Bool
Int
=
reflect
.
Int
Uint
=
reflect
.
Uint
Float
=
reflect
.
Float32
String
=
reflect
.
String
Invalid
=
reflect
.
Invalid
Bool
=
reflect
.
Bool
Int
=
reflect
.
Int
Uint
=
reflect
.
Uint
Float
=
reflect
.
Float32
String
=
reflect
.
String
)
// Option is used to specify a field that will be provided by a consumer
type
Option
struct
{
Names
[]
string
// a list of unique names to
Type
reflect
.
Kind
// value must be this type
Names
[]
string
// a list of unique names to
Type
reflect
.
Kind
// value must be this type
// TODO: add more features(?):
//Default interface{} // the default value (ignored if `Required` is true)
//Required bool // whether or not the option must be provided
// TODO: add more features(?):
//Default interface{} // the default value (ignored if `Required` is true)
//Required bool // whether or not the option must be provided
}
// options that are used by this package
var
globalOptions
[]
Option
=
[]
Option
{
Option
{
[]
string
{
"enc"
,
"encoding"
},
String
},
Option
{[]
string
{
"enc"
,
"encoding"
},
String
},
}
// the above array of Options, wrapped in a Command
var
globalCommand
*
Command
=
&
Command
{
Options
:
globalOptions
,
Options
:
globalOptions
,
}
This diff is collapsed.
Click to expand it.
commands/request.go
View file @
43670971
...
...
@@ -2,29 +2,29 @@ package commands
// Request represents a call to a command from a consumer
type
Request
struct
{
options
map
[
string
]
interface
{}
arguments
[]
string
options
map
[
string
]
interface
{}
arguments
[]
string
}
func
(
r
*
Request
)
Option
(
name
string
)
interface
{}
{
return
r
.
options
[
name
]
return
r
.
options
[
name
]
}
func
(
r
*
Request
)
SetOption
(
option
Option
,
value
interface
{})
{
// saves the option value in the map, indexed by each name
// (so commands can retrieve it using any of the names)
for
_
,
name
:=
range
option
.
Names
{
r
.
options
[
name
]
=
value
}
// saves the option value in the map, indexed by each name
// (so commands can retrieve it using any of the names)
for
_
,
name
:=
range
option
.
Names
{
r
.
options
[
name
]
=
value
}
}
func
(
r
*
Request
)
Arguments
()
[]
string
{
return
r
.
arguments
return
r
.
arguments
}
func
NewRequest
()
*
Request
{
return
&
Request
{
make
(
map
[
string
]
interface
{}),
make
([]
string
,
0
),
}
return
&
Request
{
make
(
map
[
string
]
interface
{}),
make
([]
string
,
0
),
}
}
This diff is collapsed.
Click to expand it.
commands/response.go
View file @
43670971
package
commands
import
(
"fmt
"
"strings
"
"encoding/json
"
"encoding/xml
"
"encoding/json
"
"encoding/xml
"
"fmt
"
"strings
"
)
type
ErrorType
uint
const
(
Normal
ErrorType
=
iota
// general errors
Client
// error was caused by the client, (e.g. invalid CLI usage)
// TODO: add more types of errors for better error-specific handling
Normal
ErrorType
=
iota
// general errors
Client
// error was caused by the client, (e.g. invalid CLI usage)
// TODO: add more types of errors for better error-specific handling
)
// Error is a struct for marshalling errors
type
Error
struct
{
Message
string
Code
ErrorType
Message
string
Code
ErrorType
}
type
EncodingType
string
const
(
Json
=
"json"
Xml
=
"xml"
// TODO: support more encoding types
Json
=
"json"
Xml
=
"xml"
// TODO: support more encoding types
)
type
Marshaller
func
(
v
interface
{})([]
byte
,
error
)
type
Marshaller
func
(
v
interface
{})
([]
byte
,
error
)
var
marshallers
=
map
[
EncodingType
]
Marshaller
{
Json
:
json
.
Marshal
,
Xml
:
xml
.
Marshal
,
Json
:
json
.
Marshal
,
Xml
:
xml
.
Marshal
,
}
type
Response
struct
{
req
*
Request
Error
error
ErrorType
ErrorType
Value
interface
{}
req
*
Request
Error
error
ErrorType
ErrorType
Value
interface
{}
}
func
(
r
*
Response
)
SetError
(
err
error
,
errType
ErrorType
)
{
r
.
Error
=
err
r
.
ErrorType
=
errType
r
.
Error
=
err
r
.
ErrorType
=
errType
}
func
(
r
*
Response
)
FormatError
()
Error
{
return
Error
{
r
.
Error
.
Error
(),
r
.
ErrorType
}
return
Error
{
r
.
Error
.
Error
(),
r
.
ErrorType
}
}
func
(
r
*
Response
)
Marshal
()
([]
byte
,
error
)
{
if
r
.
Error
==
nil
&&
r
.
Value
==
nil
{
return
nil
,
fmt
.
Errorf
(
"No error or value set, there is nothing to marshal"
)
}
if
r
.
Error
==
nil
&&
r
.
Value
==
nil
{
return
nil
,
fmt
.
Errorf
(
"No error or value set, there is nothing to marshal"
)
}
enc
:=
r
.
req
.
Option
(
"enc"
)
if
enc
==
nil
{
return
nil
,
fmt
.
Errorf
(
"No encoding type was specified"
)
}
encType
:=
EncodingType
(
strings
.
ToLower
(
enc
.
(
string
)))
enc
:=
r
.
req
.
Option
(
"enc"
)
if
enc
==
nil
{
return
nil
,
fmt
.
Errorf
(
"No encoding type was specified"
)
}
encType
:=
EncodingType
(
strings
.
ToLower
(
enc
.
(
string
)))
marshaller
,
ok
:=
marshallers
[
encType
]
if
!
ok
{
return
nil
,
fmt
.
Errorf
(
"No marshaller found for encoding type '%s'"
,
enc
)
}
marshaller
,
ok
:=
marshallers
[
encType
]
if
!
ok
{
return
nil
,
fmt
.
Errorf
(
"No marshaller found for encoding type '%s'"
,
enc
)
}
if
r
.
Error
!=
nil
{
err
:=
r
.
FormatError
()
return
marshaller
(
err
)
}
else
{
return
marshaller
(
r
.
Value
)
}
if
r
.
Error
!=
nil
{
err
:=
r
.
FormatError
()
return
marshaller
(
err
)
}
else
{
return
marshaller
(
r
.
Value
)
}
}
This diff is collapsed.
Click to expand it.
commands/response_test.go
View file @
43670971
package
commands
import
(
"testing
"
"fmt
"
"fmt
"
"testing
"
)
type
TestOutput
struct
{
Foo
,
Bar
string
Baz
int
Foo
,
Bar
string
Baz
int
}
func
TestMarshalling
(
t
*
testing
.
T
)
{
req
:=
NewRequest
()
req
:=
NewRequest
()
res
:=
Response
{
req
:
req
,
Value
:
TestOutput
{
"beep"
,
"boop"
,
1337
},
}
res
:=
Response
{
req
:
req
,
Value
:
TestOutput
{
"beep"
,
"boop"
,
1337
},
}
_
,
err
:=
res
.
Marshal
()
if
err
==
nil
{
t
.
Error
(
"Should have failed (no encoding type specified in request)"
)
}
_
,
err
:=
res
.
Marshal
()
if
err
==
nil
{
t
.
Error
(
"Should have failed (no encoding type specified in request)"
)
}
req
.
SetOption
(
globalOptions
[
0
],
Json
)
bytes
,
err
:=
res
.
Marshal
()
if
err
!=
nil
{
t
.
Error
(
"Should have passed"
)
}
output
:=
string
(
bytes
)
if
output
!=
"{
\"
Foo
\"
:
\"
beep
\"
,
\"
Bar
\"
:
\"
boop
\"
,
\"
Baz
\"
:1337}"
{
t
.
Error
(
"Incorrect JSON output"
)
}
req
.
SetOption
(
globalOptions
[
0
],
Json
)
bytes
,
err
:=
res
.
Marshal
()
if
err
!=
nil
{
t
.
Error
(
"Should have passed"
)
}
output
:=
string
(
bytes
)
if
output
!=
"{
\"
Foo
\"
:
\"
beep
\"
,
\"
Bar
\"
:
\"
boop
\"
,
\"
Baz
\"
:1337}"
{
t
.
Error
(
"Incorrect JSON output"
)
}
res
.
SetError
(
fmt
.
Errorf
(
"You broke something!"
),
Client
)
bytes
,
err
=
res
.
Marshal
()
if
err
!=
nil
{
t
.
Error
(
"Should have passed"
)
}
output
=
string
(
bytes
)
if
output
!=
"{
\"
Message
\"
:
\"
You broke something!
\"
,
\"
Code
\"
:1}"
{
t
.
Error
(
"Incorrect JSON output"
)
}
res
.
SetError
(
fmt
.
Errorf
(
"You broke something!"
),
Client
)
bytes
,
err
=
res
.
Marshal
()
if
err
!=
nil
{
t
.
Error
(
"Should have passed"
)
}
output
=
string
(
bytes
)
if
output
!=
"{
\"
Message
\"
:
\"
You broke something!
\"
,
\"
Code
\"
:1}"
{
t
.
Error
(
"Incorrect JSON output"
)
}
}
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment