CodeSampleX

Exemple

github.com/google/go-cmp v0.6.0: cmp.Ignore

Échantillon vérifié pour golang github.com/google/go-cmp v0.6.0: cmp.Ignore. Le contrat s'est exécuté sur go 1.26 · linux debian/x64 · docker et a réussi.

sha256:7b4a19968a08fc2b30a7abd2403e07df1690fec1d48e958b54781638bc0d2a16

Ce réseau offre une seule chose : un échantillon qui compile. Il l'a exécuté dans un bac à sable et conservé le reçu signé. Il ne note rien et ne garantit rien : si le même code compile chez vous, il ne l'a pas mesuré. Combien de clés de signature distinctes ont déposé un reçu de contrat réussi. Une seule, c'est l'auteur ; plus d'une signifie que quelqu'un d'autre l'a compilé aussi. Une clé est auto-générée sans identité enregistrée derrière, donc on compte des clés, pas des personnes. MIT-0

Preuves d'exécution

L'environnement déclaré et les exécutions signées sont séparés, pour que vous voyiez exactement ce que cet échantillon a exécuté et où.

Base de preuve
Contrat signé réussi
Reçus de vérification
1
Clés de signature qui l’ont compilé
1
Environnement déclaré linux 24 · ubuntu · glibc 2.39 x64 go

Environnements des exécutions de vérification

Environnement Contrat Étapes Exécution
go 1.26 · linux debian/x64 · docker ed25519:c1973797be207ac4 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · golang@1golang:1.26@sha256:e30143be198a…
2026-09-15

Cas

HOW
Objectif
verify github.com/google/go-cmp/cmp.Ignore in pkg:golang/github.com/google/go-cmp@v0.6.0
Paquets
Symboles
  • github.com/google/go-cmp/cmp.Ignore
Créé
2026-09-15T21:27:51Z

Contrat

  1. cmp.Ignore is an Option that causes all comparisons matching a filter to be ignored
  2. Passing an unfiltered cmp.Ignore directly to cmp.Equal panics with cannot use an unfiltered option: Ignore()
  3. cmp.FilterPath with cmp.Ignore ignores struct fields by name leaving non-ignored fields evaluated
  4. cmp.FilterPath with cmp.Ignore bypasses reflection panics on unexported struct fields without AllowUnexported
  5. cmp.FilterPath with cmp.Ignore ignores any node in the comparison path matching a specified reflect.Type
  6. cmp.FilterValues with cmp.Ignore conditionally ignores comparisons when a symmetric value predicate returns true
  7. cmp.FilterPath with cmp.Ignore ignores specific map keys or slice indices during container comparison

Fichiers

  • NOTES.md
  • PROMPT.md
  • csx.json
  • go.mod
  • go.sum
  • ignore.go
  • ignore_test.go
  • spec.json

Télécharger l’artefact source (tar.gz)

Code source

NOTES.md
# google/go-cmp: Selective Comparison Filtering with cmp.Ignore

## Known Solutions Search
A search for `github.com/google/go-cmp/cmp.Ignore` in `pkg:golang/github.com/google/go-cmp@v0.6.0` returned `NO_SAFE_MATCH`.

This sample investigates and verifies the contract of `cmp.Ignore`, demonstrating:
1. Combining `cmp.Ignore()` with `cmp.FilterPath` to selectively ignore struct fields by name.
2. Bypassing unexported struct field reflection panics by applying `cmp.Ignore()` to unexported fields without requiring `cmp.AllowUnexported`.
3. Ignoring specific types across data structures using `reflect.Type` matching.
4. Ignoring matching value pairs using `cmp.FilterValues` and symmetric predicates.
5. Selectively ignoring slice indices and map keys during container comparison.
6. Verifying that passing an unfiltered `cmp.Ignore()` directly to `cmp.Equal` panics with `cannot use an unfiltered option: Ignore()`.

## Pinned Release
`github.com/google/go-cmp v0.6.0` declared in `go.mod` and verified in `go.sum`.

