Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions touki.tests/Touki/Io/TextWriterExtensionsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// Copyright (c) 2025 Jeremy W Kuhne
// SPDX-License-Identifier: MIT
// See LICENSE file in the project root for full license information

using System.Text;
using Touki.Text;

namespace Touki.Io;

public class TextWriterExtensionsTests
{
[Fact]
public void Write_ReadOnlySpan_AppendsToStringWriter()
{
System.IO.StringWriter writer = new();
ReadOnlySpan<char> span = "Hello".AsSpan();

writer.Write(span);

writer.ToString().Should().Be("Hello");
}

[Fact]
public void Write_ReadOnlySpan_Empty_DoesNothing()
{
System.IO.StringWriter writer = new();

writer.Write([]);

writer.ToString().Should().BeEmpty();
}

[Fact]
public void WriteLine_ReadOnlySpan_AppendsAndAddsNewLine()
{
System.IO.StringWriter writer = new();
ReadOnlySpan<char> span = "Hello".AsSpan();

writer.WriteLine(span);

writer.ToString().Should().Be($"Hello{Environment.NewLine}");
}

[Fact]
public void WriteLine_ReadOnlySpan_Empty_WritesOnlyNewLine()
{
System.IO.StringWriter writer = new();

writer.WriteLine([]);

writer.ToString().Should().Be(Environment.NewLine);
}

[Fact]
public void Write_StringSegment_WritesSegmentContent()
{
System.IO.StringWriter writer = new();
StringSegment segment = new("Hello World", 6, 5);

writer.Write(segment.AsSpan());

writer.ToString().Should().Be("World");
}

[Fact]
public void WriteLine_StringSegment_WritesSegmentContentAndNewLine()
{
System.IO.StringWriter writer = new();
StringSegment segment = new("Hello World", 0, 5);

writer.WriteLine(segment.AsSpan());

writer.ToString().Should().Be($"Hello{Environment.NewLine}");
}

[Fact]
public void WriteFormatted_InterpolatedString_AppendsToStreamWriter()
{
using MemoryStream stream = new();
using System.IO.StreamWriter writer = new(stream, Encoding.UTF8, 1024, leaveOpen: true);

string name = "Touki";
int version = 42;

writer.WriteFormatted($"Library: {name}, Version: {version}");
writer.Flush();

stream.Position = 0;
using StreamReader reader = new(stream, Encoding.UTF8);
string result = reader.ReadToEnd();

result.Should().Be("Library: Touki, Version: 42");
}

[Fact]
public void WriteFormatted_EmptyBuilder_WritesNothing()
{
using MemoryStream stream = new();
using System.IO.StreamWriter writer = new(stream, Encoding.UTF8, 1024, leaveOpen: true);
writer.Flush();
long length = stream.Length;

ValueStringBuilder builder = new();
writer.WriteFormatted(ref builder);
writer.Flush();

stream.Length.Should().Be(length);
}

#if NET
[Fact]
public void WriteFormatted_StringOverload_WritesLiteralWithoutBuilder()
{
System.IO.StringWriter writer = new();

writer.WriteFormatted("Hello");

writer.ToString().Should().Be("Hello");
}
#endif
}
10 changes: 5 additions & 5 deletions touki.tests/Touki/SpanReaderEdgeCaseTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ public void TryRead_Struct_ValidatesTypeSizeAlignment()
{
// Try to read a byte (1 byte) from ushort span (2-byte elements)
// sizeof(byte) < sizeof(ushort) should trigger the exception
reader.TryRead<byte>(out byte _);
reader.TryRead(out byte _);
Assert.Fail($"Expected {nameof(ArgumentException)}");
}
catch (ArgumentException ex)
Expand All @@ -240,7 +240,7 @@ public void TryRead_Struct_Count_ValidatesTypeSizeAlignment()
try
{
// Try to read bytes from ushort span - should throw because byte size < ushort size
reader.TryRead<byte>(2, out ReadOnlySpan<byte> _);
reader.TryRead(2, out ReadOnlySpan<byte> _);
Assert.Fail($"Expected {nameof(ArgumentException)}");
}
catch (ArgumentException ex)
Expand Down Expand Up @@ -449,7 +449,7 @@ public void TryRead_Struct_EdgeCaseSizes()
SpanReader<byte> reader = new(span);

// Test reading a 16-byte struct (should succeed)
bool result = reader.TryRead<decimal>(out decimal _);
bool result = reader.TryRead(out decimal _);
result.Should().BeTrue();
reader.Position.Should().Be(16);
reader.End.Should().BeTrue();
Expand All @@ -469,7 +469,7 @@ public void TryRead_Struct_Count_EdgeCases()
SpanReader<byte> reader = new(span);

// Test reading exactly the maximum number of items that fit
bool result = reader.TryRead<uint>(4, out ReadOnlySpan<uint> values); // 4 * 4 = 16 bytes
bool result = reader.TryRead(4, out ReadOnlySpan<uint> values); // 4 * 4 = 16 bytes
result.Should().BeTrue();
values.Length.Should().Be(4);
reader.Position.Should().Be(16);
Expand All @@ -478,7 +478,7 @@ public void TryRead_Struct_Count_EdgeCases()
reader.Reset();

