Skip to content

Commit

Permalink
Merge pull request #1234 from willieferguson/akka-io-bytestring-spec
Browse files Browse the repository at this point in the history
akka-io: Ported a few tests in ByteStringSpec with bug fixes
  • Loading branch information
rogeralsing committed Aug 11, 2015
2 parents c8f06d7 + 7ddbbba commit d20f17f
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 31 deletions.
9 changes: 9 additions & 0 deletions src/core/Akka.Tests/Akka.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@
<Reference Include="FluentAssertions.Core">
<HintPath>..\..\packages\FluentAssertions.3.3.0\lib\net45\FluentAssertions.Core.dll</HintPath>
</Reference>
<Reference Include="FsCheck, Version=2.0.5.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\FsCheck.2.0.5\lib\net45\FsCheck.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="FSharp.Core, Version=4.3.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\FSharp.Core.3.1.2.5\lib\net40\FSharp.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Web" />
Expand Down Expand Up @@ -166,6 +174,7 @@
<Compile Include="TestUtils\Comparable.cs" />
<Compile Include="TestUtils\PropsWithName.cs" />
<Compile Include="TestUtils\Supervisor.cs" />
<Compile Include="Util\ByteStringSpec.cs" />
<Compile Include="Util\CollectionExtensionsSpec.cs" />
<Compile Include="Util\ContinuousEnumeratorSpec.cs" />
<Compile Include="Util\Internal\Collections\IteratorTests.cs" />
Expand Down
97 changes: 97 additions & 0 deletions src/core/Akka.Tests/Util/ByteStringSpec.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
using System.Linq;
using System.Text;
using Akka.IO;
using FsCheck;
using Xunit;