## Failure Modes
1. Direct use of unfiltered `cmp.Ignore()` panics at runtime with `cannot use an unfiltered option: Ignore()`.
2. Direct comparison of structs containing unexported private fields panics at runtime with `cannot handle unexported field` unless the unexported fields are ignored via `cmp.Ignore()` or permitted via `cmp.AllowUnexported`.
3. Partial unexported field filtering panics if any remaining unexported field is traversed without an ignore option or exporter.

## Observed Behaviour
1. `cmp.Ignore()` returns an `Option` that marks comparisons as ignored when combined with `cmp.FilterPath` or `cmp.FilterValues`.
2. Ignored fields produce no diff output in `cmp.Diff` and evaluate to equal in `cmp.Equal`.
PROMPT.md
Clean-room public code sample — generation instructions

Write a brand-new, minimal, self-contained code sample in this clean-room directory.
Do not copy, paraphrase, or reference any existing project source. Work only from this spec.

A csx.json manifest scaffold already exists. Do not recreate it from memory. Preserve its case.goal, packages and symbols; fill its empty case.contract with exact assertions and correct its environment, commands and verifierAdapter for the files you generate.

Goal: verify github.com/google/go-cmp/cmp.Ignore in pkg:golang/github.com/google/go-cmp@v0.6.0
Kind: HOW

Use EXACTLY these public packages and versions:
  - pkg:golang/github.com/google/go-cmp@v0.6.0
Demonstrate these symbols/APIs:
  - github.com/google/go-cmp/cmp.Ignore

Rules:
  - One focused purpose; the smallest project that proves the goal.
  - Include a contract test (test/contract.*) that runs OFFLINE and exits 0 exactly when the goal behavior works.
  - Pin every dependency with a lockfile so resolution is reproducible.
  - No secrets, credentials, or tokens. No real URLs (only example.com or localhost). No absolute paths.
  - No personal names, emails, company names, or project identifiers of any kind.
  - No binaries and no generated output (node_modules, dist, target, venv, .git, .env).
  - Keep it under 200 files and 256KB packed.
csx.json
{"case":{"caseId":"case:sha256:69173f2a667e238a7eeaf15ac013b6fb1e139569375baeb3dfad9e781c02b536","contract":["cmp.Ignore is an Option that causes all comparisons matching a filter to be ignored","Passing an unfiltered cmp.Ignore directly to cmp.Equal panics with cannot use an unfiltered option: Ignore()","cmp.FilterPath with cmp.Ignore ignores struct fields by name leaving non-ignored fields evaluated","cmp.FilterPath with cmp.Ignore bypasses reflection panics on unexported struct fields without AllowUnexported","cmp.FilterPath with cmp.Ignore ignores any node in the comparison path matching a specified reflect.Type","cmp.FilterValues with cmp.Ignore conditionally ignores comparisons when a symmetric value predicate returns true","cmp.FilterPath with cmp.Ignore ignores specific map keys or slice indices during container comparison"],"goal":"verify github.com/google/go-cmp/cmp.Ignore in pkg:golang/github.com/google/go-cmp@v0.6.0","kind":"HOW","packages":["pkg:golang/github.com/google/go-cmp@v0.6.0"],"schemaVersion":1,"symbols":["github.com/google/go-cmp/cmp.Ignore"]},"contractCommand":["go","test","./..."],"environment":{"arch":"x64","distro":"ubuntu","ecosystem":"golang","libc":"glibc","libcVersion":"2.39","os":"linux","osVersionBucket":"24","packageManager":"go","schemaVersion":1},"license":"MIT-0","packages":["pkg:golang/github.com/google/go-cmp@v0.6.0"],"schemaVersion":1,"subject":"pkg:golang/github.com/google/go-cmp@v0.6.0","symbols":["github.com/google/go-cmp/cmp.Ignore"],"verifierAdapter":"golang@1"}
go.mod
module example.com/ignorecmp

go 1.24

require github.com/google/go-cmp v0.6.0
go.sum
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
ignore.go
package ignorecmp

