Skip to content

Commit

Permalink
Add systest for poet registrations with PoW and cert
Browse files Browse the repository at this point in the history
  • Loading branch information
poszu committed Nov 10, 2023
1 parent a2893dc commit ffd77d0
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 5 deletions.
13 changes: 11 additions & 2 deletions systest/cluster/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ func MakePoetEndpoint(ith int) string {
return fmt.Sprintf("http://%s:%d", createPoetIdentifier(ith), poetPort)
}

func MakePoetMetricsEndpoint(testNamespace string, ith int) string {
return fmt.Sprintf("http://%s.%s:%d/metrics", createPoetIdentifier(ith), testNamespace, prometheusScrapePort)
}

func BootstrapperEndpoint(ith int) string {
return fmt.Sprintf("http://%s:%d", createBootstrapperIdentifier(ith), bootstrapperPort)
}
Expand Down Expand Up @@ -444,11 +448,11 @@ func (c *Cluster) AddCertifier(cctx *testcontext.Context, privkey string) error

// AddPoet spawns a single poet with the first available id.
// Id is of form "poet-N", where N ∈ [0, ∞).
func (c *Cluster) AddPoet(cctx *testcontext.Context) error {
func (c *Cluster) AddPoet(cctx *testcontext.Context, flags ...DeploymentFlag) error {
if err := c.persist(cctx); err != nil {
return err
}
flags := maps.Values(c.poetFlags)
flags = append(maps.Values(c.poetFlags), flags...)

id := createPoetIdentifier(c.firstFreePoetId())
cctx.Log.Debugw("deploying poet", "id", id)
Expand Down Expand Up @@ -626,6 +630,11 @@ func (c *Cluster) Bootnodes() int {
return c.bootnodes
}

// Smeshers returns number of the smeshers in the cluster.
func (c *Cluster) Smeshers() int {
return c.smeshers
}

// Total returns total number of clients.
func (c *Cluster) Total() int {
return len(c.clients)
Expand Down
9 changes: 9 additions & 0 deletions systest/cluster/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ func deployCertifierD(ctx *testcontext.Context, id, privkey string) (*NodeClient
func deployPoetD(ctx *testcontext.Context, id string, flags ...DeploymentFlag) (*NodeClient, error) {
args := []string{
"-c=" + configDir + attachedPoetConfig,
"--metrics-port=" + strconv.Itoa(prometheusScrapePort),
}
for _, flag := range flags {
args = append(args, flag.Flag())
Expand All @@ -292,6 +293,12 @@ func deployPoetD(ctx *testcontext.Context, id string, flags ...DeploymentFlag) (
WithReplicas(1).
WithTemplate(corev1.PodTemplateSpec().
WithLabels(labels).
WithAnnotations(
map[string]string{
"prometheus.io/port": strconv.Itoa(prometheusScrapePort),
"prometheus.io/scrape": "true",
},
).
WithSpec(corev1.PodSpec().
WithNodeSelector(ctx.NodeSelector).
WithVolumes(corev1.Volume().
Expand All @@ -304,6 +311,7 @@ func deployPoetD(ctx *testcontext.Context, id string, flags ...DeploymentFlag) (
WithArgs(args...).
WithPorts(
corev1.ContainerPort().WithName("rest").WithProtocol("TCP").WithContainerPort(poetPort),
corev1.ContainerPort().WithName("prometheus").WithContainerPort(prometheusScrapePort),
).
WithVolumeMounts(
corev1.VolumeMount().WithName("config").WithMountPath(configDir),
Expand Down Expand Up @@ -372,6 +380,7 @@ func deployPoetSvc(ctx *testcontext.Context, id string) (*apiv1.Service, error)
WithSelector(labels).
WithPorts(
corev1.ServicePort().WithName("rest").WithPort(poetPort).WithProtocol("TCP"),
corev1.ServicePort().WithName("prometheus").WithPort(prometheusScrapePort),
),
)

Expand Down
4 changes: 1 addition & 3 deletions systest/parameters/fastnet/poet.conf
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,4 @@ cycle-gap="30s"
jsonlog="true"
debuglog="true"

pow-difficulty=4

metrics-port=8081
pow-difficulty=4
65 changes: 65 additions & 0 deletions systest/tests/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package tests

import (
"context"
"errors"
"fmt"
"net/http"

"github.com/prometheus/common/expfmt"
)

var errMetricNotFound = errors.New("metric not found")

func fetchCounterMetric(
ctx context.Context,
url string,
metricName string,
labelFilters map[string]string,
) (float64, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return 0, fmt.Errorf("failed to create HTTP request: %v", err)
}

resp, err := http.DefaultClient.Do(req)
if err != nil {
return 0, fmt.Errorf("failed to fetch metrics: %v", err)
}
defer resp.Body.Close()

parser := expfmt.TextParser{}
metricFamilies, err := parser.TextToMetricFamilies(resp.Body)
if err != nil {
return 0, fmt.Errorf("failed to parse metric families: %v", err)
}

metricFamily, ok := metricFamilies[metricName]
if !ok {
return 0, fmt.Errorf("metric not found: %s", metricName)
}

for _, metric := range metricFamily.Metric {
if metric.Counter != nil {
// Check if the metric has the specified labels
labels := make(map[string]string)
for _, lp := range metric.Label {
labels[lp.GetName()] = lp.GetValue()
}

matches := true
for key, value := range labelFilters {
if labels[key] != value {
matches = false
break
}
}

if matches {
return metric.GetCounter().GetValue(), nil
}
}
}

return 0, errMetricNotFound
}
67 changes: 67 additions & 0 deletions systest/tests/poets_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package tests

import (
"crypto/ed25519"
"encoding/base64"
"encoding/hex"
"fmt"
"math"
Expand Down Expand Up @@ -203,3 +205,68 @@ func TestNodesUsingDifferentPoets(t *testing.T) {
)
}
}

// Test verifying that nodes can register in both poets
// - supporting PoW only
// - supporting certificates
// TODO: When PoW support is removed, convert this test to verify only the cert path.
func TestRegisteringInPoetWithPowAndCert(t *testing.T) {
tctx := testcontext.New(t, testcontext.Labels("sanity"))
tctx.PoetSize = 2

cl := cluster.New(tctx, cluster.WithKeys(10))
require.NoError(t, cl.AddBootnodes(tctx, 2))
require.NoError(t, cl.AddBootstrappers(tctx))

pubkey, privkey, err := ed25519.GenerateKey(nil)
require.NoError(t, err)
require.NoError(t, cl.AddCertifier(tctx, base64.StdEncoding.EncodeToString(privkey.Seed())))
// First poet supports PoW only (legacy)
require.NoError(t, cl.AddPoet(tctx))
// Second poet supports certs
require.NoError(
t,
cl.AddPoet(
tctx,
cluster.PoetCertifierURL("http://certifier-0"),
cluster.PoetCertifierPubkey(base64.StdEncoding.EncodeToString(pubkey)),
),
)
require.NoError(t, cl.AddSmeshers(tctx, tctx.ClusterSize-2))
require.NoError(t, cl.WaitAll(tctx))

epoch := 2
layersPerEpoch := testcontext.LayersPerEpoch.Get(tctx.Parameters)
last := uint32(layersPerEpoch * epoch)
tctx.Log.Debugw("waiting for epoch", "epoch", epoch, "layer", last)

eg, ctx := errgroup.WithContext(tctx)
for i := 0; i < cl.Total(); i++ {
client := cl.Client(i)
tctx.Log.Debugw("watching", "client", client.Name)
watchProposals(ctx, eg, client, func(proposal *pb.Proposal) (bool, error) {
return proposal.Layer.Number < last, nil
})
}

require.NoError(t, eg.Wait())

// Check that smeshers are registered in both poets
valid := map[string]string{"result": "valid"}
invalid := map[string]string{"result": "invalid"}

metricsEndpoint := cluster.MakePoetMetricsEndpoint(tctx.Namespace, 0)
powRegs, err := fetchCounterMetric(tctx, metricsEndpoint, "poet_registration_with_pow_total", valid)
require.NoError(t, err)
require.GreaterOrEqual(t, float64(cl.Smeshers()*epoch), powRegs)
powRegsInvalid, err := fetchCounterMetric(tctx, metricsEndpoint, "poet_registration_with_pow_total", invalid)
require.ErrorIs(t, err, errMetricNotFound, "metric for invalid PoW registrations value: %v", powRegsInvalid)

metricsEndpoint = cluster.MakePoetMetricsEndpoint(tctx.Namespace, 1)
certRegs, err := fetchCounterMetric(tctx, metricsEndpoint, "poet_registration_with_cert_total", valid)
require.NoError(t, err)
require.GreaterOrEqual(t, float64(cl.Smeshers()*epoch), certRegs)

certRegsInvalid, err := fetchCounterMetric(tctx, metricsEndpoint, "poet_registration_with_cert_total", invalid)
require.ErrorIs(t, err, errMetricNotFound, "metric for invalid cert registrations value: %v", certRegsInvalid)
}

0 comments on commit ffd77d0

Please sign in to comment.