Add extensive tests and improve policy configuration handling
Some checks failed
Go / build-and-release (push) Has been cancelled
Some checks failed
Go / build-and-release (push) Has been cancelled
Introduce comprehensive tests for policy validation logic, including owner and policy admin scenarios. Update `HandlePolicyConfigUpdate` to differentiate permissions for owners and policy admins, enforcing stricter field restrictions and validation flows.
This commit is contained in:
690
pkg/policy/composition_test.go
Normal file
690
pkg/policy/composition_test.go
Normal file
@@ -0,0 +1,690 @@
|
||||
package policy
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestValidateOwnerPolicyUpdate tests owner-specific validation
|
||||
func TestValidateOwnerPolicyUpdate(t *testing.T) {
|
||||
// Create a base policy
|
||||
basePolicy := &P{
|
||||
DefaultPolicy: "allow",
|
||||
Owners: []string{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
|
||||
PolicyAdmins: []string{"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
newPolicy string
|
||||
expectError bool
|
||||
errorMsg string
|
||||
}{
|
||||
{
|
||||
name: "valid owner update with non-empty owners",
|
||||
newPolicy: `{
|
||||
"default_policy": "deny",
|
||||
"owners": ["cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"],
|
||||
"policy_admins": ["dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"]
|
||||
}`,
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "invalid - empty owners list",
|
||||
newPolicy: `{
|
||||
"default_policy": "deny",
|
||||
"owners": [],
|
||||
"policy_admins": ["dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"]
|
||||
}`,
|
||||
expectError: true,
|
||||
errorMsg: "owners list cannot be empty",
|
||||
},
|
||||
{
|
||||
name: "invalid - missing owners field",
|
||||
newPolicy: `{
|
||||
"default_policy": "deny",
|
||||
"policy_admins": ["dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"]
|
||||
}`,
|
||||
expectError: true,
|
||||
errorMsg: "owners list cannot be empty",
|
||||
},
|
||||
{
|
||||
name: "invalid - bad owner pubkey format",
|
||||
newPolicy: `{
|
||||
"default_policy": "deny",
|
||||
"owners": ["not-a-valid-pubkey"]
|
||||
}`,
|
||||
expectError: true,
|
||||
errorMsg: "invalid owner pubkey",
|
||||
},
|
||||
{
|
||||
name: "valid - owner can add multiple owners",
|
||||
newPolicy: `{
|
||||
"default_policy": "deny",
|
||||
"owners": [
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
|
||||
]
|
||||
}`,
|
||||
expectError: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := basePolicy.ValidateOwnerPolicyUpdate([]byte(tt.newPolicy))
|
||||
if tt.expectError {
|
||||
if err == nil {
|
||||
t.Errorf("expected error containing %q, got nil", tt.errorMsg)
|
||||
} else if tt.errorMsg != "" && !containsSubstring(err.Error(), tt.errorMsg) {
|
||||
t.Errorf("expected error containing %q, got %q", tt.errorMsg, err.Error())
|
||||
}
|
||||
} else {
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestValidatePolicyAdminUpdate tests policy admin validation
|
||||
func TestValidatePolicyAdminUpdate(t *testing.T) {
|
||||
// Create a base policy with known owners and admins
|
||||
ownerPubkey := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
adminPubkey := "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
|
||||
allowedPubkey := "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
|
||||
|
||||
baseJSON := `{
|
||||
"default_policy": "allow",
|
||||
"owners": ["` + ownerPubkey + `"],
|
||||
"policy_admins": ["` + adminPubkey + `"],
|
||||
"kind": {
|
||||
"whitelist": [1, 3, 7]
|
||||
},
|
||||
"rules": {
|
||||
"1": {
|
||||
"description": "Text notes",
|
||||
"write_allow": ["` + allowedPubkey + `"],
|
||||
"size_limit": 10000
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
basePolicy := &P{}
|
||||
if err := json.Unmarshal([]byte(baseJSON), basePolicy); err != nil {
|
||||
t.Fatalf("failed to create base policy: %v", err)
|
||||
}
|
||||
|
||||
adminPubkeyBin := make([]byte, 32)
|
||||
for i := range adminPubkeyBin {
|
||||
adminPubkeyBin[i] = 0xbb
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
newPolicy string
|
||||
expectError bool
|
||||
errorMsg string
|
||||
}{
|
||||
{
|
||||
name: "valid - policy admin can extend write_allow",
|
||||
newPolicy: `{
|
||||
"default_policy": "allow",
|
||||
"owners": ["` + ownerPubkey + `"],
|
||||
"policy_admins": ["` + adminPubkey + `"],
|
||||
"kind": {
|
||||
"whitelist": [1, 3, 7]
|
||||
},
|
||||
"rules": {
|
||||
"1": {
|
||||
"description": "Text notes",
|
||||
"write_allow": ["` + allowedPubkey + `", "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"],
|
||||
"size_limit": 10000
|
||||
}
|
||||
}
|
||||
}`,
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "valid - policy admin can add to kind whitelist",
|
||||
newPolicy: `{
|
||||
"default_policy": "allow",
|
||||
"owners": ["` + ownerPubkey + `"],
|
||||
"policy_admins": ["` + adminPubkey + `"],
|
||||
"kind": {
|
||||
"whitelist": [1, 3, 7, 30023]
|
||||
},
|
||||
"rules": {
|
||||
"1": {
|
||||
"description": "Text notes",
|
||||
"write_allow": ["` + allowedPubkey + `"],
|
||||
"size_limit": 10000
|
||||
}
|
||||
}
|
||||
}`,
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "valid - policy admin can increase size limit",
|
||||
newPolicy: `{
|
||||
"default_policy": "allow",
|
||||
"owners": ["` + ownerPubkey + `"],
|
||||
"policy_admins": ["` + adminPubkey + `"],
|
||||
"kind": {
|
||||
"whitelist": [1, 3, 7]
|
||||
},
|
||||
"rules": {
|
||||
"1": {
|
||||
"description": "Text notes",
|
||||
"write_allow": ["` + allowedPubkey + `"],
|
||||
"size_limit": 20000
|
||||
}
|
||||
}
|
||||
}`,
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "invalid - policy admin cannot modify owners",
|
||||
newPolicy: `{
|
||||
"default_policy": "allow",
|
||||
"owners": ["dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"],
|
||||
"policy_admins": ["` + adminPubkey + `"],
|
||||
"kind": {
|
||||
"whitelist": [1, 3, 7]
|
||||
},
|
||||
"rules": {
|
||||
"1": {
|
||||
"description": "Text notes",
|
||||
"write_allow": ["` + allowedPubkey + `"],
|
||||
"size_limit": 10000
|
||||
}
|
||||
}
|
||||
}`,
|
||||
expectError: true,
|
||||
errorMsg: "cannot modify the 'owners' field",
|
||||
},
|
||||
{
|
||||
name: "invalid - policy admin cannot modify policy_admins",
|
||||
newPolicy: `{
|
||||
"default_policy": "allow",
|
||||
"owners": ["` + ownerPubkey + `"],
|
||||
"policy_admins": ["dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"],
|
||||
"kind": {
|
||||
"whitelist": [1, 3, 7]
|
||||
},
|
||||
"rules": {
|
||||
"1": {
|
||||
"description": "Text notes",
|
||||
"write_allow": ["` + allowedPubkey + `"],
|
||||
"size_limit": 10000
|
||||
}
|
||||
}
|
||||
}`,
|
||||
expectError: true,
|
||||
errorMsg: "cannot modify the 'policy_admins' field",
|
||||
},
|
||||
{
|
||||
name: "invalid - policy admin cannot remove from kind whitelist",
|
||||
newPolicy: `{
|
||||
"default_policy": "allow",
|
||||
"owners": ["` + ownerPubkey + `"],
|
||||
"policy_admins": ["` + adminPubkey + `"],
|
||||
"kind": {
|
||||
"whitelist": [1, 3]
|
||||
},
|
||||
"rules": {
|
||||
"1": {
|
||||
"description": "Text notes",
|
||||
"write_allow": ["` + allowedPubkey + `"],
|
||||
"size_limit": 10000
|
||||
}
|
||||
}
|
||||
}`,
|
||||
expectError: true,
|
||||
errorMsg: "cannot remove kind 7 from whitelist",
|
||||
},
|
||||
{
|
||||
name: "invalid - policy admin cannot remove from write_allow",
|
||||
newPolicy: `{
|
||||
"default_policy": "allow",
|
||||
"owners": ["` + ownerPubkey + `"],
|
||||
"policy_admins": ["` + adminPubkey + `"],
|
||||
"kind": {
|
||||
"whitelist": [1, 3, 7]
|
||||
},
|
||||
"rules": {
|
||||
"1": {
|
||||
"description": "Text notes",
|
||||
"write_allow": [],
|
||||
"size_limit": 10000
|
||||
}
|
||||
}
|
||||
}`,
|
||||
expectError: true,
|
||||
errorMsg: "cannot remove pubkey",
|
||||
},
|
||||
{
|
||||
name: "invalid - policy admin cannot reduce size limit",
|
||||
newPolicy: `{
|
||||
"default_policy": "allow",
|
||||
"owners": ["` + ownerPubkey + `"],
|
||||
"policy_admins": ["` + adminPubkey + `"],
|
||||
"kind": {
|
||||
"whitelist": [1, 3, 7]
|
||||
},
|
||||
"rules": {
|
||||
"1": {
|
||||
"description": "Text notes",
|
||||
"write_allow": ["` + allowedPubkey + `"],
|
||||
"size_limit": 5000
|
||||
}
|
||||
}
|
||||
}`,
|
||||
expectError: true,
|
||||
errorMsg: "cannot reduce size_limit",
|
||||
},
|
||||
{
|
||||
name: "invalid - policy admin cannot remove rule",
|
||||
newPolicy: `{
|
||||
"default_policy": "allow",
|
||||
"owners": ["` + ownerPubkey + `"],
|
||||
"policy_admins": ["` + adminPubkey + `"],
|
||||
"kind": {
|
||||
"whitelist": [1, 3, 7]
|
||||
},
|
||||
"rules": {}
|
||||
}`,
|
||||
expectError: true,
|
||||
errorMsg: "cannot remove rule for kind 1",
|
||||
},
|
||||
{
|
||||
name: "valid - policy admin can add blacklist entries for non-admin users",
|
||||
newPolicy: `{
|
||||
"default_policy": "allow",
|
||||
"owners": ["` + ownerPubkey + `"],
|
||||
"policy_admins": ["` + adminPubkey + `"],
|
||||
"kind": {
|
||||
"whitelist": [1, 3, 7],
|
||||
"blacklist": [4]
|
||||
},
|
||||
"rules": {
|
||||
"1": {
|
||||
"description": "Text notes",
|
||||
"write_allow": ["` + allowedPubkey + `"],
|
||||
"write_deny": ["eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"],
|
||||
"size_limit": 10000
|
||||
}
|
||||
}
|
||||
}`,
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "invalid - policy admin cannot blacklist owner in write_deny",
|
||||
newPolicy: `{
|
||||
"default_policy": "allow",
|
||||
"owners": ["` + ownerPubkey + `"],
|
||||
"policy_admins": ["` + adminPubkey + `"],
|
||||
"kind": {
|
||||
"whitelist": [1, 3, 7]
|
||||
},
|
||||
"rules": {
|
||||
"1": {
|
||||
"description": "Text notes",
|
||||
"write_allow": ["` + allowedPubkey + `"],
|
||||
"write_deny": ["` + ownerPubkey + `"],
|
||||
"size_limit": 10000
|
||||
}
|
||||
}
|
||||
}`,
|
||||
expectError: true,
|
||||
errorMsg: "cannot blacklist owner",
|
||||
},
|
||||
{
|
||||
name: "invalid - policy admin cannot blacklist other policy admin",
|
||||
newPolicy: `{
|
||||
"default_policy": "allow",
|
||||
"owners": ["` + ownerPubkey + `"],
|
||||
"policy_admins": ["` + adminPubkey + `"],
|
||||
"kind": {
|
||||
"whitelist": [1, 3, 7]
|
||||
},
|
||||
"rules": {
|
||||
"1": {
|
||||
"description": "Text notes",
|
||||
"write_allow": ["` + allowedPubkey + `"],
|
||||
"write_deny": ["` + adminPubkey + `"],
|
||||
"size_limit": 10000
|
||||
}
|
||||
}
|
||||
}`,
|
||||
expectError: true,
|
||||
errorMsg: "cannot blacklist policy admin",
|
||||
},
|
||||
{
|
||||
name: "valid - policy admin can blacklist whitelisted non-admin user",
|
||||
newPolicy: `{
|
||||
"default_policy": "allow",
|
||||
"owners": ["` + ownerPubkey + `"],
|
||||
"policy_admins": ["` + adminPubkey + `"],
|
||||
"kind": {
|
||||
"whitelist": [1, 3, 7]
|
||||
},
|
||||
"rules": {
|
||||
"1": {
|
||||
"description": "Text notes",
|
||||
"write_allow": ["` + allowedPubkey + `"],
|
||||
"write_deny": ["` + allowedPubkey + `"],
|
||||
"size_limit": 10000
|
||||
}
|
||||
}
|
||||
}`,
|
||||
expectError: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := basePolicy.ValidatePolicyAdminUpdate([]byte(tt.newPolicy), adminPubkeyBin)
|
||||
if tt.expectError {
|
||||
if err == nil {
|
||||
t.Errorf("expected error containing %q, got nil", tt.errorMsg)
|
||||
} else if tt.errorMsg != "" && !containsSubstring(err.Error(), tt.errorMsg) {
|
||||
t.Errorf("expected error containing %q, got %q", tt.errorMsg, err.Error())
|
||||
}
|
||||
} else {
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestIsOwner tests the IsOwner method
|
||||
func TestIsOwner(t *testing.T) {
|
||||
ownerPubkey := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
nonOwnerPubkey := "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
|
||||
|
||||
_ = nonOwnerPubkey // Silence unused variable warning
|
||||
|
||||
policyJSON := `{
|
||||
"default_policy": "allow",
|
||||
"owners": ["` + ownerPubkey + `"]
|
||||
}`
|
||||
|
||||
policy, err := New([]byte(policyJSON))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create policy: %v", err)
|
||||
}
|
||||
|
||||
// Create binary pubkeys
|
||||
ownerBin := make([]byte, 32)
|
||||
for i := range ownerBin {
|
||||
ownerBin[i] = 0xaa
|
||||
}
|
||||
|
||||
nonOwnerBin := make([]byte, 32)
|
||||
for i := range nonOwnerBin {
|
||||
nonOwnerBin[i] = 0xbb
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
pubkey []byte
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "owner is recognized",
|
||||
pubkey: ownerBin,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "non-owner is not recognized",
|
||||
pubkey: nonOwnerBin,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "nil pubkey returns false",
|
||||
pubkey: nil,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "empty pubkey returns false",
|
||||
pubkey: []byte{},
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := policy.IsOwner(tt.pubkey)
|
||||
if result != tt.expected {
|
||||
t.Errorf("expected %v, got %v", tt.expected, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestStringSliceEqual tests the helper function
|
||||
func TestStringSliceEqual(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
a []string
|
||||
b []string
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "equal slices same order",
|
||||
a: []string{"a", "b", "c"},
|
||||
b: []string{"a", "b", "c"},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "equal slices different order",
|
||||
a: []string{"a", "b", "c"},
|
||||
b: []string{"c", "a", "b"},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "different lengths",
|
||||
a: []string{"a", "b"},
|
||||
b: []string{"a", "b", "c"},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "different contents",
|
||||
a: []string{"a", "b", "c"},
|
||||
b: []string{"a", "b", "d"},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "empty slices",
|
||||
a: []string{},
|
||||
b: []string{},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "nil slices",
|
||||
a: nil,
|
||||
b: nil,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "nil vs empty",
|
||||
a: nil,
|
||||
b: []string{},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "duplicates in both",
|
||||
a: []string{"a", "a", "b"},
|
||||
b: []string{"a", "b", "a"},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := stringSliceEqual(tt.a, tt.b)
|
||||
if result != tt.expected {
|
||||
t.Errorf("expected %v, got %v", tt.expected, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestPolicyAdminContributionValidation tests the contribution validation
|
||||
func TestPolicyAdminContributionValidation(t *testing.T) {
|
||||
ownerPubkey := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
adminPubkey := "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
|
||||
|
||||
ownerPolicy := &P{
|
||||
DefaultPolicy: "allow",
|
||||
Owners: []string{ownerPubkey},
|
||||
PolicyAdmins: []string{adminPubkey},
|
||||
Kind: Kinds{
|
||||
Whitelist: []int{1, 3, 7},
|
||||
},
|
||||
rules: map[int]Rule{
|
||||
1: {
|
||||
Description: "Text notes",
|
||||
SizeLimit: ptr(int64(10000)),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
contribution *PolicyAdminContribution
|
||||
expectError bool
|
||||
errorMsg string
|
||||
}{
|
||||
{
|
||||
name: "valid - add kinds to whitelist",
|
||||
contribution: &PolicyAdminContribution{
|
||||
AdminPubkey: adminPubkey,
|
||||
CreatedAt: 1234567890,
|
||||
EventID: "event123",
|
||||
KindWhitelistAdd: []int{30023},
|
||||
},
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "valid - add to blacklist",
|
||||
contribution: &PolicyAdminContribution{
|
||||
AdminPubkey: adminPubkey,
|
||||
CreatedAt: 1234567890,
|
||||
EventID: "event123",
|
||||
KindBlacklistAdd: []int{4},
|
||||
},
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "valid - extend existing rule with larger limit",
|
||||
contribution: &PolicyAdminContribution{
|
||||
AdminPubkey: adminPubkey,
|
||||
CreatedAt: 1234567890,
|
||||
EventID: "event123",
|
||||
RulesExtend: map[int]RuleExtension{
|
||||
1: {
|
||||
SizeLimitOverride: ptr(int64(20000)),
|
||||
},
|
||||
},
|
||||
},
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "invalid - extend non-existent rule",
|
||||
contribution: &PolicyAdminContribution{
|
||||
AdminPubkey: adminPubkey,
|
||||
CreatedAt: 1234567890,
|
||||
EventID: "event123",
|
||||
RulesExtend: map[int]RuleExtension{
|
||||
999: {
|
||||
SizeLimitOverride: ptr(int64(20000)),
|
||||
},
|
||||
},
|
||||
},
|
||||
expectError: true,
|
||||
errorMsg: "cannot extend rule for kind 999",
|
||||
},
|
||||
{
|
||||
name: "invalid - size limit override smaller than owner's",
|
||||
contribution: &PolicyAdminContribution{
|
||||
AdminPubkey: adminPubkey,
|
||||
CreatedAt: 1234567890,
|
||||
EventID: "event123",
|
||||
RulesExtend: map[int]RuleExtension{
|
||||
1: {
|
||||
SizeLimitOverride: ptr(int64(5000)),
|
||||
},
|
||||
},
|
||||
},
|
||||
expectError: true,
|
||||
errorMsg: "size_limit_override for kind 1 must be >=",
|
||||
},
|
||||
{
|
||||
name: "valid - add new rule for undefined kind",
|
||||
contribution: &PolicyAdminContribution{
|
||||
AdminPubkey: adminPubkey,
|
||||
CreatedAt: 1234567890,
|
||||
EventID: "event123",
|
||||
RulesAdd: map[int]Rule{
|
||||
30023: {
|
||||
Description: "Long-form content",
|
||||
SizeLimit: ptr(int64(100000)),
|
||||
},
|
||||
},
|
||||
},
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "invalid - add rule for already-defined kind",
|
||||
contribution: &PolicyAdminContribution{
|
||||
AdminPubkey: adminPubkey,
|
||||
CreatedAt: 1234567890,
|
||||
EventID: "event123",
|
||||
RulesAdd: map[int]Rule{
|
||||
1: {
|
||||
Description: "Trying to override",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectError: true,
|
||||
errorMsg: "cannot add rule for kind 1: already defined",
|
||||
},
|
||||
{
|
||||
name: "invalid - bad pubkey length in extension",
|
||||
contribution: &PolicyAdminContribution{
|
||||
AdminPubkey: "short",
|
||||
CreatedAt: 1234567890,
|
||||
EventID: "event123",
|
||||
},
|
||||
expectError: true,
|
||||
errorMsg: "invalid admin pubkey length",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := ValidatePolicyAdminContribution(ownerPolicy, tt.contribution, nil)
|
||||
if tt.expectError {
|
||||
if err == nil {
|
||||
t.Errorf("expected error containing %q, got nil", tt.errorMsg)
|
||||
} else if tt.errorMsg != "" && !containsSubstring(err.Error(), tt.errorMsg) {
|
||||
t.Errorf("expected error containing %q, got %q", tt.errorMsg, err.Error())
|
||||
}
|
||||
} else {
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function for generic pointer
|
||||
func ptr[T any](v T) *T {
|
||||
return &v
|
||||
}
|
||||
Reference in New Issue
Block a user