import (
	"reflect"
	"unicode"

	"github.com/google/go-cmp/cmp"
)

// IgnoreFieldByName returns an Option that ignores struct fields matching the specified field name.
func IgnoreFieldByName(name string) cmp.Option {
	return cmp.FilterPath(func(p cmp.Path) bool {
		sf, ok := p.Last().(cmp.StructField)
		return ok && sf.Name() == name
	}, cmp.Ignore())
}

// IgnoreUnexportedFields returns an Option that ignores all unexported struct fields,
// preventing reflection panics when comparing structs that contain private fields.
func IgnoreUnexportedFields() cmp.Option {
	return cmp.FilterPath(func(p cmp.Path) bool {
		sf, ok := p.Last().(cmp.StructField)
		if !ok {
			return false
		}
		name := sf.Name()
		return len(name) > 0 && !unicode.IsUpper(rune(name[0]))
	}, cmp.Ignore())
}

// IgnoreType returns an Option that ignores any node in the comparison path matching targetType.
func IgnoreType(targetType reflect.Type) cmp.Option {
	return cmp.FilterPath(func(p cmp.Path) bool {
		return p.Last().Type() == targetType
	}, cmp.Ignore())
}

// IgnoreMapKey returns an Option that ignores map entries with the specified key value.
func IgnoreMapKey[K comparable](ignoredKey K) cmp.Option {
	return cmp.FilterPath(func(p cmp.Path) bool {
		mi, ok := p.Last().(cmp.MapIndex)
		if !ok {
			return false
		}
		keyVal := mi.Key()
		if !keyVal.IsValid() || !keyVal.CanInterface() {
			return false
		}
		if k, ok := keyVal.Interface().(K); ok {
			return k == ignoredKey
		}
		return false
	}, cmp.Ignore())
}

// IgnoreSliceIndex returns an Option that ignores slice elements at the specified zero-based index.
func IgnoreSliceIndex(ignoredIndex int) cmp.Option {
	return cmp.FilterPath(func(p cmp.Path) bool {
		si, ok := p.Last().(cmp.SliceIndex)
		return ok && (si.Key() == ignoredIndex)
	}, cmp.Ignore())
}

// IgnoreMatchingValues returns an Option using FilterValues that ignores comparison
// when the symmetric predicate func(T, T) bool returns true.
func IgnoreMatchingValues[T any](predicate func(x, y T) bool) cmp.Option {
	return cmp.FilterValues(predicate, cmp.Ignore())
}
ignore_test.go
package ignorecmp

import (
	"fmt"
	"reflect"
	"strings"
	"testing"
	"time"

	"github.com/google/go-cmp/cmp"
)

type Account struct {
	ID        int
	Username  string
	UpdatedAt time.Time
}

type TokenSession struct {
	SessionID string
	token     string // single unexported field
}

type MultiSecretSession struct {
	SessionID string
	token     string // unexported field
	secretKey []byte // unexported field
}

func TestUnfilteredIgnorePanics(t *testing.T) {
	defer func() {
		r := recover()
		if r == nil {
			t.Fatal("expected unfiltered cmp.Ignore() to panic when passed to cmp.Equal")
		}
		errMsg := fmt.Sprint(r)
		if !strings.Contains(errMsg, "cannot use an unfiltered option: Ignore()") {
			t.Fatalf("unexpected panic message: %s", errMsg)
		}
	}()

	_ = cmp.Equal(10, 20, cmp.Ignore())
}

