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

Commit

Permalink
Add a field to the job summary to indicate if at least one bug was cr…
Browse files Browse the repository at this point in the history
…eated
  • Loading branch information
chkeita committed Oct 31, 2023
1 parent d50fd48 commit 88b2cb5
Show file tree
Hide file tree
Showing 11 changed files with 101 additions and 16 deletions.
12 changes: 5 additions & 7 deletions src/ApiService/ApiService/Functions/Jobs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,11 @@ private async Task<HttpResponseData> Get(HttpRequestData req) {
static JobTaskInfo TaskToJobTaskInfo(Task t) => new(t.TaskId, t.Config.Task.Type, t.State);

var tasks = _context.TaskOperations.SearchStates(jobId);
if (search.WithTasks ?? false) {
var ts = await tasks.ToListAsync();
return await RequestHandling.Ok(req, JobResponse.ForJob(job, ts));
} else {
var taskInfo = await tasks.Select(TaskToJobTaskInfo).ToListAsync();
return await RequestHandling.Ok(req, JobResponse.ForJob(job, taskInfo));
}

IAsyncEnumerable<IJobTaskInfo> taskInfo = search.WithTasks ?? false ? tasks : tasks.Select(TaskToJobTaskInfo);

var crashReported = await _context.JobCrashReportedOperations.CrashReported(jobId);
return await RequestHandling.Ok(req, JobResponse.ForJob(job, taskInfo.ToEnumerable(), crashReported));
}

