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

Commit

Permalink
Laying groundwork for TimerRepro implementation (#2168)
Browse files Browse the repository at this point in the history
* Add some pre-reqs for TimerRepro

* Format and add some API to creds

* PR comment
  • Loading branch information
tevoinea authored Jul 15, 2022
1 parent 3347e7e commit 7f90c13
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 45 deletions.
2 changes: 1 addition & 1 deletion src/ApiService/ApiService/OneFuzzTypes/Enums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ public static class ScalesetStateHelper {

public static class VmStateHelper {

private static readonly IReadOnlySet<VmState> _needsWork = new HashSet<VmState> { VmState.Init, VmState.Init, VmState.ExtensionsLaunch, VmState.Stopping };
private static readonly IReadOnlySet<VmState> _needsWork = new HashSet<VmState> { VmState.Init, VmState.ExtensionsLaunch, VmState.Stopping };
private static readonly IReadOnlySet<VmState> _available = new HashSet<VmState> { VmState.Init, VmState.ExtensionsLaunch, VmState.ExtensionsFailed, VmState.VmAllocationFailed, VmState.Running, };

public static IReadOnlySet<VmState> NeedsWork => _needsWork;
Expand Down
18 changes: 11 additions & 7 deletions src/ApiService/ApiService/OneFuzzTypes/Model.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,12 @@ public record Proxy
bool Outdated
) : StatefulEntityBase<VmState>(State);

public record Error(ErrorCode Code, string[]? Errors = null);
public record Error(ErrorCode Code, string[]? Errors = null) {
public sealed override string ToString() {
var errorsString = Errors != null ? string.Join("", Errors) : string.Empty;
return $"Error {{ Code = {Code}, Errors = {errorsString} }}";
}
};

public record UserInfo(Guid? ApplicationId, Guid? ObjectId, String? Upn);

Expand Down Expand Up @@ -413,7 +418,7 @@ NotificationTemplate Config
public record BlobRef(
string Account,
Container container,
string name
string Name
);

public record Report(
Expand All @@ -436,15 +441,15 @@ public record Report(
string? MinimizedStackFunctionNamesSha256,
List<string>? MinimizedStackFunctionLines,
string? MinimizedStackFunctionLinesSha256
);
) : IReport;

public record NoReproReport(
string InputSha,
BlobRef? InputBlob,
string? Executable,
Guid TaskId,
Guid JobId,
int Tries,
long Tries,
string? Error
);

Expand All @@ -456,7 +461,7 @@ public record CrashTestResult(
public record RegressionReport(
CrashTestResult CrashTestResult,
CrashTestResult? OriginalCrashTestResult
);
) : IReport;

public record NotificationTemplate(
AdoTemplate? AdoTemplate,
Expand All @@ -471,8 +476,7 @@ public record TeamsTemplate();
public record GithubIssuesTemplate();

public record Repro(
[PartitionKey] Guid VmId,
[RowKey] Guid _,
[PartitionKey][RowKey] Guid VmId,
Guid TaskId,
ReproConfig Config,
VmState State,
Expand Down
15 changes: 15 additions & 0 deletions src/ApiService/ApiService/onefuzzlib/Creds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ public interface ICreds {
public Uri GetInstanceUrl();
public Async.Task<Guid> GetScalesetPrincipalId();
public Async.Task<T> QueryMicrosoftGraph<T>(HttpMethod method, string resource);

public GenericResource ParseResourceId(string resourceId);

public Async.Task<GenericResource> GetData(GenericResource resource);
}

public class Creds : ICreds {
Expand Down Expand Up @@ -145,6 +149,17 @@ public async Task<T> QueryMicrosoftGraph<T>(HttpMethod method, string resource)
throw new GraphQueryException($"request did not succeed: HTTP {response.StatusCode} - {errorText}");
}
}

public GenericResource ParseResourceId(string resourceId) {
return ArmClient.GetGenericResource(new ResourceIdentifier(resourceId));
}

public async Async.Task<GenericResource> GetData(GenericResource resource) {
if (!resource.HasData) {
return await resource.GetAsync();
}
return resource;
}
}

class GraphQueryException : Exception {
Expand Down
30 changes: 16 additions & 14 deletions src/ApiService/ApiService/onefuzzlib/NotificationOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public NotificationOperations(ILogTracer log, IOnefuzzContext context)
public async Async.Task NewFiles(Container container, string filename, bool failTaskOnTransientError) {
var notifications = GetNotifications(container);
var hasNotifications = await notifications.AnyAsync();
var report = await _context.Reports.GetReportOrRegression(container, filename, expectReports: hasNotifications);
var reportOrRegression = await _context.Reports.GetReportOrRegression(container, filename, expectReports: hasNotifications);

if (!hasNotifications) {
return;
Expand All @@ -34,19 +34,19 @@ public async Async.Task NewFiles(Container container, string filename, bool fail
done.Add(notification.Config);

if (notification.Config.TeamsTemplate != null) {
NotifyTeams(notification.Config.TeamsTemplate, container, filename, report);
NotifyTeams(notification.Config.TeamsTemplate, container, filename, reportOrRegression!);
}

if (report == null) {
if (reportOrRegression == null) {
continue;
}

if (notification.Config.AdoTemplate != null) {
NotifyAdo(notification.Config.AdoTemplate, container, filename, report, failTaskOnTransientError);
NotifyAdo(notification.Config.AdoTemplate, container, filename, reportOrRegression, failTaskOnTransientError);
}

if (notification.Config.GithubIssuesTemplate != null) {
GithubIssue(notification.Config.GithubIssuesTemplate, container, filename, report);
GithubIssue(notification.Config.GithubIssuesTemplate, container, filename, reportOrRegression);
}
}

Expand All @@ -58,15 +58,17 @@ public async Async.Task NewFiles(Container container, string filename, bool fail
}
}

if (report?.Report != null) {
var reportTask = await _context.TaskOperations.GetByJobIdAndTaskId(report.Report.JobId, report.Report.TaskId);
if (reportOrRegression is Report) {
var report = (reportOrRegression as Report)!;
var reportTask = await _context.TaskOperations.GetByJobIdAndTaskId(report.JobId, report.TaskId);

var crashReportedEvent = new EventCrashReported(report.Report, container, filename, reportTask?.Config);
var crashReportedEvent = new EventCrashReported(report, container, filename, reportTask?.Config);
await _context.Events.SendEvent(crashReportedEvent);
} else if (report?.RegressionReport != null) {
var reportTask = await GetRegressionReportTask(report.RegressionReport);
} else if (reportOrRegression is RegressionReport) {
var regressionReport = (reportOrRegression as RegressionReport)!;
var reportTask = await GetRegressionReportTask(regressionReport);

var regressionEvent = new EventRegressionReported(report.RegressionReport, container, filename, reportTask?.Config);
var regressionEvent = new EventRegressionReported(regressionReport, container, filename, reportTask?.Config);
await _context.Events.SendEvent(regressionEvent);
} else {
await _context.Events.SendEvent(new EventFileAdded(container, filename));
Expand Down Expand Up @@ -96,15 +98,15 @@ public IAsyncEnumerable<Notification> GetNotifications(Container container) {
return null;
}

private void GithubIssue(GithubIssuesTemplate config, Container container, string filename, RegressionReportOrReport? report) {
private void GithubIssue(GithubIssuesTemplate config, Container container, string filename, IReport report) {
throw new NotImplementedException();
}

private void NotifyAdo(AdoTemplate config, Container container, string filename, RegressionReportOrReport report, bool failTaskOnTransientError) {
private void NotifyAdo(AdoTemplate config, Container container, string filename, IReport report, bool failTaskOnTransientError) {
throw new NotImplementedException();
}

private void NotifyTeams(TeamsTemplate config, Container container, string filename, RegressionReportOrReport? report) {
private void NotifyTeams(TeamsTemplate config, Container container, string filename, IReport report) {
throw new NotImplementedException();
}
}
33 changes: 12 additions & 21 deletions src/ApiService/ApiService/onefuzzlib/Reports.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
namespace Microsoft.OneFuzz.Service;

public interface IReports {
public Async.Task<RegressionReportOrReport?> GetReportOrRegression(Container container, string fileName, bool expectReports = false, params string[] args);
public Async.Task<IReport?> GetReportOrRegression(Container container, string fileName, bool expectReports = false, params string[] args);
}

public class Reports : IReports {
Expand All @@ -15,7 +15,7 @@ public Reports(ILogTracer log, IContainers containers) {
_containers = containers;
}

public async Async.Task<RegressionReportOrReport?> GetReportOrRegression(Container container, string fileName, bool expectReports = false, params string[] args) {
public async Async.Task<IReport?> GetReportOrRegression(Container container, string fileName, bool expectReports = false, params string[] args) {
var filePath = String.Join("/", new[] { container.ContainerName, fileName });
if (!fileName.EndsWith(".json", StringComparison.Ordinal)) {
if (expectReports) {
Expand All @@ -36,26 +36,20 @@ public Reports(ILogTracer log, IContainers containers) {
return ParseReportOrRegression(blob.ToString(), filePath, expectReports);
}

private RegressionReportOrReport? ParseReportOrRegression(string content, string? filePath, bool expectReports = false) {
try {
return new RegressionReportOrReport {
RegressionReport = JsonSerializer.Deserialize<RegressionReport>(content, EntityConverter.GetJsonSerializerOptions())
};
} catch (JsonException e) {
try {
return new RegressionReportOrReport {
Report = JsonSerializer.Deserialize<Report>(content, EntityConverter.GetJsonSerializerOptions())
};
} catch (JsonException e2) {
if (expectReports) {
_log.Error($"unable to parse report ({filePath}) as a report or regression. regression error: {e.Message} report error: {e2.Message}");
}
private IReport? ParseReportOrRegression(string content, string? filePath, bool expectReports = false) {
var regressionReport = JsonSerializer.Deserialize<RegressionReport>(content, EntityConverter.GetJsonSerializerOptions());
if (regressionReport == null || regressionReport.CrashTestResult == null) {
var report = JsonSerializer.Deserialize<Report>(content, EntityConverter.GetJsonSerializerOptions());
if (expectReports && report == null) {
_log.Error($"unable to parse report ({filePath}) as a report or regression");
return null;
}
return report;
}
return regressionReport;
}

private RegressionReportOrReport? ParseReportOrRegression(IEnumerable<byte> content, string? filePath, bool expectReports = false) {
private IReport? ParseReportOrRegression(IEnumerable<byte> content, string? filePath, bool expectReports = false) {
try {
var str = System.Text.Encoding.UTF8.GetString(content.ToArray());
return ParseReportOrRegression(str, filePath, expectReports);
Expand All @@ -68,7 +62,4 @@ public Reports(ILogTracer log, IContainers containers) {
}
}

public class RegressionReportOrReport {
public RegressionReport? RegressionReport { get; set; }
public Report? Report { get; set; }
}
public interface IReport { };
8 changes: 8 additions & 0 deletions src/ApiService/IntegrationTests/Fakes/TestCreds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,12 @@ public Task<Guid> GetScalesetPrincipalId() {
public Task<T> QueryMicrosoftGraph<T>(HttpMethod method, string resource) {
throw new NotImplementedException();
}

public GenericResource ParseResourceId(string resourceId) {
throw new NotImplementedException();
}

public Task<GenericResource> GetData(GenericResource resource) {
throw new NotImplementedException();
}
}
37 changes: 36 additions & 1 deletion src/ApiService/Tests/OrmModelsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,41 @@ public static Gen<Report> Report() {
);
}

public static Gen<NoReproReport> NoReproReport() {
return Arb.Generate<Tuple<string, BlobRef?, string?, Guid, int>>().Select(
arg =>
new NoReproReport(
arg.Item1,
arg.Item2,
arg.Item3,
arg.Item4,
arg.Item4,
arg.Item5,
arg.Item3
)
);
}

public static Gen<CrashTestResult> CrashTestResult() {
return Arb.Generate<Tuple<Report, NoReproReport>>().Select(
arg =>
new CrashTestResult(
arg.Item1,
arg.Item2
)
);
}

public static Gen<RegressionReport> RegressionReport() {
return Arb.Generate<Tuple<CrashTestResult, CrashTestResult?>>().Select(
arg =>
new RegressionReport(
arg.Item1,
arg.Item2
)
);
}

public static Gen<Container> Container() {
return Arb.Generate<Tuple<NonNull<string>>>().Select(
arg => new Container(string.Join("", arg.Item1.Get.Where(c => char.IsLetterOrDigit(c) || c == '-'))!)
Expand Down Expand Up @@ -801,7 +836,7 @@ public bool NotificationTemplate(NotificationTemplate e) {


[Property]
public bool RegressionReportOrReport(RegressionReportOrReport e) {
public bool RegressionReport(RegressionReport e) {
return Test(e);
}

Expand Down
1 change: 0 additions & 1 deletion src/ApiService/Tests/TimerReproTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ private static Repro GenerateRepro() {
return new Repro(
Guid.NewGuid(),
Guid.Empty,
Guid.Empty,
new ReproConfig(
new Container(String.Empty),
String.Empty,
Expand Down

0 comments on commit 7f90c13

Please sign in to comment.