Skip to content
This repository was archived by the owner on Nov 1, 2023. It is now read-only.

Commit 2f2a649

Browse files
tevoineaAdamL-Microsoftchkeitakananbmgreisen
authored
Event export serializer (#3543)
* Release 8.7.1 (hotfix) (#3459) * Remove the retention policy setting (#3452) --------- Co-authored-by: Cheick Keita <[email protected]> * Revert "Release 8.7.1 (hotfix) (#3459)" (#3468) This reverts commit c69deed. * Redo 8.7.1 (#3469) * Redo-8.7.1-hotfix --------- Co-authored-by: Cheick Keita <[email protected]> * Support custom ado fields that mark work items as duplicate (#3467) * Add field to ado config for checking duplicate work items * Make duplicate fields nullable and add it to python models * Update broken tests * Update docs to include new ado_duplicate_fields property * Update readme with archive message (#3408) Co-authored-by: Adam <[email protected]> * Bump tokio from 1.30.0 to 1.32.0 in /src/proxy-manager (#3425) Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.30.0 to 1.32.0. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](tokio-rs/tokio@tokio-1.30.0...tokio-1.32.0) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump tokio from 1.30.0 to 1.32.0 in /src/agent (#3424) Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.30.0 to 1.32.0. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](tokio-rs/tokio@tokio-1.30.0...tokio-1.32.0) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Remove unnecessary method argument (#3473) * Bump elsa from 1.8.1 to 1.9.0 in /src/agent (#3411) Bumps [elsa](https://github.com/manishearth/elsa) from 1.8.1 to 1.9.0. - [Commits](Manishearth/elsa@v1.8.1...v1.9.0) --- updated-dependencies: - dependency-name: elsa dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump tempfile from 3.7.1 to 3.8.0 in /src/agent (#3437) Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.7.1 to 3.8.0. - [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md) - [Commits](Stebalien/tempfile@v3.7.1...v3.8.0) --- updated-dependencies: - dependency-name: tempfile dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump tempfile from 3.7.1 to 3.8.0 in /src/proxy-manager (#3436) Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.7.1 to 3.8.0. - [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md) - [Commits](Stebalien/tempfile@v3.7.1...v3.8.0) --- updated-dependencies: - dependency-name: tempfile dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Updating requirements.txt to accept >= onefuzztypes. (#3477) * Updating requirements.txt to accept >= onefuzztypes. * Trying to loosen restriction. * Bump notify from 6.0.1 to 6.1.1 in /src/agent (#3435) Bumps [notify](https://github.com/notify-rs/notify) from 6.0.1 to 6.1.1. - [Release notes](https://github.com/notify-rs/notify/releases) - [Changelog](https://github.com/notify-rs/notify/blob/main/CHANGELOG.md) - [Commits](notify-rs/notify@notify-6.0.1...notify-6.1.1) --- updated-dependencies: - dependency-name: notify dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump azure_* crates (#3478) * Release 8.8.0 (#3466) * Release 8.8.0 * Bump clap from 4.3.21 to 4.4.2 in /src/agent (#3484) Bumps [clap](https://github.com/clap-rs/clap) from 4.3.21 to 4.4.2. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](clap-rs/clap@v4.3.21...v4.4.2) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump gimli from 0.27.3 to 0.28.0 in /src/agent (#3414) Bumps [gimli](https://github.com/gimli-rs/gimli) from 0.27.3 to 0.28.0. - [Changelog](https://github.com/gimli-rs/gimli/blob/master/CHANGELOG.md) - [Commits](gimli-rs/gimli@0.27.3...0.28.0) --- updated-dependencies: - dependency-name: gimli dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump clap from 4.3.21 to 4.4.2 in /src/proxy-manager (#3474) Bumps [clap](https://github.com/clap-rs/clap) from 4.3.21 to 4.4.2. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](clap-rs/clap@v4.3.21...v4.4.2) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump winreg from 0.50.0 to 0.51.0 in /src/agent (#3434) Bumps [winreg](https://github.com/gentoo90/winreg-rs) from 0.50.0 to 0.51.0. - [Release notes](https://github.com/gentoo90/winreg-rs/releases) - [Changelog](https://github.com/gentoo90/winreg-rs/blob/master/CHANGELOG.md) - [Commits](gentoo90/winreg-rs@v0.50.0...v0.51.0) --- updated-dependencies: - dependency-name: winreg dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Adam <[email protected]> * Starting integration tests (#3438) * Starting integration tests * Ready to test the test * Parametrize test * checkpoint * Test works * Run integration tests in pipeline * fmt * . * -p * Install clang * quotes not required in yaml? * Hopefully fixed windows? * Try without killondrop * lint * small test * another test * Reuse core name * Wrong step * bump tokio? * Try with rust * make build happy * Bump pete and small clean up * Clean up and make the test pass regularly * fix broken ci * Lower the poll timeout * Set the timeout in a nicer way * fix windows * fmt * Include and copy pdbs * Ignore if pdb is missing on linux * It takes too long for coverage to be generated * lint * Only warn on missing coverage since it's flaky * Fix windows build * Small clean up * Try lowering the poll delay * fix coverage * PR comments * . * Apparently make is missing? * Remove aggressive step skipping in CI * Fix sed checks for CLI versioning (#3486) * Fix sed checks for CLI versioning * Fix. * Fix. * Changing build_cli * Trying greater than * Tring once more. * Trying major minor * trying to replace major minor * Using major minor * Bump bytes from 1.4.0 to 1.5.0 in /src/agent (#3488) Bumps [bytes](https://github.com/tokio-rs/bytes) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/tokio-rs/bytes/releases) - [Changelog](https://github.com/tokio-rs/bytes/blob/master/CHANGELOG.md) - [Commits](tokio-rs/bytes@v1.4.0...v1.5.0) --- updated-dependencies: - dependency-name: bytes dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Improve area/iteration path validation (#3489) * Add more comprehensive checks and better error messages to area/iteration path validation * Join invalid chars with space instead of comma * Make tree path validation more testable * Add error code for invalid ADO project in config * Write unit tests for tree path validation * Format tree path unit tests * Merge escape character and control character checks and clarify error message * Improve handling of unexpected breakpoints (#3493) * Improve handling of unexpected breakpoints * fmt * Update azure_* crates (#3503) * Fuzz coverage recording (#3322) * Fuzz coverage recording * Update cargo.toml * Update src/agent/coverage/fuzz/fuzz_targets/fuzz_target_record_coverage.rs Co-authored-by: George Pollard <[email protected]> * Fix fuzz --------- Co-authored-by: George Pollard <[email protected]> * Reporting coverage on task start up (#3502) * Reporting coverage on task start up * Moving metric up. * Remove feature flag from heartbeat metrics. (#3505) * Update archive notice. (#3507) * Add onefuzz service version to job created events (#3504) * Tevoinea/add version checking in local tasks (#3517) * Compare task version to service version * Swallow output when looking for appropriate name * Create directories if they don't exist in the template (#3522) * Create directories if they don't exist in the template * fmt * Support for retention policies on containers (#3501) - [x] ability to specify a retention period on a container, which applies to newly-created blobs - [x] specify default retention periods in templates from CLI side There's a small breaking change to the Python JobHelper class. * Bump rayon from 1.7.0 to 1.8.0 in /src/agent (#3520) Bumps [rayon](https://github.com/rayon-rs/rayon) from 1.7.0 to 1.8.0. - [Changelog](https://github.com/rayon-rs/rayon/blob/master/RELEASES.md) - [Commits](rayon-rs/rayon@rayon-core-v1.7.0...rayon-core-v1.8.0) --- updated-dependencies: - dependency-name: rayon dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump insta from 1.31.0 to 1.32.0 in /src/agent (#3521) Bumps [insta](https://github.com/mitsuhiko/insta) from 1.31.0 to 1.32.0. - [Changelog](https://github.com/mitsuhiko/insta/blob/master/CHANGELOG.md) - [Commits](mitsuhiko/insta@1.31.0...1.32.0) --- updated-dependencies: - dependency-name: insta dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Disable `repro` and `debug` VM CLI commands. (#3494) * Disable and VM CLI commands. * Formatting. * More formatting. * More formatting. * Removing Repro check. * Make modules case insenstive on windows (#3527) * Make modules and coverage allowlist case insensitive on Windows * Tests and fmt * PR comments * fmt * Debugging missing file coverage * fmt * Broken linux test * Add a case insensitive transformer for better perf * cargo fix * Update windows interceptor list (#3528) * Starting to work on custom converter * Add slim serializer for events export * . * Cleanup and better tests * Update feature-flags.bicep Default off --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: Adam <[email protected]> Co-authored-by: Cheick Keita <[email protected]> Co-authored-by: Kanan B <[email protected]> Co-authored-by: Marc Greisen <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Noah McGregor Harper <[email protected]> Co-authored-by: George Pollard <[email protected]> Co-authored-by: George Pollard <[email protected]>
1 parent e7b0dd5 commit 2f2a649

File tree

7 files changed

+337
-19
lines changed

7 files changed

+337
-19
lines changed

src/ApiService/ApiService/FeatureFlags.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ public static class FeatureFlagConstants {
99
public const string EnableDryRunBlobRetention = "EnableDryRunBlobRetention";
1010
public const string EnableWorkItemCreation = "EnableWorkItemCreation";
1111
public const string EnableContainerRetentionPolicies = "EnableContainerRetentionPolicies";
12+
public const string EnableSlimEventSerialization = "EnableSlimEventSerialization";
1213
}

src/ApiService/ApiService/onefuzzlib/Events.cs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ public class Events : IEvents {
3535
private readonly IContainers _containers;
3636
private readonly ICreds _creds;
3737
private readonly JsonSerializerOptions _options;
38+
private readonly JsonSerializerOptions _optionsSlim;
3839
private readonly JsonSerializerOptions _deserializingFromBlobOptions;
40+
private readonly IOnefuzzContext _context;
3941

4042
public Events(ILogger<Events> log, IOnefuzzContext context) {
4143
_queue = context.Queue;
@@ -47,9 +49,12 @@ public Events(ILogger<Events> log, IOnefuzzContext context) {
4749
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
4850
};
4951
_options.Converters.Add(new RemoveUserInfo());
52+
_optionsSlim = new JsonSerializerOptions(_options);
53+
_optionsSlim.Converters.Add(new EventExportConverter<DownloadableEventMessage>());
5054
_deserializingFromBlobOptions = new JsonSerializerOptions(EntityConverter.GetJsonSerializerOptions()) {
5155
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
5256
};
57+
_context = context;
5358
}
5459

5560
public virtual async Async.Task QueueSignalrEvent(DownloadableEventMessage message) {
@@ -58,7 +63,13 @@ public virtual async Async.Task QueueSignalrEvent(DownloadableEventMessage messa
5863
("event_id", message.EventId.ToString())
5964
};
6065
var ev = new SignalREvent("events", new List<DownloadableEventMessage>() { message });
61-
var queueResult = await _queue.QueueObject("signalr-events", ev, StorageType.Config, serializerOptions: _options);
66+
67+
var opts = await _context.FeatureManagerSnapshot.IsEnabledAsync(FeatureFlagConstants.EnableSlimEventSerialization) switch {
68+
true => _optionsSlim,
69+
false => _options
70+
};
71+
72+
var queueResult = await _queue.QueueObject("signalr-events", ev, StorageType.Config, serializerOptions: opts);
6273

6374
if (!queueResult) {
6475
_log.AddTags(tags);
@@ -155,16 +166,4 @@ await _containers.SaveBlob(
155166
);
156167
}
157168
}
158-
159-
160-
public class RemoveUserInfo : JsonConverter<UserInfo> {
161-
public override UserInfo? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
162-
throw new NotSupportedException("reading UserInfo is not supported");
163-
}
164-
165-
public override void Write(Utf8JsonWriter writer, UserInfo value, JsonSerializerOptions options) {
166-
writer.WriteStartObject();
167-
writer.WriteEndObject();
168-
}
169-
}
170169
}

src/ApiService/ApiService/onefuzzlib/WebhookOperations.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,15 @@ public interface IWebhookOperations : IOrm<Webhook> {
2020
public class WebhookOperations : Orm<Webhook>, IWebhookOperations {
2121

2222
private readonly IHttpClientFactory _httpFactory;
23+
private readonly JsonSerializerOptions _options;
24+
private readonly JsonSerializerOptions _optionsSlim;
2325

2426
public WebhookOperations(IHttpClientFactory httpFactory, ILogger<WebhookOperations> log, IOnefuzzContext context)
2527
: base(log, context) {
2628
_httpFactory = httpFactory;
29+
_options = EntityConverter.GetJsonSerializerOptions();
30+
_optionsSlim = new JsonSerializerOptions(_options);
31+
_optionsSlim.Converters.Add(new EventExportConverter<WebhookMessage>());
2732
}
2833

2934
public async Async.Task SendEvent(DownloadableEventMessage eventMessage) {
@@ -139,11 +144,15 @@ public async Task<EventPing> Ping(Webhook webhook) {
139144
string data;
140145
var instanceId = await _context.Containers.GetInstanceId();
141146
var webhookMessage = new WebhookMessage(WebhookId: webhookId, EventId: eventId, EventType: eventType, Event: webhookEvent, InstanceId: instanceId, InstanceName: _context.Creds.GetInstanceName(), CreatedAt: eventData.CreatedAt, SasUrl: eventData.SasUrl);
147+
var opts = await _context.FeatureManagerSnapshot.IsEnabledAsync(FeatureFlagConstants.EnableSlimEventSerialization) switch {
148+
true => _optionsSlim,
149+
false => _options
150+
};
142151
if (messageFormat != null && messageFormat == WebhookMessageFormat.EventGrid) {
143152
var eventGridMessage = new[] { new WebhookMessageEventGrid(Id: eventId, Data: webhookMessage, DataVersion: "2.0.0", Subject: _context.Creds.GetInstanceName(), EventType: eventType, EventTime: DateTimeOffset.UtcNow) };
144-
data = JsonSerializer.Serialize(eventGridMessage, options: EntityConverter.GetJsonSerializerOptions());
153+
data = JsonSerializer.Serialize(eventGridMessage, options: opts);
145154
} else {
146-
data = JsonSerializer.Serialize(webhookMessage, options: EntityConverter.GetJsonSerializerOptions());
155+
data = JsonSerializer.Serialize(webhookMessage, options: opts);
147156
}
148157

149158
string? digest = null;
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
using System.Collections;
2+
using System.Reflection;
3+
using System.Text.Json;
4+
using System.Text.Json.Serialization;
5+
6+
namespace Microsoft.OneFuzz.Service {
7+
public class RemoveUserInfo : JsonConverter<UserInfo> {
8+
public override UserInfo? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
9+
throw new NotSupportedException("reading UserInfo is not supported");
10+
}
11+
12+
public override void Write(Utf8JsonWriter writer, UserInfo value, JsonSerializerOptions options) {
13+
writer.WriteStartObject();
14+
writer.WriteEndObject();
15+
}
16+
}
17+
18+
/// <summary>
19+
/// <b>THIS IS A WRITE ONLY JSON CONVERTER</b>
20+
/// <br/>
21+
/// It should only be used when serializing events to be sent outside of the service
22+
/// </summary>
23+
public class EventExportConverter<T> : JsonConverter<T>
24+
where T : DownloadableEventMessage {
25+
public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
26+
throw new NotSupportedException("This converter should only be used when serializing event messages to sent outside of the service");
27+
}
28+
29+
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) {
30+
BoundedSerializer.WriteInternal(writer, value, options);
31+
}
32+
}
33+
34+
public class BoundedSerializer {
35+
private static HashSet<Type> boundedTypes = new HashSet<Type>{
36+
typeof(Guid),
37+
typeof(DateTime),
38+
typeof(int),
39+
typeof(bool),
40+
typeof(float),
41+
typeof(double),
42+
typeof(long),
43+
typeof(char),
44+
typeof(Uri)
45+
};
46+
47+
public static void WriteInternal(Utf8JsonWriter writer, object type, JsonSerializerOptions options) {
48+
writer.WriteStartObject();
49+
var properties = type.GetType().GetProperties();
50+
foreach (var property in properties) {
51+
if (property.GetValue(type, null) == null
52+
|| typeof(IEnumerable).IsAssignableFrom(property.PropertyType)
53+
|| type.GetType() == property.PropertyType) {
54+
continue;
55+
}
56+
if (HasBoundedSerialization(property)) {
57+
var serialized = JsonSerializer.Serialize(property.GetValue(type, null), property.PropertyType, options);
58+
if (!string.IsNullOrEmpty(serialized)) {
59+
writer.WritePropertyName(property.Name);
60+
writer.WriteRawValue(serialized);
61+
}
62+
} else if (property.PropertyType.IsClass) {
63+
writer.WritePropertyName(property.Name);
64+
WriteInternal(writer, property.GetValue(type, null)!, options);
65+
}
66+
}
67+
writer.WriteEndObject();
68+
}
69+
70+
public static bool HasBoundedSerialization(PropertyInfo propertyInfo) {
71+
return propertyInfo.PropertyType.IsEnum ||
72+
boundedTypes.Contains(propertyInfo.PropertyType) ||
73+
typeof(IValidatedString).IsAssignableFrom(propertyInfo.PropertyType);
74+
}
75+
}
76+
}
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text.Json;
5+
using FluentAssertions;
6+
using FsCheck;
7+
using FsCheck.Xunit;
8+
using Microsoft.OneFuzz.Service;
9+
using Microsoft.OneFuzz.Service.OneFuzzLib.Orm;
10+
using Xunit;
11+
12+
13+
namespace Tests;
14+
15+
public class EventExportConverterTests {
16+
enum Color {
17+
Red,
18+
Blue
19+
}
20+
21+
[Fact]
22+
public void BaseTypesAreBounded() {
23+
var a = new {
24+
guid = Guid.NewGuid(),
25+
date = new DateTime(),
26+
en = Color.Red,
27+
b = 1,
28+
boo = false,
29+
flo = float.Pi,
30+
doub = double.Tau,
31+
lon = long.MinValue,
32+
cha = 'a'
33+
};
34+
35+
a.GetType().GetProperties().All(p => BoundedSerializer.HasBoundedSerialization(p)).Should().BeTrue();
36+
}
37+
38+
[Fact]
39+
public void StringIsNotBounded() {
40+
var a = new {
41+
bad = "this is not bounded"
42+
};
43+
44+
BoundedSerializer.HasBoundedSerialization(a.GetType().GetProperty("bad")!).Should().BeFalse();
45+
}
46+
47+
[Fact]
48+
public void ValidatedStringIsBounded() {
49+
var a = new {
50+
scalesetid = ScalesetId.Parse("abc-123")
51+
};
52+
53+
BoundedSerializer.HasBoundedSerialization(a.GetType().GetProperty("scalesetid")!).Should().BeTrue();
54+
}
55+
56+
[Fact]
57+
public void ComplexObjectsAreSerialized() {
58+
var randomGuid = Guid.NewGuid();
59+
var a = new DownloadableEventMessage(
60+
randomGuid,
61+
EventType.CrashReported,
62+
new EventCrashReported(
63+
new Report(
64+
"https://example.com",
65+
null,
66+
"target.exe",
67+
"crash",
68+
string.Empty,
69+
new List<string> { "this", "is", "a", "stacktrace" },
70+
string.Empty,
71+
string.Empty,
72+
null,
73+
Guid.NewGuid(),
74+
Guid.NewGuid(),
75+
null,
76+
null,
77+
null,
78+
null,
79+
null,
80+
null,
81+
null,
82+
null,
83+
null,
84+
null,
85+
null,
86+
null
87+
),
88+
Container.Parse("this-is-a-container"),
89+
"crash-abc123",
90+
null
91+
),
92+
Guid.NewGuid(),
93+
"onefuzz",
94+
DateTime.Now,
95+
new Uri("https://example.com"),
96+
null
97+
);
98+
var serializerOptions = new JsonSerializerOptions(EntityConverter.GetJsonSerializerOptions());
99+
serializerOptions.Converters.Add(new EventExportConverter<DownloadableEventMessage>());
100+
101+
var serialized = JsonSerializer.Serialize(a, serializerOptions);
102+
103+
serialized.Should().NotBeNullOrEmpty();
104+
serialized.Should().NotContain("stacktrace"); // List<string> is not serialized
105+
serialized.Should().NotContain("crash-abc123"); // string is not serialized
106+
serialized.Should().Contain("this-is-a-container"); // ValidatedString is serialized
107+
serialized.Should().Contain("crash_reported"); // Enum is serialized
108+
serialized.Should().Contain(DateTime.Now.Year.ToString()); // DateTime is serialized
109+
serialized.Should().Contain(randomGuid.ToString()); // Guid id serialized
110+
}
111+
112+
[Fact]
113+
public void TestWebhookMessage() {
114+
var a = new WebhookMessageEventGrid(
115+
"2.0.0",
116+
"eventsubject",
117+
EventType.JobCreated,
118+
DateTime.Now,
119+
Guid.NewGuid(),
120+
new WebhookMessage(
121+
Guid.NewGuid(),
122+
EventType.JobCreated,
123+
new EventJobCreated(
124+
Guid.NewGuid(),
125+
new JobConfig("some project", "some name", "some build", 1, "some logs"),
126+
null,
127+
"8.0"),
128+
Guid.NewGuid(),
129+
"onefuzz",
130+
Guid.NewGuid(),
131+
DateTime.Now,
132+
new Uri("https://example.com")
133+
)
134+
);
135+
136+
var serializerOptions = new JsonSerializerOptions(EntityConverter.GetJsonSerializerOptions());
137+
serializerOptions.Converters.Add(new EventExportConverter<WebhookMessage>());
138+
139+
var serialized = JsonSerializer.Serialize(a, serializerOptions);
140+
141+
serialized.Should().Contain("eventsubject");
142+
serialized.Should().NotContain("some project");
143+
}
144+
145+
public class EventExportConverterSerializationTests {
146+
private readonly JsonSerializerOptions _opts = new JsonSerializerOptions(EntityConverter.GetJsonSerializerOptions());
147+
public EventExportConverterSerializationTests() {
148+
_ = Arb.Register<Arbitraries>();
149+
_opts.Converters.Add(new EventExportConverter<DownloadableEventMessage>());
150+
}
151+
152+
void Test<T>(T v) {
153+
// TODO: Try cloning/creating a new serializer options from the existing one?
154+
var serialized = JsonSerializer.Serialize(v, _opts);
155+
var _ = JsonSerializer.Deserialize<dynamic>(serialized);
156+
}
157+
158+
[Property]
159+
public void EventNodeHeartbeat(EventNodeHeartbeat e) => Test(e);
160+
161+
162+
[Property]
163+
public void EventTaskHeartbeat(EventTaskHeartbeat e) => Test(e);
164+
165+
[Property]
166+
public void EventTaskStopped(EventTaskStopped e) => Test(e);
167+
168+
[Property]
169+
public void EventInstanceConfigUpdated(EventInstanceConfigUpdated e) => Test(e);
170+
171+
[Property]
172+
public void EventProxyCreated(EventProxyCreated e) => Test(e);
173+
174+
[Property]
175+
public void EventProxyDeleted(EventProxyDeleted e) => Test(e);
176+
177+
[Property]
178+
public void EventProxyFailed(EventProxyFailed e) => Test(e);
179+
180+
[Property]
181+
public void EventProxyStateUpdated(EventProxyStateUpdated e) => Test(e);
182+
183+
184+
[Property]
185+
public void EventCrashReported(EventCrashReported e) => Test(e);
186+
187+
188+
[Property]
189+
public void EventRegressionReported(EventRegressionReported e) => Test(e);
190+
191+
192+
[Property]
193+
public void EventFileAdded(EventFileAdded e) => Test(e);
194+
195+
[Property]
196+
public void EventTaskFailed(EventTaskFailed e) => Test(e);
197+
198+
[Property]
199+
public void EventTaskStateUpdated(EventTaskStateUpdated e) => Test(e);
200+
201+
[Property]
202+
public void EventScalesetFailed(EventScalesetFailed e) => Test(e);
203+
204+
[Property]
205+
public void EventScalesetResizeScheduled(EventScalesetResizeScheduled e) => Test(e);
206+
207+
[Property]
208+
public void EventScalesetStateUpdated(EventScalesetStateUpdated e) => Test(e);
209+
210+
[Property]
211+
public void EventNodeDeleted(EventNodeDeleted e) => Test(e);
212+
213+
[Property]
214+
public void EventNodeCreated(EventNodeCreated e) => Test(e);
215+
216+
[Property]
217+
public void EventMessage(DownloadableEventMessage e) => Test(e);
218+
}
219+
}

0 commit comments

Comments
 (0)