Skip to content
Tracon

ToolApprovalRuleStoreContract

Namespace Tracon.Testing.Contracts.Storage · Assembly Tracon.Testing.Contracts.Xunit.dll

Behavior tests for the IToolApprovalRuleStore contract.

public abstract class ToolApprovalRuleStoreContract : TenantIsolationContract<IToolApprovalRuleStore>, IAsyncLifetime, IAsyncDisposable
Inheritance
object ← StoreCancellationContract<IToolApprovalRuleStore> ← TenantIsolationContract<IToolApprovalRuleStore> ← ToolApprovalRuleStoreContract
Implements
IAsyncLifetime, IAsyncDisposable
Inherited Members
TenantIsolationContract<IToolApprovalRuleStore>.TenantA, TenantIsolationContract<IToolApprovalRuleStore>.TenantB, TenantIsolationContract<IToolApprovalRuleStore>.UseAmbientTenant(MutableTenantContext), TenantIsolationContract<IToolApprovalRuleStore>.SeedAsync(string, string, CancellationToken), TenantIsolationContract<IToolApprovalRuleStore>.ExistsAsync(string, object), TenantIsolationContract<IToolApprovalRuleStore>.CountAsync(string, CancellationToken), TenantIsolationContract<IToolApprovalRuleStore>.TryDeleteAsync(string, object), TenantIsolationContract<IToolApprovalRuleStore>.TryOverwriteAsync(string, string), TenantIsolationContract<IToolApprovalRuleStore>.CancellableReadAsync(CancellationToken), TenantIsolationContract<IToolApprovalRuleStore>.CancellableWriteAsync(CancellationToken), TenantIsolationContract<IToolApprovalRuleStore>.WroteAnythingAsync(), TenantIsolationContract<IToolApprovalRuleStore>.Tenant_cannot_read_another_tenants_record(), TenantIsolationContract<IToolApprovalRuleStore>.Tenant_reads_its_own_record(), TenantIsolationContract<IToolApprovalRuleStore>.Tenant_does_not_see_another_tenants_record_in_the_list(), TenantIsolationContract<IToolApprovalRuleStore>.Tenant_cannot_delete_another_tenants_record(), TenantIsolationContract<IToolApprovalRuleStore>.Same_name_lives_independently_across_two_tenants(), TenantIsolationContract<IToolApprovalRuleStore>.AmbientTenant, StoreCancellationContract<IToolApprovalRuleStore>.CreateStoreAsync(), StoreCancellationContract<IToolApprovalRuleStore>.InitializeAsync(), StoreCancellationContract<IToolApprovalRuleStore>.DisposeAsync(), StoreCancellationContract<IToolApprovalRuleStore>.OnDisposeAsync(), StoreCancellationContract<IToolApprovalRuleStore>.CancellableReadAsync(CancellationToken), StoreCancellationContract<IToolApprovalRuleStore>.CancellableWriteAsync(CancellationToken), StoreCancellationContract<IToolApprovalRuleStore>.WroteAnythingAsync(), StoreCancellationContract<IToolApprovalRuleStore>.Canceled_token_throws_on_read(), StoreCancellationContract<IToolApprovalRuleStore>.The_write_this_contract_checks_can_be_read_back(), StoreCancellationContract<IToolApprovalRuleStore>.Canceled_token_throws_on_write_and_leaves_no_trace(), StoreCancellationContract<IToolApprovalRuleStore>.Store, object.GetType(), object.MemberwiseClone(), object.ToString(), object.Equals(object?), object.Equals(object?, object?), object.ReferenceEquals(object?, object?), object.GetHashCode()

A persisted approval rule is a security record: one tenant’s rule must never let another tenant’s tool call through without approval.

protected ToolApprovalRuleStoreContract()

A_list_value_that_differs_only_in_whitespace_is_the_same_condition_set()

Section titled “ A_list_value_that_differs_only_in_whitespace_is_the_same_condition_set()”

A list value written with different whitespace is the same condition, so the rule is not stored twice.

[Fact]
public Task A_list_value_that_differs_only_in_whitespace_is_the_same_condition_set()

Task

