Skip to content

Commit 01ee21f

Browse files
committed
add unit tests
1 parent 468c84c commit 01ee21f

File tree

3 files changed

+361
-0
lines changed

3 files changed

+361
-0
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// <copyright file="MockEnvironmentVariableProvider.cs" company="Datadog">
2+
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License.
3+
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
4+
// </copyright>
5+
6+
#nullable enable
7+
8+
using System.Collections.Generic;
9+
using Datadog.Trace.ClrProfiler.Managed.Loader;
10+
11+
namespace Datadog.Trace.Tests.ClrProfiler.ManagedLoader;
12+
13+
/// <summary>
14+
/// Mock implementation of <see cref="IEnvironmentVariableProvider"/> for testing purposes.
15+
/// Allows setting and getting environment variables in memory without affecting the real environment.
16+
/// </summary>
17+
internal class MockEnvironmentVariableProvider : IEnvironmentVariableProvider
18+
{
19+
private readonly Dictionary<string, string?> _environmentVariables = new();
20+
21+
/// <summary>
22+
/// Sets an environment variable in the mock provider.
23+
/// </summary>
24+
/// <param name="key">The name of the environment variable.</param>
25+
/// <param name="value">The value of the environment variable, or null to remove it.</param>
26+
public void SetEnvironmentVariable(string key, string? value)
27+
{
28+
if (value == null)
29+
{
30+
_environmentVariables.Remove(key);
31+
}
32+
else
33+
{
34+
_environmentVariables[key] = value;
35+
}
36+
}
37+
38+
/// <inheritdoc />
39+
public string? GetEnvironmentVariable(string key)
40+
{
41+
return _environmentVariables.TryGetValue(key, out var value) ? value : null;
42+
}
43+
44+
/// <summary>
45+
/// Clears all environment variables from the mock provider.
46+
/// </summary>
47+
public void Clear()
48+
{
49+
_environmentVariables.Clear();
50+
}
51+
}
Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
1+
// <copyright file="StartupTests.cs" company="Datadog">
2+
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License.
3+
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
4+
// </copyright>
5+
6+
using System.IO;
7+
using Datadog.Trace.ClrProfiler.Managed.Loader;
8+
using FluentAssertions;
9+
using Xunit;
10+
11+
namespace Datadog.Trace.Tests.ClrProfiler.ManagedLoader;
12+
13+
public class StartupTests
14+
{
15+
[Fact]
16+
public void GetTracerHomePath_WhenDdDotnetTracerHomeIsSet_ReturnsTracerHomeValue()
17+
{
18+
// Arrange
19+
const string tracerHomePath = @"C:\Program Files\Datadog\.NET Tracer";
20+
var mockProvider = new MockEnvironmentVariableProvider();
21+
mockProvider.SetEnvironmentVariable("DD_DOTNET_TRACER_HOME", tracerHomePath);
22+
23+
// Act
24+
var result = Startup.GetTracerHomePath(mockProvider);
25+
26+
// Assert
27+
result.Should().Be(tracerHomePath);
28+
}
29+
30+
[Fact]
31+
public void GetTracerHomePath_WhenDdDotnetTracerHomeHasWhitespace_ReturnsTrimmedValue()
32+
{
33+
// Arrange
34+
const string tracerHomePath = @"C:\Program Files\Datadog\.NET Tracer";
35+
var mockProvider = new MockEnvironmentVariableProvider();
36+
mockProvider.SetEnvironmentVariable("DD_DOTNET_TRACER_HOME", $" {tracerHomePath} ");
37+
38+
// Act
39+
var result = Startup.GetTracerHomePath(mockProvider);
40+
41+
// Assert
42+
result.Should().Be(tracerHomePath);
43+
}
44+
45+
[Fact]
46+
public void GetTracerHomePath_WhenDdDotnetTracerHomeIsEmpty_FallsBackToProfilerPath()
47+
{
48+
// Arrange
49+
var mockProvider = new MockEnvironmentVariableProvider();
50+
mockProvider.SetEnvironmentVariable("DD_DOTNET_TRACER_HOME", string.Empty);
51+
var profilerPath = Path.Combine(@"C:\tracer\win-x64", "Datadog.Trace.ClrProfiler.Native.dll");
52+
var expectedTracerHome = @"C:\tracer";
53+
54+
#if NETCOREAPP
55+
mockProvider.SetEnvironmentVariable("CORECLR_PROFILER_PATH_64", profilerPath);
56+
#else
57+
mockProvider.SetEnvironmentVariable("COR_PROFILER_PATH_64", profilerPath);
58+
#endif
59+
60+
// Act
61+
var result = Startup.GetTracerHomePath(mockProvider);
62+
63+
// Assert
64+
result.Should().Be(expectedTracerHome);
65+
}
66+
67+
[Fact]
68+
public void GetTracerHomePath_WhenNoEnvironmentVariablesSet_ReturnsNull()
69+
{
70+
// Arrange
71+
var mockProvider = new MockEnvironmentVariableProvider();
72+
// No environment variables set (mock starts empty)
73+
74+
// Act
75+
var result = Startup.GetTracerHomePath(mockProvider);
76+
77+
// Assert
78+
result.Should().BeNull();
79+
}
80+
81+
[Theory]
82+
[InlineData(@"C:\tracer\win-x64\profiler.dll", @"C:\tracer")]
83+
[InlineData(@"C:\tracer\linux-x64\profiler.so", @"C:\tracer")]
84+
[InlineData(@"C:\tracer\osx-arm64\libprofiler.dylib", @"C:\tracer")]
85+
[InlineData(@"C:\tracer\linux-musl-x64\profiler.so", @"C:\tracer")]
86+
public void ComputeTracerHomePathFromProfilerPath_WithArchitectureDirectory_ReturnsParentDirectory(string profilerPath, string expectedTracerHome)
87+
{
88+
// Arrange
89+
const string envVarName = "TEST_PROFILER_PATH";
90+
var mockProvider = new MockEnvironmentVariableProvider();
91+
mockProvider.SetEnvironmentVariable(envVarName, profilerPath);
92+
93+
// Act
94+
var result = Startup.ComputeTracerHomePathFromProfilerPath(mockProvider, envVarName);
95+
96+
// Assert
97+
result.Should().Be(expectedTracerHome);
98+
}
99+
100+
[Theory]
101+
[InlineData(@"C:\tracer\bin\profiler.dll", @"C:\tracer\bin")]
102+
[InlineData(@"C:\custom\path\profiler.dll", @"C:\custom\path")]
103+
public void ComputeTracerHomePathFromProfilerPath_WithoutArchitectureDirectory_ReturnsDirectParentDirectory(string profilerPath, string expectedTracerHome)
104+
{
105+
// Arrange
106+
const string envVarName = "TEST_PROFILER_PATH";
107+
var mockProvider = new MockEnvironmentVariableProvider();
108+
mockProvider.SetEnvironmentVariable(envVarName, profilerPath);
109+
110+
// Act
111+
var result = Startup.ComputeTracerHomePathFromProfilerPath(mockProvider, envVarName);
112+
113+
// Assert
114+
result.Should().Be(expectedTracerHome);
115+
}
116+
117+
[Fact]
118+
public void ComputeTracerHomePathFromProfilerPath_WhenEnvironmentVariableNotSet_ReturnsNull()
119+
{
120+
// Arrange
121+
const string envVarName = "NONEXISTENT_VAR";
122+
var mockProvider = new MockEnvironmentVariableProvider();
123+
// Variable not set (mock starts empty)
124+
125+
// Act
126+
var result = Startup.ComputeTracerHomePathFromProfilerPath(mockProvider, envVarName);
127+
128+
// Assert
129+
result.Should().BeNull();
130+
}
131+
132+
[Theory]
133+
[InlineData("")]
134+
[InlineData(" ")]
135+
[InlineData("\t")]
136+
public void ComputeTracerHomePathFromProfilerPath_WhenEnvironmentVariableIsWhitespace_ReturnsNull(string envVarValue)
137+
{
138+
// Arrange
139+
const string envVarName = "TEST_PROFILER_PATH";
140+
var mockProvider = new MockEnvironmentVariableProvider();
141+
mockProvider.SetEnvironmentVariable(envVarName, envVarValue);
142+
143+
// Act
144+
var result = Startup.ComputeTracerHomePathFromProfilerPath(mockProvider, envVarName);
145+
146+
// Assert
147+
result.Should().BeNull();
148+
}
149+
150+
#if NETCOREAPP
151+
[Fact]
152+
public void GetProfilerPathEnvVarNameForArch_NetCore_ReturnsCorrectEnvironmentVariableName()
153+
{
154+
// Act
155+
var result = Startup.GetProfilerPathEnvVarNameForArch();
156+
157+
// Assert - verify it returns one of the expected values based on current architecture
158+
var expectedValues = new[] { "CORECLR_PROFILER_PATH_64", "CORECLR_PROFILER_PATH_32", "CORECLR_PROFILER_PATH_ARM64", "CORECLR_PROFILER_PATH_ARM" };
159+
result.Should().BeOneOf(expectedValues);
160+
}
161+
162+
[Fact]
163+
public void GetProfilerPathEnvVarNameFallback_NetCore_ReturnsCoreclrProfilerPath()
164+
{
165+
// Act
166+
var result = Startup.GetProfilerPathEnvVarNameFallback();
167+
168+
// Assert
169+
result.Should().Be("CORECLR_PROFILER_PATH");
170+
}
171+
#endif
172+
173+
#if NETFRAMEWORK
174+
[Fact]
175+
public void GetProfilerPathEnvVarNameForArch_NetFramework_ReturnsCorrectEnvironmentVariableName()
176+
{
177+
// Act
178+
var result = Startup.GetProfilerPathEnvVarNameForArch();
179+
180+
// Assert - verify it returns one of the expected values based on current process
181+
var expectedValues = new[] { "COR_PROFILER_PATH_64", "COR_PROFILER_PATH_32" };
182+
result.Should().BeOneOf(expectedValues);
183+
}
184+
185+
[Fact]
186+
public void GetProfilerPathEnvVarNameFallback_NetFramework_ReturnsCorProfilerPath()
187+
{
188+
// Act
189+
var result = Startup.GetProfilerPathEnvVarNameFallback();
190+
191+
// Assert
192+
result.Should().Be("COR_PROFILER_PATH");
193+
}
194+
#endif
195+
196+
[Theory]
197+
[InlineData("win-x64")]
198+
[InlineData("win-x86")]
199+
[InlineData("linux-x64")]
200+
[InlineData("linux-arm64")]
201+
[InlineData("linux-musl-x64")]
202+
[InlineData("linux-musl-arm64")]
203+
[InlineData("osx")]
204+
[InlineData("osx-arm64")]
205+
[InlineData("osx-x64")]
206+
public void ComputeTracerHomePathFromProfilerPath_WithKnownArchitectureDirectories_GoesUpTwoLevels(string archDirectory)
207+
{
208+
// Arrange
209+
const string envVarName = "TEST_PROFILER_PATH";
210+
var mockProvider = new MockEnvironmentVariableProvider();
211+
var profilerPath = Path.Combine(@"C:\tracer", archDirectory, "profiler.dll");
212+
var expectedTracerHome = @"C:\tracer";
213+
mockProvider.SetEnvironmentVariable(envVarName, profilerPath);
214+
215+
// Act
216+
var result = Startup.ComputeTracerHomePathFromProfilerPath(mockProvider, envVarName);
217+
218+
// Assert
219+
result.Should().Be(expectedTracerHome);
220+
}
221+
222+
[Fact]
223+
public void ComputeTracerHomePathFromProfilerPath_WithUnknownArchitectureDirectory_GoesUpOneLevel()
224+
{
225+
// Arrange
226+
const string envVarName = "TEST_PROFILER_PATH";
227+
var mockProvider = new MockEnvironmentVariableProvider();
228+
var profilerPath = Path.Combine(@"C:\tracer\unknown-arch", "profiler.dll");
229+
var expectedTracerHome = @"C:\tracer\unknown-arch";
230+
mockProvider.SetEnvironmentVariable(envVarName, profilerPath);
231+
232+
// Act
233+
var result = Startup.ComputeTracerHomePathFromProfilerPath(mockProvider, envVarName);
234+
235+
// Assert
236+
result.Should().Be(expectedTracerHome);
237+
}
238+
239+
[Fact]
240+
public void GetTracerHomePath_IntegrationTest_PrefersExplicitTracerHomeOverInferred()
241+
{
242+
// Arrange
243+
const string explicitTracerHome = @"C:\explicit\tracer";
244+
const string inferredTracerHome = @"C:\inferred\tracer";
245+
var profilerPath = Path.Combine(inferredTracerHome, "win-x64", "profiler.dll");
246+
247+
var mockProvider = new MockEnvironmentVariableProvider();
248+
mockProvider.SetEnvironmentVariable("DD_DOTNET_TRACER_HOME", explicitTracerHome);
249+
#if NETCOREAPP
250+
mockProvider.SetEnvironmentVariable("CORECLR_PROFILER_PATH_64", profilerPath);
251+
#else
252+
mockProvider.SetEnvironmentVariable("COR_PROFILER_PATH_64", profilerPath);
253+
#endif
254+
255+
// Act
256+
var result = Startup.GetTracerHomePath(mockProvider);
257+
258+
// Assert
259+
result.Should().Be(explicitTracerHome, "explicit DD_DOTNET_TRACER_HOME should take precedence over inferred path");
260+
}
261+
262+
[Fact]
263+
public void GetTracerHomePath_IntegrationTest_FallsBackToGeneralProfilerPathWhenArchSpecificNotSet()
264+
{
265+
// Arrange
266+
var mockProvider = new MockEnvironmentVariableProvider();
267+
var profilerPath = Path.Combine(@"C:\tracer\win-x64", "profiler.dll");
268+
var expectedTracerHome = @"C:\tracer";
269+
270+
// No DD_DOTNET_TRACER_HOME set
271+
// No arch-specific env vars set
272+
// Set the fallback
273+
#if NETCOREAPP
274+
mockProvider.SetEnvironmentVariable("CORECLR_PROFILER_PATH", profilerPath);
275+
#else
276+
mockProvider.SetEnvironmentVariable("COR_PROFILER_PATH", profilerPath);
277+
#endif
278+
279+
// Act
280+
var result = Startup.GetTracerHomePath(mockProvider);
281+
282+
// Assert
283+
result.Should().Be(expectedTracerHome);
284+
}
285+
286+
[Fact]
287+
public void GetTracerHomePath_IntegrationTest_PrefersArchSpecificOverGeneral()
288+
{
289+
// Arrange
290+
var mockProvider = new MockEnvironmentVariableProvider();
291+
var archSpecificProfilerPath = Path.Combine(@"C:\arch-specific\win-x64", "profiler.dll");
292+
var generalProfilerPath = Path.Combine(@"C:\general\win-x64", "profiler.dll");
293+
var expectedTracerHome = @"C:\arch-specific";
294+
295+
#if NETCOREAPP
296+
mockProvider.SetEnvironmentVariable("CORECLR_PROFILER_PATH_64", archSpecificProfilerPath);
297+
mockProvider.SetEnvironmentVariable("CORECLR_PROFILER_PATH", generalProfilerPath);
298+
#else
299+
mockProvider.SetEnvironmentVariable("COR_PROFILER_PATH_64", archSpecificProfilerPath);
300+
mockProvider.SetEnvironmentVariable("COR_PROFILER_PATH", generalProfilerPath);
301+
#endif
302+
303+
// Act
304+
var result = Startup.GetTracerHomePath(mockProvider);
305+
306+
// Assert
307+
result.Should().Be(expectedTracerHome, "architecture-specific profiler path should take precedence over general path");
308+
}
309+
}

tracer/test/Datadog.Trace.Tests/Datadog.Trace.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545

4646
<ProjectReference Include="..\..\src\Datadog.Trace\Datadog.Trace.csproj" />
4747
<ProjectReference Include="..\..\src\Datadog.Trace.Annotations\Datadog.Trace.Annotations.csproj" />
48+
<ProjectReference Include="..\..\src\Datadog.Trace.ClrProfiler.Managed.Loader\Datadog.Trace.ClrProfiler.Managed.Loader.csproj" />
4849
<ProjectReference Include="..\Datadog.Trace.TestHelpers\Datadog.Trace.TestHelpers.csproj" />
4950
</ItemGroup>
5051

0 commit comments

Comments
 (0)