Stufe 4c (#764): Bezeichner auf Englisch - Typen, Methoden, Felder, Parameter, Locals, Testnamen

Mit Roslyn umbenannt (Verweise folgen, Zeichenketten bleiben unberuehrt).
Nicht umbenannt, weil gespeichert oder ueber die API gebunden (Stufe 4e):
Properties, Record-Parameter, Enum-Member sowie die Parameter der
Endpunkt-Handler (Routen-/Query-Bindung ueber den Namen). Die JSON-Felder
anonymer Objekte bleiben ausdruecklich benannt (JsonFilter: pfad).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-10-04 13:18:43 +02:00
co-authored by Claude Opus 5.5
parent 837a634a22
commit 77062facc9
190 changed files with 4813 additions and 4813 deletions
@@ -36,7 +36,7 @@ public sealed class AtomicFileTests : IDisposable
// ═══════════════════════════════════════════════════════════
[Fact]
public void Inhalt_wird_geschrieben()
public void Content_is_written()
{
var path = Path_("datei.json");
@@ -46,7 +46,7 @@ public sealed class AtomicFileTests : IDisposable
}
[Fact]
public void Eine_bestehende_Datei_wird_ersetzt()
public void An_existing_file_is_replaced()
{
var path = Path_("datei.json");
File.WriteAllText(path, "alter Inhalt der deutlich laenger ist");
@@ -57,7 +57,7 @@ public sealed class AtomicFileTests : IDisposable
}
[Fact]
public void Fehlende_Verzeichnisse_werden_angelegt()
public void Missing_directories_are_created()
{
var path = Path_(Path.Combine("a", "b", "c", "datei.json"));
@@ -67,7 +67,7 @@ public sealed class AtomicFileTests : IDisposable
}
[Fact]
public void Es_bleiben_keine_Nebendateien_zurueck()
public void No_side_files_are_left_behind()
{
var path = Path_("datei.json");
@@ -78,7 +78,7 @@ public sealed class AtomicFileTests : IDisposable
}
[Fact]
public void Umlaute_und_Emoji_werden_als_UTF8_ohne_BOM_geschrieben()
public void Umlauts_and_emoji_are_written_as_UTF8_without_BOM()
{
var path = Path_("datei.txt");
const string content = "Grüße aus München 🦀";
@@ -91,7 +91,7 @@ public sealed class AtomicFileTests : IDisposable
}
[Fact]
public async Task Die_asynchrone_Fassung_verhaelt_sich_gleich()
public async Task The_async_version_behaves_the_same()
{
var path = Path_("datei.json");
@@ -111,29 +111,29 @@ public sealed class AtomicFileTests : IDisposable
/// only see a complete document.
/// </summary>
[Fact]
public async Task Waehrend_des_Schreibens_wird_nie_ein_halber_Inhalt_sichtbar()
public async Task While_writing_half_content_is_never_visible()
{
var path = Path_("gross.json");
var klein = JsonSerializer.Serialize(Enumerable.Range(0, 50).Select(i => $"eintrag-{i}"));
var gross = JsonSerializer.Serialize(Enumerable.Range(0, 20_000).Select(i => $"eintrag-{i}"));
var small = JsonSerializer.Serialize(Enumerable.Range(0, 50).Select(i => $"eintrag-{i}"));
var large = JsonSerializer.Serialize(Enumerable.Range(0, 20_000).Select(i => $"eintrag-{i}"));
AtomicFile.WriteAllText(path, klein);
AtomicFile.WriteAllText(path, small);
var fehler = 0;
var gelesen = 0;
var error = 0;
var readBack = 0;
// Hard time limit, so an error in the writer does not leave the test hanging.
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(20));
var schreiber = Task.Run(async () =>
var writer = Task.Run(async () =>
{
try
{
// #722: Writing continues until the reader has seen enough — not a fixed
// number of times. Under parallel load the reader otherwise only got five looks.
for (var i = 0; (i < 40 || Volatile.Read(ref gelesen) < 20) && !cts.IsCancellationRequested; i++)
for (var i = 0; (i < 40 || Volatile.Read(ref readBack) < 20) && !cts.IsCancellationRequested; i++)
{
AtomicFile.WriteAllText(path, i % 2 == 0 ? gross : klein);
AtomicFile.WriteAllText(path, i % 2 == 0 ? large : small);
await Task.Delay(1);
}
}
@@ -143,7 +143,7 @@ public sealed class AtomicFileTests : IDisposable
}
});
var leser = Task.Run(async () =>
var reader = Task.Run(async () =>
{
while (!cts.IsCancellationRequested)
{
@@ -151,15 +151,15 @@ public sealed class AtomicFileTests : IDisposable
{
// AtomicFile.ReadAllText, so the reader does not block the
// writer — that is exactly what the helper exists for.
var inhalt = AtomicFile.ReadAllText(path);
Interlocked.Increment(ref gelesen);
var content = AtomicFile.ReadAllText(path);
Interlocked.Increment(ref readBack);
// Must always be a complete JSON array.
JsonSerializer.Deserialize<string[]>(inhalt);
JsonSerializer.Deserialize<string[]>(content);
}
catch (JsonException)
{
Interlocked.Increment(ref fehler);
Interlocked.Increment(ref error);
}
catch (IOException)
{
@@ -169,10 +169,10 @@ public sealed class AtomicFileTests : IDisposable
}
});
await Task.WhenAll(schreiber, leser);
await Task.WhenAll(writer, reader);
gelesen.ShouldBeGreaterThan(5, "der Test muss tatsächlich gelesen haben");
fehler.ShouldBe(0, "es darf nie ein unvollständiges Dokument sichtbar sein");
readBack.ShouldBeGreaterThan(5, "der Test muss tatsächlich gelesen haben");
error.ShouldBe(0, "es darf nie ein unvollständiges Dokument sichtbar sein");
}
/// <summary>
@@ -184,7 +184,7 @@ public sealed class AtomicFileTests : IDisposable
/// File.Replace copes with a sharing reader. Hence Replace.
/// </summary>
[Fact]
public void Ein_offener_Leser_blockiert_das_Schreiben_nicht()
public void An_open_reader_does_not_block_writing()
{
var path = Path_("gehalten.json");
AtomicFile.WriteAllText(path, """{"stand":"alt"}""");
@@ -198,7 +198,7 @@ public sealed class AtomicFileTests : IDisposable
}
[Fact]
public void Parallele_Schreibvorgaenge_hinterlassen_eine_gueltige_Datei()
public void Parallel_writes_leave_a_valid_file()
{
var path = Path_("parallel.json");
@@ -19,56 +19,56 @@ public sealed class OwnerOnlyFileTests : IDisposable
try { Directory.Delete(_dir, recursive: true); } catch { /* Cleaning up is best effort */ }
}
private const UnixFileMode NurBesitzer = UnixFileMode.UserRead | UnixFileMode.UserWrite;
private const UnixFileMode OwnerOnly = UnixFileMode.UserRead | UnixFileMode.UserWrite;
[LinuxFact]
[System.Runtime.Versioning.SupportedOSPlatform("linux")]
public void AtomicFile_ersetzt_eine_offene_Datei_durch_eine_nur_fuer_den_Besitzer()
public void AtomicFile_replaces_an_open_file_with_an_owner_only_one()
{
var pfad = Path.Combine(_dir, "InstanceSettings.json");
File.WriteAllText(pfad, "{}");
File.SetUnixFileMode(pfad, NurBesitzer | UnixFileMode.GroupRead | UnixFileMode.OtherRead);
var path = Path.Combine(_dir, "InstanceSettings.json");
File.WriteAllText(path, "{}");
File.SetUnixFileMode(path, OwnerOnly | UnixFileMode.GroupRead | UnixFileMode.OtherRead);
AtomicFile.WriteAllText(pfad, "{\"a\":1}");
AtomicFile.WriteAllText(path, "{\"a\":1}");
File.GetUnixFileMode(pfad).ShouldBe(NurBesitzer);
File.GetUnixFileMode(path).ShouldBe(OwnerOnly);
}
[LinuxFact]
[System.Runtime.Versioning.SupportedOSPlatform("linux")]
public void AtomicFile_legt_neue_Dateien_nur_fuer_den_Besitzer_an()
public void AtomicFile_creates_new_files_owner_only()
{
var pfad = Path.Combine(_dir, "neu.json");
var path = Path.Combine(_dir, "neu.json");
AtomicFile.WriteAllText(pfad, "{}");
AtomicFile.WriteAllText(path, "{}");
File.GetUnixFileMode(pfad).ShouldBe(NurBesitzer);
File.GetUnixFileMode(path).ShouldBe(OwnerOnly);
}
[LinuxFact]
[System.Runtime.Versioning.SupportedOSPlatform("linux")]
public void OpenAppend_legt_neue_Dateien_nur_fuer_den_Besitzer_an()
public void OpenAppend_creates_new_files_owner_only()
{
var pfad = Path.Combine(_dir, "protokoll.log");
var path = Path.Combine(_dir, "protokoll.log");
using (var stream = OwnerOnlyFile.OpenAppend(pfad))
using (var stream = OwnerOnlyFile.OpenAppend(path))
stream.WriteByte((byte)'x');
File.GetUnixFileMode(pfad).ShouldBe(NurBesitzer);
File.GetUnixFileMode(path).ShouldBe(OwnerOnly);
}
[Fact]
public void OpenAppend_haengt_an_statt_zu_ueberschreiben()
public void OpenAppend_appends_instead_of_overwriting()
{
var pfad = Path.Combine(_dir, "anhang.txt");
var path = Path.Combine(_dir, "anhang.txt");
foreach (var teil in new[] { "eins", "zwei" })
foreach (var part in new[] { "eins", "zwei" })
{
using var stream = OwnerOnlyFile.OpenAppend(pfad);
using var stream = OwnerOnlyFile.OpenAppend(path);
using var writer = new StreamWriter(stream);
writer.Write(teil);
writer.Write(part);
}
File.ReadAllText(pfad).ShouldBe("einszwei");
File.ReadAllText(path).ShouldBe("einszwei");
}
}
@@ -37,27 +37,27 @@ public sealed class PathBoundaryTests : IDisposable
// ═══════════════════════════════════════════════════════════
[Fact]
public void Ein_Nachbarverzeichnis_mit_gleichem_Praefix_liegt_ausserhalb()
public void A_sibling_directory_with_the_same_prefix_lies_outside()
{
PathBoundary.IsInside(Path.Combine(_root + "-Backup", "geheim.txt"), _root)
.ShouldBeFalse();
}
[Fact]
public void Das_Wurzelverzeichnis_selbst_liegt_innerhalb()
public void The_root_directory_itself_lies_inside()
{
PathBoundary.IsInside(_root, _root).ShouldBeTrue();
PathBoundary.IsInside(_root + Path.DirectorySeparatorChar, _root).ShouldBeTrue();
}
[Fact]
public void Ein_Unterverzeichnis_liegt_innerhalb()
public void A_subdirectory_lies_inside()
{
PathBoundary.IsInside(Path.Combine(_root, "a", "b", "c.txt"), _root).ShouldBeTrue();
}
[Fact]
public void Punkt_Punkt_fuehrt_hinaus()
public void Dot_dot_leads_outside()
{
PathBoundary.IsInside(Path.Combine(_root, "..", "evil.txt"), _root).ShouldBeFalse();
}
@@ -67,7 +67,7 @@ public sealed class PathBoundaryTests : IDisposable
// ═══════════════════════════════════════════════════════════
[LinuxFact]
public void Unter_Linux_ist_ein_Verzeichnis_mit_anderer_Schreibweise_ein_anderes()
public void On_Linux_a_directory_with_different_case_is_a_different_one()
{
// "workspace" next to "Workspace": two real, separate directories.
var lower = Path.Combine(_base, "workspace");
@@ -77,7 +77,7 @@ public sealed class PathBoundaryTests : IDisposable
}
[WindowsFact]
public void Unter_Windows_meint_eine_andere_Schreibweise_dasselbe_Verzeichnis()
public void On_Windows_a_different_case_means_the_same_directory()
{
var lower = Path.Combine(_base, "workspace");
@@ -85,16 +85,16 @@ public sealed class PathBoundaryTests : IDisposable
}
[Fact]
public void Der_Schluessel_fuer_Sperren_folgt_der_Plattform()
public void The_key_for_locks_follows_the_platform()
{
var upper = Path.Combine(_base, "Config.json");
var lower = Path.Combine(_base, "config.json");
var gleich = PathBoundary.CanonicalKey(upper) == PathBoundary.CanonicalKey(lower);
var same = PathBoundary.CanonicalKey(upper) == PathBoundary.CanonicalKey(lower);
// Under Windows the same file — the same lock. Under Linux two files
// that must not share one.
gleich.ShouldBe(OperatingSystem.IsWindows() || OperatingSystem.IsMacOS());
same.ShouldBe(OperatingSystem.IsWindows() || OperatingSystem.IsMacOS());
}
// ═══════════════════════════════════════════════════════════
@@ -102,20 +102,20 @@ public sealed class PathBoundaryTests : IDisposable
// ═══════════════════════════════════════════════════════════
[LinuxFact]
public void Eine_Verknuepfung_aus_dem_Wurzelverzeichnis_heraus_wird_erkannt()
public void A_link_out_of_the_root_directory_is_recognised()
{
// The case the plain path calculation does not see: "Workspace/raus" points
// outside, but "Workspace/raus/beute.txt" lies lexically inside.
var draussen = Path.Combine(_base, "Draussen");
Directory.CreateDirectory(draussen);
Directory.CreateSymbolicLink(Path.Combine(_root, "raus"), draussen);
var outside = Path.Combine(_base, "Draussen");
Directory.CreateDirectory(outside);
Directory.CreateSymbolicLink(Path.Combine(_root, "raus"), outside);
PathBoundary.IsInside(Path.Combine(_root, "raus", "beute.txt"), _root)
.ShouldBeFalse();
}
[LinuxFact]
public void Eine_Verknuepfung_innerhalb_des_Wurzelverzeichnisses_bleibt_erlaubt()
public void A_link_inside_the_root_directory_stays_allowed()
{
// Counter-check: whoever stays inside is not locked out.
var ziel = Path.Combine(_root, "echte-daten");
@@ -127,22 +127,22 @@ public sealed class PathBoundaryTests : IDisposable
}
[LinuxFact]
public void Ein_Wurzelverzeichnis_hinter_einer_Verknuepfung_sperrt_sich_nicht_selbst_aus()
public void A_root_directory_behind_a_link_does_not_lock_itself_out()
{
// If the workspace itself lies behind a link (common with /var → /private/var
// or mounted data directories), the resolution must apply on both sides
// — otherwise nothing matches any more after resolving.
var echt = Path.Combine(_base, "EchterOrt");
Directory.CreateDirectory(echt);
var ueber = Path.Combine(_base, "Verknuepft");
Directory.CreateSymbolicLink(ueber, echt);
var real = Path.Combine(_base, "EchterOrt");
Directory.CreateDirectory(real);
var over = Path.Combine(_base, "Verknuepft");
Directory.CreateSymbolicLink(over, real);
PathBoundary.IsInside(Path.Combine(ueber, "datei.txt"), ueber).ShouldBeTrue();
PathBoundary.IsInside(Path.Combine(echt, "datei.txt"), ueber).ShouldBeTrue();
PathBoundary.IsInside(Path.Combine(over, "datei.txt"), over).ShouldBeTrue();
PathBoundary.IsInside(Path.Combine(real, "datei.txt"), over).ShouldBeTrue();
}
[Fact]
public void Nicht_existierende_Pfade_bleiben_pruefbar()
public void Non_existent_paths_stay_checkable()
{
// When writing, the file does not exist yet. What does not exist cannot be a
// link — the resolution must not fail on that.