A_path_carrying_separator_characters_does_not_merge_two_condition_sets()

Section titled “ A_path_carrying_separator_characters_does_not_merge_two_condition_sets()”

Two different condition sets stay two rules even when a path carries the characters a store might use to join the fields it compares.

[Fact]
public Task A_path_carrying_separator_characters_does_not_merge_two_condition_sets()

Task

A path is free text - a JSON property name may hold any character. A store that deduplicates on a joined text of path, operator, and value must not let one set’s path read as another set’s field boundary. Otherwise the second rule is merged into the first: the store keeps the first rule and hands it back as if the second had been saved.

[Fact]
public Task Added_rule_is_read_back()

Task

[Fact]
public Task Argument_conditions_round_trip()

Task

Condition_scoped_rule_added_twice_leaves_a_single_record()

Section titled “ Condition_scoped_rule_added_twice_leaves_a_single_record()”
[Fact]
public Task Condition_scoped_rule_added_twice_leaves_a_single_record()

Task

Reports how many records the given tenant sees through the listing endpoint.

protected override ValueTask<int> CountAsync(string tenantId, CancellationToken cancellationToken)

tenantId string

The reading tenant.

cancellationToken CancellationToken

The token every store call inside the hook must be handed; see TenantIsolationContract.SeedAsync.

ValueTask<int>

The number of records seen.

Deleting_a_nonexistent_rule_returns_false()

Section titled “ Deleting_a_nonexistent_rule_returns_false()”
[Fact]
public Task Deleting_a_nonexistent_rule_returns_false()

Task

Different_agent_becomes_a_separate_rule()

Section titled “ Different_agent_becomes_a_separate_rule()”
[Fact]
public Task Different_agent_becomes_a_separate_rule()

Task

Different_conditions_become_a_separate_rule()

Section titled “ Different_conditions_become_a_separate_rule()”
[Fact]
public Task Different_conditions_become_a_separate_rule()

Task

Different_source_fingerprint_becomes_a_separate_rule()

Section titled “ Different_source_fingerprint_becomes_a_separate_rule()”

Two rules that differ only in their source fingerprint are two rules.

[Fact]
public Task Different_source_fingerprint_becomes_a_separate_rule()

Task

A server that moved to another endpoint keeps its tool names. If the fingerprint were not part of the identity, a rule for the new endpoint would come back as the old rule, which names the old endpoint and never approves the new one.

Reports whether the record is visible from the given tenant’s viewpoint.

protected override ValueTask<bool> ExistsAsync(string tenantId, object key)

tenantId string

The reading tenant.

key object

The key returned by TenantIsolationContract.SeedAsync.

ValueTask<bool>

true if the record is visible.

Same_scope_added_twice_leaves_a_single_record()

Section titled “ Same_scope_added_twice_leaves_a_single_record()”
[Fact]
public Task Same_scope_added_twice_leaves_a_single_record()

Task

SeedAsync(string, string, CancellationToken)

Section titled “ SeedAsync(string, string, CancellationToken)”

Writes a sample record for the given tenant.

protected override ValueTask<object> SeedAsync(string tenantId, string name, CancellationToken cancellationToken)

tenantId string

The tenant that owns the record.

name string

The name distinguishing the record. The same name may be used by two tenants.

cancellationToken CancellationToken

The token every store call inside the hook must be handed. The cancellation contract calls this hook with a token that is already cancelled, so a hook that drops the token reports a store as sound when it is not.

ValueTask<object>

The key to use for reading the record back.

The source fingerprint of a rule is stored and returned as given, both on the record the add returns and on a later read.

[Fact]
public Task Source_fingerprint_round_trips()

Task

The rule only approves a tool of the source it names. A store that drops the value hands back a rule without a source, which approves no remote tool, so every remembered approval for one would ask again forever.

Attempts to delete the record on behalf of the given tenant.

protected override ValueTask<bool?> TryDeleteAsync(string tenantId, object key)

tenantId string

The tenant attempting the delete.

key object

The key returned by TenantIsolationContract.SeedAsync.

ValueTask<bool?>

true if the delete succeeded, false if the record was not found; null if the store does not offer deletion.