Skip to content
This repository has been archived by the owner on Feb 14, 2023. It is now read-only.

Commit

Permalink
test: 1.0.0 (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
t-bast authored Sep 3, 2018
1 parent 01fcb60 commit 7528070
Show file tree
Hide file tree
Showing 7 changed files with 376 additions and 4 deletions.
1 change: 1 addition & 0 deletions proto/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test_samples
1 change: 1 addition & 0 deletions proto/.travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ install:
- go get -u github.com/golang/protobuf/protoc-gen-go
script:
- protoc --go_out=. chainscript.proto
- ./test.sh
29 changes: 25 additions & 4 deletions proto/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,31 @@ pull the latest changes with `git subtree`.
Stratumn provides opinionated reference implementations that should suit most
projects:

| Language | Repository | Status |
| ---------- | ------------------------------------------ | ----------- |
| Golang | https://github.com/stratumn/go-chainscript | Development |
| Javascript | https://github.com/stratumn/js-chainscript | Development |
| Language | Repository | Status |
| ---------- | ------------------------------------------ | ------ |
| Golang | https://github.com/stratumn/go-chainscript | 1.0.0 |
| Javascript | https://github.com/stratumn/js-chainscript | 1.0.0 |

## Testing

For implementations to be compatible, we use a common set of test cases that
every implementation needs to pass.

### Regression samples

In the `samples` folder we provide serialized segments. ChainScript
implementations should unit test that they're able to correctly deserialize and
validate these segments.

See the [test samples](samples/README.md) for more details.

### Nightly tests

The `./test.sh` script is run nightly and verifies that known implementations
remain compatible with each other.

Every implementation needs to provide a docker image that allows generating and
validating test segments.

## Design Choices

Expand Down
18 changes: 18 additions & 0 deletions proto/samples/1.0.0.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[
{
"id": "simple-segment",
"data": "CqkBCgUxLjAuMFIaeyJhZ2UiOjQyLCJuYW1lIjoiYmF0bWFuIn1agwEKImdpdGh1Yi5jb20vc3RyYXR1bW4vZ28tY2hhaW5zY3JpcHRSAioqWQAAAAAAAEVAogEXCgx0ZXN0X3Byb2Nlc3NSB3N0YXJ0ZWSqAQh0ZXN0X21hcPIBBGluaXT6AQVzZXR1cIICBHRhZzGCAgR0YWcyogYNImJydWNlIHdheW5lIhIiCiD+guJRvG+H8s6FgL7rUYz+Ad9ZCOdEJewvy0qRNPqxUw=="
},
{
"id": "segment-references",
"data": "ClsKBTEuMC4wWlIKImdpdGh1Yi5jb20vc3RyYXR1bW4vZ28tY2hhaW5zY3JpcHRiBwoBKlICcDFiBwoBGFICcDKiAQ4KDHRlc3RfcHJvY2Vzc6oBCHRlc3RfbWFwEiIKIITTHLe5RoRjtHSsJHMI2XlfvqpHVHM5x+u9ZBj4jNvC"
},
{
"id": "segment-evidences",
"data": "CkkKBTEuMC4wWkAKImdpdGh1Yi5jb20vc3RyYXR1bW4vZ28tY2hhaW5zY3JpcHSiAQ4KDHRlc3RfcHJvY2Vzc6oBCHRlc3RfbWFwEmEKIEqdVtTkX9fClNM7V+uNbDe26edEp1h/wt2uM2hehHXbUh0KBTAuMS4wUgdiaXRjb2luWgd0ZXN0bmV0ogEBKlIeCgUxLjAuM1IIZXRoZXJldW1aB21haW5uZXSiAQEY"
},
{
"id": "segment-signatures",
"data": "CvoJCgUxLjAuMFpACiJnaXRodWIuY29tL3N0cmF0dW1uL2dvLWNoYWluc2NyaXB0ogEOCgx0ZXN0X3Byb2Nlc3OqAQh0ZXN0X21hcKIBrQIKBTEuMC4wUhNbdmVyc2lvbixkYXRhLG1ldGFdogGBAS0tLS0tQkVHSU4gRUQyNTUxOSBQVUJMSUMgS0VZLS0tLS0KTUNvd0JRWURLMlZ3QXlFQTNJN1RyeXVOWkRCUW5EZGdkS2tXamZaR2crOGtEQmcvT3Q3LzFoeXBCNlk9Ci0tLS0tRU5EIEVEMjU1MTkgUFVCTElDIEtFWS0tLS0tCqoBiAEtLS0tLUJFR0lOIE1FU1NBR0UtLS0tLQpiVy85QThSL1FINEY0ZklrSERRS3Zib0NFKzdTbTFNL0RYM3o1WlAyN0I4MGlZY2R4MjFZNVhaSnNSRlltcGl0Cms3aFZCdU5OWmVDSnFTcEpZUnhFRHc9PQotLS0tLUVORCBNRVNTQUdFLS0tLS0KogH8BgoFMS4wLjBSFFt2ZXJzaW9uLG1ldGEubWFwSWRdogHLAy0tLS0tQkVHSU4gUlNBIFBVQkxJQyBLRVktLS0tLQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXVFc3VjdmNOUWFrc2IxODNYeU9HCnVFVjRhL0JjeGsrWVlCUVNkc24rU2hMYzI5Z0g2OXloa0lvMW9IeCs0YXVNK0RQVVNMeWsyK3MrNU5HWDliNXEKSjV6UHpIUWFadHFKNWcxazUxMThhY1BVdXhqY0tSSlJRTTNOZjNCakhsVUY4YjVCMjlXcXNCN3BvSHl5ZEVTcgpJVjhSNEZWNEhNMXgwNlpxRzZkczc2N3RBaTZiSmpxbm81aEoxV3RzeVl3UEYyN0pJOWUwMllKeDdsMzJJSHJMCmZnbWlWT2VjRzg1MGF1U0VZWUdwbm5KN01CbWdaYW5yM0RQNXB1M1RkdFhpU1N2OTFOSjdxSVRZcEt2VmNiWlgKZnQ0NkF0cnJvVEZJNWxKUDBJc0oyQTdGU0hYNnRoQ0ZGK3dyb3ZXWGJiUnV5bjE5M2M1YmI1SzJQemZ3anZ1ZApOd0lEQVFBQgotLS0tLUVORCBSU0EgUFVCTElDIEtFWS0tLS0tCqoBjAMtLS0tLUJFR0lOIE1FU1NBR0UtLS0tLQpCdEcycmRUMWlRaEJ1Y1BBMDIzNWtiRWdlMml6cTJHdTg4Q1Y2MjZ0a0JEY3pmYlc2dmRrOG55V2Y3TzVpVUVDCjQyMjlXb3ZyNTR1a1ZHcUpxaWJ0cmh4U21wTE9hUFNPeEN1aUkvUG1FNHZVclV6cmlaNEhmbXFnRVpWMGxpbU8KVHVxN0MzakxGaXYxZ1Nrc1lIclVSbTdaNFo4dVF4RkxaRlkvMUZVVEx3angzN3UrK3ZUTGJXSkpISTgxM3Ywcwo4RVd4NldxdFh6RFdVQld6a0VaR2N0MERvRW9pcWJyZFFRVmZSWWdMQmc0eTF6Y1FRL09uNnRFRWhSQmtMTmJECkE5UkJVRUlJSUVFa3JtNStaQnh0czBva1RlQTBlSTdIWGtxSXp4TkUrM3dlV2hHZkNPdXJ4dGM5U2FsTnBDK1IKaFZhOGxNVUU3RkVOM01BRkh1WXBYdz09Ci0tLS0tRU5EIE1FU1NBR0UtLS0tLQoSIgognOmf9nPlNqqBKtACeX0XAdMmKMWBxLRijUT53EHii9I="
}
]
121 changes: 121 additions & 0 deletions proto/samples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# Test Samples

We provide a description of the contents of each serialized segment sample.
ChainScript implementation should test that they're able to deserialize these
segments properly and validate their content.

## 1.0.0

**simple-segment**: a segment containing data and metadata but no references,
evidences or signatures.

Note: we replaced `link.data` and `link.meta.data` with the objects that they
represent in the following JSON snippet.
The real ChainScript contains only serialized bytes in those fields, but it
should be tested that the values can be correctly extracted.

```json
{
"link": {
"version": "1.0.0",
"data": {
"name": "batman",
"age": 42
},
"meta": {
"clientId": "github.com/stratumn/go-chainscript",
"prevLinkHash": "Kio=",
"priority": 42,
"process": { "name": "test_process", "state": "started" },
"mapId": "test_map",
"action": "init",
"step": "setup",
"tags": ["tag1", "tag2"],
"data": "bruce wayne"
}
},
"meta": { "linkHash": "/oLiUbxvh/LOhYC+61GM/gHfWQjnRCXsL8tKkTT6sVM=" }
}
```

**segment-references**: a segment with two references to other segments.

```json
{
"link": {
"version": "1.0.0",
"meta": {
"clientId": "github.com/stratumn/go-chainscript",
"refs": [
{ "linkHash": "Kg==", "process": "p1" },
{ "linkHash": "GA==", "process": "p2" }
],
"process": { "name": "test_process" },
"mapId": "test_map"
}
},
"meta": { "linkHash": "hNMct7lGhGO0dKwkcwjZeV++qkdUcznH671kGPiM28I=" }
}
```

**segment-evidences**: a segment with two external evidences.

```json
{
"link": {
"version": "1.0.0",
"meta": {
"clientId": "github.com/stratumn/go-chainscript",
"process": { "name": "test_process" },
"mapId": "test_map"
}
},
"meta": {
"linkHash": "Sp1W1ORf18KU0ztX641sN7bp50SnWH/C3a4zaF6Edds=",
"evidences": [
{
"version": "0.1.0",
"backend": "bitcoin",
"provider": "testnet",
"proof": "Kg=="
},
{
"version": "1.0.3",
"backend": "ethereum",
"provider": "mainnet",
"proof": "GA=="
}
]
}
}
```

**segment-signatures**: a segment with two link signatures (RSA and Ed25519).

```json
{
"link": {
"version": "1.0.0",
"meta": {
"clientId": "github.com/stratumn/go-chainscript",
"process": { "name": "test_process" },
"mapId": "test_map"
},
"signatures": [
{
"version": "1.0.0",
"payloadPath": "[version,data,meta]",
"publicKey": "LS0tLS1CRUdJTiBFRDI1NTE5IFBVQkxJQyBLRVktLS0tLQpNQ293QlFZREsyVndBeUVBRk5hL3BYL0ErTFVac3ZxbzFyRDBSSnVTVnZ5TWNsZ1lzZDNZUndrSWc0UT0KLS0tLS1FTkQgRUQyNTUxOSBQVUJMSUMgS0VZLS0tLS0K",
"signature": "LS0tLS1CRUdJTiBNRVNTQUdFLS0tLS0KSDRtSnNmZkRRVS9ubDAxcjFDQi9tQzhvVW4rZVkvQzd1VVl4OEVEU1BYOCtHRWFES2JsSFMxbjlPOTV0N3VQaQpoSE1ES2pOUkFVekpQNGZzOGszQ0FnPT0KLS0tLS1FTkQgTUVTU0FHRS0tLS0tCg=="
},
{
"version": "1.0.0",
"payloadPath": "[version,meta.mapId]",
"publicKey": "LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBem0yWGdyUzRuSGdTM29BczhKRE4KU0grL0hGOW9Ha1R4ZWszRWpiVHZ6d3F2TzNuc0N5SEZDSm5XWjIwcnFUemtXTGpuaFdDRStGUzUzd1NsS24wWAp2TzFtbmVzaDFwNHVXYmlWQktIUzhmOGl6Z2dBY2ZEbHY1TjNEeUx5dFBxQ0pwMmZ2WnUwL09POHVOdmdwOE5VCjBLOTR4dklUR1N4MnNGZGN6clJCZFNLVzJxY0RmbmdSMjFmVVV6dE02ZzRjWVB6MjBSekhwRWNHd282MnJRcVYKNjlBemxhYnNpWlZrTzNnNlZVL0FPbXFMMXFXWDU2aGZ1ZzFkNnpaaXBuSjNUclZZQlBBY3VTSjVmUHdtb1lrNgpycFVpckgvRWdTZVBUQkpEZXVBWWRaM2xPUS9ZTDRicTR4SjdOMVVSU0o0Nk1meElKYlhyZzVBc2VNY1Z3ekIrClF3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K",
"signature": "LS0tLS1CRUdJTiBNRVNTQUdFLS0tLS0KeDBTM2JDbHh2TlQyV0doanEreDUvUDFrRGlUaGhWVjZJMkczYVVMMDlQbFlNODhSeGprM1V2ZENLY3ZmNFpweApJTmdNeHlRdmNUcWdZOUxOdmRIR3NpdmtDNHdlbVpsb1l2bUNsTmZhWThGSUxmcXNyTG1yOC9TL2g1THhZTUcwCkhWbnpUZFppRlU0RDVzYnRqa3VIUVpOMDRLMkpLeDQ3a2hhWkp6V3BqVnlwMytFQmljZXhLYW9MT2k0bGdGMlgKbS9PR3ZkNVRoR1FwcW4yTmQ3cFU1dTErSUpScGR4VWVnRVd6VEJqa2NUY2xERktDZXpTTVFFMmFQVk9jV1lCago0eUFaU0srQXZmOHJyM1Z0WUxvVDFGekJ4ZFNIOWpWTkw1MXZ0eFNwSXpLaTBGNldFVEJPMlB3TFhwT0k1VzFyCmJ0aEJmcHdETlJzVUpFRGdTNEcyU1E9PQotLS0tLUVORCBNRVNTQUdFLS0tLS0K"
}
]
},
"meta": { "linkHash": "d5ufjKXj2mpbtiMIEZzNGv5JEnJneuIUYvR25ai0sio=" }
}
```
59 changes: 59 additions & 0 deletions proto/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env bash

mkdir -p test_samples

# Make sure images are up-to-date:
docker pull stratumn/go-chainscript:latest
docker pull stratumn/js-chainscript:latest

# Mount a directory for reading/writing samples.
MOUNT=type=bind,source="$(pwd)"/test_samples,target=/samples

# Go container details.
GO_CONTAINER=stratumn/go-chainscript:latest
GO_CONTAINER_SAMPLE_FILE=/samples/go-samples.json

# Javascript container details.
JS_CONTAINER=stratumn/js-chainscript:latest
JS_CONTAINER_SAMPLE_FILE=/samples/js-samples.json

# Sample files (outside of the Docker context):
GO_SAMPLE_FILE=./test_samples/go-samples.json
JS_SAMPLE_FILE=./test_samples/js-samples.json

# Generate test samples from all repositories:
docker run --mount $MOUNT $GO_CONTAINER generate $GO_CONTAINER_SAMPLE_FILE
if [ ! $? -eq 0 ]; then
exit 1
fi

docker run --mount $MOUNT $JS_CONTAINER generate $JS_CONTAINER_SAMPLE_FILE
if [ ! $? -eq 0 ]; then
exit 1
fi

# Verify files:
if [ ! -e $GO_SAMPLE_FILE ]; then
echo "go-samples.json is missing"
exit 1
fi

if [ ! -e $JS_SAMPLE_FILE ]; then
echo "js-samples.json is missing"
exit 1
fi

# Validate test samples:
echo "---------- Javascript ----------"
docker run --mount $MOUNT $JS_CONTAINER validate $GO_CONTAINER_SAMPLE_FILE
if [ ! $? -eq 0 ]; then
exit 1
fi
echo "--------------------"

echo "---------- Golang ----------"
docker run --mount $MOUNT $GO_CONTAINER validate $JS_CONTAINER_SAMPLE_FILE
if [ ! $? -eq 0 ]; then
exit 1
fi
echo "--------------------"
151 changes: 151 additions & 0 deletions regression_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
// Copyright 2017-2018 Stratumn SAS. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Regression tests defined in https://github.com/stratumn/chainscript/tree/master/samples.

package chainscript_test

import (
"context"
"encoding/base64"
"encoding/json"
"io/ioutil"
"testing"

"github.com/golang/protobuf/proto"
"github.com/stratumn/go-chainscript"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestRegression(t *testing.T) {
t.Run("v1.0.0", func(t *testing.T) {
type TestData struct {
ID string `json:"id"`
Data string `json:"data"`
}

b, err := ioutil.ReadFile("./proto/samples/1.0.0.json")
require.NoError(t, err)

var testData []TestData
err = json.Unmarshal(b, &testData)
require.NoError(t, err)

testSegments := make(map[string]*chainscript.Segment)
for _, td := range testData {
data, err := base64.StdEncoding.DecodeString(td.Data)
require.NoError(t, err)

var segment chainscript.Segment
err = proto.Unmarshal(data, &segment)
require.NoError(t, err)

err = segment.Validate(context.Background(), nil)
require.NoError(t, err)

testSegments[td.ID] = &segment
}

t.Run("simple-segment", func(t *testing.T) {
s, ok := testSegments["simple-segment"]
require.True(t, ok)

assert.Equal(t, "1.0.0", s.Link.Version)
assert.Equal(t, "github.com/stratumn/go-chainscript", s.Link.Meta.ClientId)
assert.Equal(t, []byte{42, 42}, s.Link.Meta.PrevLinkHash)
assert.Equal(t, 42.0, s.Link.Meta.Priority)
assert.Equal(t, "test_process", s.Link.Meta.Process.Name)
assert.Equal(t, "started", s.Link.Meta.Process.State)
assert.Equal(t, "test_map", s.Link.Meta.MapId)
assert.Equal(t, "init", s.Link.Meta.Action)
assert.Equal(t, "setup", s.Link.Meta.Step)
assert.ElementsMatch(t, []string{"tag1", "tag2"}, s.Link.Meta.Tags)

type CustomData struct {
Name string `json:"name"`
Age int `json:"age"`
}

linkData := CustomData{}
err = s.Link.StructurizeData(&linkData)
require.NoError(t, err)
assert.Equal(t, "batman", linkData.Name)
assert.Equal(t, 42, linkData.Age)

linkMetadata := ""
err = s.Link.StructurizeMetadata(&linkMetadata)
require.NoError(t, err)
assert.Equal(t, "bruce wayne", linkMetadata)
})

t.Run("segment-references", func(t *testing.T) {
s, ok := testSegments["segment-references"]
require.True(t, ok)

assert.Equal(t, "1.0.0", s.Link.Version)
assert.Equal(t, "test_process", s.Link.Meta.Process.Name)
assert.Equal(t, "test_map", s.Link.Meta.MapId)

refs := s.Link.Meta.Refs
require.Len(t, refs, 2)

assert.Equal(t, "p1", refs[0].Process)
assert.Equal(t, []byte{42}, refs[0].LinkHash)

assert.Equal(t, "p2", refs[1].Process)
assert.Equal(t, []byte{24}, refs[1].LinkHash)
})

t.Run("segment-evidences", func(t *testing.T) {
s, ok := testSegments["segment-evidences"]
require.True(t, ok)

assert.Equal(t, "1.0.0", s.Link.Version)
assert.Equal(t, "test_process", s.Link.Meta.Process.Name)
assert.Equal(t, "test_map", s.Link.Meta.MapId)

require.Len(t, s.Meta.Evidences, 2)

btc := s.GetEvidence("bitcoin", "testnet")
require.NotNil(t, btc)
assert.Equal(t, "0.1.0", btc.Version)
assert.Equal(t, []byte{42}, btc.Proof)

eth := s.GetEvidence("ethereum", "mainnet")
require.NotNil(t, eth)
assert.Equal(t, "1.0.3", eth.Version)
assert.Equal(t, []byte{24}, eth.Proof)
})

t.Run("segment-signatures", func(t *testing.T) {
s, ok := testSegments["segment-signatures"]
require.True(t, ok)

assert.Equal(t, "1.0.0", s.Link.Version)
assert.Equal(t, "test_process", s.Link.Meta.Process.Name)
assert.Equal(t, "test_map", s.Link.Meta.MapId)

require.Len(t, s.Link.Signatures, 2)
assert.NoError(t, s.Link.Signatures[0].Validate(s.Link))
assert.NoError(t, s.Link.Signatures[1].Validate(s.Link))

assert.Equal(t, "1.0.0", s.Link.Signatures[0].Version)
assert.Equal(t, "[version,data,meta]", s.Link.Signatures[0].PayloadPath)

assert.Equal(t, "1.0.0", s.Link.Signatures[1].Version)
assert.Equal(t, "[version,meta.mapId]", s.Link.Signatures[1].PayloadPath)
})
})
}

0 comments on commit 7528070

Please sign in to comment.