diff --git a/receiver/filelogreceiver/filelog_test.go b/receiver/filelogreceiver/filelog_test.go index d19f1b36c73f6..12f7a40fbe8ad 100644 --- a/receiver/filelogreceiver/filelog_test.go +++ b/receiver/filelogreceiver/filelog_test.go @@ -11,6 +11,7 @@ import ( "path/filepath" "runtime" "sync" + "sync/atomic" "testing" "time" @@ -31,6 +32,7 @@ import ( "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator" "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/helper" "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/input/file" + "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/parser/json" "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza/operator/parser/regex" ) @@ -313,3 +315,69 @@ func rotationTestConfig(tempDir string) *FileLogConfig { }(), } } + +func TestConsumeContract(t *testing.T) { + + // Number of log records to send per scenario. + const logsPerTest = 100 + + tmpDir := t.TempDir() + filePattern := "test-*.log" + flg := &fileLogGenerator{t: t, tmpDir: tmpDir, filePattern: filePattern} + + cfg := createDefaultConfig() + cfg.RetryOnFailure.Enabled = true + cfg.RetryOnFailure.InitialInterval = 1 * time.Millisecond + cfg.RetryOnFailure.MaxInterval = 10 * time.Millisecond + cfg.InputConfig.Include = []string{filepath.Join(tmpDir, filePattern)} + cfg.InputConfig.StartAt = "beginning" + jsonParser := json.NewConfig() + tsField := entry.NewAttributeField("ts") + jsonParser.TimeParser = &helper.TimeParser{ + ParseFrom: &tsField, + Layout: time.RFC3339, + LayoutType: "gotime", + } + jsonParser.ParseTo = entry.RootableField{Field: entry.NewAttributeField()} + logField := entry.NewAttributeField("log") + jsonParser.BodyField = &logField + cfg.Operators = []operator.Config{{Builder: jsonParser}} + + // Run the contract checker. This will trigger test failures if any problems are found. + receivertest.CheckConsumeContract(receivertest.CheckConsumeContractParams{ + T: t, + Factory: NewFactory(), + DataType: component.DataTypeLogs, + Config: cfg, + Generator: flg, + GenerateCount: logsPerTest, + }) +} + +// A generator that can send data to exampleReceiver. +type fileLogGenerator struct { + t *testing.T + tmpDir string + filePattern string + tmpFile *os.File + sequenceNum int64 +} + +func (g *fileLogGenerator) Start() { + tmpFile, err := os.CreateTemp(g.tmpDir, g.filePattern) + require.NoError(g.t, err) + g.tmpFile = tmpFile +} + +func (g *fileLogGenerator) Shutdown() { + g.tmpFile.Close() + os.Remove(g.tmpFile.Name()) +} + +func (g *fileLogGenerator) Generate() []receivertest.UniqueIDAttrVal { + id := fmt.Sprintf("%d", atomic.AddInt64(&g.sequenceNum, 1)) + logLine := fmt.Sprintf(`{"ts": "%s", "log": "log-%s", "%s": "%s"}`, time.Now().Format(time.RFC3339), id, + receivertest.UniqueIDAttrName, id) + g.tmpFile.WriteString(logLine + "\n") + return []receivertest.UniqueIDAttrVal{id} +}