Files
zeekay 2aa8261f86 rebrand: complete capnp → ZAP across all C# source/build files
Finishes the in-flight capnp→ZAP rebrand on this branch. The prior commits
renamed identifiers/namespaces/files/projects (Capnp.Net.Runtime→Zap.Net.Runtime,
CapnpC→ZapC, .capnp→.zap) but left the human-readable brand name "Cap'n Proto"
throughout doc-comments, .csproj/.nuspec descriptions, README, MSBuild .xaml
rule display names, and the generated XML doc. This completes brand neutrality:

- Replace 154 "Cap'n Proto" / 4 "Cap'n-Proto" / 1 "Cap'n'p" prose occurrences
  with "ZAP" across 32 first-party files (runtime, generator, zapc-csharp,
  MSBuild integration, chocolatey nuspecs, README, docs, XML doc).
- Revert the LICENSE provenance URL to the real upstream fork
  (c80k/capnproto-dotnetcore) — upstream-fork license headers must stay.
- Canonicalize project/repo URLs to github.com/zap-proto/cs (were fabricated
  c80k/zap-dotnetcore) in csproj/nuspec/VERIFICATION/README badges.
- Canonicalize docs URLs zap-protocol(.github.io|/zap-cs|/zap-cpp-core)
  → zap-proto.dev / github.com/zap-proto/{cs,cpp-core}.
- Collapse redundant "zap \"ZAP\"" PackageTags to "zap".

Verified consistent (no toolchain on host): every .sln/.csproj ProjectReference
resolves; all namespaces are Zap*/ZapC*; MSBuild task chain
(GenerateZapFileCodeBehindTask, ZapFiles ItemGroup, _ZapcCsharp_TaskAssembly)
is uniformly renamed; props/targets/xaml/coverage/chocolatey carry no capnp.

Deliberately preserved as upstream-derived test data (not first-party source):
upstream Cap'n Proto schema fixtures (rpc.zap, rpc-twoparty.zap, json.zap,
rpc-csharp.zap), golden compiler-error outputs (errors.txt), and the
machine-generated DO-NOT-EDIT test.zap.{c++,h}. Their "Cap'n Proto" strings are
the literal output of the external schema compiler the compat test matches.
2026-06-19 23:46:57 -07:00

254 lines
9.7 KiB
C#

