Add conformance testing

This patch adds a go-multiaddr CLI to aid in testing this
implementation of multiaddr. It takes a multiaddr in string or
packed form as input, and prints detailed information about the
multiaddr. This tool can be useful beyond testing, of course.

Another addition is a Makefile target for running the new
multiaddr conformance test suite. This test suite lives at
https://github.com/multiformats/multiaddr and is fetched to be
run against our new go-multiaddr CLI. This target is to be run in CI

Neither the test suite nor the CLI are complete yet.

Currently the output looks like this:

```
> go run ./multiaddr /ip4/192.0.2.42/tcp/443 | jq .
{
  "string": "/ip4/192.0.2.42/tcp/443",
  "stringSize": "23",
  "packed": "0x04c000022a0601bb",
  "packedSize": "8",
  "components": [
    {
      "string": "/ip4/192.0.2.42",
      "stringSize": "15",
      "packed": "0x04c000022a",
      "packedSize": "5",
      "value": "192.0.2.42",
      "rawValue": "0xc000022a",
      "valueSize": "4",
      "protocol": "ip4",
      "codec": "4",
      "uvarint": "0x04",
      "lengthPrefix": ""
    },
    {
      "string": "/tcp/443",
      "stringSize": "8",
      "packed": "0x0601bb",
      "packedSize": "3",
      "value": "443",
      "rawValue": "0x01bb",
      "valueSize": "2",
      "protocol": "tcp",
      "codec": "6",
      "uvarint": "0x06",
      "lengthPrefix": ""
    }
  ]
}
```

And the Makefile target:

```
> make conformance
go get -d -v .
go build -o tmp/multiaddr/test/go-multiaddr ./multiaddr
cd tmp/multiaddr/test && MULTIADDR_BIN="./go-multiaddr" go test -v
=== RUN   TestGodog
MULTIADDR_BIN="./go-multiaddr"
Feature: Multiaddr

  Scenario: Banana                              # multiaddr.feature:3
    Given the multiaddr /ip4/192.0.2.42/tcp/443 # main_test.go:81 -> github.com/multiformats/multiaddr/test_test.theMultiaddr
    Then the packed form is 0x04c000022a0601bb  # main_test.go:98 -> github.com/multiformats/multiaddr/test_test.thePackedFormIs
    And the packed size is 8 bytes              # main_test.go:105 -> github.com/multiformats/multiaddr/test_test.thePackedSizeIs
    And the components are:                     # main_test.go:126 -> github.com/multiformats/multiaddr/test_test.theComponentsAre
      | string          | stringSize | packed       | packedSize | value      | valueSize | protocol | codec | uvarint | lengthPrefix | rawValue   |
      | /ip4/192.0.2.42 | 15         | 0x04c000022a | 5          | 192.0.2.42 | 4         | ip4      | 4     | 0x04    |              | 0xc000022a |
      | /tcp/443        | 8          | 0x0601bb     | 3          | 443        | 2         | tcp      | 6     | 0x06    |              | 0x01bb     |

  Scenario: Banana #2                               # multiaddr.feature:12
    Given the multiaddr 0x04c000022a0601bb          # main_test.go:81 -> github.com/multiformats/multiaddr/test_test.theMultiaddr
    Then the string form is /ip4/192.0.2.42/tcp/443 # main_test.go:112 -> github.com/multiformats/multiaddr/test_test.theStringFormIs
    And the string size is 23 bytes                 # main_test.go:119 -> github.com/multiformats/multiaddr/test_test.theStringSizeIs
    And the components are:                         # main_test.go:126 -> github.com/multiformats/multiaddr/test_test.theComponentsAre
      | string          | stringSize | packed       | packedSize | value      | valueSize | protocol | codec | uvarint | lengthPrefix | rawValue   |
      | /ip4/192.0.2.42 | 15         | 0x04c000022a | 5          | 192.0.2.42 | 4         | ip4      | 4     | 0x04    |              | 0xc000022a |
      | /tcp/443        | 8          | 0x0601bb     | 3          | 443        | 2         | tcp      | 6     | 0x06    |              | 0x01bb     |

2 scenarios (2 passed)
8 steps (8 passed)
3.187755ms
--- PASS: TestGodog (0.00s)
PASS
ok  	github.com/multiformats/multiaddr/test	0.012s
```
This commit is contained in:
Lars Gierth 2019-03-27 17:16:59 +01:00
parent ce21123d51
commit e791f319f0
5 changed files with 113 additions and 1 deletions

