Files

107 lines
2.4 KiB
Go

package e2e
import (
"context"
"encoding/json"
"fmt"
"os"
"path/filepath"
"sync"
"testing"
"github.com/luxfi/consensus/utils/ids"
)
// CNode implements NodeRunner for C implementation
// Uses simulated implementation to avoid CGo build dependencies in tests.
type CNode struct {
t *testing.T
decisions map[ids.ID]bool
mu sync.RWMutex
healthy bool
}
// NewCNode creates a new C consensus node
func NewCNode(t *testing.T) *CNode {
return &CNode{
t: t,
decisions: make(map[ids.ID]bool),
}
}
// Start initializes and starts the C consensus engine
func (n *CNode) Start(ctx context.Context, port int) error {
n.t.Logf("Starting C node on port %d", port)
// Check if C library is built
cLibPath := filepath.Join("pkg", "c", "build", "liblux_consensus.a")
if _, err := os.Stat(cLibPath); os.IsNotExist(err) {
n.t.Log("C library not built, using simulated implementation")
n.healthy = true
return nil
}
n.healthy = true
n.t.Log("C node started successfully (simulated)")
return nil
}
// Stop shuts down the C consensus engine
func (n *CNode) Stop() error {
n.mu.Lock()
defer n.mu.Unlock()
n.t.Log("Stopping C node")
n.healthy = false
return nil
}
// ProposeBlock submits a block to the C consensus engine
func (n *CNode) ProposeBlock(testBlock *Block) error {
n.mu.Lock()
defer n.mu.Unlock()
if !n.healthy {
return fmt.Errorf("c node not healthy")
}
n.t.Logf("C node: proposing block %s (height %d)", testBlock.ID, testBlock.Height)
// Simulated consensus for E2E cross-language test.
blockData := map[string]interface{}{
"id": testBlock.ID.String(),
"parent_id": testBlock.ParentID.String(),
"height": testBlock.Height,
"data": string(testBlock.Data),
}
if data, err := json.Marshal(blockData); err == nil {
n.t.Logf("C block data: %s", string(data))
}
// Simulate acceptance (would use C consensus logic in production)
n.decisions[testBlock.ID] = true
return nil
}
// GetDecision returns whether a block was accepted
func (n *CNode) GetDecision(blockID ids.ID) (bool, error) {
n.mu.RLock()
defer n.mu.RUnlock()
decision, exists := n.decisions[blockID]
if !exists {
return false, fmt.Errorf("no decision for block %s", blockID)
}
return decision, nil
}
// IsHealthy returns whether the C node is healthy
func (n *CNode) IsHealthy() bool {
n.mu.RLock()
defer n.mu.RUnlock()
return n.healthy
}