Skip to content

Commit

Permalink
test changes
Browse files Browse the repository at this point in the history
  • Loading branch information
ettec committed Nov 13, 2024
1 parent cdf31a3 commit 24389a8
Show file tree
Hide file tree
Showing 8 changed files with 327 additions and 119 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ func (r *CapabilitiesRegistry) getAddress() common.Address {
type capability struct {
donCapabilityConfig *pb.CapabilityConfig
registryConfig kcr.CapabilitiesRegistryCapability
// internalOnly is true if the capability is published in the registry but not made available outside the DON in which it runs
internalOnly bool
}

// SetupDON sets up a new DON with the given capabilities and returns the DON ID
Expand Down
147 changes: 117 additions & 30 deletions core/capabilities/integration_tests/framework/don.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package framework

import (
"context"
"encoding/hex"
"fmt"
"strconv"
"testing"
Expand All @@ -13,6 +14,8 @@ import (

"github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types"

"github.com/smartcontractkit/chainlink-common/pkg/services"

"github.com/smartcontractkit/chainlink/v2/core/services/registrysyncer"

commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities"
Expand Down Expand Up @@ -40,20 +43,43 @@ import (

type DonContext struct {
EthBlockchain *EthBlockchain
p2pNetwork *MockRageP2PNetwork
p2pNetwork *FakeRageP2PNetwork
capabilityRegistry *CapabilitiesRegistry
}

func CreateDonContext(ctx context.Context, t *testing.T) DonContext {
ethBlockchain := NewEthBlockchain(t, 1000, 1*time.Second)
rageP2PNetwork := NewMockRageP2PNetwork(t, 1000)
rageP2PNetwork := NewFakeRageP2PNetwork(ctx, t, 1000)
capabilitiesRegistry := NewCapabilitiesRegistry(ctx, t, ethBlockchain)

servicetest.Run(t, rageP2PNetwork)
servicetest.Run(t, ethBlockchain)
return DonContext{EthBlockchain: ethBlockchain, p2pNetwork: rageP2PNetwork, capabilityRegistry: capabilitiesRegistry}
}

func (c DonContext) WaitForCapabilitiesToBeExposed(t *testing.T, dons ...*DON) {
allExpectedCapabilities := make(map[CapabilityRegistration]bool)
for _, don := range dons {
caps, err := don.GetExternalCapabilities()
require.NoError(t, err)
for k, v := range caps {
allExpectedCapabilities[k] = v
}
}

require.Eventually(t, func() bool {
registrations := c.p2pNetwork.GetCapabilityRegistrations()

for k := range allExpectedCapabilities {
if _, ok := registrations[k]; !ok {
return false
}
}

return true
}, 1*time.Minute, 1*time.Second, "timeout waiting for capabilities to be exposed")
}

type capabilityNode struct {
*cltest.TestApplication
registry *capabilities.Registry
Expand All @@ -64,12 +90,13 @@ type capabilityNode struct {
}

type DON struct {
services.StateMachine
t *testing.T
config DonConfiguration
lggr logger.Logger
nodes []*capabilityNode
standardCapabilityJobs []*job.Job
externalCapabilities []capability
publishedCapabilities []capability
capabilitiesRegistry *CapabilitiesRegistry

nodeConfigModifiers []func(c *chainlink.Config, node *capabilityNode)
Expand All @@ -84,10 +111,13 @@ func NewDON(ctx context.Context, t *testing.T, lggr logger.Logger, donConfig Don
dependentDONs []commoncap.DON, donContext DonContext, supportsOCR bool) *DON {
don := &DON{t: t, lggr: lggr.Named(donConfig.name), config: donConfig, capabilitiesRegistry: donContext.capabilityRegistry}

protocolRoundInterval := 1 * time.Second

var newOracleFactoryFn standardcapabilities.NewOracleFactoryFn
var libOcr *MockLibOCR
var libOcr *FakeLibOCR
if supportsOCR {
libOcr = NewMockLibOCR(t, lggr, donConfig.F, 1*time.Second)
// This is required to support the non standard OCR3 capability - will be removed when required OCR3 behaviour is implemented as standard capabilities
libOcr = NewFakeLibOCR(t, lggr, donConfig.F, protocolRoundInterval)
servicetest.Run(t, libOcr)
}

Expand All @@ -110,7 +140,8 @@ func NewDON(ctx context.Context, t *testing.T, lggr logger.Logger, donConfig Don
don.nodes = append(don.nodes, cn)

if supportsOCR {
factory := newMockLibOcrOracleFactory(libOcr, donConfig.KeyBundles[i], len(donConfig.Members), int(donConfig.F))
factory := newFakeOracleFactoryFactory(t, lggr, donConfig.KeyBundles[i], len(donConfig.Members), donConfig.F,
protocolRoundInterval)
newOracleFactoryFn = factory.NewOracleFactory
}

Expand All @@ -134,12 +165,10 @@ func NewDON(ctx context.Context, t *testing.T, lggr logger.Logger, donConfig Don

// Initialise must be called after all capabilities have been added to the DONs and before Start is called
func (d *DON) Initialise() {
if len(d.externalCapabilities) > 0 {
id := d.capabilitiesRegistry.setupDON(d.config, d.externalCapabilities)
id := d.capabilitiesRegistry.setupDON(d.config, d.publishedCapabilities)

//nolint:gosec // disable G115
d.config.DON.ID = uint32(id)
}
//nolint:gosec // disable G115
d.config.DON.ID = uint32(id)
}

func (d *DON) GetID() uint32 {
Expand All @@ -150,6 +179,29 @@ func (d *DON) GetID() uint32 {
return d.config.ID
}

func (d *DON) GetExternalCapabilities() (map[CapabilityRegistration]bool, error) {
result := map[CapabilityRegistration]bool{}
for _, publishedCapability := range d.publishedCapabilities {
if publishedCapability.internalOnly {
continue
}

for _, node := range d.nodes {
peerIDBytes, err := peerIDToBytes(node.peerID.PeerID)
if err != nil {
return nil, fmt.Errorf("failed to convert peer ID to bytes: %w", err)
}
result[CapabilityRegistration{
nodePeerID: hex.EncodeToString(peerIDBytes[:]),
capabilityID: publishedCapability.registryConfig.LabelledName + "@" + publishedCapability.registryConfig.Version,
capabilityDonID: d.GetID(),
}] = true
}
}

return result, nil
}

func (d *DON) GetConfigVersion() uint32 {
return d.config.ConfigVersion
}
Expand All @@ -162,20 +214,22 @@ func (d *DON) GetPeerIDs() []peer {
return d.config.peerIDs
}

func (d *DON) Start(ctx context.Context, t *testing.T) {
func (d *DON) Start(ctx context.Context) error {
for _, triggerFactory := range d.triggerFactories {
for _, node := range d.nodes {
trigger := triggerFactory.CreateNewTrigger(t)
err := node.registry.Add(ctx, trigger)
require.NoError(t, err)
trigger := triggerFactory.CreateNewTrigger(d.t)
if err := node.registry.Add(ctx, trigger); err != nil {
return fmt.Errorf("failed to add trigger: %w", err)
}
}
}

for _, targetFactory := range d.targetFactories {
for _, node := range d.nodes {
target := targetFactory.CreateNewTarget(t)
err := node.registry.Add(ctx, target)
require.NoError(t, err)
target := targetFactory.CreateNewTarget(d.t)
if err := node.registry.Add(ctx, target); err != nil {
return fmt.Errorf("failed to add target: %w", err)
}
}
}

Expand All @@ -184,26 +238,39 @@ func (d *DON) Start(ctx context.Context, t *testing.T) {
}

if d.addOCR3NonStandardCapability {
libocr := NewMockLibOCR(t, d.lggr, d.config.F, 1*time.Second)
servicetest.Run(t, libocr)
libocr := NewFakeLibOCR(d.t, d.lggr, d.config.F, 1*time.Second)
servicetest.Run(d.t, libocr)

for _, node := range d.nodes {
addOCR3Capability(ctx, t, d.lggr, node.registry, libocr, d.config.F, node.KeyBundle)
addOCR3Capability(ctx, d.t, d.lggr, node.registry, libocr, d.config.F, node.KeyBundle)
}
}

for _, capabilityJob := range d.standardCapabilityJobs {
err := d.AddJob(ctx, capabilityJob)
require.NoError(t, err)
if err := d.AddJob(ctx, capabilityJob); err != nil {
return fmt.Errorf("failed to add standard capability job: %w", err)
}
}

return nil
}

func (d *DON) Close() error {
for _, node := range d.nodes {
if err := node.Stop(); err != nil {
return fmt.Errorf("failed to stop node: %w", err)
}
}

return nil
}

const StandardCapabilityTemplateJobSpec = `
type = "standardcapabilities"
schemaVersion = 1
name = "%s"
command="%s"
config="%s"
config=%s
`

func (d *DON) AddStandardCapability(name string, command string, config string) {
Expand All @@ -214,11 +281,30 @@ func (d *DON) AddStandardCapability(name string, command string, config string)
d.standardCapabilityJobs = append(d.standardCapabilityJobs, &capabilitiesSpecJob)
}

func (d *DON) AddPublishedStandardCapability(name string, command string, config string,
defaultCapabilityRequestConfig *pb.CapabilityConfig,
registryConfig kcr.CapabilitiesRegistryCapability) {
spec := fmt.Sprintf(StandardCapabilityTemplateJobSpec, name, command, config)
capabilitiesSpecJob, err := standardcapabilities.ValidatedStandardCapabilitiesSpec(spec)
require.NoError(d.t, err)

d.standardCapabilityJobs = append(d.standardCapabilityJobs, &capabilitiesSpecJob)

d.publishedCapabilities = append(d.publishedCapabilities, capability{
donCapabilityConfig: defaultCapabilityRequestConfig,
registryConfig: registryConfig,
})
}

// TODO - add configuration for remote support - do this for each capability as an option
func (d *DON) AddTargetCapability(targetFactory TargetFactory) {
d.targetFactories = append(d.targetFactories, targetFactory)
}

func (d *DON) AddTriggerCapability(triggerFactory TriggerFactory) {
d.triggerFactories = append(d.triggerFactories, triggerFactory)
}

func (d *DON) AddExternalTriggerCapability(triggerFactory TriggerFactory) {
d.triggerFactories = append(d.triggerFactories, triggerFactory)

Expand All @@ -243,7 +329,7 @@ func (d *DON) AddExternalTriggerCapability(triggerFactory TriggerFactory) {
},
}

d.externalCapabilities = append(d.externalCapabilities, triggerCapability)
d.publishedCapabilities = append(d.publishedCapabilities, triggerCapability)
}

func (d *DON) AddJob(ctx context.Context, j *job.Job) error {
Expand Down Expand Up @@ -323,9 +409,10 @@ func (d *DON) AddOCR3NonStandardCapability() {
CapabilityType: uint8(registrysyncer.ContractCapabilityTypeConsensus),
}

d.externalCapabilities = append(d.externalCapabilities, capability{
d.publishedCapabilities = append(d.publishedCapabilities, capability{
donCapabilityConfig: newCapabilityConfig(),
registryConfig: ocr,
internalOnly: true,
})
}

Expand Down Expand Up @@ -357,7 +444,7 @@ func (d *DON) AddEthereumWriteTargetNonStandardCapability(forwarderAddr common.A
},
}

d.externalCapabilities = append(d.externalCapabilities, capability{
d.publishedCapabilities = append(d.publishedCapabilities, capability{
donCapabilityConfig: targetCapabilityConfig,
registryConfig: writeChain,
})
Expand All @@ -366,7 +453,7 @@ func (d *DON) AddEthereumWriteTargetNonStandardCapability(forwarderAddr common.A
}

func addOCR3Capability(ctx context.Context, t *testing.T, lggr logger.Logger, capabilityRegistry *capabilities.Registry,
libocr *MockLibOCR, donF uint8, ocr2KeyBundle ocr2key.KeyBundle) {
libocr *FakeLibOCR, donF uint8, ocr2KeyBundle ocr2key.KeyBundle) {
requestTimeout := 10 * time.Minute
cfg := ocr3.Config{
Logger: lggr,
Expand Down Expand Up @@ -394,6 +481,6 @@ func addOCR3Capability(ctx context.Context, t *testing.T, lggr logger.Logger, ca
libocr.AddNode(plugin, transmitter, ocr2KeyBundle)
}

func Context(tb testing.TB) context.Context {
return testutils.Context(tb)
func Context(tb testing.TB) (ctx context.Context, cancel func()) {
return context.WithCancel(testutils.Context(tb))
}
Loading

0 comments on commit 24389a8

Please sign in to comment.