Skip to content
Snippets Groups Projects
Unverified Commit 835e2ef7 authored by jonastheis's avatar jonastheis
Browse files

Added framework that abstracts the docker network and provides convenience functionality

parent ef2eeee3
Branches
No related tags found
No related merge requests found
......@@ -23,4 +23,4 @@ RUN go mod verify
COPY . .
ENTRYPOINT ["go", "test"]
ENTRYPOINT ["go", "test", "./tests"]
package framework
import (
"fmt"
"net/http"
"time"
)
type Framework struct {
peers []*Peer
httpClient *http.Client
}
func New() *Framework {
fmt.Printf("Finding available peers...\n")
f := &Framework{
peers: getAvailablePeers(),
httpClient: &http.Client{Timeout: 10 * time.Second},
}
if len(f.peers) == 0 {
panic("Could not find any peers in Docker network.")
}
fmt.Printf("Finding available peers... done. Peers: %v\n", f.peers)
fmt.Printf("Waiting for autopeering...\n")
f.waitForAutopeering()
fmt.Printf("Waiting for autopeering... done\n")
return f
}
func (f *Framework) waitForAutopeering() {
maxTries := autopeeringMaxTries
for maxTries > 0 {
for _, p := range f.peers {
resp := new(GetNeighborResponse)
if err := f.HttpGet(p, apiGetNeighbors, resp); err != nil {
fmt.Printf("request error: %v\n", err)
} else {
p.SetNeighbors(resp.Chosen, resp.Accepted)
}
}
// verify neighbor requirement
min := 100
total := 0
for _, p := range f.peers {
neighbors := p.TotalNeighbors()
if neighbors < min {
min = neighbors
}
total += neighbors
}
if min >= autopeeringMinimumNeighbors {
fmt.Printf("Neighbors: min=%d avg=%.2f\n", min, float64(total)/float64(len(f.peers)))
return
}
fmt.Println("Not done yet. Try again in 5 seconds...")
time.Sleep(5 * time.Second)
maxTries--
}
panic("Peering not successful.")
}
func (f *Framework) HttpGet(peer *Peer, endpoint string, target interface{}) error {
url := fmt.Sprintf("%s%s", peer.api, endpoint)
return getJson(f.httpClient, url, target)
}
func (f *Framework) Peers() []*Peer {
return f.peers
}
package framework
const (
hostnamePeerMaster = "peer_master"
hostnamePeerReplicaPrefix = "integration-tests_peer_replica_"
autopeeringMaxTries = 50
autopeeringMinimumNeighbors = 2
apiPort = "8080"
apiGetNeighbors = "getNeighbors"
)
package framework
import (
"fmt"
"net"
)
type Peer struct {
name string
ip net.IP
api string
chosen []Neighbor
accepted []Neighbor
}
func NewPeer(name string, ip net.IP) *Peer {
return &Peer{
name: name,
ip: ip,
api: getWebApi(ip),
}
}
func (p *Peer) String() string {
return fmt.Sprintf("Peer:{%s, %s, %s, %d}", p.name, p.ip.String(), p.api, p.TotalNeighbors())
}
func (p *Peer) TotalNeighbors() int {
return len(p.chosen) + len(p.accepted)
}
func (p *Peer) SetNeighbors(chosen, accepted []Neighbor) {
p.chosen = make([]Neighbor, len(chosen))
copy(p.chosen, chosen)
p.accepted = make([]Neighbor, len(accepted))
copy(p.accepted, accepted)
}
func getAvailablePeers() (peers []*Peer) {
// get peer master
if addr, err := net.LookupIP(hostnamePeerMaster); err != nil {
fmt.Printf("Could not resolve %s\n", hostnamePeerMaster)
} else {
p := NewPeer(hostnamePeerMaster, addr[0])
peers = append(peers, p)
}
// get peer replicas
for i := 1; ; i++ {
peerName := fmt.Sprintf("%s%d", hostnamePeerReplicaPrefix, i)
if addr, err := net.LookupIP(peerName); err != nil {
//fmt.Printf("Could not resolve %s\n", peerName)
break
} else {
p := NewPeer(peerName, addr[0])
peers = append(peers, p)
}
}
return
}
func getWebApi(ip net.IP) string {
return fmt.Sprintf("http://%s:%s/", ip.String(), apiPort)
}
type GetNeighborResponse struct {
KnownPeers []Neighbor `json:"known,omitempty"`
Chosen []Neighbor `json:"chosen"`
Accepted []Neighbor `json:"accepted"`
Error string `json:"error,omitempty"`
}
type Neighbor struct {
ID string `json:"id"` // comparable node identifier
PublicKey string `json:"publicKey"` // public key used to verify signatures
Services []PeerService `json:"services,omitempty"`
}
type PeerService struct {
ID string `json:"id"` // ID of the service
Address string `json:"address"` // network address of the service
}
package framework
import (
"encoding/json"
"net/http"
)
func getJson(client *http.Client, url string, target interface{}) error {
r, err := client.Get(url)
if err != nil {
return err
}
defer r.Body.Close()
return json.NewDecoder(r.Body).Decode(target)
}
module github.com/iotaledger/goshimmer/tools/integration-tests/tests
module github.com/iotaledger/goshimmer/tools/integration-tests/tester
go 1.14
......
package tests
import (
"fmt"
"os"
"testing"
"github.com/iotaledger/goshimmer/tools/integration-tests/tester/framework"
"github.com/stretchr/testify/assert"
)
var f *framework.Framework
func TestMain(m *testing.M) {
f = framework.New()
// call the tests
os.Exit(m.Run())
}
func TestExample(t *testing.T) {
fmt.Println("This is an independent test.")
fmt.Printf("There are %d peers in the Docker network available.\n", len(f.Peers()))
assert.Equal(t, 6, len(f.Peers()))
}
package main
import (
"encoding/json"
"fmt"
"net"
"net/http"
"os"
"testing"
"time"
)
const (
peerMasterHostname = "peer_master"
peerReplicaHostnamePrefix = "integration-tests_peer_replica_"
getNeighborsAPI = "getNeighbors"
webApiPort = "8080"
minimumNeighbors = 2
)
var (
peersIp []net.IP
peersWebApi []string
)
func TestMain(m *testing.M) {
fmt.Printf("Finding available peers...\n")
peersIp = getAvailablePeers()
peersWebApi = getPeersWebAPI(peersIp)
fmt.Printf("Finding available peers... done. Peers: %v\n", peersIp)
fmt.Printf("Waiting for autopeering...\n")
waitForNeighbors(peersWebApi)
fmt.Printf("Waiting for autopeering... done\n")
// call the tests
os.Exit(m.Run())
}
func TestExample(t *testing.T) {
fmt.Println("This is a test")
}
func getAvailablePeers() (p []net.IP) {
// get peer master
if addr, err := net.LookupIP(peerMasterHostname); err != nil {
fmt.Printf("Could not resolve %s\n", peerMasterHostname)
} else {
p = append(p, addr[0])
}
// get peer replicas
for i := 1; ; i++ {
peerName := fmt.Sprintf("%s%d", peerReplicaHostnamePrefix, i)
if addr, err := net.LookupIP(peerName); err != nil {
//fmt.Printf("Could not resolve %s\n", peerName)
break
} else {
p = append(p, addr[0])
}
}
if len(p) == 0 {
panic("Could not find any peers in Docker network.")
}
return
}
func getPeersWebAPI(ips []net.IP) (apis []string) {
for _, ip := range ips {
url := fmt.Sprintf("http://%s:%s", ip.String(), webApiPort)
apis = append(apis, url)
}
return
}
func waitForNeighbors(peers []string) {
client := &http.Client{Timeout: 10 * time.Second}
neighbors := make(map[string]int)
maxTries := 50
for maxTries > 0 {
for _, base := range peers {
resp := new(Response)
url := fmt.Sprintf("%s/%s", base, getNeighborsAPI)
if err := getJson(client, url, resp); err != nil {
fmt.Printf("request error: %v\n", err)
neighbors[base] = 0
} else {
totalNeighbors := len(resp.Chosen) + len(resp.Accepted)
neighbors[base] = totalNeighbors
}
}
min := 100
total := 0
for _, num := range neighbors {
if num < min {
min = num
}
fmt.Printf("total=%d, len(neighbors)=%d\n", total, len(neighbors))
total += num
}
if min >= minimumNeighbors {
fmt.Printf("Neighbors: min=%d avg=%.2f\n", min, float64(total)/float64(len(neighbors)))
return
}
fmt.Println("Wait for 5 seconds...")
time.Sleep(5 * time.Second)
maxTries--
}
panic("Peering not successful.")
}
func getJson(client *http.Client, url string, target interface{}) error {
r, err := client.Get(url)
if err != nil {
return err
}
defer r.Body.Close()
return json.NewDecoder(r.Body).Decode(target)
}
type Response struct {
KnownPeers []Neighbor `json:"known,omitempty"`
Chosen []Neighbor `json:"chosen"`
Accepted []Neighbor `json:"accepted"`
Error string `json:"error,omitempty"`
}
type Neighbor struct {
ID string `json:"id"` // comparable node identifier
PublicKey string `json:"publicKey"` // public key used to verify signatures
Services []peerService `json:"services,omitempty"`
}
type peerService struct {
ID string `json:"id"` // ID of the service
Address string `json:"address"` // network address of the service
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment