Skip to content

Commit 27cc7e1

Browse files
authored
test: Add tests to monitor any changes in the public API surface in NewRelic.Api.Agent (#2749)
1 parent 32e54c1 commit 27cc7e1

File tree

5 files changed

+183
-4
lines changed

5 files changed

+183
-4
lines changed

.github/dependabot.yml

+6-4
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ updates:
2626

2727
# Update a specific set of packages for unit and integration tests
2828
- package-ecosystem: nuget
29-
directories:
30-
- /tests/Agent/IntegrationTests
31-
- /
29+
directories: # not recursive - only the specified directory will be scanned for .csproj or .sln files
30+
- /tests/Agent/IntegrationTests # will pick up container, integration and unbounded test solutions
31+
- / # will pick up FullAgent.sln which contains the unit tests
3232
schedule:
3333
interval: weekly
3434
groups:
@@ -37,10 +37,12 @@ updates:
3737
- "*"
3838
allow:
3939
- dependency-name: "coverlet.collector"
40-
- dependency-name: "JustMock"
40+
- dependency-name: "JustMock" # until we upgrade unit tests to target 4.8.1, we can' upgrade to the 20204 JustMock release
4141
- dependency-name: "Microsoft.NET.Test.Sdk"
4242
- dependency-name: "Microsoft.VisualStudio.Azure.Containers.Tools.Targets"
4343
- dependency-name: "Microsoft.VisualStudio.Threading.Analyzers"
4444
- dependency-name: "NUnit*"
4545
- dependency-name: "Selenium*"
4646
- dependency-name: "xunit*"
47+
- dependency-name: "PublicApiGenerator"
48+
- dependency-name: "Verify.NUnit"

FullAgent.sln

+7
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AwsSdk", "src\Agent\NewReli
217217
EndProject
218218
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureFunction", "src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\AzureFunction\AzureFunction.csproj", "{338AD83A-ED68-438A-8FB1-E93A3AE87EA8}"
219219
EndProject
220+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PublicApiChangeTests", "tests\Agent\UnitTests\PublicApiChangeTests\PublicApiChangeTests.csproj", "{A8F6EFEA-1C31-4461-A7B4-25C30D954EE2}"
221+
EndProject
220222
Global
221223
GlobalSection(SolutionConfigurationPlatforms) = preSolution
222224
Debug|Any CPU = Debug|Any CPU
@@ -455,6 +457,10 @@ Global
455457
{338AD83A-ED68-438A-8FB1-E93A3AE87EA8}.Debug|Any CPU.Build.0 = Debug|Any CPU
456458
{338AD83A-ED68-438A-8FB1-E93A3AE87EA8}.Release|Any CPU.ActiveCfg = Release|Any CPU
457459
{338AD83A-ED68-438A-8FB1-E93A3AE87EA8}.Release|Any CPU.Build.0 = Release|Any CPU
460+
{A8F6EFEA-1C31-4461-A7B4-25C30D954EE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
461+
{A8F6EFEA-1C31-4461-A7B4-25C30D954EE2}.Debug|Any CPU.Build.0 = Debug|Any CPU
462+
{A8F6EFEA-1C31-4461-A7B4-25C30D954EE2}.Release|Any CPU.ActiveCfg = Release|Any CPU
463+
{A8F6EFEA-1C31-4461-A7B4-25C30D954EE2}.Release|Any CPU.Build.0 = Release|Any CPU
458464
EndGlobalSection
459465
GlobalSection(SolutionProperties) = preSolution
460466
HideSolutionNode = FALSE
@@ -524,6 +530,7 @@ Global
524530
{DC3E4801-A54A-42A4-AC45-DBD2F0CAE438} = {E5B988C0-5D19-407E-8210-71FFB90C579A}
525531
{37262C22-6A3A-4AD7-AB78-3853D2B2931D} = {5E86E10A-C38F-48CB-ADE9-67B22BB2F50A}
526532
{338AD83A-ED68-438A-8FB1-E93A3AE87EA8} = {5E86E10A-C38F-48CB-ADE9-67B22BB2F50A}
533+
{A8F6EFEA-1C31-4461-A7B4-25C30D954EE2} = {E5B988C0-5D19-407E-8210-71FFB90C579A}
527534
EndGlobalSection
528535
GlobalSection(ExtensibilityGlobals) = postSolution
529536
SolutionGuid = {D8B98070-6B8E-403C-A07F-A3F2E4A3A3D0}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
8+
<IsPackable>false</IsPackable>
9+
<IsTestProject>true</IsTestProject>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="PublicApiGenerator" Version="11.1.0" />
14+
<PackageReference Include="Verify.NUnit" Version="26.4.4" />
15+
<PackageReference Include="coverlet.collector" Version="6.0.2">
16+
<PrivateAssets>all</PrivateAssets>
17+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
18+
</PackageReference>
19+
<PackageReference Include="JustMock" Version="2023.3.1122.188" />
20+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
21+
<PackageReference Include="MoreLinq" Version="2.4.0" />
22+
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
23+
<PackageReference Include="NUnit" Version="4.2.2" />
24+
<PackageReference Include="NUnit.Analyzers" Version="4.3.0">
25+
<PrivateAssets>all</PrivateAssets>
26+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
27+
</PackageReference>
28+
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0">
29+
<PrivateAssets>all</PrivateAssets>
30+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
31+
</PackageReference>
32+
</ItemGroup>
33+
34+
<ItemGroup>
35+
<ProjectReference Include="..\..\..\..\src\Agent\NewRelic.Api.Agent\NewRelic.Api.Agent.csproj" />
36+
</ItemGroup>
37+
38+
<ItemGroup>
39+
<Using Include="NUnit.Framework" />
40+
</ItemGroup>
41+
42+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
[assembly: System.Reflection.AssemblyMetadata("RepositoryUrl", "https://github.com/newrelic/dotnet-agent")]
2+
[assembly: System.Runtime.Versioning.TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName=".NET Standard 2.0")]
3+
namespace NewRelic.Api.Agent
4+
{
5+
public static class Constants
6+
{
7+
public const string DistributedTracePayloadKey = "Newrelic";
8+
}
9+
public interface IAgent
10+
{
11+
NewRelic.Api.Agent.ISpan CurrentSpan { get; }
12+
NewRelic.Api.Agent.ITransaction CurrentTransaction { get; }
13+
NewRelic.Api.Agent.ITraceMetadata TraceMetadata { get; }
14+
System.Collections.Generic.Dictionary<string, string> GetLinkingMetadata();
15+
}
16+
public interface IDistributedTracePayload
17+
{
18+
string HttpSafe();
19+
bool IsEmpty();
20+
string Text();
21+
}
22+
public interface ISpan
23+
{
24+
NewRelic.Api.Agent.ISpan AddCustomAttribute(string key, object value);
25+
NewRelic.Api.Agent.ISpan SetName(string name);
26+
}
27+
public interface ITraceMetadata
28+
{
29+
bool IsSampled { get; }
30+
string SpanId { get; }
31+
string TraceId { get; }
32+
}
33+
public interface ITransaction
34+
{
35+
NewRelic.Api.Agent.ISpan CurrentSpan { get; }
36+
void AcceptDistributedTraceHeaders<T>(T carrier, System.Func<T, string, System.Collections.Generic.IEnumerable<string>> getter, NewRelic.Api.Agent.TransportType transportType);
37+
NewRelic.Api.Agent.ITransaction AddCustomAttribute(string key, object value);
38+
void InsertDistributedTraceHeaders<T>(T carrier, System.Action<T, string, string> setter);
39+
NewRelic.Api.Agent.SegmentWrapper? RecordDatastoreSegment(string vendor, string model, string operation, string? commandText = null, string? host = null, string? portPathOrID = null, string? databaseName = null);
40+
void SetUserId(string userid);
41+
}
42+
public static class NewRelic
43+
{
44+
public static void DisableBrowserMonitoring(bool overrideManual = false) { }
45+
public static NewRelic.Api.Agent.IAgent GetAgent() { }
46+
public static string GetBrowserTimingHeader() { }
47+
public static string GetBrowserTimingHeader(string nonce) { }
48+
public static System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, string>> GetRequestMetadata() { }
49+
public static System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, string>> GetResponseMetadata() { }
50+
public static void IgnoreApdex() { }
51+
public static void IgnoreTransaction() { }
52+
public static void IncrementCounter(string name) { }
53+
public static void NoticeError(System.Exception exception) { }
54+
public static void NoticeError(System.Exception exception, System.Collections.Generic.IDictionary<string, object>? parameters) { }
55+
public static void NoticeError(System.Exception exception, System.Collections.Generic.IDictionary<string, string>? parameters) { }
56+
public static void NoticeError(string message, System.Collections.Generic.IDictionary<string, object>? parameters) { }
57+
public static void NoticeError(string message, System.Collections.Generic.IDictionary<string, string>? parameters) { }
58+
public static void NoticeError(string message, System.Collections.Generic.IDictionary<string, object>? parameters, bool isExpected) { }
59+
public static void NoticeError(string message, System.Collections.Generic.IDictionary<string, string>? parameters, bool isExpected) { }
60+
public static void RecordCustomEvent(string eventType, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, object>> attributes) { }
61+
public static void RecordLlmFeedbackEvent(string traceId, object rating, string category = "", string message = "", System.Collections.Generic.IDictionary<string, object>? metadata = null) { }
62+
public static void RecordMetric(string name, float value) { }
63+
public static void RecordResponseTimeMetric(string name, long millis) { }
64+
public static void SetApplicationName(string applicationName, string? applicationName2 = null, string? applicationName3 = null) { }
65+
public static void SetErrorGroupCallback(System.Func<System.Collections.Generic.IReadOnlyDictionary<string, object>, string> callback) { }
66+
public static void SetLlmTokenCountingCallback(System.Func<string, string, int> callback) { }
67+
public static void SetTransactionName(string? category, string name) { }
68+
public static void SetTransactionUri(System.Uri uri) { }
69+
public static void SetUserParameters(string? userName, string? accountName, string? productName) { }
70+
public static void StartAgent() { }
71+
}
72+
public class SegmentWrapper : System.IDisposable
73+
{
74+
public void Dispose() { }
75+
public static NewRelic.Api.Agent.SegmentWrapper GetDatastoreWrapper([System.Runtime.CompilerServices.Dynamic] object transaction, string vendor, string model, string operation, string? commandText, string? host, string? portPathOrID, string? databaseName) { }
76+
}
77+
[System.AttributeUsage(System.AttributeTargets.Method)]
78+
public class TraceAttribute : System.Attribute
79+
{
80+
public TraceAttribute() { }
81+
}
82+
[System.AttributeUsage(System.AttributeTargets.Method)]
83+
public class TransactionAttribute : NewRelic.Api.Agent.TraceAttribute
84+
{
85+
public TransactionAttribute() { }
86+
public bool Web { get; set; }
87+
}
88+
public enum TransportType
89+
{
90+
Unknown = 0,
91+
HTTP = 1,
92+
HTTPS = 2,
93+
Kafka = 3,
94+
JMS = 4,
95+
IronMQ = 5,
96+
AMQP = 6,
97+
Queue = 7,
98+
Other = 8,
99+
}
100+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2020 New Relic, Inc. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
using System.Reflection;
5+
using DiffEngine;
6+
using PublicApiGenerator;
7+
8+
namespace PublicApiChangeTests;
9+
10+
[TestFixture]
11+
public class PublicApiTest
12+
{
13+
[Test]
14+
public Task PublicApiHasNotChanged()
15+
{
16+
if (BuildServerDetector.Detected) // don't launch the diff engine if the test fails on a build server
17+
DiffRunner.Disabled = true;
18+
19+
// Get the assembly for the library we want to document
20+
Assembly assembly = typeof(NewRelic.Api.Agent.IAgent).Assembly;
21+
22+
// Retrieve the public API for all types in the assembly
23+
string publicApi = assembly.GeneratePublicApi();
24+
25+
// Run a snapshot test on the returned string
26+
return Verify(publicApi);
27+
}
28+
}

0 commit comments

Comments
 (0)