From 67f56f0795ac0214f9828c42f8face229e204c1d Mon Sep 17 00:00:00 2001 From: David Miller Date: Sat, 21 Feb 2009 06:55:20 +0000 Subject: ClojureCLR: added ClojureCLR project to repo. --- .../Clojure/Clojure.Tests/LibTests/AFnImplTests.cs | 22 + .../LibTests/APersistentVectorTests.cs | 707 ++++++++ .../Clojure/Clojure.Tests/LibTests/ARefTests.cs | 22 + .../Clojure.Tests/LibTests/AReferenceTests.cs | 98 ++ .../Clojure/Clojure.Tests/LibTests/AgentTests.cs | 22 + .../Clojure.Tests/LibTests/ArraySeqTests.cs | 214 +++ .../Clojure.Tests/LibTests/ArrayStreamTests.cs | 22 + .../Clojure/Clojure.Tests/LibTests/AtomTests.cs | 22 + .../Clojure.Tests/LibTests/CachedSeqTests.cs | 22 + .../Clojure/Clojure.Tests/LibTests/ConsTests.cs | 428 +++++ .../Clojure/Clojure.Tests/LibTests/DelayTests.cs | 22 + .../Clojure/Clojure.Tests/LibTests/FnSeqTests.cs | 120 ++ .../Clojure/Clojure.Tests/LibTests/IObjTests.cs | 91 + .../Clojure.Tests/LibTests/ISeqTestHelper.cs | 54 + .../Clojure.Tests/LibTests/IteratorStreamTests.cs | 22 + .../Clojure/Clojure.Tests/LibTests/KeywordTests.cs | 239 +++ .../LibTests/LazilyPersistentVectorTests.cs | 220 +++ .../Clojure.Tests/LibTests/LazyConsTests.cs | 123 ++ .../Clojure.Tests/LibTests/LispReaderTests.cs | 1789 ++++++++++++++++++++ .../LibTests/LockingTransactionTests.cs | 194 +++ .../Clojure.Tests/LibTests/MapEntryTests.cs | 369 ++++ .../Clojure.Tests/LibTests/NamespaceTests.cs | 257 +++ .../Clojure/Clojure.Tests/LibTests/NumbersTests.cs | 137 ++ .../Clojure/Clojure.Tests/LibTests/ObjTests.cs | 68 + .../LibTests/PersistentArrayMapTests.cs | 917 ++++++++++ .../LibTests/PersistentHashMapTests.cs | 242 +++ .../LibTests/PersistentHashSetTests.cs | 188 ++ .../Clojure.Tests/LibTests/PersistentListTests.cs | 245 +++ .../Clojure.Tests/LibTests/PersistentQueueTests.cs | 22 + .../LibTests/PersistentStructMapTests.cs | 22 + .../LibTests/PersistentTreeMapTests.cs | 233 +++ .../LibTests/PersistentTreeSetTests.cs | 58 + .../LibTests/PersistentVectorTests.cs | 330 ++++ .../Clojure/Clojure.Tests/LibTests/RangeTests.cs | 182 ++ .../Clojure/Clojure.Tests/LibTests/RefTests.cs | 23 + .../Clojure.Tests/LibTests/RestFnImplTests.cs | 22 + .../Clojure/Clojure.Tests/LibTests/RestFnTests.cs | 22 + .../Clojure.Tests/LibTests/StreamSeqTests.cs | 22 + .../Clojure.Tests/LibTests/StringSeqTests.cs | 163 ++ .../Clojure/Clojure.Tests/LibTests/SymbolTests.cs | 326 ++++ .../Clojure/Clojure.Tests/LibTests/TestTest.cs | 62 + 41 files changed, 8363 insertions(+) create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/AFnImplTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/APersistentVectorTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/ARefTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/AReferenceTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/AgentTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/ArraySeqTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/ArrayStreamTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/AtomTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/CachedSeqTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/ConsTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/DelayTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/FnSeqTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/IObjTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/ISeqTestHelper.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/IteratorStreamTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/KeywordTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/LazilyPersistentVectorTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/LazyConsTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/LispReaderTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/LockingTransactionTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/MapEntryTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/NamespaceTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/NumbersTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/ObjTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentArrayMapTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentHashMapTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentHashSetTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentListTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentQueueTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentStructMapTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentTreeMapTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentTreeSetTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentVectorTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/RangeTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/RefTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/RestFnImplTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/RestFnTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/StreamSeqTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/StringSeqTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/SymbolTests.cs create mode 100644 ClojureCLR/Clojure/Clojure.Tests/LibTests/TestTest.cs (limited to 'ClojureCLR/Clojure/Clojure.Tests/LibTests') diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/AFnImplTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/AFnImplTests.cs new file mode 100644 index 00000000..3c79b69b --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/AFnImplTests.cs @@ -0,0 +1,22 @@ +/** + * Copyright (c) David Miller. All rights reserved. + * The use and distribution terms for this software are covered by the + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) + * which can be found in the file epl-v10.html at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Clojure.Tests.LibTests +{ + // TODO: Add AFnImpl tests + class AFnImplTests + { + } +} diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/APersistentVectorTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/APersistentVectorTests.cs new file mode 100644 index 00000000..88213a02 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/APersistentVectorTests.cs @@ -0,0 +1,707 @@ +/** + * Copyright (c) David Miller. All rights reserved. + * The use and distribution terms for this software are covered by the + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) + * which can be found in the file epl-v10.html at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using NUnit.Framework; +using Rhino.Mocks; + +using clojure.lang; + +using RMExpect = Rhino.Mocks.Expect; + + +namespace Clojure.Tests.LibTests +{ + + // TODO: Add tests for APersistentVector.SubVector + // TODO: Add tests for APersistentVector.stream + + [TestFixture] + public class APersistentVectorTests : AssertionHelper + { + + // Usually, we test the abstract classes via the simplest concrete class that derives from it. + // For APersistentVector, all the concrete classes are fairly complicated. + // Hence we create a test concrete implementation class. + // This class has no guarantees of persistence/immutability, thread-safety, + // or much of anything else, certainly not efficiency. + // We determined the methods to override by trying to compile the class with no methods. + // Thus, we have implemented only the absolute minimum. + // We will write tests for these methods, too. + // This class just has an underlying List to hold values. + class CPV : APersistentVector + { + object[] _values; + + public CPV(object[] values) + : base(null) + { + _values = values; + } + + + public CPV(IPersistentMap meta, object[] values) + : base(meta) + { + _values = values; + } + + public override IObj withMeta(IPersistentMap meta) + { + return meta == _meta + ? this + : new CPV(meta, _values); + } + + //public override object applyTo(ISeq arglist) + //{ + // throw new NotImplementedException(); + //} + + public override IPersistentStack pop() + { + if (_values.Length == 0) + throw new InvalidOperationException("Can't pop a null stack."); + + object[] newArr = new object[_values.Length - 1]; + Array.Copy(_values, newArr, _values.Length - 1); + + return new CPV(_meta, newArr); + } + + public override IPersistentVector cons(object o) + { + object[] newArr = new object[_values.Length + 1]; + _values.CopyTo(newArr, 0); + newArr[_values.Length] = o; + return new CPV(_meta, newArr); + } + + public override IPersistentVector assocN(int i, object val) + { + if ( 0 <= i && i < _values.Length ) + { + object[] newArr = new object[_values.Length]; + _values.CopyTo(newArr, 0); + newArr[i] = val; + return new CPV(_meta, newArr); + } + if ( i == _values.Length ) + return cons(val); + throw new IndexOutOfRangeException(); + } + + public override object nth(int i) + { + return _values[i]; + } + + public override int length() + { + return _values.Length; + } + + private static CPV EMPTY = new CPV(new object[0]); + public override IPersistentCollection empty() + { + return EMPTY; + } + + public override int count() + { + return _values.Length; + } + } + + #region C-tor tests + + [Test] + public void NoMetaCtorHasNoMeta() + { + CPV v = new CPV(new object[] { 1, 2, 3 }); + + Expect(v.meta(),Null); + } + + [Test] + public void MetaCtorHasMeta() + { + MockRepository mocks = new MockRepository(); + IPersistentMap meta = mocks.StrictMock(); + mocks.ReplayAll(); + + CPV v = new CPV(meta,new object[] { 1, 2, 3 }); + + Expect(v.meta(), SameAs(meta)); + mocks.VerifyAll(); + } + + #endregion + + #region Object tests + + [Test] + public void ToStringMentionsTheCount() + { + CPV v = new CPV(new object[] { 1, 2, 3 }); + string str = v.ToString(); + + Expect(str.Contains("3")); + } + + [Test] + public void HashCodeRepeats() + { + CPV v = new CPV(new object[] { 1, 2, 3 }); + + Expect(v.GetHashCode(), EqualTo(v.GetHashCode())); + } + + [Test] + public void HashCodeDependsOnItems() + { + CPV v1 = new CPV(new object[] { 1, 2, 3 }); + CPV v2 = new CPV(new object[] { 1, 2, 4 }); + + Expect(v1.GetHashCode(), Not.EqualTo(v2.GetHashCode())); + } + + [Test] + public void EqualsOnNonPersistentVectorIsFalse() + { + CPV v1 = new CPV(new object[] { 1, 2, 3 }); + + Expect(v1.equiv(7), False); + } + + [Test] + public void EqualsOnPersistentVectorWithDifferentItemsIsFalse() + { + CPV v1 = new CPV(new object[] { 1, 2, 3 }); + CPV v2 = new CPV(new object[] { 1, 2, 4 }); + CPV v3 = new CPV(new object[] { 1, 2 }); + CPV v4 = new CPV(new object[] { 1, 2, 3, 4 }); + + Expect(v1.equiv(v2), False); + Expect(v1.equiv(v3), False); + Expect(v1.equiv(v4), False); + } + + [Test] + public void EqualsOnPersistentVectorWithSameItemsIsTrue() + { + CPV v1 = new CPV(new object[] { 1, 2, 3 }); + CPV v2 = new CPV(new object[] { 1, 2, 3 }); + CPV v3 = new CPV(new object[] { 1 }); + CPV v4 = new CPV(new object[] { 1 }); + CPV v5 = new CPV(new object[] { }); + CPV v6 = new CPV(new object[] { }); + + Expect(v1.equiv(v2)); + Expect(v3.equiv(v4)); + Expect(v5.equiv(v6)); + } + + [Test] + public void EqualsOnSimilarISeqWorks() + { + CPV v1 = new CPV(new object[] { 'a', 'b', 'c' }); + StringSeq s1 = StringSeq.create("abc"); + + Expect(v1.equiv(s1)); + } + + [Test] + public void EqualsOnDissimilarISeqFails() + { + CPV v1 = new CPV(new object[] { 'a', 'b', 'c' }); + StringSeq s1 = StringSeq.create("ab"); + StringSeq s2 = StringSeq.create("abd"); + StringSeq s3 = StringSeq.create("abcd"); + + Expect(v1.equiv(s1), False); + Expect(v1.equiv(s2), False); + Expect(v1.equiv(s3), False); + } + + + #endregion + + #region IFn tests + + [Test] + public void InvokeCallsNth() + { + CPV v = new CPV(new object[] { 5, 6, 7 }); + + Expect(v.invoke(0),EqualTo(5)); + Expect(v.invoke(1),EqualTo(6)); + Expect(v.invoke(2),EqualTo(7)); + Expect(v.invoke("1"), EqualTo(6)); + Expect(v.invoke(1.0), EqualTo(6)); + Expect(v.invoke(1.2), EqualTo(6)); + Expect(v.invoke(1.8), EqualTo(6)); // Rounds or not-- should it? + Expect(v.invoke(1.4M), EqualTo(6)); + } + + + #endregion + + #region IPersistentCollection tests + + [Test] + public void SeqOnCount0YieldsNull() + { + CPV v = new CPV(new object[0]); + + Expect(v.seq(), Null); + } + + [Test] + public void SeqOnPositiveCountYieldsNotNull() + { + CPV v = new CPV(new object[]{ 1,2,3}); + + Expect(v.seq(), Not.Null); + } + + [Test] + public void SeqOnPositiveCountYieldsValidSequence() + { + CPV v = new CPV(new object[] { 1, 2, 3 }); + ISeq s = v.seq(); + + Expect(s.first(), EqualTo(1)); + Expect(s.rest().first(), EqualTo(2)); + Expect(s.rest().rest().first(), EqualTo(3)); + Expect(s.rest().rest().rest(), Null); + } + + [Test] + public void Explicit_IPersistentCollection_cons_works() + { + CPV v = new CPV(new object[] { 1, 2 }); + IPersistentCollection c = v as IPersistentCollection; + + Expect(c, Not.Null); + + IPersistentCollection c2 = c.cons(3); + Expect(c2.count(), EqualTo(3)); + + ISeq s2 = c2.seq(); + + Expect(s2.first(), EqualTo(1)); + Expect(s2.rest().first(), EqualTo(2)); + Expect(s2.rest().rest().first(), EqualTo(3)); + Expect(s2.rest().rest().rest(), Null); + } + + #endregion + + #region Reversible tests + + [Test] + public void RseqOnCount0YieldsNull() + { + CPV v = new CPV(new object[0]); + + Expect(v.rseq(), Null); + } + + [Test] + public void RSeqOnPositiveCountYieldsNotNull() + { + CPV v = new CPV(new object[] { 1, 2, 3 }); + + Expect(v.rseq(), Not.Null); + } + + [Test] + public void RseqOnPositiveCountYieldsValidSequence() + { + CPV v = new CPV(new object[] { 1, 2, 3 }); + ISeq s = v.rseq(); + + Expect(s.first(), EqualTo(3)); + Expect(s.rest().first(), EqualTo(2)); + Expect(s.rest().rest().first(), EqualTo(1)); + Expect(s.rest().rest().rest(), Null); + } + + + #endregion + + #region Associative tests + + [Test] + public void ContainsKeyOnNonNumericIsFalse() + { + CPV v = new CPV(new object[] { 4, 5, 6 }); + + Expect(v.containsKey("a"), False); + } + + [Test] + public void ContainsKeyOnIndexInRangeIsTrue() + { + CPV v = new CPV(new object[] { 4, 5, 6 }); + + Expect(v.containsKey(1.2)); + } + + + [Test] + public void ContainsKeyOnIndexOutOfRangeIsFalse() + { + CPV v = new CPV(new object[] { 4, 5, 6 }); + + Expect(v.containsKey(5),False); + } + + [Test] + public void EntryAtOnNonNumericReturnsNull() + { + CPV v = new CPV(new object[] { 4, 5, 6 }); + + IMapEntry me = v.entryAt("a"); + + Expect(me, Null); + } + + [Test] + public void EntryAtOnIndexInRangeReturnsEntry() + { + CPV v = new CPV(new object[] { 4, 5, 6 }); + + IMapEntry me = v.entryAt(1); + + Expect(me.key(), EqualTo(1)); + Expect(me.val(),EqualTo(5)); + } + + + [Test] + public void EntryAtOnIndexOutOfRangeReturnsNull() + { + CPV v = new CPV(new object[] { 4, 5, 6 }); + + IMapEntry me = v.entryAt(5); + + Expect(me, Null); + } + + [Test] + [ExpectedException(typeof(ArgumentException))] + public void AssocWithNonNumericKeyThrowsException() + { + CPV v = new CPV(new object[] { 4, 5, 6 }); + Associative a = v.assoc("a", 7); + } + + [Test] + public void AssocWithNumericKeyInRangeChangesValue() + { + //This just checks that APersistentVector.assoc calls CPV.assocN + CPV v = new CPV(new object[] { 4, 5, 6 }); + Associative a = v.assoc(1, 10); + + Expect(a.valAt(0), EqualTo(4)); + Expect(a.valAt(1), EqualTo(10)); + Expect(a.valAt(2), EqualTo(6)); + Expect(a.count(), EqualTo(3)); + } + + [Test] + public void AssocWithNumericKeyOnePastEndAddValue() + { + //This just checks that APersistentVector.assoc calls CPV.assocN + CPV v = new CPV(new object[] { 4, 5, 6 }); + Associative a = v.assoc(3, 10); + + Expect(a.valAt(0), EqualTo(4)); + Expect(a.valAt(1), EqualTo(5)); + Expect(a.valAt(2), EqualTo(6)); + Expect(a.valAt(3), EqualTo(10)); + Expect(a.count(), EqualTo(4)); + } + + [Test] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void AssocWithNumericKeyOutOfRangeHighThrowsException() + { + //This just checks that APersistentVector.assoc calls CPV.assocN + CPV v = new CPV(new object[] { 4, 5, 6 }); + Associative a = v.assoc(4, 10); + } + + [Test] + [ExpectedException(typeof(IndexOutOfRangeException))] + public void AssocWithNumericKeyOutOfRangeLowThrowsException() + { + //This just checks that APersistentVector.assoc calls CPV.assocN + CPV v = new CPV(new object[] { 4, 5, 6 }); + Associative a = v.assoc(-1, 10); + } + + [Test] + public void ValAtOnNonNumericReturnsDefault() + { + CPV v = new CPV(new object[] { 4, 5, 6 }); + + object val1 = v.valAt("a"); + object val2 = v.valAt("a", "abc"); + + Expect(val1, Null); + Expect(val2, EqualTo("abc")); + } + + [Test] + public void ValAtOnIndexInRangeReturnsEntry() + { + CPV v = new CPV(new object[] { 4, 5, 6 }); + + object val1 = v.valAt(1); + object val2 = v.valAt(1, "abc"); + + Expect(val1, EqualTo(5)); + Expect(val2, EqualTo(5)); + } + + + [Test] + public void ValAtOnIndexOutOfRangeReturnsDefault() + { + CPV v = new CPV(new object[] { 4, 5, 6 }); + + IMapEntry me = v.entryAt(5); + + object val1 = v.valAt(4); + object val2 = v.valAt(4, "abc"); + + Expect(val1, Null); + Expect(val2, EqualTo("abc")); + } + + + + #endregion + + #region IPersistentStack tests + + [Test] + public void PeekOnCount0ReturnsNull() + { + CPV v = new CPV(new object[] {}); + + Expect(v.peek(), Null); + } + + [Test] + public void PeekOnPositiveCountReturnsLastItem() + { + CPV v = new CPV(new object[] { 1, 2, 3 }); + + Expect(v.peek(), EqualTo(3)); + } + + #endregion + + #region APersistentVector.Seq tests + + // We'll do all the tests indirectly. + + [Test] + public void SeqFirstAndRestWork() + { + CPV v = new CPV(new object[] { 4, 5, 6 }); + ISeq s = v.seq(); + + Expect(s.first(), EqualTo(4)); + Expect(s.rest().first(), EqualTo(5)); + Expect(s.rest().rest().first(), EqualTo(6)); + Expect(s.rest().rest().rest(), Null); + } + + [Test] + public void SeqIndexedWorks() + { + CPV v = new CPV(new object[] { 4, 5, 6 }); + ISeq s0 = v.seq(); + IndexedSeq i0 = s0 as IndexedSeq; + + ISeq s1 = s0.rest(); + IndexedSeq i1 = s1 as IndexedSeq; + + Expect(i0.index(), EqualTo(0)); + Expect(i1.index(), EqualTo(1)); + } + + [Test] + public void SeqCountWorks() + { + CPV v = new CPV(new object[] { 4, 5, 6 }); + ISeq s = v.seq(); + + Expect(s.count(), EqualTo(3)); + Expect(s.rest().count(), EqualTo(2)); + Expect(s.rest().rest().count(), EqualTo(1)); + } + + [Test] + public void SeqWithMetaHasMeta() + { + MockRepository mocks = new MockRepository(); + IPersistentMap meta = mocks.StrictMock(); + mocks.ReplayAll(); + + CPV v = new CPV(new object[] { 4, 5, 6 }); + IObj s = (IObj)v.seq(); + IObj obj = s.withMeta(meta); + + Expect(obj.meta(), SameAs(meta)); + mocks.VerifyAll(); + } + + [Test] + public void SeqReduceWithNoStartIterates() + { + MockRepository mocks = new MockRepository(); + IFn fn = mocks.StrictMock(); + RMExpect.Call(fn.invoke(1, 2)).Return(5); + RMExpect.Call(fn.invoke(5, 3)).Return(7); + mocks.ReplayAll(); + + CPV v = new CPV(new object[] { 1, 2, 3 }); + IReduce r = (IReduce)v.seq(); + object ret = r.reduce(fn); + + Expect(ret, EqualTo(7)); + mocks.VerifyAll(); + } + + [Test] + public void SeqReduceWithStartIterates() + { + MockRepository mocks = new MockRepository(); + IFn fn = mocks.StrictMock(); + RMExpect.Call(fn.invoke(20, 1)).Return(10); + RMExpect.Call(fn.invoke(10, 2)).Return(5); + RMExpect.Call(fn.invoke(5, 3)).Return(7); + mocks.ReplayAll(); + + CPV v = new CPV(new object[] { 1, 2, 3 }); + IReduce r = (IReduce)v.seq(); + object ret = r.reduce(fn, 20); + + Expect(ret, EqualTo(7)); + mocks.VerifyAll(); + } + + #endregion + + #region APersistentVector.RSeq tests + + // We'll do all the tests indirectly. + + [Test] + public void RSeqFirstAndRestWork() + { + CPV v = new CPV(new object[] { 4, 5, 6 }); + ISeq s = v.rseq(); + + Expect(s.first(), EqualTo(6)); + Expect(s.rest().first(), EqualTo(5)); + Expect(s.rest().rest().first(), EqualTo(4)); + Expect(s.rest().rest().rest(), Null); + } + + [Test] + public void RSeqIndexedWorks() + { + CPV v = new CPV(new object[] { 4, 5, 6 }); + ISeq s0 = v.rseq(); + IndexedSeq i0 = s0 as IndexedSeq; + + ISeq s1 = s0.rest(); + IndexedSeq i1 = s1 as IndexedSeq; + + Expect(i0.index(), EqualTo(0)); + Expect(i1.index(), EqualTo(1)); + } + + [Test] + public void RSeqCountWorks() + { + CPV v = new CPV(new object[] { 4, 5, 6 }); + ISeq s = v.rseq(); + + Expect(s.count(), EqualTo(3)); + Expect(s.rest().count(), EqualTo(2)); + Expect(s.rest().rest().count(), EqualTo(1)); + } + + [Test] + public void RSeqWithMetaHasMeta() + { + MockRepository mocks = new MockRepository(); + IPersistentMap meta = mocks.StrictMock(); + mocks.ReplayAll(); + + CPV v = new CPV(new object[] { 4, 5, 6 }); + IObj s = (IObj)v.rseq(); + IObj obj = s.withMeta(meta); + + Expect(obj.meta(), SameAs(meta)); + mocks.VerifyAll(); + } + + [Test] + public void RSeqReduceWithNoStartIterates() + { + MockRepository mocks = new MockRepository(); + IFn fn = mocks.StrictMock(); + RMExpect.Call(fn.invoke(3, 2)).Return(5); + RMExpect.Call(fn.invoke(5, 1)).Return(7); + mocks.ReplayAll(); + + CPV v = new CPV(new object[] { 1, 2, 3 }); + IReduce r = (IReduce)v.rseq(); + object ret = r.reduce(fn); + + Expect(ret, EqualTo(7)); + mocks.VerifyAll(); + } + + [Test] + public void RSeqReduceWithStartIterates() + { + MockRepository mocks = new MockRepository(); + IFn fn = mocks.StrictMock(); + RMExpect.Call(fn.invoke(20, 3)).Return(10); + RMExpect.Call(fn.invoke(10, 2)).Return(5); + RMExpect.Call(fn.invoke(5, 1)).Return(7); + mocks.ReplayAll(); + + CPV v = new CPV(new object[] { 1, 2, 3 }); + IReduce r = (IReduce)v.rseq(); + object ret = r.reduce(fn, 20); + + Expect(ret, EqualTo(7)); + mocks.VerifyAll(); + } + + #endregion + + } +} diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/ARefTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/ARefTests.cs new file mode 100644 index 00000000..c2cbe01e --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/ARefTests.cs @@ -0,0 +1,22 @@ +/** + * Copyright (c) David Miller. All rights reserved. + * The use and distribution terms for this software are covered by the + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) + * which can be found in the file epl-v10.html at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Clojure.Tests.LibTests +{ + // TODO: Add tests for Aref + class ARefTests + { + } +} diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/AReferenceTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/AReferenceTests.cs new file mode 100644 index 00000000..8f621ae2 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/AReferenceTests.cs @@ -0,0 +1,98 @@ +/** + * Copyright (c) David Miller. All rights reserved. + * The use and distribution terms for this software are covered by the + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) + * which can be found in the file epl-v10.html at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using NUnit.Framework; +using Rhino.Mocks; + +using clojure.lang; + +using RMExpect = Rhino.Mocks.Expect; + +namespace Clojure.Tests.LibTests +{ + + [TestFixture] + public class AReferenceTests : AssertionHelper + { + // AReference is abstract. We need a class to instantiate. + + class ConcreteAReference : AReference + { + public ConcreteAReference() : base() { } + public ConcreteAReference(IPersistentMap meta) : base(meta) { } + } + + + #region C-tor tests + + [Test] + public void Default_ctor_creates_with_null_metadata() + { + ConcreteAReference c = new ConcreteAReference(); + Expect(c.meta(), Null); + } + + [Test] + public void Map_ctor_creates_with_given_metadata() + { + MockRepository mocks = new MockRepository(); + IPersistentMap meta = mocks.StrictMock(); + mocks.ReplayAll(); + + ConcreteAReference c = new ConcreteAReference(meta); + Expect(c.meta(), EqualTo(meta)); + + mocks.VerifyAll(); + } + + #endregion + + + #region IReference tests + + [Test] + public void AlterMeta_changes_meta() + { + MockRepository mocks = new MockRepository(); + IPersistentMap meta = mocks.StrictMock(); + IFn fn = mocks.StrictMock(); + RMExpect.Call(fn.applyTo(null)).IgnoreArguments().Return(meta); + mocks.ReplayAll(); + + ConcreteAReference c = new ConcreteAReference(); + c.alterMeta(fn, null); + + Expect(c.meta(), EqualTo(meta)); + mocks.VerifyAll(); + } + + [Test] + public void ResetMeta_sets_meta() + { + MockRepository mocks = new MockRepository(); + IPersistentMap meta = mocks.StrictMock(); + mocks.ReplayAll(); + + ConcreteAReference c = new ConcreteAReference(); + c.resetMeta(meta); + + Expect(c.meta(), EqualTo(meta)); + mocks.VerifyAll(); + } + + + #endregion + } +} diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/AgentTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/AgentTests.cs new file mode 100644 index 00000000..76bd2185 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/AgentTests.cs @@ -0,0 +1,22 @@ +/** + * Copyright (c) David Miller. All rights reserved. + * The use and distribution terms for this software are covered by the + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) + * which can be found in the file epl-v10.html at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Clojure.Tests.LibTests +{ + // TODO: Add tests for Agent + class AgentTests + { + } +} diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/ArraySeqTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/ArraySeqTests.cs new file mode 100644 index 00000000..cd033bb9 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/ArraySeqTests.cs @@ -0,0 +1,214 @@ +/** + * Copyright (c) David Miller. All rights reserved. + * The use and distribution terms for this software are covered by the + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) + * which can be found in the file epl-v10.html at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using NUnit.Framework; +using Rhino.Mocks; + +using clojure.lang; + +using RMExpect = Rhino.Mocks.Expect; + +namespace Clojure.Tests.LibTests +{ + [TestFixture] + public class ArraySeqTests : AssertionHelper + { + + #region C-tor tests + + [Test] + public void Create_on_nothing_returns_null() + { + ArraySeq a = ArraySeq.create(); + + Expect(a, Null); + } + + [Test] + public void Create_on_array_creates() + { + object[] array = new object[] { 1, 2, 3 }; + ArraySeq a = ArraySeq.create(array); + + Expect(a, Not.Null); + } + + [Test] + public void Create_on_null_returns_null() + { + ArraySeq a = ArraySeq.create(null); + + Expect(a, Null); + } + + [Test] + public void Create_on_array_has_no_meta() + { + object[] array = new object[] { 1, 2, 3 }; + ArraySeq a = ArraySeq.create(array); + + Expect(a.meta(), Null); + } + + [Test] + public void Create_on_array_and_index_creates() + { + object[] array = new object[] { 1, 2, 3 }; + ArraySeq a = ArraySeq.create(array,0); + + Expect(a, Not.Null); + } + + [Test] + public void Create_on_array_and_index_with_high_index_returns_null() + { + object[] array = new object[] { 1, 2, 3 }; + ArraySeq a = ArraySeq.create(array, 10); + + Expect(a, Null); + } + + [Test] + public void Create_on_array_and_index_has_no_meta() + { + object[] array = new object[] { 1, 2, 3 }; + ArraySeq a = ArraySeq.create(array,0); + + Expect(a.meta(), Null); + } + + #endregion + + #region IPersistentCollection tests + + [Test] + public void ArraySeq_has_correct_count_1() + { + object[] array = new object[] { 1, 2, 3 }; + ArraySeq a = ArraySeq.create(array); + + Expect(a.count(), EqualTo(3)); + } + + [Test] + public void ArraySeq_has_correct_count_2() + { + object[] array = new object[] { 1, 2, 3 }; + ArraySeq a = ArraySeq.create(array,1); + + Expect(a.count(), EqualTo(2)); + } + + #endregion + + + #region IReduce tests + + [Test] + public void ReduceWithNoStartIterates() + { + MockRepository mocks = new MockRepository(); + IFn fn = mocks.StrictMock(); + RMExpect.Call(fn.invoke(2, 3)).Return(5); + RMExpect.Call(fn.invoke(5, 4)).Return(7); + mocks.ReplayAll(); + + object[] array = new object[] { 2, 3, 4 }; + ArraySeq a = ArraySeq.create(array); + object ret = a.reduce(fn); + + Expect(ret, EqualTo(7)); + + mocks.VerifyAll(); + } + + [Test] + public void ReduceWithStartIterates() + { + MockRepository mocks = new MockRepository(); + IFn fn = mocks.StrictMock(); + RMExpect.Call(fn.invoke(20, 2)).Return(10); + RMExpect.Call(fn.invoke(10, 3)).Return(5); + RMExpect.Call(fn.invoke(5, 4)).Return(7); + mocks.ReplayAll(); + + object[] array = new object[] { 2, 3, 4 }; + ArraySeq a = ArraySeq.create(array); + object ret = a.reduce(fn, 20); + + Expect(ret, EqualTo(7)); + + mocks.VerifyAll(); + } + #endregion + + } + + [TestFixture] + public class ArraySeq_ISeq_Tests : ISeqTestHelper + { + object[] _array0; + object[] _array1; + ArraySeq _a0; + ArraySeq _a1; + + [SetUp] + public void Setup() + { + _array0 = new object[] { 1, 2, 3 }; + _array1 = new object[] { 2, 3 }; + _a0 = ArraySeq.create(_array0); + _a1 = ArraySeq.create(_array0, 1); + } + + [Test] + public void ArraySeq_ISeq_std_ctor_has_correct_elements() + { + VerifyISeqContents(_a0, _array0); + } + + [Test] + public void ArraySeq_ISeq_index_ctor_has_correct_elements() + { + VerifyISeqContents(_a1, _array1 ); + } + + [Test] + public void ArraySeq_ISeq_std_ctor_conses() + { + VerifyISeqCons(_a0, 4, _array0); + } + + [Test] + public void ArraySeq_ISeq_index_ctor_conses() + { + VerifyISeqCons(_a1, 4, _array1); + } + + + } + + [TestFixture] + public class ArraySeq_IObj_Tests : IObjTests + { + [SetUp] + public void Setup() + { + object[] array = new object[] { 1, 2, 3 }; + _objWithNullMeta = _obj = ArraySeq.create(array, 0); + _expectedType = typeof(ArraySeq); + } + } +} diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/ArrayStreamTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/ArrayStreamTests.cs new file mode 100644 index 00000000..45377efb --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/ArrayStreamTests.cs @@ -0,0 +1,22 @@ +/** + * Copyright (c) David Miller. All rights reserved. + * The use and distribution terms for this software are covered by the + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) + * which can be found in the file epl-v10.html at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Clojure.Tests.LibTests +{ + // TODO: Add ArrayStream tests + class ArrayStreamTests + { + } +} diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/AtomTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/AtomTests.cs new file mode 100644 index 00000000..d4ea90b5 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/AtomTests.cs @@ -0,0 +1,22 @@ +/** + * Copyright (c) David Miller. All rights reserved. + * The use and distribution terms for this software are covered by the + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) + * which can be found in the file epl-v10.html at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Clojure.Tests.LibTests +{ + // TODO: Add tests for Atom + class AtomTests + { + } +} diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/CachedSeqTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/CachedSeqTests.cs new file mode 100644 index 00000000..cd4b967d --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/CachedSeqTests.cs @@ -0,0 +1,22 @@ +/** + * Copyright (c) David Miller. All rights reserved. + * The use and distribution terms for this software are covered by the + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) + * which can be found in the file epl-v10.html at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Clojure.Tests.LibTests +{ + // TODO: write tests for CachedSeq + class CachedSeqTests + { + } +} diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/ConsTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/ConsTests.cs new file mode 100644 index 00000000..b01e1786 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/ConsTests.cs @@ -0,0 +1,428 @@ +/** + * Copyright (c) David Miller. All rights reserved. + * The use and distribution terms for this software are covered by the + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) + * which can be found in the file epl-v10.html at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using NUnit.Framework; +using Rhino.Mocks; + +using clojure.lang; +using System.Collections; + +namespace Clojure.Tests.LibTests +{ + [TestFixture] + public class ConsTests : AssertionHelper + { + #region C-tor tests + + [Test] + public void NoMetaCtorHasNoMeta() + { + Cons c = new Cons("abc",null); + Expect(c.meta(),Null); + } + + [Test] + public void MetaCtorHasMeta() + { + MockRepository mocks = new MockRepository(); + IPersistentMap meta = mocks.StrictMock(); + mocks.ReplayAll(); + + Cons c = new Cons(meta, "abc", null); + + Expect(c.meta(), SameAs(meta)); + mocks.VerifyAll(); + } + + #endregion + + #region IPersistentCollection tests + + [Test] + public void CountOfOneItem() + { + Cons c = new Cons("abc", null); + + Expect(c.count(), EqualTo(1)); + } + + [Test] + public void CountOfTwoItems() + { + Cons c1 = new Cons("abc", null); + Cons c2 = new Cons("def", c1); + + Expect(c2.count(), EqualTo(2)); + } + + [Test] + public void SeqReturnsSelf() + { + Cons c1 = new Cons("abc", null); + + Expect(c1.seq(), SameAs(c1)); + } + + [Test] + public void EmptyIsNull() + { + // Test of ASeq + Cons c = new Cons("abc", null); + Expect(c.empty(), Null); + } + + [Test] + public void IPC_Cons_works() + { + Cons c1 = new Cons("abc", null); + IPersistentCollection ipc1 = c1 as IPersistentCollection; + + IPersistentCollection ipc2 = ipc1.cons("def"); + ISeq s = ipc2.seq(); + + Expect(s.first(), EqualTo("def")); + Expect(s.rest(), SameAs(c1)); + } + + #endregion + + #region ASeq tests + + // Some aspects of ASeq have been tested above. + // Here are the remaining bits + + private Cons CreateComplicatedCons() + { + Cons c1 = new Cons(1, null); + Cons c2 = new Cons(2, c1); + Cons c3 = new Cons("abc", null); + Cons c4 = new Cons(c3, c2); + Cons c5 = new Cons("def", c4); + + return c5; + } + + [Test] + public void EqualsDoesValueComparison() + { + Cons a = CreateComplicatedCons(); + Cons b = CreateComplicatedCons(); + + Expect(a.Equals(b)); + Expect(a, EqualTo(b)); + } + + [Test] + public void GetHashCodeComputesOnValue() + { + Cons a = CreateComplicatedCons(); + Cons b = CreateComplicatedCons(); + + Expect(a.GetHashCode(), EqualTo(b.GetHashCode())); + } + + + #endregion + + #region ASeq.ICollection tests + + [Test] + [ExpectedException(typeof(ArgumentException))] + public void ASeqICollCopyToFailsOnNullArray() + { + ICollection ic = new Cons(1, null); + ic.CopyTo(null, 0); + } + + [Test] + [ExpectedException(typeof(ArgumentException))] + public void ASeqICollCopyToFailsOnInsufficientSpace() + { + ICollection ic = new Cons(1, new Cons(2, new Cons(3,null))); + Array arr = new object[2]; + ic.CopyTo(arr, 0); + } + + [Test] + [ExpectedException(typeof(ArgumentException))] + public void ASeqICollCopyToFailsOnInsufficientSpace2() + { + ICollection ic = new Cons(1, new Cons(2, new Cons(3, null))); + Array arr = new object[10]; + ic.CopyTo(arr, 8); + } + + [Test] + [ExpectedException(typeof(ArgumentException))] + public void ASeqICollCopyToFailsOnMultidimArray() + { + ICollection ic = new Cons(1, new Cons(2, new Cons(3, null))); + Array arr = Array.CreateInstance(typeof(int), 4, 4); + ic.CopyTo(arr, 0); + } + + [Test] + [ExpectedException(typeof(ArgumentOutOfRangeException))] + public void ASeqICollCopyToFailsOnNegativeIndex() + { + ICollection ic = new Cons(1, new Cons(2, new Cons(3, null))); + Array arr = new object[10]; + ic.CopyTo(arr, -1); + } + + [Test] + public void ASeqICollCopyToCopiesToIndex0() + { + ICollection ic = new Cons(1, new Cons(2, new Cons(3, null))); + int[] arr = new int[4]; + ic.CopyTo(arr, 0); + + Expect(arr[0], EqualTo(1)); + Expect(arr[1], EqualTo(2)); + Expect(arr[2], EqualTo(3)); + Expect(arr[3], EqualTo(0)); + } + + [Test] + public void ASeqICollCopyToCopiesToIndexPositive() + { + ICollection ic = new Cons(1, new Cons(2, new Cons(3, null))); + int[] arr = new int[4]; + ic.CopyTo(arr, 1); + + Expect(arr[0], EqualTo(0)); + Expect(arr[1], EqualTo(1)); + Expect(arr[2], EqualTo(2)); + Expect(arr[3], EqualTo(3)); + } + + [Test] + public void ASeqICollCountWorks() + { + ICollection ic = new Cons(1, new Cons(2, new Cons(3, null))); + + Expect(ic.Count, EqualTo(3)); + } + + [Test] + public void ASeqICollIsSynchronized() + { + ICollection ic = new Cons(1, new Cons(2, new Cons(3, null))); + Expect(ic.IsSynchronized); + } + + [Test] + [ExpectedException(typeof(NotImplementedException))] + public void ASeqICollHasDoesntImplementSyncRoot() + { + ICollection ic = new Cons(1, new Cons(2, new Cons(3, null))); + Object o = ic.SyncRoot; + } + + [Test] + public void ASeqIEnumWorks() + { + ICollection ic = new Cons(1, new Cons(2, new Cons(3, null))); + IEnumerator e = ic.GetEnumerator(); + + Expect(e.MoveNext()); + Expect(e.Current, EqualTo(1)); + Expect(e.MoveNext()); + Expect(e.Current, EqualTo(2)); + Expect(e.MoveNext()); + Expect(e.Current, EqualTo(3)); + Expect(e.MoveNext(),False); + } + + + #endregion + + #region SeqIterator tests + + [Test] + public void SeqIteratorOnEmptySeqGoesNowhere() + { + SeqEnumerator s = new SeqEnumerator(null); + + Expect(s.MoveNext(), False); + } + + [Test] + [ExpectedException(typeof(InvalidOperationException))] + public void SeqIteratorOnEmptyHasNoCurrent() + { + SeqEnumerator s = new SeqEnumerator(null); + object o = s.Current; + } + + [Test] + public void SeqIteratorIterates() + { + Cons c = new Cons(1, new Cons(2, null)); + SeqEnumerator s = new SeqEnumerator(c); + + Expect(s.MoveNext()); + Expect(s.Current, EqualTo(1)); + Expect(s.MoveNext()); + Expect(s.Current, EqualTo(2)); + Expect(s.Current, EqualTo(2)); + Expect(s.MoveNext(), False); + } + + [Test] + [ExpectedException(typeof(InvalidOperationException))] + public void SeqIteratorMovedToEmptyHasNoCurrent() + { + Cons c = new Cons(1, new Cons(2, null)); + SeqEnumerator s = new SeqEnumerator(c); + + s.MoveNext(); + s.MoveNext(); + s.MoveNext(); + object o = s.Current; + } + + + [ExpectedException(typeof(InvalidOperationException))] + public void SeqIteratorResetAtBeginningWorks() + { + Cons c = new Cons(1, new Cons(2, null)); + SeqEnumerator s = new SeqEnumerator(c); + + s.Reset(); + + Expect(s.MoveNext()); + Expect(s.Current, EqualTo(1)); + Expect(s.MoveNext()); + Expect(s.Current, EqualTo(2)); + Expect(s.Current, EqualTo(2)); + Expect(s.MoveNext(), False); + } + + [Test] + public void SeqIteratorResetAtFirstWorks() + { + Cons c = new Cons(1, new Cons(2, null)); + SeqEnumerator s = new SeqEnumerator(c); + + s.MoveNext(); + s.Reset(); + + Expect(s.MoveNext()); + Expect(s.Current, EqualTo(1)); + Expect(s.MoveNext()); + Expect(s.Current, EqualTo(2)); + Expect(s.Current, EqualTo(2)); + Expect(s.MoveNext(), False); + } + + [Test] + public void SeqIteratorResetInMiddleWorks() + { + Cons c = new Cons(1, new Cons(2, null)); + SeqEnumerator s = new SeqEnumerator(c); + + s.MoveNext(); + s.MoveNext(); + s.Reset(); + + Expect(s.MoveNext()); + Expect(s.Current, EqualTo(1)); + Expect(s.MoveNext()); + Expect(s.Current, EqualTo(2)); + Expect(s.Current, EqualTo(2)); + Expect(s.MoveNext(), False); + } + + [Test] + public void SeqIteratorResetAtEndWorks() + { + Cons c = new Cons(1, new Cons(2, null)); + SeqEnumerator s = new SeqEnumerator(c); + + s.MoveNext(); + s.MoveNext(); + s.MoveNext(); + s.Reset(); + + Expect(s.MoveNext()); + Expect(s.Current, EqualTo(1)); + Expect(s.MoveNext()); + Expect(s.Current, EqualTo(2)); + Expect(s.Current, EqualTo(2)); + Expect(s.MoveNext(), False); + } + + #endregion + } + + [TestFixture] + public class Cons_ISeq_Tests : ISeqTestHelper + { + + [Test] + public void Cons_ISeq_has_correct_values() + { + Cons c1 = new Cons("def", null); + Cons c2 = new Cons("abc", c1); + + VerifyISeqContents(c2, new object[] { "abc", "def" }); + } + + [Test] + public void Cons_ISeq_with_meta_has_correct_values() + { + MockRepository mocks = new MockRepository(); + IPersistentMap meta = mocks.StrictMock(); + mocks.ReplayAll(); + + Cons c1 = new Cons("def", null); + Cons c2 = new Cons(meta,"abc", c1); + + VerifyISeqContents(c2, new object[] { "abc", "def" }); + mocks.VerifyAll(); + } + + [Test] + public void Cons_ISeq_conses() + { + + Cons c1 = new Cons("def", null); + Cons c2 = new Cons("abc", c1); + + VerifyISeqCons(c2, "ghi", new object[] { "abc", "def" }); + } + + + + } + + + [TestFixture] + public class Cons_IMeta_Tests : IObjTests + { + [SetUp] + public void Setup() + { + IPersistentMap meta = PersistentHashMap.create("a", 1, "b", 2); + + Cons c1 = new Cons("abc", null); + Cons c2 = new Cons(meta,"def", c1); + _obj = c2; + _objWithNullMeta = c1; + _expectedType = typeof(Cons); + } + } +} diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/DelayTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/DelayTests.cs new file mode 100644 index 00000000..07d51a1c --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/DelayTests.cs @@ -0,0 +1,22 @@ +/** + * Copyright (c) David Miller. All rights reserved. + * The use and distribution terms for this software are covered by the + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) + * which can be found in the file epl-v10.html at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Clojure.Tests.LibTests +{ + class DelayTests + { + //TODO: Write Delay tests + } +} diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/FnSeqTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/FnSeqTests.cs new file mode 100644 index 00000000..93d64773 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/FnSeqTests.cs @@ -0,0 +1,120 @@ +/** + * Copyright (c) David Miller. All rights reserved. + * The use and distribution terms for this software are covered by the + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) + * which can be found in the file epl-v10.html at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using NUnit.Framework; +using Rhino.Mocks; + +using clojure.lang; + +using RMExpect = Rhino.Mocks.Expect; + +namespace Clojure.Tests.LibTests +{ + [TestFixture] + public class FnSeqTests : AssertionHelper + { + #region C-tor tests + + // Couldn't think of anything except to make sure it doesn't throw an exception. + [Test] + public void CtorWorks() + { + FnSeq fs = new FnSeq("abc",null); + + Expect(fs, Not.Null); + } + + #endregion + } + + [TestFixture] + public class FnSeq_ISeq_Tests : ISeqTestHelper + { + object[] _restValues; + object[] _values; + MockRepository _mocks; + FnSeq _fs; + + [SetUp] + public void Setup() + { + _restValues = new object[] { 2, 3, 4 }; + _values = new object[] { "abc", 2, 3, 4 }; + _mocks = new MockRepository(); + IFn _fn = _mocks.StrictMock(); + RMExpect.Call(_fn.invoke()).Return(PersistentList.create(_restValues)); + + _fs = new FnSeq("abc", _fn); + + _mocks.ReplayAll(); + } + + [TearDown] + public void Teardown() + { + _mocks.VerifyAll(); + } + + + [Test] + public void FnSeq_ISeq_has_correct_values() + { + VerifyISeqContents(_fs, _values); + } + + [Test] + public void FnSeq_ISeq_conses() + { + VerifyISeqCons(_fs, 12, _values); + } + + [Test] + public void RestCachesResult() + { + _fs.rest(); + _fs.rest(); + } + + + + } + + [TestFixture] + public class FnSeq_IObj_Tests : IObjTests + { + MockRepository _mocks; + + [SetUp] + public void Setup() + { + _mocks = new MockRepository(); + IFn fn = _mocks.StrictMock(); + RMExpect.Call(fn.invoke()).Return(null); + _mocks.ReplayAll(); + + FnSeq fs = new FnSeq("abc", fn); + + _obj = _objWithNullMeta = fs; + _expectedType = typeof(FnSeq); + } + + [TearDown] + public void TearDown() + { + _mocks.ReplayAll(); + } + + } +} diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/IObjTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/IObjTests.cs new file mode 100644 index 00000000..34f1ba72 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/IObjTests.cs @@ -0,0 +1,91 @@ +/** + * Copyright (c) David Miller. All rights reserved. + * The use and distribution terms for this software are covered by the + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) + * which can be found in the file epl-v10.html at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using NUnit.Framework; +using Rhino.Mocks; +using clojure.lang; + +namespace Clojure.Tests.LibTests +{ + /// + /// Base class for testing the IMeta interface functionality. + /// + public abstract class IObjTests : AssertionHelper + { + /// + /// Object to test for null meta. Set null if no test. Initialize in Setup. + /// + protected IObj _objWithNullMeta; + + + /// + /// The object to test. Initialize in Setup. + /// + protected IObj _obj; + + /// + /// Expected type of return from withMeta. Set null if no test. Initialize in Setup. + /// + protected Type _expectedType; + + + MockRepository _mocks = null; + IPersistentMap _meta = null; + + void InitMocks() + { + _mocks = new MockRepository(); + _meta = _mocks.StrictMock(); + _mocks.ReplayAll(); + } + + + [Test] + public void withMeta_has_correct_meta() + { + InitMocks(); + IObj obj2 = _obj.withMeta(_meta); + Expect(obj2.meta(), SameAs(_meta)); + _mocks.VerifyAll(); + } + + [Test] + public void withMeta_returns_correct_type() + { + if (_expectedType == null) + return; + + InitMocks(); + IObj obj2 = _obj.withMeta(_meta); + Expect(obj2, TypeOf(_expectedType)); + _mocks.VerifyAll(); + } + + [Test] + public void withMeta_returns_self_if_no_change() + { + IObj obj2 = _obj.withMeta(_obj.meta()); + Expect(obj2, SameAs(_obj)); + } + + [Test] + public void Verify_Null_Meta() + { + if (_objWithNullMeta == null) + return; + Expect(_objWithNullMeta.meta(), Null); + } + } +} diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/ISeqTestHelper.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/ISeqTestHelper.cs new file mode 100644 index 00000000..ba04a65e --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/ISeqTestHelper.cs @@ -0,0 +1,54 @@ +/** + * Copyright (c) David Miller. All rights reserved. + * The use and distribution terms for this software are covered by the + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) + * which can be found in the file epl-v10.html at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NUnit.Framework; +using clojure.lang; + +namespace Clojure.Tests.LibTests +{ + public class ISeqTestHelper : AssertionHelper + { + public void VerifyISeqContents(ISeq s, IList values) + { + int i=0; + + for (; s != null; s = s.rest(), i++) + Expect(s.first(), EqualTo(values[i])); + + Expect(i, EqualTo(values.Count)); + } + + public void VerifyISeqCons(ISeq s, object newVal, IList values) + { + ISeq newSeq = s.cons(newVal); + + Expect(newSeq.first(), EqualTo(newVal)); + VerifyISeqContents(newSeq.rest(), values); + } + + public void VerifyISeqRestTypes(ISeq s, Type type) + { + for ( ; s.rest() != null; s = s.rest()) + Expect(s.rest(), InstanceOfType(type)); + } + + public void VerifyISeqRestMaintainsMeta(ISeq s) + { + IPersistentMap meta = ((IMeta)s).meta(); + + for (; s.rest() != null; s = s.rest()) + Expect(((IMeta)s.rest()).meta(), EqualTo(meta)); + } + } +} diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/IteratorStreamTests.cs b/ClojureCLR/Clojure/