namespace Akka.Tests.Util
{

/// <summary>
/// TODO: Should we use the FsCheck.XUnit integration when they upgrade to xUnit 2
/// </summary>
public class ByteStringSpec
{
class Generators
{

// TODO: Align with JVM Akka Generator
public static Arbitrary<ByteString> ByteStrings()
{
return Arb.From(Arb.Generate<byte[]>().Select(ByteString.Create));
}
}

public ByteStringSpec()
{
Arb.Register<Generators>();
}

[Fact]
public void A_ByteString_must_have_correct_size_when_concatenating()
{
Prop.ForAll((ByteString a, ByteString b) => (a + b).Count == a.Count + b.Count)
.QuickCheckThrowOnFailure();
}

[Fact]
public void A_ByteString_must_have_correct_size_when_dropping()
{
Prop.ForAll((ByteString a, ByteString b) => (a + b).Drop(b.Count).Count == a.Count)
.QuickCheckThrowOnFailure();
}

[Fact]
public void A_ByteString_must_be_sequential_when_taking()
{
Prop.ForAll((ByteString a, ByteString b) => (a + b).Take(a.Count).SequenceEqual(a))
.QuickCheckThrowOnFailure();
}
[Fact]
public void A_ByteString_must_be_sequential_when_dropping()
{
Prop.ForAll((ByteString a, ByteString b) => (a + b).Drop(a.Count).SequenceEqual(b))
.QuickCheckThrowOnFailure();
}

[Fact]
public void A_ByteString_must_be_equal_to_the_original_when_compacting()
{
Prop.ForAll((ByteString xs) =>
{
var ys = xs.Compact();
return xs.SequenceEqual(ys) && ys.IsCompact();
}).QuickCheckThrowOnFailure();
}
[Fact]
public void A_ByteString_must_be_equal_to_the_original_when_recombining()
{
Prop.ForAll((ByteString xs, int from, int until) =>
{
var tmp1 = xs.SplitAt(until);
var tmp2 = tmp1.Item1.SplitAt(until);
return (tmp2.Item1 + tmp2.Item2 + tmp1.Item2).SequenceEqual(xs);
}).QuickCheckThrowOnFailure();
}

[Fact]
public void A_ByteString_must_behave_as_expected_when_created_from_and_decoding_to_String()
{
Prop.ForAll((string s) => ByteString.FromString(s, Encoding.UTF8).DecodeString(Encoding.UTF8) == (s ?? "")) // TODO: What should we do with null string?
.QuickCheckThrowOnFailure();
}
[Fact]
public void A_ByteString_must_behave_as_expected_when_compacting()
{
Prop.ForAll((ByteString a) =>
{
var wasCompact = a.IsCompact();
var b = a.Compact();
return ((!wasCompact) || (b == a)) &&
b.SequenceEqual(a) &&
b.IsCompact() &&
b.Compact() == b;
}).QuickCheckThrowOnFailure();
}
}
}
2 changes: 2 additions & 0 deletions src/core/Akka.Tests/packages.config
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<packages>
<package id="fastJSON" version="2.0.27.1" targetFramework="net45" />
<package id="FluentAssertions" version="3.3.0" targetFramework="net45" />
<package id="FsCheck" version="2.0.5" targetFramework="net45" />
<package id="FSharp.Core" version="3.1.2.5" targetFramework="net45" />
<package id="xunit" version="2.0.0" targetFramework="net45" />
<package id="xunit.abstractions" version="2.0.0" targetFramework="net45" />
<package id="xunit.assert" version="2.0.0" targetFramework="net45" />
Expand Down
69 changes: 40 additions & 29 deletions src/core/Akka/Util/ByteIterator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,7 @@ public override int CopyToBuffer(ByteBuffer buffer)
internal class MultiByteIterator : ByteIterator
{
private ILinearSeq<ByteArrayIterator> _iterators;
private ByteArrayIterator _current;
private static readonly ByteArrayIterator[] ClearedList = new ByteArrayIterator[0];
private static readonly ILinearSeq<ByteArrayIterator> ClearedList = new ArrayLinearSeq<ByteArrayIterator>(new ByteArrayIterator[0]);

public MultiByteIterator(params ByteArrayIterator[] iterators)
{
Expand All @@ -166,18 +165,26 @@ public MultiByteIterator(ILinearSeq<ByteArrayIterator> iterators)

private MultiByteIterator Normalize()
{
Func<IEnumerable<ByteArrayIterator>, IEnumerable<ByteArrayIterator>> norm = null;
Func<ILinearSeq<ByteArrayIterator>, ILinearSeq<ByteArrayIterator>> norm = null;
norm = xs =>
{
if (!xs.Any()) return ClearedList;
if (!xs.First().HasNext) return norm(xs.Skip(1));
if (xs.IsEmpty) return ClearedList;
if (!xs.Head.HasNext) return norm(xs.Tail());
return xs;

};
_iterators = new ArrayLinearSeq<ByteArrayIterator>(norm(_iterators).ToArray());
_iterators = norm(_iterators);
return this;
}


private ByteArrayIterator Current
{
get
{
return _iterators.Head;
}
}
private void DropCurrent()
{
_iterators = _iterators.Tail();
Expand All @@ -190,17 +197,17 @@ protected override void Clear()

public override bool HasNext
{
get { return _current.HasNext; }
get { return Current.HasNext; }
}

public override byte Head
{
get { return _current.Head; }
get { return Current.Head; }
}

public override byte Next()
{
var result = _current.Next();
var result = Current.Next();
Normalize();
return result;
}
Expand All @@ -217,11 +224,11 @@ public override ByteIterator Take(int n)
var builder = new List<ByteArrayIterator>();
while (rest > 0 && !_iterators.IsEmpty)
{
_current.Take(rest);
if (_current.HasNext)
Current.Take(rest);
if (Current.HasNext)
{
rest -= _current.Len;
builder.Add(_current);
rest -= Current.Len;
builder.Add(Current);
}
_iterators = _iterators.Tail();
}
Expand All @@ -233,8 +240,8 @@ public override ByteIterator Drop(int n)
{
if (n > 0 && Len > 0)
{
var nCurrent = Math.Min(n, _current.Len);
_current.Drop(n);
var nCurrent = Math.Min(n, Current.Len);
Current.Drop(n);
var rest = n - nCurrent;
Normalize();
return Drop(rest);
Expand All @@ -248,10 +255,10 @@ public override ByteIterator TakeWhile(Func<byte, bool> p)
var builder = new List<ByteArrayIterator>();
while (!stop && !_iterators.IsEmpty)
{
var lastLen = _current.Len;
_current.TakeWhile(p);
if (_current.HasNext) builder.Add(_current);
if (_current.Len < lastLen) stop = true;
var lastLen = Current.Len;
Current.TakeWhile(p);
if (Current.HasNext) builder.Add(Current);
if (Current.Len < lastLen) stop = true;
DropCurrent();
}
_iterators = new ArrayLinearSeq<ByteArrayIterator>(builder.ToArray());
Expand All @@ -262,8 +269,8 @@ public override ByteIterator DropWhile(Func<byte, bool> p)
{
if (Len > 0)
{
_current.DropWhile(p);
var dropMore = _current.Len == 0;
Current.DropWhile(p);
var dropMore = Current.Len == 0;
Normalize();
if (dropMore) return DropWhile(p);
}
Expand All @@ -280,12 +287,12 @@ public override ByteString ToByteString()

protected MultiByteIterator GetToArray<T>(T[] xs, int offset, int n, int elemSize, Func<T> getSingle, Action<T[], int, int> getMulti)
{
if(n >= 0) return this;
if(n <= 0) return this;
Func<int> nDoneF = () =>
{
if (_current.Len >= elemSize)
if (Current.Len >= elemSize)
{
var nCurrent = Math.Min(n, _current.Len/elemSize);
var nCurrent = Math.Min(n, Current.Len/elemSize);
getMulti(xs, offset, nCurrent);
return nCurrent;
}
Expand All @@ -302,13 +309,13 @@ protected MultiByteIterator GetToArray<T>(T[] xs, int offset, int n, int elemSiz

public override ByteIterator GetBytes(byte[] xs, int offset, int n)
{
return GetToArray(xs, offset, n, 1, GetByte, (a, b, c) => _current.GetBytes(a, b, c));
return GetToArray(xs, offset, n, 1, GetByte, (a, b, c) => Current.GetBytes(a, b, c));
}


public override byte[] ToArray()
{
throw new NotImplementedException();
return GetBytes(Len);
}

public override int CopyToBuffer(ByteBuffer buffer)
Expand Down Expand Up @@ -484,7 +491,7 @@ private ArrayLinearSeq(T[] array, int offset, int length)

public bool IsEmpty
{
get { return _length > 0; }
get { return _length == 0; }
}

public T Head
Expand Down Expand Up @@ -516,6 +523,7 @@ private class Enumerator : IEnumerator<T>
{
private readonly ILinearSeq<T> _orig;
private ILinearSeq<T> _seq;
private T _current;

public Enumerator(ILinearSeq<T> seq)
{
Expand All @@ -530,8 +538,11 @@ public void Dispose()

public bool MoveNext()
{
if (_seq.IsEmpty)
return false;
_current = _seq.Head;
_seq = _seq.Tail();
return !_seq.IsEmpty;
return true;
}

public void Reset()
Expand All @@ -541,7 +552,7 @@ public void Reset()

public T Current
{
get { return _seq.Head; }
get { return _current; }
}

object IEnumerator.Current
Expand Down
13 changes: 11 additions & 2 deletions src/core/Akka/Util/ByteString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public static ByteString FromByteBuffer(ByteBuffer buffer)
return Create(buffer);
}

public static readonly ByteString Empty = new ByteString1C(new byte[0]);
public static readonly ByteString Empty = CompactByteString.EmptyCompactByteString;

public static ByteStringBuilder NewBuilder()
{
Expand Down Expand Up @@ -225,6 +225,11 @@ public override string DecodeString(Encoding charset)
{
return charset.GetString(_length == _bytes.Length ? _bytes : ToArray());
}

public override IEnumerator<byte> GetEnumerator()
{
return _bytes.Skip(_startIndex).Take(_length).GetEnumerator();
}
}

internal class ByteStrings : ByteString
Expand Down Expand Up @@ -499,9 +504,13 @@ public static ByteString Create(byte[] buffer)

partial /*object*/ class CompactByteString
{
internal static readonly CompactByteString EmptyCompactByteString = new ByteString1C(new byte[0]);

public static CompactByteString FromString(string str, Encoding encoding)
{
return new ByteString1C(encoding.GetBytes(str));
return string.IsNullOrEmpty(str)
? EmptyCompactByteString
: new ByteString1C(encoding.GetBytes(str));
}

public static ByteString FromArray(byte[] array, int offset, int length)
Expand Down

0 comments on commit d20f17f

Please sign in to comment.