From ae0ea319178ee792896503ae44e7b2b25de053f7 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Fri, 19 Jan 2024 11:49:05 +0000 Subject: [PATCH 1/2] Fix `Non-serializable data ('System.Object[]') found` in tests --- .../InstrumentationDefinitionsTests.cs | 23 +++-- .../Logging/ExceptionRedactorTests.cs | 92 ++++++++++--------- .../OpenTelemetryOperationNameMapperTests.cs | 56 +++++------ 3 files changed, 92 insertions(+), 79 deletions(-) diff --git a/tracer/test/Datadog.Trace.Tests/CallTarget/InstrumentationDefinitionsTests.cs b/tracer/test/Datadog.Trace.Tests/CallTarget/InstrumentationDefinitionsTests.cs index 91a6d0bef9af..028aeb42d367 100644 --- a/tracer/test/Datadog.Trace.Tests/CallTarget/InstrumentationDefinitionsTests.cs +++ b/tracer/test/Datadog.Trace.Tests/CallTarget/InstrumentationDefinitionsTests.cs @@ -55,17 +55,24 @@ public void CanGetIntegrationIdFromInstrumentAttributeWithMultipleTypeNames() info.Value.Should().Be(IntegrationId.MongoDb); } - [Theory] - [InlineData(typeof(System.Data.SqlClient.SqlCommand), (int)IntegrationId.SqlClient)] - [InlineData(typeof(System.Data.SQLite.SQLiteCommand), (int)IntegrationId.Sqlite)] - public void CanGetIntegrationIdForAdoNetAttribute(Type targetType, int expected) + [Fact] + public void CanGetIntegrationIdForAdoNetAttribute() { - var integrationType = typeof(CommandExecuteNonQueryIntegration).FullName; + var types = new[] + { + (typeof(System.Data.SqlClient.SqlCommand), (int)IntegrationId.SqlClient), + (typeof(System.Data.SQLite.SQLiteCommand), (int)IntegrationId.Sqlite), + }; - var info = InstrumentationDefinitions.GetIntegrationId(integrationType, targetType); + foreach (var (targetType, expected) in types) + { + var integrationType = typeof(CommandExecuteNonQueryIntegration).FullName; - info.Should().NotBeNull(); - info.Value.Should().Be((IntegrationId)expected); + var info = InstrumentationDefinitions.GetIntegrationId(integrationType, targetType); + + info.Should().NotBeNull(); + info.Value.Should().Be((IntegrationId)expected); + } } [Fact] diff --git a/tracer/test/Datadog.Trace.Tests/Logging/ExceptionRedactorTests.cs b/tracer/test/Datadog.Trace.Tests/Logging/ExceptionRedactorTests.cs index 5ff2b4ecf899..01f8c6ab0896 100644 --- a/tracer/test/Datadog.Trace.Tests/Logging/ExceptionRedactorTests.cs +++ b/tracer/test/Datadog.Trace.Tests/Logging/ExceptionRedactorTests.cs @@ -56,54 +56,60 @@ public void RedactStackTrace_IsEmptyForEmptyException() redacted.Should().BeEmpty(); } - [Theory] - [MemberData(nameof(TestData.MethodsToRedact), MemberType = typeof(TestData))] - public void RedactStackTrace_RedactsUserCode(object method) + [Fact] + public void RedactStackTrace_RedactsUserCode() { - var methodBase = method.Should().NotBeNull().And.BeAssignableTo().Subject; - var stackFrame = new TestStackFrame(methodBase); - var stackTrace = new StackTrace(stackFrame); + foreach (var method in TestData.MethodsToRedact()) + { + var methodBase = method.Should().NotBeNull().And.BeAssignableTo().Subject; + var stackFrame = new TestStackFrame(methodBase); + var stackTrace = new StackTrace(stackFrame); - var sb = new StringBuilder(); - ExceptionRedactor.RedactStackTrace(sb, stackTrace); - var redacted = sb.ToString(); + var sb = new StringBuilder(); + ExceptionRedactor.RedactStackTrace(sb, stackTrace); + var redacted = sb.ToString(); - redacted.Should().Be($"{ExceptionRedactor.StackFrameAt}{ExceptionRedactor.Redacted}" + Environment.NewLine); + redacted.Should().Be($"{ExceptionRedactor.StackFrameAt}{ExceptionRedactor.Redacted}" + Environment.NewLine); + } } - [Theory] - [MemberData(nameof(TestData.MethodsToNotRedact), MemberType = typeof(TestData))] - public void RedactStackTrace_DoesNotRedactBclAndDatadog(object method) + [Fact] + public void RedactStackTrace_DoesNotRedactBclAndDatadog() { - var methodBase = method.Should().NotBeNull().And.BeAssignableTo().Subject; - var stackFrame = new TestStackFrame(methodBase); - var stackTrace = new StackTrace(stackFrame); + foreach (var method in TestData.MethodsToNotRedact()) + { + var methodBase = method.Should().NotBeNull().And.BeAssignableTo().Subject; + var stackFrame = new TestStackFrame(methodBase); + var stackTrace = new StackTrace(stackFrame); - var sb = new StringBuilder(); - ExceptionRedactor.RedactStackTrace(sb, stackTrace); - var redacted = sb.ToString(); + var sb = new StringBuilder(); + ExceptionRedactor.RedactStackTrace(sb, stackTrace); + var redacted = sb.ToString(); - redacted.Should().Be(stackTrace.ToString()); + redacted.Should().Be(stackTrace.ToString()); + } } - [Theory] - [MemberData(nameof(TestData.ToStringTestData), MemberType = typeof(TestData))] - public void RedactStackTrace_ContainsExpectedStrings(StackTrace stackTrace, string expectedToString) + [Fact] + public void RedactStackTrace_ContainsExpectedStrings() { - var sb = new StringBuilder(); - ExceptionRedactor.RedactStackTrace(sb, stackTrace); - var redacted = sb.ToString(); - - if (expectedToString.Length == 0) + foreach (var (stackTrace, expectedToString) in TestData.ToStringTestData()) { - redacted.Should().BeEmpty(); - return; - } + var sb = new StringBuilder(); + ExceptionRedactor.RedactStackTrace(sb, stackTrace); + var redacted = sb.ToString(); - redacted.Should().Contain(expectedToString); - redacted.Should().EndWith(Environment.NewLine); + if (expectedToString.Length == 0) + { + redacted.Should().BeEmpty(); + return; + } - HasExpectedFrames(stackTrace, redacted); + redacted.Should().Contain(expectedToString); + redacted.Should().EndWith(Environment.NewLine); + + HasExpectedFrames(stackTrace, redacted); + } } [Fact] @@ -200,16 +206,16 @@ public static class TestData #endif }; - public static IEnumerable ToStringTestData() + public static IEnumerable<(StackTrace StackTrace, string ExpectedToString)> ToStringTestData() { - yield return new object[] { new StackTrace(InvokeException()), "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.ThrowException()" }; - yield return new object[] { new StackTrace(new Exception()), string.Empty }; - yield return new object[] { NoParameters(), "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.TestData.NoParameters()" }; - yield return new object[] { OneParameter(1), "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.TestData.OneParameter(Int32 x)" }; - yield return new object[] { TwoParameters(1, null), "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.TestData.TwoParameters(Int32 x, String y)" }; - yield return new object[] { Generic(), "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.TestData.Generic[T]()" }; - yield return new object[] { Generic(), "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.TestData.Generic[T1,T2]()" }; - yield return new object[] { new ClassWithConstructor().StackTrace, "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.TestData.ClassWithConstructor..ctor()" }; + yield return (new StackTrace(InvokeException()), "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.ThrowException()"); + yield return (new StackTrace(new Exception()), string.Empty); + yield return (NoParameters(), "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.TestData.NoParameters()"); + yield return (OneParameter(1), "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.TestData.OneParameter(Int32 x)"); + yield return (TwoParameters(1, null), "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.TestData.TwoParameters(Int32 x, String y)"); + yield return (Generic(), "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.TestData.Generic[T]()"); + yield return (Generic(), "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.TestData.Generic[T1,T2]()"); + yield return (new ClassWithConstructor().StackTrace, "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.TestData.ClassWithConstructor..ctor()"); } [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] diff --git a/tracer/test/Datadog.Trace.Tests/OpenTelemetryOperationNameMapperTests.cs b/tracer/test/Datadog.Trace.Tests/OpenTelemetryOperationNameMapperTests.cs index 6ba50e1eab07..2a489b1562e9 100644 --- a/tracer/test/Datadog.Trace.Tests/OpenTelemetryOperationNameMapperTests.cs +++ b/tracer/test/Datadog.Trace.Tests/OpenTelemetryOperationNameMapperTests.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using Datadog.Trace.Activity; using Datadog.Trace.Tagging; +using Datadog.Trace.TestHelpers; using Xunit; namespace Datadog.Trace.Tests @@ -15,37 +16,36 @@ namespace Datadog.Trace.Tests public class OpenTelemetryOperationNameMapperTests { // Note: These test cases were copy/pasted from parametric tests (with some find/replace to make it work here) - public static IEnumerable NameData => - new List - { - // expected_operation_name, span_kind, tags_related_to_operation_name - new object[] { "http.server.request", SpanKinds.Server, new Dictionary() { { "http.request.method", "GET" } } }, - new object[] { "http.client.request", SpanKinds.Client, new Dictionary() { { "http.request.method", "GET" } } }, - new object[] { "redis.query", SpanKinds.Client, new Dictionary() { { "db.system", "Redis" } } }, - new object[] { "kafka.receive", SpanKinds.Client, new Dictionary() { { "messaging.system", "Kafka" }, { "messaging.operation", "Receive" } } }, - new object[] { "kafka.receive", SpanKinds.Server, new Dictionary() { { "messaging.system", "Kafka" }, { "messaging.operation", "Receive" } } }, - new object[] { "kafka.receive", SpanKinds.Producer, new Dictionary() { { "messaging.system", "Kafka" }, { "messaging.operation", "Receive" } } }, - new object[] { "kafka.receive", SpanKinds.Consumer, new Dictionary() { { "messaging.system", "Kafka" }, { "messaging.operation", "Receive" } } }, - new object[] { "aws.s3.request", SpanKinds.Client, new Dictionary() { { "rpc.system", "aws-api" }, { "rpc.service", "S3" } } }, - new object[] { "aws.client.request", SpanKinds.Client, new Dictionary() { { "rpc.system", "aws-api" } } }, - new object[] { "grpc.client.request", SpanKinds.Client, new Dictionary() { { "rpc.system", "GRPC" } } }, - new object[] { "grpc.server.request", SpanKinds.Server, new Dictionary() { { "rpc.system", "GRPC" } } }, - new object[] { "aws.my-function.invoke", SpanKinds.Client, new Dictionary() { { "faas.invoked_provider", "aws" }, { "faas.invoked_name", "My-Function" } } }, - new object[] { "datasource.invoke", SpanKinds.Server, new Dictionary() { { "faas.trigger", "Datasource" } } }, - new object[] { "graphql.server.request", SpanKinds.Server, new Dictionary() { { "graphql.operation.type", "query" } } }, - new object[] { "amqp.server.request", SpanKinds.Server, new Dictionary() { { "network.protocol.name", "Amqp" } } }, - new object[] { "server.request", SpanKinds.Server, new Dictionary() }, - new object[] { "amqp.client.request", SpanKinds.Client, new Dictionary() { { "network.protocol.name", "Amqp" } } }, - new object[] { "client.request", SpanKinds.Client, new Dictionary() }, - new object[] { "internal", SpanKinds.Internal, new Dictionary() }, - new object[] { "consumer", SpanKinds.Consumer, new Dictionary() }, - new object[] { "producer", SpanKinds.Producer, new Dictionary() }, - new object[] { "internal", null, new Dictionary() }, - }; + public static TheoryData NameData => new() + { + // expected_operation_name, span_kind, tags_related_to_operation_name + { "http.server.request", SpanKinds.Server, new SerializableDictionary { { "http.request.method", "GET" } } }, + { "http.client.request", SpanKinds.Client, new SerializableDictionary { { "http.request.method", "GET" } } }, + { "redis.query", SpanKinds.Client, new SerializableDictionary { { "db.system", "Redis" } } }, + { "kafka.receive", SpanKinds.Client, new SerializableDictionary { { "messaging.system", "Kafka" }, { "messaging.operation", "Receive" } } }, + { "kafka.receive", SpanKinds.Server, new SerializableDictionary { { "messaging.system", "Kafka" }, { "messaging.operation", "Receive" } } }, + { "kafka.receive", SpanKinds.Producer, new SerializableDictionary { { "messaging.system", "Kafka" }, { "messaging.operation", "Receive" } } }, + { "kafka.receive", SpanKinds.Consumer, new SerializableDictionary { { "messaging.system", "Kafka" }, { "messaging.operation", "Receive" } } }, + { "aws.s3.request", SpanKinds.Client, new SerializableDictionary { { "rpc.system", "aws-api" }, { "rpc.service", "S3" } } }, + { "aws.client.request", SpanKinds.Client, new SerializableDictionary { { "rpc.system", "aws-api" } } }, + { "grpc.client.request", SpanKinds.Client, new SerializableDictionary { { "rpc.system", "GRPC" } } }, + { "grpc.server.request", SpanKinds.Server, new SerializableDictionary { { "rpc.system", "GRPC" } } }, + { "aws.my-function.invoke", SpanKinds.Client, new SerializableDictionary { { "faas.invoked_provider", "aws" }, { "faas.invoked_name", "My-Function" } } }, + { "datasource.invoke", SpanKinds.Server, new SerializableDictionary { { "faas.trigger", "Datasource" } } }, + { "graphql.server.request", SpanKinds.Server, new SerializableDictionary { { "graphql.operation.type", "query" } } }, + { "amqp.server.request", SpanKinds.Server, new SerializableDictionary { { "network.protocol.name", "Amqp" } } }, + { "server.request", SpanKinds.Server, new SerializableDictionary() }, + { "amqp.client.request", SpanKinds.Client, new SerializableDictionary() { { "network.protocol.name", "Amqp" } } }, + { "client.request", SpanKinds.Client, new SerializableDictionary() }, + { "internal", SpanKinds.Internal, new SerializableDictionary() }, + { "consumer", SpanKinds.Consumer, new SerializableDictionary() }, + { "producer", SpanKinds.Producer, new SerializableDictionary() }, + { "internal", null, new SerializableDictionary() }, + }; [Theory] [MemberData(nameof(NameData))] - public void OperationName_ShouldBeSet_BasedOnTags(string expectedOperationName, string expectedActivityKind, Dictionary tags) + public void OperationName_ShouldBeSet_BasedOnTags(string expectedOperationName, string expectedActivityKind, SerializableDictionary tags) { var span = new Span(new SpanContext(1, 1), DateTimeOffset.UtcNow, new OpenTelemetryTags()); From 36aa7d27bf9b46bc560d4b239070c1ece4fc88d0 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Mon, 22 Jan 2024 09:48:46 +0000 Subject: [PATCH 2/2] Fix incorrect casts --- .../Logging/ExceptionRedactorTests.cs | 36 +++++++++---------- .../OpenTelemetryOperationNameMapperTests.cs | 4 +-- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/tracer/test/Datadog.Trace.Tests/Logging/ExceptionRedactorTests.cs b/tracer/test/Datadog.Trace.Tests/Logging/ExceptionRedactorTests.cs index 01f8c6ab0896..8edabd251499 100644 --- a/tracer/test/Datadog.Trace.Tests/Logging/ExceptionRedactorTests.cs +++ b/tracer/test/Datadog.Trace.Tests/Logging/ExceptionRedactorTests.cs @@ -171,18 +171,18 @@ private static Exception InvokeException() public static class TestData { - public static TheoryData MethodsToRedact() => new() - { + public static List MethodsToRedact() => + [ typeof(AssertionExtensions).GetMethod(nameof(AssertionExtensions.Should), types: new[] { typeof(object) }), typeof(Xunit.Assert).GetMethod(nameof(Assert.False), types: new[] { typeof(bool) }), typeof(VerifyTests.VerifierSettings).GetMethod(nameof(VerifyTests.VerifierSettings.DisableClipboard)), typeof(VerifyTests.VerifierSettings).GetProperty(nameof(VerifyTests.VerifierSettings.StrictJson))?.GetMethod, typeof(VerifyTests.VerifierSettings).GetProperty(nameof(VerifyTests.VerifierSettings.StrictJson))?.SetMethod, typeof(VerifyTests.SerializationSettings).GetConstructor(Array.Empty()), - }; + ]; - public static TheoryData MethodsToNotRedact() => new() - { + public static List MethodsToNotRedact() => + [ typeof(ExceptionRedactorTests.TestData).GetMethod(nameof(NoParameters)), typeof(Datadog.Trace.Tracer).GetMethod(nameof(Tracer.UnsafeSetTracerInstance), BindingFlags.Static | BindingFlags.NonPublic), typeof(Datadog.Trace.Tracer).GetProperty(nameof(Tracer.Instance))?.GetMethod, @@ -204,19 +204,19 @@ public static class TestData typeof(Microsoft.CodeAnalysis.DiagnosticDescriptor).GetProperty(nameof(Microsoft.CodeAnalysis.DiagnosticDescriptor.Id))?.GetMethod, typeof(Microsoft.Extensions.DependencyInjection.ServiceCollection).GetMethod(nameof(Microsoft.Extensions.DependencyInjection.ServiceCollection.Contains), types: new[] { typeof(Microsoft.Extensions.DependencyInjection.ServiceDescriptor) }), #endif - }; - - public static IEnumerable<(StackTrace StackTrace, string ExpectedToString)> ToStringTestData() - { - yield return (new StackTrace(InvokeException()), "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.ThrowException()"); - yield return (new StackTrace(new Exception()), string.Empty); - yield return (NoParameters(), "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.TestData.NoParameters()"); - yield return (OneParameter(1), "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.TestData.OneParameter(Int32 x)"); - yield return (TwoParameters(1, null), "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.TestData.TwoParameters(Int32 x, String y)"); - yield return (Generic(), "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.TestData.Generic[T]()"); - yield return (Generic(), "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.TestData.Generic[T1,T2]()"); - yield return (new ClassWithConstructor().StackTrace, "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.TestData.ClassWithConstructor..ctor()"); - } + ]; + + public static List<(StackTrace StackTrace, string ExpectedToString)> ToStringTestData() => + [ + (new StackTrace(InvokeException()), "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.ThrowException()"), + (new StackTrace(new Exception()), string.Empty), + (NoParameters(), "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.TestData.NoParameters()"), + (OneParameter(1), "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.TestData.OneParameter(Int32 x)"), + (TwoParameters(1, null), "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.TestData.TwoParameters(Int32 x, String y)"), + (Generic(), "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.TestData.Generic[T]()"), + (Generic(), "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.TestData.Generic[T1,T2]()"), + (new ClassWithConstructor().StackTrace, "Datadog.Trace.Tests.Logging.ExceptionRedactorTests.TestData.ClassWithConstructor..ctor()"), + ]; [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] public static unsafe StackTrace FunctionPointerParameter(delegate* x) => new(); diff --git a/tracer/test/Datadog.Trace.Tests/OpenTelemetryOperationNameMapperTests.cs b/tracer/test/Datadog.Trace.Tests/OpenTelemetryOperationNameMapperTests.cs index 2a489b1562e9..1b5c3e4e7e38 100644 --- a/tracer/test/Datadog.Trace.Tests/OpenTelemetryOperationNameMapperTests.cs +++ b/tracer/test/Datadog.Trace.Tests/OpenTelemetryOperationNameMapperTests.cs @@ -140,14 +140,14 @@ public OperationNameData(object[] data) ExpectedActivityKind = data[1]?.ToString() ?? string.Empty; - Tags = data[2] is null ? new Dictionary() : (Dictionary)data[2]; + Tags = data[2] is null ? new SerializableDictionary() : (SerializableDictionary)data[2]; } public string ExpectedOperationName { get; } public string ExpectedActivityKind { get; } - public Dictionary Tags { get; } + public SerializableDictionary Tags { get; } } } }