Add captured configuration comparison
This commit is contained in:
92
configuration_diff_contract_test.go
Normal file
92
configuration_diff_contract_test.go
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
package promptkit_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gitea.maximumdirect.net/eric/ConfigKit"
|
||||||
|
"gitea.maximumdirect.net/eric/promptkit"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConfigurationInspectionDiffsCapturedValues(t *testing.T) {
|
||||||
|
left := comparisonInspection(t, "earlier-model")
|
||||||
|
right := comparisonInspection(t, "later-model")
|
||||||
|
|
||||||
|
differences, err := left.Diff(right)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("compare captured configurations: %v", err)
|
||||||
|
}
|
||||||
|
if len(differences) != 1 {
|
||||||
|
t.Fatalf("difference count = %d, want 1: %+v", len(differences), differences)
|
||||||
|
}
|
||||||
|
difference := differences[0]
|
||||||
|
if got, want := difference.Path.String(), "/profiles/offline/model"; got != want {
|
||||||
|
t.Fatalf("difference path = %q, want %q", got, want)
|
||||||
|
}
|
||||||
|
if !strings.Contains(difference.Left.YAML, "earlier-model") || !strings.Contains(difference.Right.YAML, "later-model") {
|
||||||
|
t.Fatalf("difference snapshots = (%q, %q)", difference.Left.YAML, difference.Right.YAML)
|
||||||
|
}
|
||||||
|
|
||||||
|
reversed, err := right.Diff(left)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("compare reversed configurations: %v", err)
|
||||||
|
}
|
||||||
|
if len(reversed) != 1 || reversed[0].Path.String() != difference.Path.String() ||
|
||||||
|
!strings.Contains(reversed[0].Left.YAML, "later-model") ||
|
||||||
|
!strings.Contains(reversed[0].Right.YAML, "earlier-model") {
|
||||||
|
t.Fatalf("reversed difference = %+v", reversed)
|
||||||
|
}
|
||||||
|
|
||||||
|
equal := comparisonInspection(t, "earlier-model")
|
||||||
|
if equal, err := left.Diff(equal); err != nil || len(equal) != 0 {
|
||||||
|
t.Fatalf("compare equal configurations = (%+v, %v), want no differences", equal, err)
|
||||||
|
}
|
||||||
|
if equal, err := left.Diff(left); err != nil || len(equal) != 0 {
|
||||||
|
t.Fatalf("compare view with itself = (%+v, %v), want no differences", equal, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigurationInspectionDiffRejectsZeroViews(t *testing.T) {
|
||||||
|
valid := comparisonInspection(t, "current-model")
|
||||||
|
var zero promptkit.ConfigurationInspection
|
||||||
|
|
||||||
|
for _, comparison := range []struct {
|
||||||
|
name string
|
||||||
|
left, right promptkit.ConfigurationInspection
|
||||||
|
}{
|
||||||
|
{name: "zero left", left: zero, right: valid},
|
||||||
|
{name: "zero right", left: valid, right: zero},
|
||||||
|
{name: "both zero", left: zero, right: zero},
|
||||||
|
} {
|
||||||
|
t.Run(comparison.name, func(t *testing.T) {
|
||||||
|
differences, err := comparison.left.Diff(comparison.right)
|
||||||
|
if !errors.Is(err, promptkit.ErrInvalidConfig) || len(differences) != 0 {
|
||||||
|
t.Fatalf("Diff() = (%+v, %v), want ErrInvalidConfig and no records", differences, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func comparisonInspection(t *testing.T, model string) promptkit.ConfigurationInspection {
|
||||||
|
t.Helper()
|
||||||
|
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{
|
||||||
|
Underlays: []configkit.Underlay{{Inputs: []configkit.Input{{Source: configkit.Mapping("comparison fixture", map[string]any{
|
||||||
|
"backends": map[string]any{"local": map[string]any{
|
||||||
|
"endpoint": "https://example.invalid/v1",
|
||||||
|
}},
|
||||||
|
"profiles": map[string]any{"offline": map[string]any{
|
||||||
|
"backend": "local",
|
||||||
|
"model": model,
|
||||||
|
}},
|
||||||
|
})}}}},
|
||||||
|
}})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("construct comparison engine: %v", err)
|
||||||
|
}
|
||||||
|
inspection, err := engine.InspectConfiguration()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("inspect comparison engine: %v", err)
|
||||||
|
}
|
||||||
|
return inspection
|
||||||
|
}
|
||||||
@@ -27,6 +27,20 @@ func (e *Engine) InspectConfiguration() (ConfigurationInspection, error) {
|
|||||||
return ConfigurationInspection{source: e.internal.InspectConfiguration()}, nil
|
return ConfigurationInspection{source: e.internal.InspectConfiguration()}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Diff compares this view's captured effective configuration with other. This
|
||||||
|
// view is the earlier (left) value and other is the later (right) value. The
|
||||||
|
// comparison delegates to ConfigKit's frozen effective-value semantics, so
|
||||||
|
// source or resolution history alone does not create differences. Either zero
|
||||||
|
// view returns ErrInvalidConfig and no records. Returned records can contain
|
||||||
|
// ordinary application data and are not evidence of equivalent execution
|
||||||
|
// behavior; callers choose where and to whom to disclose them.
|
||||||
|
func (v ConfigurationInspection) Diff(other ConfigurationInspection) ([]configkit.Difference, error) {
|
||||||
|
if v.source == nil || other.source == nil {
|
||||||
|
return nil, ErrInvalidConfig
|
||||||
|
}
|
||||||
|
return configuration.Diff(v.source, other.source)
|
||||||
|
}
|
||||||
|
|
||||||
// Metadata returns detached effective presence and history records.
|
// Metadata returns detached effective presence and history records.
|
||||||
func (v ConfigurationInspection) Metadata() configkit.Metadata {
|
func (v ConfigurationInspection) Metadata() configkit.Metadata {
|
||||||
if v.source == nil {
|
if v.source == nil {
|
||||||
|
|||||||
@@ -82,6 +82,12 @@ existing validation, and attribution matches the selected source revision.
|
|||||||
|
|
||||||
## Stage 2: Add The Private Bridge And Public Method
|
## Stage 2: Add The Private Bridge And Public Method
|
||||||
|
|
||||||
|
**Status: Complete.** Added the private captured-result bridge and public
|
||||||
|
`ConfigurationInspection.Diff` method. External-package tests cover changed and
|
||||||
|
equal values, operand direction, self-comparison, and all zero-view pairs.
|
||||||
|
`GOTOOLCHAIN=local go test . ./internal/configuration ./internal/engine` and
|
||||||
|
`git diff --check` passed.
|
||||||
|
|
||||||
Scope: the small integration path and basic facade tests.
|
Scope: the small integration path and basic facade tests.
|
||||||
|
|
||||||
1. In `internal/configuration/inspection.go`, add the private wrapper and
|
1. In `internal/configuration/inspection.go`, add the private wrapper and
|
||||||
|
|||||||
@@ -16,6 +16,15 @@ type Inspection interface {
|
|||||||
Explain(configkit.Path) (configkit.Explanation, bool)
|
Explain(configkit.Path) (configkit.Explanation, bool)
|
||||||
WriteEffective(io.Writer) error
|
WriteEffective(io.Writer) error
|
||||||
WriteExplanation(io.Writer, configkit.Path) error
|
WriteExplanation(io.Writer, configkit.Path) error
|
||||||
|
capturedResult() *configkit.Result[document]
|
||||||
|
}
|
||||||
|
|
||||||
|
type inspectionResult struct {
|
||||||
|
*configkit.Result[document]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (inspection inspectionResult) capturedResult() *configkit.Result[document] {
|
||||||
|
return inspection.Result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inspection returns only the retained result's inspection operations.
|
// Inspection returns only the retained result's inspection operations.
|
||||||
@@ -23,7 +32,19 @@ func (state *loaded) Inspection() Inspection {
|
|||||||
if state == nil {
|
if state == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return state.result
|
return inspectionResult{Result: state.result}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Diff compares two captured ConfigKit results without reconstructing them.
|
||||||
|
func Diff(left, right Inspection) ([]configkit.Difference, error) {
|
||||||
|
var leftResult, rightResult *configkit.Result[document]
|
||||||
|
if left != nil {
|
||||||
|
leftResult = left.capturedResult()
|
||||||
|
}
|
||||||
|
if right != nil {
|
||||||
|
rightResult = right.capturedResult()
|
||||||
|
}
|
||||||
|
return configkit.Diff(leftResult, rightResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
func secretProviderPath(path configkit.Path) bool {
|
func secretProviderPath(path configkit.Path) bool {
|
||||||
|
|||||||
Reference in New Issue
Block a user