var jobs = await _context.JobOperations.SearchState(states: search.State ?? Enumerable.Empty<JobState>()).ToListAsync();
Expand Down
4 changes: 4 additions & 0 deletions src/ApiService/ApiService/Functions/QueueJobResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ public async Async.Task Run([QueueTrigger("job-result", Connection = "AzureWebJo
var jobResultType = data.Type;
_log.LogInformation($"job result data type: {jobResultType}");

if (jobResultType == "CrashReported") {
var _result = await _context.JobCrashReportedOperations.ReportCrash(job.JobId, jr.TaskId);
}

Dictionary<string, double> value;
if (jr.Value.Count > 0) {
value = jr.Value;
Expand Down
7 changes: 5 additions & 2 deletions src/ApiService/ApiService/OneFuzzTypes/Model.cs
Original file line number Diff line number Diff line change
Expand Up @@ -968,9 +968,12 @@ public record Job(
StoredUserInfo? UserInfo,
string? Error = null,
DateTimeOffset? EndTime = null
) : StatefulEntityBase<JobState>(State) {
) : StatefulEntityBase<JobState>(State);

}
public record JobCrashReported(
[PartitionKey] Guid JobId,
[RowKey] Guid TaskId
) : EntityBase;

// This is like UserInfo but lacks the UPN:
public record StoredUserInfo(Guid? ApplicationId, Guid? ObjectId);
Expand Down
9 changes: 6 additions & 3 deletions src/ApiService/ApiService/OneFuzzTypes/Responses.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ public record ContainerInfo(
Uri SasUrl
) : BaseResponse();


public record JobResponse(
Guid JobId,
JobState State,
Expand All @@ -101,10 +102,11 @@ public record JobResponse(
IEnumerable<IJobTaskInfo>? TaskInfo,
StoredUserInfo? UserInfo,
[property: JsonPropertyName("Timestamp")] // must retain capital T for backcompat
DateTimeOffset? Timestamp
DateTimeOffset? Timestamp,
bool CrashReported
// not including UserInfo from Job model
) : BaseResponse() {
public static JobResponse ForJob(Job j, IEnumerable<IJobTaskInfo>? taskInfo)
public static JobResponse ForJob(Job j, IEnumerable<IJobTaskInfo>? taskInfo, bool crashReported = false)
=> new(
JobId: j.JobId,
State: j.State,
Expand All @@ -113,7 +115,8 @@ public static JobResponse ForJob(Job j, IEnumerable<IJobTaskInfo>? taskInfo)
EndTime: j.EndTime,
TaskInfo: taskInfo,
UserInfo: j.UserInfo,
Timestamp: j.Timestamp
Timestamp: j.Timestamp,
CrashReported: crashReported
);
public DateTimeOffset? StartTime => EndTime is DateTimeOffset endTime ? endTime.Subtract(TimeSpan.FromHours(Config.Duration)) : null;
}
Expand Down
5 changes: 3 additions & 2 deletions src/ApiService/ApiService/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ namespace Microsoft.OneFuzz.Service;
public class Program {

/// <summary>
///
///
/// </summary>
public class LoggingMiddleware : IFunctionsWorkerMiddleware {
/// <summary>
///
///
/// </summary>
/// <param name="context"></param>
/// <param name="next"></param>
Expand Down Expand Up @@ -198,6 +198,7 @@ public static async Async.Task Main() {
.AddScoped<INodeMessageOperations, NodeMessageOperations>()
.AddScoped<ISubnet, Subnet>()
.AddScoped<IAutoScaleOperations, AutoScaleOperations>()
.AddScoped<IJobCrashReportedOperations, JobCrashReportedOperations>()
.AddSingleton<GraphServiceClient>(new GraphServiceClient(new DefaultAzureCredential()))
.AddSingleton<DependencyTrackingTelemetryModule>()
.AddSingleton<ICreds, Creds>()
Expand Down
28 changes: 28 additions & 0 deletions src/ApiService/ApiService/onefuzzlib/JobCrashReported.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System.Threading.Tasks;
using ApiService.OneFuzzLib.Orm;
using Microsoft.Extensions.Logging;
namespace Microsoft.OneFuzz.Service;

public interface IJobCrashReportedOperations : IOrm<JobCrashReported> {
public Task<bool> CrashReported(Guid jobId);
public Task<OneFuzzResultVoid> ReportCrash(Guid jobId, Guid taskId);
}

public class JobCrashReportedOperations : Orm<JobCrashReported>, IJobCrashReportedOperations {
public JobCrashReportedOperations(ILogger<JobCrashReportedOperations> logTracer, IOnefuzzContext context) : base(logTracer, context) {
}

public async Task<bool> CrashReported(Guid jobId) {
return await QueryAsync(Query.RowKey(jobId.ToString())).AnyAsync();
}

public async Task<OneFuzzResultVoid> ReportCrash(Guid jobId, Guid taskId) {

var result = await Update(new JobCrashReported(jobId, taskId));
if (!result.IsOk) {
return OneFuzzResultVoid.Error(ErrorCode.UNABLE_TO_UPDATE, "Failed to update job crash reported");
}

return OneFuzzResultVoid.Ok;
}
}
3 changes: 2 additions & 1 deletion src/ApiService/ApiService/onefuzzlib/OnefuzzContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public interface IOnefuzzContext {
ITeams Teams { get; }
IGithubIssues GithubIssues { get; }
IAdo Ado { get; }

IJobCrashReportedOperations JobCrashReportedOperations { get; }
IFeatureManagerSnapshot FeatureManagerSnapshot { get; }
IConfigurationRefresher ConfigurationRefresher { get; }
}
Expand Down Expand Up @@ -101,6 +101,7 @@ public OnefuzzContext(IServiceProvider serviceProvider) {
public ITeams Teams => _serviceProvider.GetRequiredService<ITeams>();
public IGithubIssues GithubIssues => _serviceProvider.GetRequiredService<IGithubIssues>();
public IAdo Ado => _serviceProvider.GetRequiredService<IAdo>();
public IJobCrashReportedOperations JobCrashReportedOperations => _serviceProvider.GetRequiredService<IJobCrashReportedOperations>();

public IFeatureManagerSnapshot FeatureManagerSnapshot => _serviceProvider.GetRequiredService<IFeatureManagerSnapshot>();

Expand Down
2 changes: 1 addition & 1 deletion src/ApiService/ApiService/onefuzzlib/notifications/Ado.cs
Original file line number Diff line number Diff line change
Expand Up @@ -663,8 +663,8 @@ public async Async.Task Process(IList<(string, string)> notificationInfo, bool i
_logTracer.AddTags(notificationInfo);
_logTracer.AddTag("WorkItemId", entry.Id.HasValue ? entry.Id.Value.ToString() : "");
_logTracer.LogEvent(adoEventType);
}
}
}

private static bool IsADODuplicateWorkItem(WorkItem wi, Dictionary<string, string>? duplicateFields) {
// A work item could have System.State == Resolve && System.Reason == Duplicate
Expand Down
25 changes: 25 additions & 0 deletions src/ApiService/IntegrationTests/Fakes/TestContext.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using Microsoft.Extensions.Caching.Memory;
Expand Down Expand Up @@ -42,6 +43,7 @@ public TestContext(IHttpClientFactory httpClientFactory, OneFuzzLoggerProvider p
ReproOperations = new ReproOperations(provider.CreateLogger<ReproOperations>(), this);
Reports = new Reports(provider.CreateLogger<Reports>(), Containers);
NotificationOperations = new NotificationOperations(provider.CreateLogger<NotificationOperations>(), this);
JobCrashReportedOperations = new JobCrashReportedOperations(provider.CreateLogger<JobCrashReportedOperations>(), this);

FeatureManagerSnapshot = new TestFeatureManagerSnapshot();
WebhookOperations = new TestWebhookOperations(httpClientFactory, provider.CreateLogger<WebhookOperations>(), this);
Expand All @@ -65,9 +67,28 @@ public Async.Task InsertAll(params EntityBase[] objs)
InstanceConfig ic => ConfigOperations.Insert(ic),
Notification n => NotificationOperations.Insert(n),
Webhook w => WebhookOperations.Insert(w),
JobCrashReported crashReported => JobCrashReportedOperations.Insert(crashReported),
_ => throw new NotSupportedException($"You will need to add an TestContext.InsertAll case for {x.GetType()} entities"),
}));

public Async.Task InsertAll(IEnumerable<EntityBase> objs)
=> Async.Task.WhenAll(
objs.Select(x => x switch {
Task t => TaskOperations.Insert(t),
Node n => NodeOperations.Insert(n),
Pool p => PoolOperations.Insert(p),
Job j => JobOperations.Insert(j),
JobResult jr => JobResultOperations.Insert(jr),
Repro r => ReproOperations.Insert(r),
Scaleset ss => ScalesetOperations.Insert(ss),
NodeTasks nt => NodeTasksOperations.Insert(nt),
InstanceConfig ic => ConfigOperations.Insert(ic),
Notification n => NotificationOperations.Insert(n),
Webhook w => WebhookOperations.Insert(w),
JobCrashReported crashReported => JobCrashReportedOperations.Insert(crashReported),
_ => throw new NotSupportedException($"You will need to add an TestContext.InsertAll case for {x.GetType()} entities"),
}));

// Implementations:

public IMemoryCache Cache { get; }
Expand Down Expand Up @@ -109,6 +130,8 @@ public Async.Task InsertAll(params EntityBase[] objs)

public IWebhookMessageLogOperations WebhookMessageLogOperations { get; }

public IJobCrashReportedOperations JobCrashReportedOperations {get;}

// -- Remainder not implemented --

public IConfig Config => throw new System.NotImplementedException();
Expand Down Expand Up @@ -143,4 +166,6 @@ public Async.Task InsertAll(params EntityBase[] objs)
public IAdo Ado => throw new NotImplementedException();

public IConfigurationRefresher ConfigurationRefresher => throw new NotImplementedException();


}
21 changes: 21 additions & 0 deletions src/ApiService/IntegrationTests/JobsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -226,4 +226,25 @@ await Context.InsertAll(
Assert.Equal(task.Config.Task.Type, returnedTasks[0].Type);

}

[Fact]
public async Async.Task Get_CanFindSpecificJobWithBugs() {
var taskConfig = new TaskConfig(_jobId, new List<Guid>(), new TaskDetails(TaskType.Coverage, 60));
await Context.InsertAll(
new Job(_jobId, JobState.Stopped, _config, null),
new Task(_jobId, Guid.NewGuid(), TaskState.Running, Os.Windows, taskConfig),
new JobCrashReported(_jobId, Guid.NewGuid())
);

var func = new Jobs(Context, LoggerProvider.CreateLogger<Jobs>());

var ctx = new TestFunctionContext();
var result = await func.Run(TestHttpRequestData.FromJson("GET", new JobSearch(JobId: _jobId)), ctx);
Assert.Equal(HttpStatusCode.OK, result.StatusCode);

var response = BodyAs<JobResponse>(result);
Assert.Equal(_jobId, response.JobId);
Assert.NotNull(response.TaskInfo);
Assert.True(response.CrashReported);
}
}
1 change: 1 addition & 0 deletions src/pytypes/onefuzztypes/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,7 @@ class Job(BaseModel):
task_info: Optional[List[Union[Task, JobTaskInfo]]]
user_info: Optional[UserInfo]
start_time: Optional[datetime] = None
crash_reported: Optional[bool] = None


class NetworkConfig(BaseModel):
Expand Down

0 comments on commit 88b2cb5

Please sign in to comment.