//go:build enable_antithesis_sdk package assert import ( "runtime" "sync" "sync/atomic" "github.com/antithesishq/antithesis-sdk-go/internal" ) type trackerInfo struct { Filename string Classname string PassCount int FailCount int } type emitTracker map[string]*trackerInfo // assert_tracker (global) keeps track of the unique asserts evaluated var ( assertTracker emitTracker = make(emitTracker) trackerMutex sync.Mutex trackerInfoMutex sync.Mutex ) func (tracker emitTracker) getTrackerEntry(messageKey string, filename, classname string) *trackerInfo { var trackerEntry *trackerInfo var ok bool if tracker == nil { return nil } trackerMutex.Lock() defer trackerMutex.Unlock() if trackerEntry, ok = tracker[messageKey]; !ok { trackerEntry = newTrackerInfo(filename, classname) tracker[messageKey] = trackerEntry } return trackerEntry } func newTrackerInfo(filename, classname string) *trackerInfo { trackerInfo := trackerInfo{ PassCount: 0, FailCount: 0, Filename: filename, Classname: classname, } return &trackerInfo } func (ti *trackerInfo) emit(ai *assertInfo) { if ti == nil || ai == nil { return } // Registrations are just sent to voidstar hit := ai.Hit if !hit { emitAssert(ai) return } var err error cond := ai.Condition trackerInfoMutex.Lock() defer trackerInfoMutex.Unlock() if cond { if ti.PassCount == 0 { err = emitAssert(ai) } if err == nil { ti.PassCount++ } return } if ti.FailCount == 0 { err = emitAssert(ai) } if err == nil { ti.FailCount++ } } func versionMessage() { languageBlock := map[string]any{ "name": "Go", "version": runtime.Version(), } versionBlock := map[string]any{ "language": languageBlock, "sdk_version": internal.SDK_Version, "protocol_version": internal.Protocol_Version, } internal.Json_data(map[string]any{"antithesis_sdk": versionBlock}) } // package-level flag var hasEmitted atomic.Bool // initialzed to false func emitAssert(ai *assertInfo) error { if hasEmitted.CompareAndSwap(false, true) { versionMessage() } return internal.Json_data(wrappedAssertInfo{ai}) }