func TestIgnoreFieldByName(t *testing.T) {
	acc1 := Account{
		ID:        1001,
		Username:  "alice",
		UpdatedAt: time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC),
	}
	acc2 := Account{
		ID:        1001,
		Username:  "alice",
		UpdatedAt: time.Date(2026, 9, 15, 12, 0, 0, 0, time.UTC), // different timestamp
	}

	optIgnoreTimestamp := IgnoreFieldByName("UpdatedAt")

	if !cmp.Equal(acc1, acc2, optIgnoreTimestamp) {
		t.Fatalf("expected accounts to be equal when UpdatedAt is ignored, diff: %s", cmp.Diff(acc1, acc2, optIgnoreTimestamp))
	}

	diff := cmp.Diff(acc1, acc2, optIgnoreTimestamp)
	if diff != "" {
		t.Fatalf("expected empty diff when ignored field differs, got: %s", diff)
	}

	// Changing a non-ignored field causes inequality
	acc2.Username = "bob"
	if cmp.Equal(acc1, acc2, optIgnoreTimestamp) {
		t.Fatal("expected accounts to differ when non-ignored field differs")
	}
	diffWithBob := cmp.Diff(acc1, acc2, optIgnoreTimestamp)
	if !strings.Contains(diffWithBob, "Username") {
		t.Fatalf("expected diff to show Username mismatch, got: %s", diffWithBob)
	}
	if strings.Contains(diffWithBob, "UpdatedAt") {
		t.Fatalf("expected diff not to report UpdatedAt difference when ignored, got: %s", diffWithBob)
	}
}

func TestIgnoreUnexportedFields(t *testing.T) {
	t.Run("DirectComparisonPanicsOnUnexportedField", func(t *testing.T) {
		a := MultiSecretSession{SessionID: "sess-1", token: "tok-aaa", secretKey: []byte{1, 2}}
		b := MultiSecretSession{SessionID: "sess-1", token: "tok-bbb", secretKey: []byte{3, 4}}

		defer func() {
			r := recover()
			if r == nil {
				t.Fatal("expected unexported field comparison to panic without options")
			}
			msg := fmt.Sprint(r)
			if !strings.Contains(msg, "cannot handle unexported field") {
				t.Fatalf("unexpected panic message: %s", msg)
			}
		}()

		_ = cmp.Equal(a, b)
	})

	t.Run("IgnoreUnexportedFieldsBypassesPanicAndIgnoresAllPrivateFields", func(t *testing.T) {
		a := MultiSecretSession{SessionID: "sess-1", token: "tok-aaa", secretKey: []byte{1, 2}}
		b := MultiSecretSession{SessionID: "sess-1", token: "tok-bbb", secretKey: []byte{3, 4}}

		opt := IgnoreUnexportedFields()

		if !cmp.Equal(a, b, opt) {
			t.Fatalf("expected equality when unexported fields are ignored, diff: %s", cmp.Diff(a, b, opt))
		}

		diff := cmp.Diff(a, b, opt)
		if diff != "" {
			t.Fatalf("expected empty diff, got: %s", diff)
		}

		// When exported field differs, inequality is detected properly
		b.SessionID = "sess-2"
		if cmp.Equal(a, b, opt) {
			t.Fatal("expected inequality when exported SessionID differs")
		}
		diffSess := cmp.Diff(a, b, opt)
		if !strings.Contains(diffSess, "SessionID") {
			t.Fatalf("expected diff to report SessionID mismatch, got: %s", diffSess)
		}
	})

	t.Run("IgnoreSpecificUnexportedFieldByName", func(t *testing.T) {
		a := TokenSession{SessionID: "sess-1", token: "tok-aaa"}
		b := TokenSession{SessionID: "sess-1", token: "tok-bbb"}

		opt := IgnoreFieldByName("token")

		if !cmp.Equal(a, b, opt) {
			t.Fatalf("expected equality when token is ignored, diff: %s", cmp.Diff(a, b, opt))
		}

		diff := cmp.Diff(a, b, opt)
		if diff != "" {
			t.Fatalf("expected empty diff when only unexported field is ignored, got: %s", diff)
		}
	})

	t.Run("PartialIgnorePanicsOnRemainingUnexportedFields", func(t *testing.T) {
		a := MultiSecretSession{SessionID: "sess-1", token: "tok-aaa", secretKey: []byte{1}}
		b := MultiSecretSession{SessionID: "sess-1", token: "tok-bbb", secretKey: []byte{2}}

		// Ignoring only 'token' leaves 'secretKey' unhandled
		opt := IgnoreFieldByName("token")

		defer func() {
			r := recover()
			if r == nil {
				t.Fatal("expected panic on remaining unhandled unexported field secretKey")
			}
			msg := fmt.Sprint(r)
			if !strings.Contains(msg, "cannot handle unexported field at {ignorecmp.MultiSecretSession}.secretKey") {
				t.Fatalf("unexpected panic message: %s", msg)
			}
		}()

		_ = cmp.Equal(a, b, opt)
	})
}