2
.gitignore vendored
View File

@ -1 +1,3 @@
.vscode/
multiaddr/multiaddr
tmp/

View File

@ -20,7 +20,7 @@ install:
script:
- bash <(curl -s https://raw.githubusercontent.com/ipfs/ci-helpers/master/travis-ci/run-standard-tests.sh)
- make conformance
cache:
directories:

View File

@ -12,3 +12,18 @@ deps: gx covertools
publish:
gx-go rewrite --undo
conformance: tmp/multiaddr
go get -d -v .
go build -o tmp/multiaddr/test/go-multiaddr ./multiaddr
cd tmp/multiaddr/test && MULTIADDR_BIN="./go-multiaddr" go test -v
tmp/multiaddr:
mkdir -p tmp/
git clone https://github.com/multiformats/multiaddr tmp/multiaddr/
# TODO(lgierth): drop this once multiaddr test suite is merged
git --work-tree=tmp/multiaddr/ --git-dir=tmp/multiaddr/.git checkout feat/test
clean:
rm -rf tmp/
.PHONY: gx covertools deps publish conformance clean

2
codecov.yml Normal file
View File

@ -0,0 +1,2 @@
ignore:
- "multiaddr"

93
multiaddr/main.go Normal file
View File

@ -0,0 +1,93 @@
package main
import (
"encoding/hex"
"flag"
"fmt"
"os"
"strings"
maddr "github.com/multiformats/go-multiaddr"
)
var (
flagHelp bool
)
func main() {
flag.Usage = func() {
usage := `usage: %s [options] ADDR
Print details about the given multiaddr.
Options:
`
fmt.Fprintf(os.Stderr, usage, os.Args[0])
flag.PrintDefaults()
}
flag.BoolVar(&flagHelp, "h", false, "display help message")
flag.Parse()
if flagHelp || len(flag.Args()) == 0 {
flag.Usage()
os.Exit(0)
}
addrStr := flag.Args()[0]
var addr maddr.Multiaddr
var err error
if strings.HasPrefix(addrStr, "0x") {
addrBytes, err := hex.DecodeString(addrStr[2:])
if err != nil {
fmt.Fprintf(os.Stderr, "parse error: %s\n", err)
os.Exit(1)
}
addr, err = maddr.NewMultiaddrBytes(addrBytes)
} else {
addr, err = maddr.NewMultiaddr(addrStr)
}
if err != nil {
fmt.Fprintf(os.Stderr, "parse error: %s\n", err)
os.Exit(1)
}
infoCommand(addr)
}
func infoCommand(addr maddr.Multiaddr) {
var compsJson []string
maddr.ForEach(addr, func(comp maddr.Component) bool {
lengthPrefix := ""
if comp.Protocol().Size == maddr.LengthPrefixedVarSize {
lengthPrefix = "0x" + hex.EncodeToString(maddr.CodeToVarint(len(comp.RawValue())))
}
compsJson = append(compsJson, `{`+
fmt.Sprintf(`"string": "%s", `, comp.String())+
fmt.Sprintf(`"stringSize": "%d", `, len(comp.String()))+
fmt.Sprintf(`"packed": "0x%x", `, comp.Bytes())+
fmt.Sprintf(`"packedSize": "%d", `, len(comp.Bytes()))+
fmt.Sprintf(`"value": %#v, `, comp.Value())+
fmt.Sprintf(`"rawValue": "0x%x", `, comp.RawValue())+
fmt.Sprintf(`"valueSize": "%d", `, len(comp.RawValue()))+
fmt.Sprintf(`"protocol": "%s", `, comp.Protocol().Name)+
fmt.Sprintf(`"codec": "%d", `, comp.Protocol().Code)+
fmt.Sprintf(`"uvarint": "0x%x", `, comp.Protocol().VCode)+
fmt.Sprintf(`"lengthPrefix": "%s"`, lengthPrefix)+
`}`)
return true
})
addrJson := `{
"string": "%[1]s",
"stringSize": "%[2]d",
"packed": "0x%[3]x",
"packedSize": "%[4]d",
"components": [
%[5]s
]
}`
fmt.Fprintf(os.Stdout, addrJson+"\n",
addr.String(), len(addr.String()), addr.Bytes(), len(addr.Bytes()), strings.Join(compsJson, ",\n "))
}