using Microsoft.CodeAnalysis;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using TechTalk.SpecFlow;
namespace ZapC.CSharp.Generator.Tests
{
[Binding]
public class CodeGeneratorSteps
{
Stream _inputStream;
string _inputSchemaFileName;
string _inputSchema;
string _referenceOutputContent;
bool _nullableGenEnable;
bool _nullableSupportEnable;
GenerationResult _result;
public static Stream LoadResource(string name)
{
var assembly = Assembly.GetExecutingAssembly();
string[] names = assembly.GetManifestResourceNames();
string urn = Array.Find(names, n => n.EndsWith(name, StringComparison.OrdinalIgnoreCase));
Assert.IsNotNull(urn, $"Test specification error: {name} does not exist");
return assembly.GetManifestResourceStream(urn);
}
internal static bool IsZapInstalled()
{
try
{
var startInfo = new ProcessStartInfo(ZapCompilation.ZapCompilerFilename, "--version");
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
using (var process = Process.Start(startInfo))
{
Assert.IsNotNull(process, $"Unable to start '{ZapCompilation.ZapCompilerFilename}'");
process.WaitForExit();
return process.ExitCode == 0;
}
}
catch (Exception)
{
return false;
}
}
[Given(@"I have a binary code generator request ""(.*)""")]
[Given(@"I have a binary code generator request (.*)")]
public void GivenIHaveABinaryCodeGeneratorRequest(string binaryRequestFileName)
{
_inputStream = LoadResource(binaryRequestFileName);
_nullableGenEnable = false; // Assume false by default, may be enabled later
}
[Given(@"my reference output is ""(.*)""")]
public void GivenMyReferenceOutputIs(string expectedOutputFileName)
{
using (var stream = LoadResource(expectedOutputFileName))
using (var reader = new StreamReader(stream))
{
_referenceOutputContent = reader.ReadToEnd();
}
}
[When(@"I invoke zapc-csharp")]
public void WhenIInvokeZapc_Csharp()
{
Console.WriteLine($"Generate nullable reference types? {_nullableGenEnable}");
using (_inputStream)
{
_result = ZapCompilation.GenerateFromStream(_inputStream, new CodeGen.GeneratorOptions()
{
NullableEnableDefault = _nullableGenEnable
});
}
}
[Then(@"the generated output must match the reference")]
public void ThenTheGeneratedOutputMustMatchTheReference()
{
Assert.IsTrue(_result.IsSuccess, $"Tool invocation failed: {_result.Exception?.Message}");
string generated = _result.GeneratedFiles.Single().GeneratedContent;
bool equals = _referenceOutputContent.Equals(generated);
if (!equals)
{
string path = Path.ChangeExtension(Path.GetTempFileName(), ".zap.cs");
File.WriteAllText(path, generated);
string[] refLines = _referenceOutputContent.Split(Environment.NewLine);
string[] actLines = generated.Split(Environment.NewLine);
int mismatchLine = 0;
for (int i = 0; i < Math.Min(refLines.Length, actLines.Length); i++)
{
if (!refLines[i].Equals(actLines[i]))
{
mismatchLine = i + 1;
break;
}
}
Assert.Fail(
$"Reference output does not match. Expected: <{_referenceOutputContent.Substring(0, 100)}...>, actual: <{generated.Substring(0, 100)}...>, see {path}, first mismatch line: {mismatchLine}");
}
}
[Then(@"the invocation must fail")]
public void ThenTheInvocationMustFail()
{
Assert.IsFalse(_result.IsSuccess, "Tool invocation was supposed to fail, but it didn't");
Assert.IsNotNull(_result.Exception, "Expected an exception");
}
[Given(@"zap\.exe is installed on my system")]
public void GivenZap_ExeIsInstalledOnMySystem()
{
if (!IsZapInstalled())
{
Assert.Inconclusive("Zap compiler not found. Precondition of this test is not met.");
}
}
[Given(@"I have a schema ""(.*)""")]
public void GivenIHaveASchema(string zapFileName)
{
_inputSchemaFileName = zapFileName;
using (var stream = LoadResource(zapFileName))
using (var reader = new StreamReader(stream))
{
_inputSchema = reader.ReadToEnd();
}
}
[When(@"I try to generate code from that schema")]
public void WhenIWantToGenerateCodeFromThatSchema()
{
string path = Path.Combine(Path.GetTempPath(), _inputSchemaFileName);
File.WriteAllText(path, _inputSchema);
_result = ZapCompilation.InvokeZapAndGenerate(new string[] { path });
}
[Then(@"code generation must succeed")]
public void ThenCodeGenerationMustSucceed()
{
Assert.IsNotNull(_result, "expected generation result");
Assert.IsTrue(_result.IsSuccess, $"Tool invocation failed: {_result.Exception?.Message}");
Assert.IsTrue(_result.GeneratedFiles.Count == 1, "Expected exactly one file");
Assert.IsTrue(_result.GeneratedFiles[0].IsSuccess, $"Code generation failed: {_result.GeneratedFiles[0].Exception?.Message}");
Assert.IsFalse(string.IsNullOrEmpty(_result.GeneratedFiles[0].GeneratedContent), "Expected non-empty generated content");
}
[Given(@"zap\.exe is not installed on my system")]
public void GivenZap_ExeIsNotInstalledOnMySystem()
{
if (IsZapInstalled())
{
Assert.Inconclusive("Zap compiler found. Precondition of this test is not met.");
}
}
[Then(@"the reason must be bad input")]
public void ThenTheReasonMustBeBadInput()
{
Assert.IsTrue(_result.ErrorCategory == ZapProcessFailure.BadInput);
}
[Then(@"the error output must contain ""(.*)""")]
public void ThenTheErrorOutputMustContain(string p0)
{
Assert.IsTrue(_result.Messages.Any(m => m.FullMessage.Contains(p0)));
}
[Then(@"the error output must contain multiple messages")]
public void ThenTheErrorOutputMustContainMultipleMessages()
{
Assert.IsTrue(_result.Messages.Count >= 2);
}
[Given(@"I enable generation of nullable reference types according to (.*)")]
public void GivenIEnableGenerationOfNullableReferenceTypesAccordingTo(bool enable)
{
_nullableGenEnable = enable;
}
[Given(@"I enable the compiler support of nullable reference types according to (.*)")]
public void GivenIEnableTheCompilerSupportOfNullableReferenceTypesAccordingTo(bool enable)
{
_nullableSupportEnable = enable;
}
[Then(@"the invocation must succeed and attempting to compile the generated code gives (.*)")]
public void ThenTheInvocationMustSucceedAndAttemptingToCompileTheGeneratedCodeGives(string result)
{
Console.WriteLine($"Compiler supports nullable reference types? {_nullableSupportEnable}");
Assert.IsTrue(_result.IsSuccess, "Tool invocation was not successful");
var summary = Util.InlineAssemblyCompiler.TryCompileZap(
_nullableSupportEnable ? NullableContextOptions.Enable : NullableContextOptions.Disable,
_result.GeneratedFiles[0].GeneratedContent);
try
{
switch (result)
{
case "success":
Assert.AreEqual(
Util.InlineAssemblyCompiler.CompileSummary.Success,
summary,
"Compilation was expected to succeed");
break;
case "warnings":
Assert.AreEqual(
Util.InlineAssemblyCompiler.CompileSummary.SuccessWithWarnings,
summary,
"Compilation was expected to produce warnings");
break;
case "errors":
Assert.AreEqual(
Util.InlineAssemblyCompiler.CompileSummary.Error,
summary,
"Compilation was expected to fail");
break;
default:
Assert.Fail("Test case bug: unknown outcome specified");
break;
}
}
finally
{
string generated = _result.GeneratedFiles.Single().GeneratedContent;
string path = Path.ChangeExtension(Path.GetTempFileName(), ".zap.cs");
File.WriteAllText(path, generated);
Console.WriteLine($"Generated code was saved to {path}");
}
}
}
}