func TestIgnoreType(t *testing.T) {
	t1 := time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC)
	t2 := time.Date(2026, 12, 31, 23, 59, 59, 0, time.UTC)

	optIgnoreTime := IgnoreType(reflect.TypeOf(time.Time{}))

	if !cmp.Equal(t1, t2, optIgnoreTime) {
		t.Fatalf("expected cmp.Equal to return true when time.Time is ignored")
	}

	acc1 := Account{ID: 5, Username: "user5", UpdatedAt: t1}
	acc2 := Account{ID: 5, Username: "user5", UpdatedAt: t2}

	if !cmp.Equal(acc1, acc2, optIgnoreTime) {
		t.Fatalf("expected struct with differing time.Time field to match when time.Time is ignored")
	}
}

func TestIgnoreMatchingValuesWithFilterValues(t *testing.T) {
	// Ignore comparisons between strings if either string is the wildcard "*"
	ignoreWildcard := IgnoreMatchingValues(func(x, y string) bool {
		return x == "*" || y == "*"
	})

	type Config struct {
		Host string
		Port string
	}

	c1 := Config{Host: "localhost", Port: "8080"}
	c2 := Config{Host: "*", Port: "8080"}

	if !cmp.Equal(c1, c2, ignoreWildcard) {
		t.Fatalf("expected Configs to match when Host has wildcard, diff: %s", cmp.Diff(c1, c2, ignoreWildcard))
	}

	c3 := Config{Host: "*", Port: "9090"}
	if cmp.Equal(c1, c3, ignoreWildcard) {
		t.Fatalf("expected Port mismatch to cause inequality")
	}
}

func TestIgnoreMapKeyAndSliceIndex(t *testing.T) {
	t.Run("IgnoreMapKey", func(t *testing.T) {
		m1 := map[string]int{"status": 200, "cache_ttl": 60, "cluster": 1}
		m2 := map[string]int{"status": 200, "cache_ttl": 9999, "cluster": 1}

		opt := IgnoreMapKey("cache_ttl")

		if !cmp.Equal(m1, m2, opt) {
			t.Fatalf("expected maps to be equal when cache_ttl key is ignored, diff: %s", cmp.Diff(m1, m2, opt))
		}

		m3 := map[string]int{"status": 500, "cache_ttl": 9999, "cluster": 1}
		if cmp.Equal(m1, m3, opt) {
			t.Fatal("expected status mismatch to be detected")
		}
	})

	t.Run("IgnoreSliceIndex", func(t *testing.T) {
		s1 := []string{"commit-hash-abc", "active", "zone-us-east"}
		s2 := []string{"commit-hash-xyz", "active", "zone-us-east"}

		opt := IgnoreSliceIndex(0)

		if !cmp.Equal(s1, s2, opt) {
			t.Fatalf("expected slices to be equal when index 0 is ignored, diff: %s", cmp.Diff(s1, s2, opt))
		}

		s3 := []string{"commit-hash-xyz", "inactive", "zone-us-east"}
		if cmp.Equal(s1, s3, opt) {
			t.Fatal("expected index 1 mismatch to be detected")
		}
	})
}
spec.json
{
  "schemaVersion": 1,
  "goal": "verify github.com/google/go-cmp/cmp.Ignore in pkg:golang/github.com/google/go-cmp@v0.6.0",
  "kind": "HOW",
  "packages": [
    "pkg:golang/github.com/google/go-cmp@v0.6.0"
  ],
  "symbols": [
    "github.com/google/go-cmp/cmp.Ignore"
  ]
}

Seeder d'origine

anonyme