// Test reading one more than what fits
result = reader.TryRead<uint>(5, out values); // 5 * 4 = 20 bytes (too much)
result = reader.TryRead(5, out values); // 5 * 4 = 20 bytes (too much)
result.Should().BeFalse();
values.Length.Should().Be(0);
reader.Position.Should().Be(0);
Expand Down
2 changes: 1 addition & 1 deletion touki.tests/Touki/SpanReaderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1218,7 +1218,7 @@ public void SpanReader_TryRead_Struct_LargerThanElementSize()
SpanReader<byte> reader = new(span);

// Test reading larger struct (ulong is 8 bytes)
reader.TryRead<ulong>(out ulong value).Should().BeTrue();
reader.TryRead(out ulong value).Should().BeTrue();
reader.Position.Should().Be(8);
reader.End.Should().BeTrue();

Expand Down
98 changes: 12 additions & 86 deletions touki.tests/Touki/StreamExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,18 @@ public void WriteFormatted_SimpleString_WritesToMemoryStream()
result.Should().Be("Hello World!");
}

#if NET
[Fact]
public void WriteFormatted_StringOverload_WritesUtf16Bytes()
{
using MemoryStream stream = new();

stream.WriteFormatted("Hi");

stream.ToArray().Should().BeEquivalentTo(Encoding.Unicode.GetBytes("Hi"));
}
#endif

[Fact]
public void WriteFormatted_EmptyBuilder_WritesNothing()
{
Expand Down Expand Up @@ -133,92 +145,6 @@ public void WriteFormatted_MultipleWrites_AppendToStream()
result.Should().Be("First part. Second part.");
}

[Fact]
public void WriteFormatted_StreamWriterUnicode_WritesCorrectly()
{
using MemoryStream stream = new();
StreamWriter writer = new(stream, Encoding.Unicode);

#pragma warning disable IDE0082 // 'typeof' can be converted to 'nameof'
writer.WriteFormatted($"Hello from {typeof(StreamWriter).Name}!");
#pragma warning restore IDE0082
writer.Flush();

stream.Position = 0;
StreamReader reader = new(stream, Encoding.Unicode);
string result = reader.ReadToEnd();

result.Should().Be("Hello from StreamWriter!");
}

[Fact]
public void WriteFormatted_StreamWriterUTF8_WritesCorrectly()
{
using MemoryStream stream = new();
StreamWriter writer = new(stream, Encoding.UTF8);

writer.WriteFormatted($"UTF-{8} Text");
writer.Flush();

stream.Position = 0;
StreamReader reader = new(stream, Encoding.UTF8);
string result = reader.ReadToEnd();

result.Should().Be("UTF-8 Text");
}

[Fact]
public void WriteFormatted_StreamWriterInterpolatedValues_WritesCorrectly()
{
using MemoryStream stream = new();
StreamWriter writer = new(stream, Encoding.UTF8);

string name = "StreamWriter";
int value = 123;
double pi = 3.14159;

writer.WriteFormatted($"Name: {name}, Value: {value}, Pi: {pi:F2}");
writer.Flush();

stream.Position = 0;
StreamReader reader = new(stream, Encoding.UTF8);
string result = reader.ReadToEnd();

result.Should().Be("Name: StreamWriter, Value: 123, Pi: 3.14");
}

[Fact]
public void WriteFormatted_StreamWriterMultipleWrites_AppendCorrectly()
{
using MemoryStream stream = new();
StreamWriter writer = new(stream, Encoding.Unicode);

writer.WriteFormatted($"Part one. ");
writer.WriteFormatted($"Part two.");
writer.Flush();

stream.Position = 0;
StreamReader reader = new(stream, Encoding.Unicode);
string result = reader.ReadToEnd();

result.Should().Be("Part one. Part two.");
}

[Fact]
public void WriteFormatted_StreamWriterEmptyBuilder_WritesNothing()
{
using MemoryStream stream = new();
StreamWriter writer = new(stream, Encoding.UTF8);
writer.Flush();
long length = stream.Length;

ValueStringBuilder builder = new();
writer.WriteFormatted(ref builder);
writer.Flush();

stream.Length.Should().Be(length);
}

[Fact]
public void Write_ReadOnlySpan_WritesToTextWriter()
{
Expand Down
2 changes: 0 additions & 2 deletions touki/Framework/System/Number.NumberBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Text;

namespace System;

internal static partial class Number
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
// The .NET Foundation licenses this file to you under the MIT license.

using Touki;
using Touki.Text;

namespace System.Runtime.CompilerServices;

Expand Down
1 change: 0 additions & 1 deletion touki/Framework/Touki/Exceptions/ThrowHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
// multiple times for different instantiation.
//

using System.Buffers;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization;
Expand Down
47 changes: 0 additions & 47 deletions touki/Framework/Touki/Io/StreamExtensions.cs

This file was deleted.

Loading
Loading