I have a simple Service Bus trigger and I can develop with it on Windows without any issue. But when I am using the trigger on my Mac I get this error:
Put token failed. status-code: 401, status-description: InvalidSignature: The token has an invalid signature..
Message processing error (Action=Receive, ClientId=MessageReceiver1my-topic/Subscriptions/my-sub, EntityPath=my-topic/Subscriptions/my-sub, Endpoint=my-dev.servicebus.windows.net)
The function is the boiler plate Service Bus function:
namespace MyApp.Functions;
public static class MyFunction
{
[Function("MyFunction")]
public static void Run([ServiceBusTrigger("my-topic", "my-sub", Connection = "ServiceBusConnection")] string mySbMsg,
FunctionContext context)
{
var logger = context.GetLogger("MyFunction");
logger.LogInformation($"C# ServiceBus topic trigger function processed message: {mySbMsg}");
}
}
I updated my nuget packages to the following:
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.10.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.0.13" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.ServiceBus" Version="5.7.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Timer" Version="4.1.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.7.0" />
I have copied my local.settings.json so that it matches what's on my Windows machine which runs fine.
UPDATE After much testing, this only appears to be happening when running from Rider OR Visual Studio. I have the Azure tools installed and all other functions work correctly. If I run func start it runs fine.
How do I fix this issue?
Related
Currently I am trying to develop a C# (ASP.NET MVC) web application on a macOS, I am running on .NET 6.0.402
When I run dotnet ef update database to update my database I get this error:
Method not found: 'System.Collections.Generic.IList`1<Microsoft.EntityFrameworkCore.Metadata.Conventions.IModelFinalizingConvention> Microsoft.EntityFrameworkCore.Metadata.Conventions.ConventionSet.get_ModelFinalizingConventions()'.
I did fiddle with my Migrations-> [serial]_[name].designer.cs file since it did not auto-generate the information to match the model I had when I ran dotnet ef migrations add.
Jokes.cs (Model)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace JokeWebApp.Models
{
public class Joke
{
public int Id { get; set; }
public string? JokeQuestion { get; set; }
public string? JokeAnswer { get; set; }
//ctor shortcut for constructor
public Joke()
{
}
}
}
20221109024428_initialsetup.Designer.cs (Data->Migrations)
// <auto-generated />
using System;
using JokeWebApp.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace JokeWebApp.Data.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20221109024428_initialsetup")]
partial class initialsetup
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "6.0.10")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("JokeWebApp.Models.Joke", b =>
{
b.Property<int>("Id").ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("JokeAnswer")
.HasColumnType("nvarchar(max)");
b.Property<string>("JokeQuestion")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Joke");
});
...
Project.csproj
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>aspnet-JokeWebApp-c27aee20-1e9d-4266-993b-368018ae336f</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<None Update="app.db" CopyToOutputDirectory="PreserveNewest" ExcludeFromSingleFile="true" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="6.0.10" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.10" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="6.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.10" />
</ItemGroup>
</Project>
I am not sure if I am missing a required package or I messed up somewhere in my fiddling of the designer.cs file.
Can somebody point me in the right direction?
I made sure the package references in my Project.csproj were up to date. Wondering if there may be some discrepency with:
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.0" />
The other packages has a version of "6.0.10", not sure if I should put that for the version for the Microsoft.EntityFrameworkCore.SqlServer.SqlServer since it was a package I downloaded in order to have access to
SqlServerValueGenerationStrategy.IdentityColumn .
I also read on another thread the issue may be due to an old version of DLL. How do I make sure that everything is the latest files, what are the built items I need to delete before I can rebuild the application?
The NuGet version 7.0.0 onwards of EntityFrameworkCore, only works if you have the NET 7.0 version installed, so in your case you must update again to 6.0.13, which is the latest version to date. I had the same problem so I hope you were able to finally fix it by installing NET 7.0 or going back to the old references.
Slowly migrating system up from .net core 2.1 to 3.1.
While updating IdentityServer4 to 3.1 version.
I've stucked into problem method AddIdentityServer where options are specified..
var builder = services.AddIdentityServer(options =>
{
(!string.IsNullOrWhiteSpace(identityServerSettingsConfig.PublicOrigin))
{
options.PublicOrigin = identityServerSettingsConfig.PublicOrigin;
}
})
Error: 'IdentityServerOptions' does not contain a definition for 'PublicOrigin' and no accessible extension method 'PublicOrigin' accepting a first argument of type 'IdentityServerOptions' could be found
Installed packages:
<PackageReference Include="IdentityServer4" Version="4.1.2" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="4.1.2" />
<PackageReference Include="IdentityServer4.EntityFramework" Version="2.5.3" />
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.5" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="3.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.0">
The IdentityServerOptions.PublicOrigin property was removed in IdentityServer4 1.0 back in 2016.
This GitHub issue is asking the same question as yourself: https://github.com/IdentityServer/IdentityServer4/issues/4535
One of IdentityServer's authors said it was removed and explained why - and how you can work-around it (assuming you actually need it, I mention this because you probably don't need to restore this functionality):
leastprivilege commented on 19 Jun 2020:
It's gone. It was a hack - please use the forwarded headers approach in ASP.NET Core from now on.
The workaround is to add a middleware step that calls HttpContextExtensions.SetIdentityServerOrigin at the beginning of your pipeline, so it should look something like this:
In the code-block below, add the code between the //------- comments.
I included other Configure pipeline/appBuilder methods from one of my own IS4 projects so you can see a complete example.
using IdentityServer4.Extensions; // For IS4's `HttpContextExtensions`
public class Startup
{
// ...
public void Configure( IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime applicationLifetime )
{
_ = app
//-------------------------------- Add the code below this line
.Use( async (ctx, next) =>
{
ctx.SetIdentityServerOrigin( "https://example.com" );
await next();
})
//-------------------------------- Add the code above this line
.UseCors()
.UseAuthentication()
.UseOpenApi()
.UseSwaggerUi3()
.UseIdentityServer()
.UseRouting()
.UseAuthorization()
.UseEndpoints( routeBuilder =>
{
_ = routeBuilder.MapControllers();
} )
.UseStaticFiles();
}
}
I have a solution name BugDemo consisting of 2 projects. Here is the github repo.
a class library named Data.
an Asp.Net Core Minimal Api named Api referencing Data project. I set Api project as the startup project.
I use User Secret to share secret.json between these 2 projects.
{
"ConnectionStrings": {
"DefaultConnection": "Server=.;Database=BugDemoDb;Integrated Security=true;TrustServerCertificate=true"
}
}
I successfully generated the database with the following (executed from solution directory):
dotnet ef migrations add Initialization --startup-project Data --project Data
dotnet ef database update --startup-project Data
I attempted to invoke scaffolding with the following:
$env:codegen_trace=1
dotnet-aspnet-codegenerator minimalapi --project api
And I got the following errors:
Line: minimalapi --project api Trace: Executing external command:
dotnet msbuild C:\Projects\BugDemo\api\Api.csproj
/t:EvaluateProjectInfoForCodeGeneration
/p:OutputFile=C:\Users\amd\AppData\Local\Temp\wybiwf1d.d4d;CodeGenerationTargetLocation=C:\Users\amd.dotnet\tools.store\dotnet-aspnet-codegenerator\7.0.0-rc.1.22452.2\dotnet-aspnet-codegenerator\7.0.0-rc.1.22452.2\tools\net7.0\any;Configuration=Debug -restore
Building project ... Trace: Executing external command: dotnet build
C:\Projects\BugDemo\api\Api.csproj --configuration Debug --framework
net7.0
Trace: Executing external command: dotnet exec --runtimeconfig
C:\Projects\BugDemo\api\bin\Debug\net7.0\Api.runtimeconfig.json
--depsfile C:\Projects\BugDemo\api\bin\Debug\net7.0\Api.deps.json C:\Users\amd.nuget\packages\microsoft.visualstudio.web.codegeneration.design\7.0.0-rc.1.22452.2\lib\net7.0\dotnet-aspnet-codegenerator-design.dll
--no-dispatch --port-number 62322 minimalapi --project api --dispatcher-version 7.0.0-rc.1.22452.2
Trace: Command Line: --no-dispatch --port-number 62322 minimalapi
--project api --dispatcher-version 7.0.0-rc.1.22452.2 Scaffolding failed. Could not load information for project ..\Data\Data.csproj
Trace: at
Microsoft.VisualStudio.Web.CodeGeneration.Utils.RoslynWorkspaceHelper.GetProjectReferenceInformation(IEnumerable1 projectReferenceStrings) at Microsoft.VisualStudio.Web.CodeGeneration.Utils.RoslynWorkspace..ctor(IProjectContext projectInformation, String configuration) at Microsoft.VisualStudio.Web.CodeGeneration.Design.CodeGenCommandExecutor.AddFrameworkServices(ServiceProvider serviceProvider, IProjectContext projectInformation) at Microsoft.VisualStudio.Web.CodeGeneration.Design.CodeGenCommandExecutor.Execute(Action1
simModeAction) at
Microsoft.VisualStudio.Web.CodeGeneration.Design.Program.<>c__DisplayClass4_0.<b__0>d.MoveNext()
RunTime 00:00:12.60
Project Api
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>b3fdc987-781a-4fd4-853d-e279524cb5c6</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.0-rc.1.22427.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.0-rc.1.22426.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.0-rc.1.22426.7">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="7.0.0-rc.1.22452.2" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Data\Data.csproj" />
</ItemGroup>
</Project>
using Data;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddDbContext<AppDbContext>(opts =>
{
opts.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"));
});
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.MapGet("/", async (AppDbContext ctx) =>
{
return await ctx.Students.ToListAsync();
});
app.Run();
Project Data
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UserSecretsId>b3fdc987-781a-4fd4-853d-e279524cb5c6</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.0-rc.1.22426.7">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.0-rc.1.22426.7" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0-rc.1.22426.10" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="7.0.0-rc.1.22452.2" />
</ItemGroup>
</Project>
namespace Data;
public class Student
{
public int Id { get; set; }
public string Name { get; set; } = default!;
}
using Microsoft.EntityFrameworkCore;
namespace Data;
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> opts) : base(opts) { }
public DbSet<Student> Students { get; set; }
protected override void OnModelCreating(ModelBuilder mb)
{
base.OnModelCreating(mb);
mb.Entity<Student>().HasData(new Student[]
{
new Student{ Id=1,Name="Albert Einstein"},
new Student{ Id=2,Name="Isaac Newton"},
new Student{ Id=3,Name="Blaise Pascal"},
new Student{ Id=4,Name="Nicola Tesla"}
});
}
}
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
namespace Data;
public class AppDesignTimeDbContextFactory : IDesignTimeDbContextFactory<AppDbContext>
{
public AppDbContext CreateDbContext(string[] args)
{
IConfiguration config = new ConfigurationBuilder()
.AddUserSecrets<Data.AppDesignTimeDbContextFactory>()
.Build();
var opts = new DbContextOptionsBuilder<AppDbContext>();
opts.UseSqlServer(config.GetConnectionString("DefaultConnection"));
return new AppDbContext(opts.Options);
}
}
Question
How to fix this issue?
The issue is fixed in Visual Studio version - 17.3.4 and above. Currenly the latest one is 17.3.4
The problem was that during scaffolding the CodeGeneration library was downgraded from 6.0.10 to 6.0.9.
With the fix it is not downgrading anymore and it works properly.
https://github.com/dotnet/Scaffolding/issues/2034
I've raised that to the project community. There is an issue with downgrading the version of the Microsoft.VisualStudio.Web.CodeGeneration.Design library during scaffolding. As I understand how the discussion ended - they assigned the issue to a developer and in future will be fixed(as I can see in next major version).
You can follow the it in github.
The scaffolding project during the process of scaffolding updates the libraries of the projects and do a build behind the scene. And wrongly downgrading their own project version.
My workaround is to create a clean new project with pre-configured Identity, scaffolding what I need and copy the results to my project.
Works perfect.
I am trying to add logging functionalities to a .Net Core 3.1 Console application using Serilog. I have setup the Logger configuration in the code itself (not appsettings.json as of now). I have tried various combinations, but, to my surprise, every time it is logging to the Console window only but not to the file.
I have enclosed the Logger inside using block as suggested in few articles but still no luck. Could you please let me know what I am missing here? Thanks.
Here is my Main Method:
public static async Task Main(string[] args)
{
using (var logger = BuildSerilog())
{
try
{
logger.Information("It's logging to the console but not in the file.");
}
catch (Exception ex)
{
logger.Fatal(ex, "Application crashed");
}
}
}
private static Logger BuildSerilog()
{
var logger = new LoggerConfiguration()
.WriteTo.File("app.log")
.WriteTo.Console()
.CreateLogger();
Log.Logger = logger;
return logger;
}
Nuget Packages referenced in the project:
<PackageReference Include="Serilog" Version="2.9.0" />
<PackageReference Include="Serilog.AspNetCore" Version="3.2.0" />
<PackageReference Include="Serilog.Extensions.Logging" Version="3.0.1" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
I have a function that I'm porting from Azure Functions v1 to v2, and as part of that I've run into an issue updating my unit tests which create a stubbed HttpRequestMessage. Here's the code that works on Functions v1, targeting .NET Framework 4.7
public class FunctionExample
{
[FunctionName(nameof(SomeFunction))]
public static async Task<HttpResponseMessage> SomeFunction
(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "SomeFunction")]
HttpRequestMessage request
)
{
var body = await request.Content.ReadAsStringAsync();
if (string.IsNullOrEmpty(body))
{
return request.CreateResponse(HttpStatusCode.BadRequest, "Bad job");
}
else
{
return request.CreateResponse(HttpStatusCode.OK, "Good job");
}
}
}
And my test code
public class FunctionExampleTests
{
[Test]
public async Task TestSomeFunction()
{
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("http://localhost/"),
Content = new StringContent("", Encoding.UTF8, "application/json")
};
request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey,
new HttpConfiguration());
var response = await FunctionExample.SomeFunction(request);
var content = await response.Content.ReadAsStringAsync();
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest));
Assert.That(content, Is.EqualTo("\"Bad job\""));
}
}
After porting to v2, my function project csproj file looks like this. The only differences are that I'm no longer targeting full framework, and the addition of the AzureFunctionsVersion node.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AzureFunctionsVersion>v2</AzureFunctionsVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="1.0.24" />
</ItemGroup>
</Project>
And this is the csproj for my test project after retargeting to .NET Core 2.0
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="nunit" Version="3.11.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FunctionExample\FunctionExample.csproj" />
</ItemGroup>
</Project>
Previously, I was using the answers to this question to properly stub out HttpRequestMessage but that no longer appears to work.
When I try to compile this, I get the following compilation errors
Error CS0246 The type or namespace name 'HttpConfiguration' could not be found (are you missing a using directive or an assembly reference?)
Error CS0103 The name 'HttpPropertyKeys' does not exist in the current context
So if I just remove the line, hoping that the fix is no longer needed
request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration());
Instead I get this error message
System.InvalidOperationException : The HttpRequestMessage instance is not properly initialized. Use HttpRequestMessageHttpContextExtensions.GetHttpRequestMessage to create an HttpRequestMessage for the current request.
Trying to follow the error message's directions didn't prove fruitful to me, I tried to set the HttpContext like was done in this question
request.Properties.Add(nameof(HttpContext), new DefaultHttpContext());
But that gave me a different error (same as in the question)
System.ArgumentNullException : Value cannot be null.
Parameter name: provider
Azure Functions is somewhat based on ASP.NET MVC WebApi, which has had some changes for .NET Core. HttpConfiguration for example doesn't appear to be available in any packages that target .NET Core/Standard. In order to fix this, I had to install a couple of packages in my test project, namely Microsoft.AspNetCore.Mvc for AddMvc() and Microsoft.AspNetCore.Mvc.WebApiCompatShim for .AddWebApiConventions(), which:
Provides compatibility in ASP.NET Core MVC with ASP.NET Web API 2 to simplify migration of existing Web API implementations
So I added these to my test project
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.WebApiCompatShim" Version="2.2.0" />
and now my test project looks like this
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="nunit" Version="3.11.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.WebApiCompatShim" Version="2.2.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FunctionExampleFunction\FunctionExampleFunction.csproj" />
</ItemGroup>
</Project>
To mock the services that the ArgumentNullException was implying were missing (which in this case I think are MediaTypeFormatters), I had to essentially bootstrap MVC to get the HttpContext initialized properly.
[Test]
public async Task TestSomeFunction()
{
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("http://localhost/"),
Content = new StringContent("", Encoding.UTF8, "application/json")
};
var services = new ServiceCollection()
.AddMvc()
.AddWebApiConventions()
.Services
.BuildServiceProvider();
request.Properties.Add(nameof(HttpContext), new DefaultHttpContext
{
RequestServices = services
});
var response = await FunctionExample.SomeFunction(request);
var content = await response.Content.ReadAsStringAsync();
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest));
Assert.That(content, Is.EqualTo("\"Bad job\""));
}
And that makes the test compile, run, and pass.