diff --git a/src/ApiService/ApiService/TestHooks/NodeOperationsTestHooks.cs b/src/ApiService/ApiService/TestHooks/NodeOperationsTestHooks.cs index be1e54405..7bccdafba 100644 --- a/src/ApiService/ApiService/TestHooks/NodeOperationsTestHooks.cs +++ b/src/ApiService/ApiService/TestHooks/NodeOperationsTestHooks.cs @@ -7,7 +7,6 @@ using Microsoft.OneFuzz.Service; using Microsoft.OneFuzz.Service.OneFuzzLib.Orm; - #if DEBUG namespace ApiService.TestHooks { @@ -186,9 +185,11 @@ namespace ApiService.TestHooks { numResults = int.Parse(query["numResults"]); } var r = _nodeOps.SearchStates(poolId, scaleSetId, states, poolName, excludeUpdateScheduled, numResults); - var resp = req.CreateResponse(HttpStatusCode.OK); - await resp.WriteStringAsync(JsonSerializer.Serialize(await r.ToListAsync(), EntityConverter.GetJsonSerializerOptions())); + + var json = JsonSerializer.Serialize(await r.ToListAsync(), EntityConverter.GetJsonSerializerOptions()); + var resp = req.CreateResponse(HttpStatusCode.OK); + await resp.WriteStringAsync(json); return resp; } diff --git a/src/ApiService/ApiService/TestHooks/NotificationOperationsTestHooks.cs b/src/ApiService/ApiService/TestHooks/NotificationOperationsTestHooks.cs new file mode 100644 index 000000000..58e5acf7e --- /dev/null +++ b/src/ApiService/ApiService/TestHooks/NotificationOperationsTestHooks.cs @@ -0,0 +1,82 @@ +using System.Net; +using System.Text.Json; +using System.Threading.Tasks; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Azure.Functions.Worker.Http; +using Microsoft.OneFuzz.Service; +using Microsoft.OneFuzz.Service.OneFuzzLib.Orm; + + +#if DEBUG +namespace ApiService.TestHooks { + public class NotificationOperationsTestHooks { + + private readonly ILogTracer _log; + private readonly IConfigOperations _configOps; + private readonly INotificationOperations _notificationOps; + + public NotificationOperationsTestHooks(ILogTracer log, IConfigOperations configOps, INotificationOperations notificationOps) { + _log = log.WithTag("TestHooks", nameof(NotificationOperationsTestHooks)); + _configOps = configOps; ; + _notificationOps = notificationOps; + } + + [Function("NewFilesTestHook")] + public async Task NewFiles([HttpTrigger(AuthorizationLevel.Anonymous, "put", Route = "testhooks/notificationOperations/newFiles")] HttpRequestData req) { + _log.Info("new files"); + var query = UriExtension.GetQueryComponents(req.Url); + + var container = query["container"]; + var fileName = query["fileName"]; + var failTaskOnTransientError = UriExtension.GetBoolValue("failTaskOnTransientError", query, true); + + await _notificationOps.NewFiles(new Container(container), fileName, failTaskOnTransientError); + var resp = req.CreateResponse(HttpStatusCode.OK); + return resp; + } + + [Function("GetNotificationsTestHook")] + public async Task GetNotifications([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "testhooks/notificationOperations/getNotifications")] HttpRequestData req) { + _log.Info("get notifications"); + + var s = await req.ReadAsStringAsync(); + + var query = UriExtension.GetQueryComponents(req.Url); + var container = query["container"]; + var notifications = _notificationOps.GetNotifications(new Container(container)); + + var json = JsonSerializer.Serialize(await notifications.ToListAsync(), EntityConverter.GetJsonSerializerOptions()); + var resp = req.CreateResponse(HttpStatusCode.OK); + await resp.WriteStringAsync(json); + return resp; + } + + [Function("GetQueueTasksTestHook")] + public async Task GetQueueTasksTestHook([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "testhooks/notificationOperations/getQueueTasks")] HttpRequestData req) { + + _log.Info("get queue tasks"); + var queueuTasks = _notificationOps.GetQueueTasks(); + + var json = JsonSerializer.Serialize(await queueuTasks.ToListAsync(), EntityConverter.GetJsonSerializerOptions()); + var resp = req.CreateResponse(HttpStatusCode.OK); + await resp.WriteStringAsync(json); + return resp; + } + + + [Function("GetRegressionReportTaskTestHook")] + public async Task GetRegressionReportTask([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "testhooks/notificationOperations/getRegressionReportTask")] HttpRequestData req) { + _log.Info("get regression report task"); + + var s = await req.ReadAsStringAsync(); + var report = JsonSerializer.Deserialize(s!, EntityConverter.GetJsonSerializerOptions()); + var task = (_notificationOps as NotificationOperations)!.GetRegressionReportTask(report); + + var json = JsonSerializer.Serialize(task, EntityConverter.GetJsonSerializerOptions()); + var resp = req.CreateResponse(HttpStatusCode.OK); + await resp.WriteStringAsync(json); + return resp; + } + } +} +#endif diff --git a/src/ApiService/ApiService/onefuzzlib/NotificationOperations.cs b/src/ApiService/ApiService/onefuzzlib/NotificationOperations.cs index 66b229b84..e93d22188 100644 --- a/src/ApiService/ApiService/onefuzzlib/NotificationOperations.cs +++ b/src/ApiService/ApiService/onefuzzlib/NotificationOperations.cs @@ -6,6 +6,8 @@ namespace Microsoft.OneFuzz.Service; public interface INotificationOperations : IOrm { Async.Task NewFiles(Container container, string filename, bool failTaskOnTransientError); + IAsyncEnumerable GetNotifications(Container container); + IAsyncEnumerable<(Task, IEnumerable)> GetQueueTasks(); } public class NotificationOperations : Orm, INotificationOperations { @@ -81,7 +83,7 @@ public class NotificationOperations : Orm, INotificationOperations .Where(taskTuple => taskTuple.Item2 != null)!; } - private async Async.Task GetRegressionReportTask(RegressionReport report) { + public async Async.Task GetRegressionReportTask(RegressionReport report) { if (report.CrashTestResult.CrashReport != null) { return await _context.TaskOperations.GetByJobIdAndTaskId(report.CrashTestResult.CrashReport.JobId, report.CrashTestResult.CrashReport.TaskId); } diff --git a/src/ApiService/Tests/OrmModelsTest.cs b/src/ApiService/Tests/OrmModelsTest.cs index a50b8f5cd..7f95eb157 100644 --- a/src/ApiService/Tests/OrmModelsTest.cs +++ b/src/ApiService/Tests/OrmModelsTest.cs @@ -911,6 +911,12 @@ namespace Tests { return Test(e); } + [Property] + public bool Container(Container c) { + return Test(c); + } + + /* //Sample function on how repro a failing test run, using Replay //functionality of FsCheck. Feel free to