Implement policy system with comprehensive testing and configuration
Some checks failed
Go / build (push) Has been cancelled
Some checks failed
Go / build (push) Has been cancelled
- Introduced a new policy system for event processing, allowing fine-grained control over event storage and retrieval based on various criteria. - Added support for policy configuration via JSON files, including whitelists, blacklists, and custom scripts. - Implemented a test suite for the policy system, ensuring 100% test coverage of core functionality and edge cases. - Created benchmark tests to evaluate policy performance under various conditions. - Updated event handling to integrate policy checks for both read and write access. - Enhanced documentation with examples and usage instructions for the policy system. - Bumped version to v0.16.0.
This commit is contained in:
305
pkg/policy/benchmark_test.go
Normal file
305
pkg/policy/benchmark_test.go
Normal file
@@ -0,0 +1,305 @@
|
||||
package policy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"next.orly.dev/pkg/encoders/event"
|
||||
"next.orly.dev/pkg/encoders/tag"
|
||||
)
|
||||
|
||||
// Helper function to create test event
|
||||
func createTestEventBench(id, pubkey, content string, kind uint16) *event.E {
|
||||
return &event.E{
|
||||
ID: []byte(id),
|
||||
Kind: kind,
|
||||
Pubkey: []byte(pubkey),
|
||||
Content: []byte(content),
|
||||
Tags: &tag.S{},
|
||||
CreatedAt: time.Now().Unix(),
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCheckKindsPolicy(b *testing.B) {
|
||||
policy := &P{
|
||||
Kind: Kinds{
|
||||
Whitelist: []int{1, 3, 5, 7, 9735},
|
||||
},
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
policy.checkKindsPolicy(1)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCheckRulePolicy(b *testing.B) {
|
||||
// Create test event
|
||||
testEvent := createTestEventBench("test-event-id", "test-pubkey", "test content", 1)
|
||||
|
||||
rule := Rule{
|
||||
Description: "test rule",
|
||||
WriteAllow: []string{"test-pubkey"},
|
||||
SizeLimit: int64Ptr(10000),
|
||||
ContentLimit: int64Ptr(1000),
|
||||
MustHaveTags: []string{"p"},
|
||||
}
|
||||
|
||||
policy := &P{}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
policy.checkRulePolicy("write", testEvent, rule, []byte("test-pubkey"))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCheckPolicy(b *testing.B) {
|
||||
// Create test event
|
||||
testEvent := createTestEventBench("test-event-id", "test-pubkey", "test content", 1)
|
||||
|
||||
policy := &P{
|
||||
Kind: Kinds{
|
||||
Whitelist: []int{1, 3, 5},
|
||||
},
|
||||
Rules: map[int]Rule{
|
||||
1: {
|
||||
Description: "test rule",
|
||||
WriteAllow: []string{"test-pubkey"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
policy.CheckPolicy("write", testEvent, []byte("test-pubkey"), "127.0.0.1")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCheckPolicyWithScript(b *testing.B) {
|
||||
// Create temporary directory
|
||||
tempDir := b.TempDir()
|
||||
scriptPath := filepath.Join(tempDir, "policy.sh")
|
||||
|
||||
// Create a simple test script
|
||||
scriptContent := `#!/bin/bash
|
||||
while IFS= read -r line; do
|
||||
echo '{"id":"test","action":"accept","msg":""}'
|
||||
done
|
||||
`
|
||||
err := os.WriteFile(scriptPath, []byte(scriptContent), 0755)
|
||||
if err != nil {
|
||||
b.Fatalf("Failed to create test script: %v", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
manager := &PolicyManager{
|
||||
ctx: ctx,
|
||||
configDir: tempDir,
|
||||
scriptPath: scriptPath,
|
||||
enabled: true,
|
||||
disabled: false,
|
||||
responseChan: make(chan PolicyResponse, 100),
|
||||
}
|
||||
|
||||
// Start the policy manager
|
||||
err = manager.StartPolicy()
|
||||
if err != nil {
|
||||
b.Fatalf("Failed to start policy: %v", err)
|
||||
}
|
||||
defer manager.StopPolicy()
|
||||
|
||||
// Give the script time to start
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
// Create test event
|
||||
testEvent := createTestEventBench("test-event-id", "test-pubkey", "test content", 1)
|
||||
|
||||
policy := &P{
|
||||
Manager: manager,
|
||||
Kind: Kinds{},
|
||||
Rules: map[int]Rule{
|
||||
1: {
|
||||
Description: "test rule with script",
|
||||
Script: "policy.sh",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
policy.CheckPolicy("write", testEvent, []byte("test-pubkey"), "127.0.0.1")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkLoadFromFile(b *testing.B) {
|
||||
// Create temporary directory
|
||||
tempDir := b.TempDir()
|
||||
configPath := filepath.Join(tempDir, "policy.json")
|
||||
|
||||
// Create test config
|
||||
configData := `{
|
||||
"kind": {
|
||||
"whitelist": [1, 3, 5, 7, 9735],
|
||||
"blacklist": []
|
||||
},
|
||||
"rules": {
|
||||
"1": {
|
||||
"description": "text notes",
|
||||
"write_allow": [],
|
||||
"size_limit": 32000
|
||||
},
|
||||
"3": {
|
||||
"description": "contacts",
|
||||
"write_allow": ["npub1example1"],
|
||||
"script": "policy.sh"
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
err := os.WriteFile(configPath, []byte(configData), 0644)
|
||||
if err != nil {
|
||||
b.Fatalf("Failed to create test config: %v", err)
|
||||
}
|
||||
|
||||
policy := &P{}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
err := policy.LoadFromFile(configPath)
|
||||
if err != nil {
|
||||
b.Fatalf("Failed to load config: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCheckPolicyMultipleKinds(b *testing.B) {
|
||||
// Create policy with many rules
|
||||
rules := make(map[int]Rule)
|
||||
for i := 1; i <= 100; i++ {
|
||||
rules[i] = Rule{
|
||||
Description: "test rule",
|
||||
WriteAllow: []string{"test-pubkey"},
|
||||
}
|
||||
}
|
||||
|
||||
policy := &P{
|
||||
Kind: Kinds{},
|
||||
Rules: rules,
|
||||
}
|
||||
|
||||
// Create test events with different kinds
|
||||
events := make([]*event.E, 100)
|
||||
for i := 0; i < 100; i++ {
|
||||
events[i] = createTestEvent("test-event-id", "test-pubkey", "test content", uint16(i+1))
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
event := events[i%100]
|
||||
policy.CheckPolicy("write", event, []byte("test-pubkey"), "127.0.0.1")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCheckPolicyLargeWhitelist(b *testing.B) {
|
||||
// Create large whitelist
|
||||
whitelist := make([]int, 1000)
|
||||
for i := 0; i < 1000; i++ {
|
||||
whitelist[i] = i + 1
|
||||
}
|
||||
|
||||
policy := &P{
|
||||
Kind: Kinds{
|
||||
Whitelist: whitelist,
|
||||
},
|
||||
Rules: map[int]Rule{},
|
||||
}
|
||||
|
||||
testEvent := createTestEvent("test-event-id", "test-pubkey", "test content", 500) // Kind in the middle of the whitelist
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
policy.CheckPolicy("write", testEvent, []byte("test-pubkey"), "127.0.0.1")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCheckPolicyLargeBlacklist(b *testing.B) {
|
||||
// Create large blacklist
|
||||
blacklist := make([]int, 1000)
|
||||
for i := 0; i < 1000; i++ {
|
||||
blacklist[i] = i + 1
|
||||
}
|
||||
|
||||
policy := &P{
|
||||
Kind: Kinds{
|
||||
Blacklist: blacklist,
|
||||
},
|
||||
Rules: map[int]Rule{},
|
||||
}
|
||||
|
||||
testEvent := createTestEvent("test-event-id", "test-pubkey", "test content", 1500) // Kind not in blacklist
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
policy.CheckPolicy("write", testEvent, []byte("test-pubkey"), "127.0.0.1")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCheckPolicyComplexRule(b *testing.B) {
|
||||
// Create test event with many tags
|
||||
testEvent := createTestEventBench("test-event-id", "test-pubkey", "test content", 1)
|
||||
|
||||
// Add many tags
|
||||
for i := 0; i < 100; i++ {
|
||||
tagItem1 := tag.New()
|
||||
tagItem1.T = append(tagItem1.T, []byte("p"), []byte("test-pubkey"))
|
||||
*testEvent.Tags = append(*testEvent.Tags, tagItem1)
|
||||
|
||||
tagItem2 := tag.New()
|
||||
tagItem2.T = append(tagItem2.T, []byte("e"), []byte("test-event"))
|
||||
*testEvent.Tags = append(*testEvent.Tags, tagItem2)
|
||||
}
|
||||
|
||||
rule := Rule{
|
||||
Description: "complex rule",
|
||||
WriteAllow: []string{"test-pubkey"},
|
||||
SizeLimit: int64Ptr(100000),
|
||||
ContentLimit: int64Ptr(10000),
|
||||
MustHaveTags: []string{"p", "e"},
|
||||
Privileged: true,
|
||||
}
|
||||
|
||||
policy := &P{}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
policy.checkRulePolicy("write", testEvent, rule, []byte("test-pubkey"))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCheckPolicyLargeEvent(b *testing.B) {
|
||||
// Create large content
|
||||
largeContent := strings.Repeat("a", 100000) // 100KB content
|
||||
|
||||
policy := &P{
|
||||
Kind: Kinds{},
|
||||
Rules: map[int]Rule{
|
||||
1: {
|
||||
Description: "size limit test",
|
||||
SizeLimit: int64Ptr(200000), // 200KB limit
|
||||
ContentLimit: int64Ptr(200000), // 200KB content limit
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Create test event with large content
|
||||
testEvent := createTestEvent("test-event-id", "test-pubkey", largeContent, 1)
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
policy.CheckPolicy("write", testEvent, []byte("test-pubkey"), "127.0.0.1")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user