diff options
author | David Miller <dmiller2718@gmail.com> | 2009-02-21 06:55:20 +0000 |
---|---|---|
committer | David Miller <dmiller2718@gmail.com> | 2009-02-21 06:55:20 +0000 |
commit | 67f56f0795ac0214f9828c42f8face229e204c1d (patch) | |
tree | f01b57d581c3a48d87fb4d72b023bc8d609a24cd /ClojureCLR/Clojure/Clojure.Tests | |
parent | 64d79207eed0fe057a19fe4d3d0f6b714a63c69a (diff) |
ClojureCLR: added ClojureCLR project to repo.
Diffstat (limited to 'ClojureCLR/Clojure/Clojure.Tests')
43 files changed, 8520 insertions, 0 deletions
diff --git a/ClojureCLR/Clojure/Clojure.Tests/Clojure.Tests.csproj b/ClojureCLR/Clojure/Clojure.Tests/Clojure.Tests.csproj new file mode 100644 index 00000000..9bf437a0 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/Clojure.Tests.csproj @@ -0,0 +1,121 @@ +<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{656E1517-B0CA-47B4-B068-3DF43DC41F8A}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Clojure.Tests</RootNamespace>
+ <AssemblyName>Clojure.Tests</AssemblyName>
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <TargetFrameworkSubset>
+ </TargetFrameworkSubset>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Castle.Core, Version=1.0.3.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\..\dev\RhinoMocks\Castle.Core.dll</HintPath>
+ </Reference>
+ <Reference Include="Castle.DynamicProxy2, Version=2.0.3.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\..\dev\RhinoMocks\Castle.DynamicProxy2.dll</HintPath>
+ </Reference>
+ <Reference Include="nunit.framework, Version=2.4.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL" />
+ <Reference Include="Rhino.Mocks, Version=3.5.0.1337, Culture=neutral, PublicKeyToken=0b3305902db7183f, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\..\dev\RhinoMocks\Rhino.Mocks.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Xml.Linq">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data.DataSetExtensions">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ <Reference Include="vjslib" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="LibTests\AFnImplTests.cs" />
+ <Compile Include="LibTests\AgentTests.cs" />
+ <Compile Include="LibTests\APersistentVectorTests.cs" />
+ <Compile Include="LibTests\AReferenceTests.cs" />
+ <Compile Include="LibTests\ARefTests.cs" />
+ <Compile Include="LibTests\ArraySeqTests.cs" />
+ <Compile Include="LibTests\ArrayStreamTests.cs" />
+ <Compile Include="LibTests\AtomTests.cs" />
+ <Compile Include="LibTests\CachedSeqTests.cs" />
+ <Compile Include="LibTests\ConsTests.cs" />
+ <Compile Include="LibTests\DelayTests.cs" />
+ <Compile Include="LibTests\FnSeqTests.cs" />
+ <Compile Include="LibTests\IObjTests.cs" />
+ <Compile Include="LibTests\ISeqTestHelper.cs" />
+ <Compile Include="LibTests\IteratorStreamTests.cs" />
+ <Compile Include="LibTests\KeywordTests.cs" />
+ <Compile Include="LibTests\LazilyPersistentVectorTests.cs" />
+ <Compile Include="LibTests\LazyConsTests.cs" />
+ <Compile Include="LibTests\LispReaderTests.cs" />
+ <Compile Include="LibTests\LockingTransactionTests.cs" />
+ <Compile Include="LibTests\MapEntryTests.cs" />
+ <Compile Include="LibTests\NamespaceTests.cs" />
+ <Compile Include="LibTests\NumbersTests.cs" />
+ <Compile Include="LibTests\ObjTests.cs" />
+ <Compile Include="LibTests\PersistentArrayMapTests.cs" />
+ <Compile Include="LibTests\PersistentHashMapTests.cs" />
+ <Compile Include="LibTests\PersistentHashSetTests.cs" />
+ <Compile Include="LibTests\PersistentListTests.cs" />
+ <Compile Include="LibTests\PersistentQueueTests.cs" />
+ <Compile Include="LibTests\PersistentStructMapTests.cs" />
+ <Compile Include="LibTests\PersistentTreeMapTests.cs" />
+ <Compile Include="LibTests\PersistentTreeSetTests.cs" />
+ <Compile Include="LibTests\PersistentVectorTests.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="LibTests\RangeTests.cs" />
+ <Compile Include="LibTests\RefTests.cs" />
+ <Compile Include="LibTests\RestFnImplTests.cs" />
+ <Compile Include="LibTests\RestFnTests.cs" />
+ <Compile Include="LibTests\StreamSeqTests.cs" />
+ <Compile Include="LibTests\StringSeqTests.cs" />
+ <Compile Include="LibTests\SymbolTests.cs" />
+ <Compile Include="LibTests\TestTest.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Clojure\Clojure.csproj">
+ <Project>{B8089F66-DFBD-4906-BEE0-B317689C2524}</Project>
+ <Name>Clojure</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
\ No newline at end of file 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<int> 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<IPersistentMap>();
+ 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<IPersistentMap>();
+ 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<IFn>();
+ 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<IFn>();
+ 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<IPersistentMap>();
+ 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<IFn>();
+ 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<IFn>();
+ 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<IPersistentMap>();
+ 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<IPersistentMap>();
+ IFn fn = mocks.StrictMock<IFn>();
+ 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<IPersistentMap>();
+ 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<IFn>();
+ 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<IFn>();
+ 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<IPersistentMap>();
+ 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<IPersistentMap>();
+ 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<IFn>();
+ 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<IFn>();
+ 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
+{
+ /// <summary>
+ /// Base class for testing the IMeta interface functionality.
+ /// </summary>
+ public abstract class IObjTests : AssertionHelper
+ {
+ /// <summary>
+ /// Object to test for null meta. Set null if no test. Initialize in Setup.
+ /// </summary>
+ protected IObj _objWithNullMeta;
+
+
+ /// <summary>
+ /// The object to test. Initialize in Setup.
+ /// </summary>
+ protected IObj _obj;
+
+ /// <summary>
+ /// Expected type of return from withMeta. Set null if no test. Initialize in Setup.
+ /// </summary>
+ protected Type _expectedType;
+
+
+ MockRepository _mocks = null;
+ IPersistentMap _meta = null;
+
+ void InitMocks()
+ {
+ _mocks = new MockRepository();
+ _meta = _mocks.StrictMock<IPersistentMap>();
+ _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<object> 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<object> 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/Clojure.Tests/LibTests/IteratorStreamTests.cs new file mode 100644 index 00000000..abc8291d --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/IteratorStreamTests.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 IteratorStream
+ class IteratorStreamTests
+ {
+ }
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/KeywordTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/KeywordTests.cs new file mode 100644 index 00000000..6960f14c --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/KeywordTests.cs @@ -0,0 +1,239 @@ +/**
+ * 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;
+using System.Collections;
+
+
+namespace Clojure.Tests.LibTests
+{
+ [TestFixture]
+ public class KeywordTests : AssertionHelper
+ {
+
+ #region c-tor tests
+
+ [Test]
+ public void InternCreatesKeywordBasedOnSymbol()
+ {
+ Symbol sym = Symbol.intern("def","abc");
+ Keyword k1 = Keyword.intern(sym);
+ Expect(k1.Name,EqualTo(sym.Name));
+ Expect(k1.Namespace,EqualTo(sym.Namespace));
+ }
+
+ [Test]
+ public void InternReturnsSameKeywordOnEqualSym()
+ {
+ Symbol sym1 = Symbol.intern("def", "abc");
+ Symbol sym2 = Symbol.intern("def", "abc");
+ Keyword k1 = Keyword.intern(sym1);
+ Keyword k2 = Keyword.intern(sym2);
+
+ Expect(Object.ReferenceEquals(k1, k2));
+ }
+
+ [Test]
+ public void Intern2CreatesKeywordBasedOnSymbol()
+ {
+ Keyword k1 = Keyword.intern("def","abc");
+ Expect(k1.Name, EqualTo("abc"));
+ Expect(k1.Namespace, EqualTo("def"));
+ }
+
+ [Test]
+ public void Intern2ReturnsSameKeywordOnEqualSym()
+ {
+ Keyword k1 = Keyword.intern("def", "abc");
+ Keyword k2 = Keyword.intern("def", "abc");
+
+ Expect(Object.ReferenceEquals(k1, k2));
+ }
+
+ #endregion
+
+ #region object override tests
+
+ [Test]
+ public void ToStringReturnsStringNameWithColonPrepended()
+ {
+ Symbol sym1 = Symbol.intern("abc");
+ Symbol sym2 = Symbol.intern("abc/def");
+ Keyword k1 = Keyword.intern(sym1);
+ Keyword k2 = Keyword.intern(sym2);
+
+ Expect(k1.ToString(), EqualTo(":abc"));
+ Expect(k2.ToString(), EqualTo(":abc/def"));
+ }
+
+ [Test]
+ public void EqualOnIdentityIsTrue()
+ {
+ Symbol sym1 = Symbol.intern("abc");
+ Keyword k1 = Keyword.intern(sym1);
+
+ Expect(k1.Equals(k1));
+ }
+
+ [Test]
+ public void EqualsOnNonKeywordIsFalse()
+ {
+ Symbol sym1 = Symbol.intern("abc");
+ Keyword k1 = Keyword.intern(sym1);
+
+ Expect(k1.Equals(sym1), False);
+ }
+
+ //[Test]
+ //public void EqualsDependsOnSym()
+ //{
+ // Symbol sym1 = Symbol.intern("abc");
+ // Symbol sym2 = Symbol.intern("abc");
+ // Keyword k1 = Keyword.intern(sym1);
+ // Keyword k2 = Keyword.intern(sym2);
+ // // I don't know how we ever create two keywords that will force
+ // // the code to go into the sym.equals part of the code.
+ // // At least, not through the factory methods.
+ //}
+
+ [Test]
+ public void HashCodeDependsOnValue()
+ {
+ Symbol sym1 = Symbol.intern("abc");
+ Symbol sym2 = Symbol.intern("abc/def");
+ Keyword k1 = Keyword.intern(sym1);
+ Keyword k2 = Keyword.intern(sym2);
+
+ Expect(k1.GetHashCode(), Not.EqualTo(k2.GetHashCode()));
+ }
+
+
+ #endregion
+
+ #region Named tests
+
+ public void NameAndNamespaceComeFromTheSymbol()
+ {
+ Symbol sym1 = Symbol.intern("def", "abc");
+ Keyword k1 = Keyword.intern(sym1);
+ Symbol sym2 = Symbol.intern("abc");
+ Keyword k2 = Keyword.intern(sym2);
+ Expect(k1.Name, EqualTo("abc"));
+ Expect(k1.Namespace, EqualTo("def"));
+ Expect(k2.Name, EqualTo("abc"));
+ Expect(k2.Namespace, Null);
+ }
+
+ #endregion
+
+ #region IFn Tests
+
+ [Test]
+ public void Invoke2IndexesIntoItsFirstArg()
+ {
+ Keyword k1 = Keyword.intern(Symbol.intern("abc"));
+ Keyword k2 = Keyword.intern(Symbol.intern("ab"));
+
+ IDictionary dict = new Hashtable();
+ dict[k1] = 7;
+ dict["abc"] = 8;
+
+ Expect(k1.invoke(dict), EqualTo(7));
+ Expect(k2.invoke(dict), Null);
+ }
+
+ [Test]
+ public void Invoke3IndexesIntoItsFirstArg()
+ {
+ Keyword k1 = Keyword.intern(Symbol.intern("abc"));
+ Keyword k2 = Keyword.intern(Symbol.intern("ab"));
+
+ IDictionary dict = new Hashtable();
+ dict[k1] = 7;
+ dict["abc"] = 8;
+
+ Expect(k1.invoke(dict, 20), EqualTo(7));
+ Expect(k2.invoke(dict, 20), EqualTo(20));
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException))]
+ public void InvokeOnNoArgsFails()
+ {
+ Keyword k1 = Keyword.intern(Symbol.intern("abc"));
+ object o = k1.invoke();
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException))]
+ public void InvokeOnTooManyArgsFails()
+ {
+ Keyword k1 = Keyword.intern(Symbol.intern("abc"));
+ IDictionary dict = new Hashtable();
+ dict[k1] = 7;
+ dict["abc"] = 8;
+
+ object o = k1.invoke(dict, 20, null);
+ }
+
+ #endregion
+
+ #region IComparable tests
+
+ [Test]
+ [ExpectedException(typeof(InvalidCastException))]
+ public void CompareToNonKeywordFails()
+ {
+ Symbol s1 = Symbol.intern("abc");
+ Keyword k1 = Keyword.intern(s1);
+ int c = k1.CompareTo(s1);
+ }
+
+ [Test]
+ public void CompareToEqualKeywordIsZero()
+ {
+ Keyword k1 = Keyword.intern(Symbol.intern("abc"));
+ Keyword k2 = Keyword.intern(Symbol.intern("abc"));
+
+ Expect(k1.CompareTo(k2), EqualTo(0));
+ }
+
+ [Test]
+ public void CompareDependsOnSymbolCompare()
+ {
+ Symbol sym1 = Symbol.intern("abc");
+ Symbol sym2 = Symbol.intern("a", "abc");
+ Symbol sym3 = Symbol.intern("b", "abc");
+ Keyword k1 = Keyword.intern(sym1);
+ Keyword k2 = Keyword.intern(sym2);
+ Keyword k3 = Keyword.intern(sym3);
+
+ Expect(k1.CompareTo(k2), LessThan(0));
+ Expect(k2.CompareTo(k1), GreaterThan(0));
+ Expect(k1.CompareTo(k3), LessThan(0));
+ Expect(k3.CompareTo(k1), GreaterThan(0));
+ }
+
+
+ #endregion
+ }
+
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/LazilyPersistentVectorTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/LazilyPersistentVectorTests.cs new file mode 100644 index 00000000..e5549288 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/LazilyPersistentVectorTests.cs @@ -0,0 +1,220 @@ +/**
+ * 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 LazilyPersistentVectorTests : AssertionHelper
+ {
+ #region C-tor tests
+
+ [Test]
+ public void CreateOwningOnNoParamsReturnsEmptyVector()
+ {
+ IPersistentVector v = LazilyPersistentVector.createOwning();
+ Expect(v.count(),EqualTo(0));
+ }
+
+ [Test]
+ public void CreatingOwningOnParamsReturnsVector()
+ {
+ IPersistentVector v = LazilyPersistentVector.createOwning(1, 2, 3);
+ Expect(v.count(), EqualTo(3));
+ Expect(v.nth(0), EqualTo(1));
+ Expect(v.nth(1), EqualTo(2));
+ Expect(v.nth(2), EqualTo(3));
+ }
+
+ [Test]
+ public void CreateOnEmptySeqReturnsEmptyVector()
+ {
+ IPersistentVector v = LazilyPersistentVector.create(new object[] {});
+ Expect(v.count(), EqualTo(0));
+ }
+
+ [Test]
+ public void CreateOnNonEmptyCollectionReturnsVector()
+ {
+ IPersistentVector v = LazilyPersistentVector.createOwning(new object[] {1, 2, 3});
+ Expect(v.count(), EqualTo(3));
+ Expect(v.nth(0), EqualTo(1));
+ Expect(v.nth(1), EqualTo(2));
+ Expect(v.nth(2), EqualTo(3));
+ }
+
+
+ #endregion
+
+ #region IPersistentVector tests
+
+ [Test]
+ public void NthInRangeWorks()
+ {
+ IPersistentVector v = LazilyPersistentVector.createOwning(1, 2, 3);
+
+ Expect(v.count(), EqualTo(3));
+ Expect(v.nth(0), EqualTo(1));
+ Expect(v.nth(1), EqualTo(2));
+ Expect(v.nth(2), EqualTo(3));
+ }
+
+ [Test]
+ [ExpectedException(typeof(IndexOutOfRangeException))]
+ public void NthOutOfRangeLowFails()
+ {
+ IPersistentVector v = LazilyPersistentVector.createOwning(1, 2, 3);
+
+ Expect(v.nth(-4), EqualTo(1));
+ }
+
+ [Test]
+ [ExpectedException(typeof(IndexOutOfRangeException))]
+ public void NthOutOfRangeHighFails()
+ {
+ IPersistentVector v = LazilyPersistentVector.createOwning(1, 2, 3);
+
+ Expect(v.nth(4), EqualTo(1));
+ }
+
+ [Test]
+ public void AssocnInRangeModifies()
+ {
+ IPersistentVector v = LazilyPersistentVector.createOwning(1, 2, 3);
+ IPersistentVector v2 = v.assocN(1, 4);
+
+ Expect(v.count(), EqualTo(3));
+ Expect(v.nth(0), EqualTo(1));
+ Expect(v.nth(1), EqualTo(2));
+ Expect(v.nth(2), EqualTo(3));
+
+ Expect(v2.count(), EqualTo(3));
+ Expect(v2.nth(0), EqualTo(1));
+ Expect(v2.nth(1), EqualTo(4));
+ Expect(v2.nth(2), EqualTo(3));
+ }
+
+ [Test]
+ public void AssocnAtEndModifies()
+ {
+ IPersistentVector v = LazilyPersistentVector.createOwning(1, 2, 3);
+ IPersistentVector v2 = v.assocN(3, 4);
+
+ Expect(v.count(), EqualTo(3));
+ Expect(v.nth(0), EqualTo(1));
+ Expect(v.nth(1), EqualTo(2));
+ Expect(v.nth(2), EqualTo(3));
+
+ Expect(v2.count(), EqualTo(4));
+ Expect(v2.nth(0), EqualTo(1));
+ Expect(v2.nth(1), EqualTo(2));
+ Expect(v2.nth(2), EqualTo(3));
+ Expect(v2.nth(3), EqualTo(4));
+ }
+
+ [Test]
+ [ExpectedException(typeof(IndexOutOfRangeException))]
+ public void AssocNOutOfRangeLowFails()
+ {
+ IPersistentVector v = LazilyPersistentVector.createOwning(1, 2, 3);
+ IPersistentVector v2 = v.assocN(-4, 4);
+ }
+
+ [Test]
+ [ExpectedException(typeof(IndexOutOfRangeException))]
+ public void AssocNOutOfRangeHighFails()
+ {
+ IPersistentVector v = LazilyPersistentVector.createOwning(1, 2, 3);
+ IPersistentVector v2 = v.assocN(4, 4);
+ }
+
+
+ [Test]
+ public void ConsAddsAtEnd()
+ {
+ IPersistentVector v = LazilyPersistentVector.createOwning(1, 2, 3);
+ IPersistentVector v2 = v.cons(4);
+
+ Expect(v.count(), EqualTo(3));
+ Expect(v.nth(0), EqualTo(1));
+ Expect(v.nth(1), EqualTo(2));
+ Expect(v.nth(2), EqualTo(3));
+
+ Expect(v2.count(), EqualTo(4));
+ Expect(v2.nth(0), EqualTo(1));
+ Expect(v2.nth(1), EqualTo(2));
+ Expect(v2.nth(2), EqualTo(3));
+ Expect(v2.nth(3), EqualTo(4));
+ }
+
+ [Test]
+ public void LengthWorks()
+ {
+ IPersistentVector v = LazilyPersistentVector.createOwning(1, 2, 3);
+
+ Expect(v.length(), EqualTo(3));
+ }
+
+ #endregion
+
+ #region IPersistentStack tests
+
+ [Test]
+ public void PopOnNonEmptyWorks()
+ {
+ IPersistentVector v = LazilyPersistentVector.createOwning(1, 2, 3);
+ IPersistentVector v2 = (IPersistentVector)((IPersistentStack)v).pop();
+
+ Expect(v.count(), EqualTo(3));
+ Expect(v.nth(0), EqualTo(1));
+ Expect(v.nth(1), EqualTo(2));
+ Expect(v.nth(2), EqualTo(3));
+
+ Expect(v2.count(), EqualTo(2));
+ Expect(v2.nth(0), EqualTo(1));
+ Expect(v2.nth(1), EqualTo(2));
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException))]
+ public void PopOnEmptyFails()
+ {
+ IPersistentVector v = LazilyPersistentVector.createOwning();
+ IPersistentStack v2 = ((IPersistentStack)v).pop();
+ }
+
+ #endregion
+ }
+
+ [TestFixture]
+ public class LazilyPersistentVector_IObj_Tests : IObjTests
+ {
+ [SetUp]
+ public void Setup()
+ {
+ IPersistentVector v = LazilyPersistentVector.createOwning(1, 2, 3);
+
+ _obj = _objWithNullMeta = (IObj)v;
+ _expectedType = typeof(LazilyPersistentVector);
+ }
+ }
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/LazyConsTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/LazyConsTests.cs new file mode 100644 index 00000000..0a230c0e --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/LazyConsTests.cs @@ -0,0 +1,123 @@ +/**
+ * 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 LazyConsTests : AssertionHelper
+ {
+
+ #region C-tor tests
+
+ // Couldn't think of anything except to make sure it doesn't throw an exception.
+ [Test]
+ public void CtorWorks()
+ {
+ LazyCons lc = new LazyCons(null);
+
+ Expect(lc, Not.Null);
+ }
+
+ #endregion
+ }
+
+ [TestFixture]
+ public class LazyCons_ISeq_Tests : ISeqTestHelper
+ {
+ MockRepository _mocks ;
+ IFn _fn;
+ LazyCons _lc;
+ object[] _values;
+
+ [SetUp]
+ public void Setup()
+ {
+ _mocks = new MockRepository();
+ _fn = _mocks.StrictMock<IFn>();
+ RMExpect.Call(_fn.invoke()).Return(10);
+ RMExpect.Call(_fn.invoke(null)).Return(new Cons(20,null));
+ _lc = new LazyCons(_fn);
+ _values = new object[] { 10, 20 };
+ _mocks.ReplayAll();
+ }
+
+ [TearDown]
+ public void Teardown()
+ {
+ _mocks.VerifyAll();
+ }
+
+ [Test]
+ public void ISeq_has_proper_values()
+ {
+ VerifyISeqContents(_lc, _values);
+ }
+
+ [Test]
+ public void First_caches()
+ {
+ _lc.first();
+ _lc.first();
+
+ // Need to meet expectation that _rest is called.
+ _lc.rest();
+ }
+
+ [Test]
+ public void Rest_calcs_first()
+ {
+ _lc.rest();
+ }
+
+ [Test]
+ public void Rest_caches()
+ {
+ _lc.rest();
+ _lc.rest();
+ }
+
+
+
+ }
+
+ [TestFixture]
+ public class LazyCons_IObj_Tests : IObjTests
+ {
+ [SetUp]
+ public void Setup()
+ {
+ MockRepository mocks = new MockRepository();
+ IPersistentMap meta = mocks.StrictMock<IPersistentMap>();
+ IFn fn = mocks.StrictMock<IFn>();
+ RMExpect.Call(fn.invoke()).Return(10);
+ RMExpect.Call(fn.invoke(null)).Return(null);
+ mocks.ReplayAll();
+
+ _objWithNullMeta = new LazyCons(fn);
+ _obj = _objWithNullMeta.withMeta(meta);
+ _expectedType = typeof(LazyCons);
+
+ mocks.VerifyAll();
+ }
+ }
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/LispReaderTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/LispReaderTests.cs new file mode 100644 index 00000000..99d45e36 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/LispReaderTests.cs @@ -0,0 +1,1789 @@ +/**
+ * 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 System.IO;
+
+
+using NUnit.Framework;
+using Rhino.Mocks;
+
+using clojure.lang;
+
+using RMExpect = Rhino.Mocks.Expect;
+using java.math;
+
+using clojure.lang.Readers;
+
+
+namespace Clojure.Tests.LibTests
+{
+ [TestFixture]
+ public class LispReaderTests : AssertionHelper
+ {
+ #region matchNumber tests
+
+ [Test]
+ public void MatchNumberMatchesZero()
+ {
+ object o1 = LispReader.matchNumber("0");
+ object o2 = LispReader.matchNumber("-0");
+ object o3 = LispReader.matchNumber("+0");
+
+ Expect(o1, EqualTo(0));
+ Expect(o2, EqualTo(0));
+ Expect(o3, EqualTo(0));
+ }
+
+ [Test]
+ public void MatchNumberMatchesDecimal()
+ {
+ object o1 = LispReader.matchNumber("123");
+ object o2 = LispReader.matchNumber("+123");
+ object o3 = LispReader.matchNumber("-123");
+ object o4 = LispReader.matchNumber("123456789123456789123456789");
+
+ Expect(o1, EqualTo(123));
+ Expect(o2, EqualTo(123));
+ Expect(o3, EqualTo(-123));
+ Expect(o4, EqualTo(new BigInteger("123456789123456789123456789")));
+ }
+
+ [Test]
+ public void MatchNumberMatchesHexadecimal()
+ {
+ object o1 = LispReader.matchNumber("0X12A");
+ object o2 = LispReader.matchNumber("0xFFF");
+ object o3 = LispReader.matchNumber("0xFFFFFFFFFFFFFFFFFFFFFFFF");
+
+ Expect(o1, EqualTo(0x12A));
+ Expect(o2, EqualTo(0xFFF));
+ Expect(o3, EqualTo(new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFF", 16)));
+ }
+
+
+ [Test]
+ public void MatchNumberMatchesOctal()
+ {
+ object o1 = LispReader.matchNumber("0123");
+ object o2 = LispReader.matchNumber("+0123");
+ object o3 = LispReader.matchNumber("-0123");
+ object o4 = LispReader.matchNumber("01234567012345670123456777");
+
+ Expect(o1, EqualTo(83));
+ Expect(o2, EqualTo(83));
+ Expect(o3, EqualTo(-83));
+ Expect(o4, EqualTo(new BigInteger("1234567012345670123456777", 8)));
+ }
+
+ [Test]
+ public void MatchNumberMatchesSpecifiedRadix()
+ {
+ object o1 = LispReader.matchNumber("2R1100");
+ object o2 = LispReader.matchNumber("4R123");
+ object o3 = LispReader.matchNumber("-4R123");
+ object o4 = LispReader.matchNumber("30R1234AQ");
+
+ Expect(o1, EqualTo(12));
+ Expect(o2, EqualTo(27));
+ Expect(o3, EqualTo(-27));
+ Expect(o4, EqualTo(new BigInteger("1234AQ", 30).longValue()));
+ }
+
+ [Test]
+ public void MatchNumberMatchesFloats()
+ {
+ object o1 = LispReader.matchNumber("123.7");
+ object o2 = LispReader.matchNumber("-123.7E4");
+ object o3 = LispReader.matchNumber("+1.237e4");
+ object o4 = LispReader.matchNumber("+1.237e-4");
+ object o5 = LispReader.matchNumber("1.237e+4");
+
+ Expect(o1, EqualTo(123.7));
+ Expect(o2, EqualTo(-1237000.0));
+ Expect(o3, EqualTo(1.237e4));
+ Expect(o4, EqualTo(1.237e-4));
+ Expect(o5, EqualTo(1.237e4));
+ }
+
+ [Test]
+ public void MatchNumberMatchesDecimals()
+ {
+ object o1 = LispReader.matchNumber("123.7M");
+ // MS implementation of BigDecimal parser does not allow these.
+ //object o2 = LispReader.matchNumber("-123.7E4M");
+ //object o3 = LispReader.matchNumber("+1.237e4M");
+ //object o4 = LispReader.matchNumber("+1.237e-4M");
+ //object o5 = LispReader.matchNumber("1.237e+4M");
+
+ Expect(o1, EqualTo(new BigDecimal("123.7")));
+ //Expect(o2, EqualTo(-1237000.0M));
+ //Expect(o3, EqualTo(1.237e4M));
+ //Expect(o4, EqualTo(1.237e-4M));
+ //Expect(o5, EqualTo(1.237e4M));
+ }
+
+ [Test]
+ public void MatchNumberMatchesRatios()
+ {
+ object o1 = LispReader.matchNumber("12/1");
+ object o2 = LispReader.matchNumber("12/4");
+ object o3 = LispReader.matchNumber("12/5");
+ object o4 = LispReader.matchNumber("12345678900000/123456789");
+
+ Expect(o1, EqualTo(12));
+ Expect(o2, EqualTo(3));
+ Expect(o3, EqualTo(new Ratio(new BigInteger("12"),new BigInteger("5"))));
+ Expect(o4, EqualTo(100000));
+ }
+
+ [Test]
+ public void MatchNumberReadsWholeString()
+ {
+ object o1 = LispReader.matchNumber(" 123");
+ object o2 = LispReader.matchNumber("123 ");
+ object o3 = LispReader.matchNumber(" 12.3");
+ object o4 = LispReader.matchNumber("12.3 ");
+ object o5 = LispReader.matchNumber(" 1/23");
+ object o6 = LispReader.matchNumber("1/23 ");
+
+ Expect(o1, Null);
+ Expect(o2, Null);
+ Expect(o3, Null);
+ Expect(o4, Null);
+ Expect(o5, Null);
+ Expect(o6, Null);
+ }
+
+ [Test]
+ public void MatchNumberFailsToMatchWeirdThings()
+ {
+ object o1 = LispReader.matchNumber("123a");
+ object o2 = LispReader.matchNumber("0x123Z");
+ object o4 = LispReader.matchNumber("12.4/24.2");
+ object o5 = LispReader.matchNumber("1.7M3");
+
+ Expect(o1, Null);
+ Expect(o2, Null);
+ Expect(o4, Null);
+ Expect(o5, Null);
+ }
+
+
+ [Test]
+ [ExpectedException(typeof(java.lang.NumberFormatException))]
+ public void MatchNumberFailsOnRadixSnafu()
+ {
+ object o3 = LispReader.matchNumber("10RAA");
+ }
+ #endregion
+
+ #region Helpers
+
+ static TextReader CreatePushbackReaderFromString(string s)
+ {
+ return new StringReader(s);
+ }
+
+ static object ReadFromString(string s)
+ {
+ return LispReader.read(CreatePushbackReaderFromString(s),true,null,false);
+ }
+
+ static LineNumberingReader CreateLNPBRFromString(string s)
+ {
+ return new LineNumberingReader(new StringReader(s));
+ }
+
+ static object ReadFromStringNumbering(string s)
+ {
+ return LispReader.read(CreateLNPBRFromString(s),true,null,false);
+ }
+
+
+ #endregion
+
+ #region Testing EOF
+
+ [Test]
+ public void EofValueReturnedOnEof()
+ {
+ object o = LispReader.read(CreatePushbackReaderFromString(" "), false, 7, false);
+ Expect(o, EqualTo(7));
+ }
+
+ [Test]
+ [ExpectedException(typeof(System.IO.EndOfStreamException))]
+ public void EofValueFailsOnEof()
+ {
+ object o = LispReader.read(CreatePushbackReaderFromString(" "), true, 7, false);
+ }
+
+ #endregion
+
+ #region Testing a few numbers
+
+ [Test]
+ public void ReadReadsIntegers()
+ {
+ object o1 = ReadFromString("123");
+ object o2 = ReadFromString("-123");
+ object o3 = ReadFromString("+123");
+ object o4 = ReadFromString("123456789123456789123456789");
+
+ Expect(o1, EqualTo(123));
+ Expect(o2, EqualTo(-123));
+ Expect(o3, EqualTo(123));
+ Expect(o4, EqualTo(new BigInteger("123456789123456789123456789")));
+ }
+
+ [Test]
+ public void ReadReadsFloats()
+ {
+ object o1 = ReadFromString("123.4");
+ object o2 = ReadFromString("-123.4E4");
+ object o3 = ReadFromString("+123.4E-2");
+
+ Expect(o1, EqualTo(123.4));
+ Expect(o2, EqualTo(-123.4E4));
+ Expect(o3, EqualTo(123.4E-2));
+ }
+
+ [Test]
+ public void ReadReadsRatios()
+ {
+ object o1 = ReadFromString("123/456");
+ object o2 = ReadFromString("-123/456");
+ object o3 = ReadFromString("+123/456");
+
+ Expect(o1, TypeOf(typeof(Ratio)));
+ Expect(o2, TypeOf(typeof(Ratio)));
+ Expect(o3, TypeOf(typeof(Ratio)));
+ }
+
+
+
+ #endregion
+
+ #region Special tokens
+
+ [Test]
+ public void SlashAloneIsSlash()
+ {
+ object o = ReadFromString("/");
+ Expect(o, TypeOf(typeof(Symbol)));
+ Expect(((Symbol)o).Name, EqualTo("/"));
+ Expect(((Symbol)o).Namespace, Null);
+ }
+
+ [Test]
+ public void ClojureSlashIsSpecial()
+ {
+ object o = ReadFromString("clojure.core//");
+ Expect(o, TypeOf(typeof(Symbol)));
+ Expect(((Symbol)o).Name, EqualTo("/"));
+ Expect(((Symbol)o).Namespace, EqualTo("clojure.core"));
+ }
+
+ [Test]
+ public void TrueReturnsT()
+ {
+ object o = ReadFromString("true");
+ Expect(o, TypeOf(typeof(bool)));
+ Expect(o,EqualTo(true));
+ }
+
+ [Test]
+ public void FalseReturnsF()
+ {
+ object o = ReadFromString("false");
+ Expect(o, TypeOf(typeof(bool)));
+ Expect(o, EqualTo(false));
+ }
+
+ [Test]
+ public void NilIsNull()
+ {
+ object o = ReadFromString("nil");
+ Expect(o, Null);
+ }
+
+ #endregion
+
+ #region Symbolic tests
+
+ [Test]
+ public void ReadReadsSymbolWithNoNS()
+ {
+ object o1 = ReadFromString("abc");
+
+ Expect(o1, TypeOf(typeof(Symbol)));
+ Expect(((Symbol)o1).Name, EqualTo("abc"));
+ Expect(((Symbol)o1).Namespace, Null);
+ }
+
+ [Test]
+ public void ReadReadsSymbolWithNS()
+ {
+ object o1 = ReadFromString("ab/cd");
+
+ Expect(o1, TypeOf(typeof(Symbol)));
+ Expect(((Symbol)o1).Name, EqualTo("cd"));
+ Expect(((Symbol)o1).Namespace, EqualTo("ab"));
+ }
+
+ [Test]
+ public void TwoSlashesIsOkayApparently()
+ {
+ object o1 = ReadFromString("ab/cd/e");
+
+ Expect(o1, TypeOf(typeof(Symbol)));
+ Expect(((Symbol)o1).Name, EqualTo("e"));
+ Expect(((Symbol)o1).Namespace, EqualTo("ab/cd"));
+ }
+
+ [Test]
+ [ExpectedException(typeof(Exception))]
+ public void NamespaceEndingWithColonSlashIsBad()
+ {
+ object o1 = ReadFromString("ab:/cd");
+ }
+
+ [Test]
+ [ExpectedException(typeof(Exception))]
+ public void NameEndingWithColonIsBad()
+ {
+ object o1 = ReadFromString("ab/cd:");
+ }
+
+ [Test]
+ [ExpectedException(typeof(Exception))]
+ public void NameEndingWithColonIsBad2()
+ {
+ object o1 = ReadFromString("cd:");
+ }
+
+ [Test]
+ public void NameMayContainMultipleColons()
+ {
+ object o1 = ReadFromString("a:b:c/d:e:f");
+ Expect(o1, TypeOf(typeof(Symbol)));
+ }
+
+ [Test]
+ [ExpectedException(typeof(Exception))]
+ public void NameContainingDoubleColonNotAtBeginningIsBad()
+ {
+ object o1 = ReadFromString("ab::cd");
+ }
+
+ [Test]
+ [ExpectedException(typeof(Exception))]
+ public void NamespaceContainingDoubleColonNotAtBeginningIsBad()
+ {
+ object o1 = ReadFromString("ab::cd/ef");
+ }
+
+ #endregion
+
+ #region Keyword tests
+
+ [Test]
+ public void LeadingColonIsKeyword()
+ {
+ object o1 = ReadFromString(":abc");
+ Expect(o1, TypeOf(typeof(Keyword)));
+ Expect(((Keyword)o1).Namespace, Null);
+ Expect(((Keyword)o1).Name, EqualTo("abc"));
+ }
+
+ [Test]
+ public void LeadingColonWithNSIsKeyword()
+ {
+ object o1 = ReadFromString(":ab/cd");
+ Expect(o1, TypeOf(typeof(Keyword)));
+ Expect(((Keyword)o1).Namespace, EqualTo("ab"));
+ Expect(((Keyword)o1).Name, EqualTo("cd"));
+ }
+
+ // TODO: Add more tests dealing with :: resolution.
+
+ [Test]
+ public void LeadingDoubleColonMakesKeywordInCurrentNamespace()
+ {
+ object o1 = ReadFromString("::abc");
+ Expect(o1, TypeOf(typeof(Keyword)));
+ Expect(((Keyword)o1).Namespace, EqualTo(((Namespace)RT.CURRENT_NS.deref()).Name.Name));
+ Expect(((Keyword)o1).Name, EqualTo("abc"));
+ }
+
+ // At one time, this test worked. Now, according to the documentation, it should not work. Did something change? Never mind.
+ //[Test]
+ //public void LeadingDoubleColonDoesNotSetNamespaceIfPeriodsInName()
+ //{
+ // object o1 = ReadFromString("::ab.cd");
+ // Expect(o1, TypeOf(typeof(Keyword)));
+ // Expect(((Keyword)o1).Namespace, Null);
+ // Expect(((Keyword)o1).Name, EqualTo("ab.cd"));
+ //}
+
+ #endregion
+
+ #region String tests
+
+ [Test]
+ public void DoubleQuotesSurroundAString()
+ {
+ object o1 = ReadFromString("\"abc\"");
+ Expect(o1,TypeOf(typeof(string)));
+ Expect(o1, EqualTo("abc"));
+ }
+
+ [Test]
+ [ExpectedException(typeof(System.IO.EndOfStreamException))]
+ public void NoEndingDoubleQuoteFails()
+ {
+ object o1 = ReadFromString("\"abc");
+ }
+
+ [Test]
+ public void EmptyStringWorks()
+ {
+ object o1 = ReadFromString("\"\"");
+ Expect(o1, TypeOf(typeof(string)));
+ Expect(o1, EqualTo(String.Empty));
+
+ }
+
+ [Test]
+ public void EscapesWorkInStrings()
+ {
+ char[] chars = new char[] {
+ '"', 'a',
+ '\\', 't', 'b',
+ '\\', 'r', 'c',
+ '\\', 'n', 'd',
+ '\\', '\\', 'e',
+ '\\', '"', 'f',
+ '\\', 'b', 'g',
+ '\\', 'f', 'h', '"'
+ };
+
+ string s = new String(chars);
+ Expect(s.Length, EqualTo(24));
+
+
+ object o1 = ReadFromString(s);
+ Expect(o1, EqualTo("a\tb\rc\nd\\e\"f\bg\fh"));
+ }
+
+ [Test]
+ [ExpectedException(typeof(System.IO.EndOfStreamException))]
+ public void EOFinEscapeIsError()
+ {
+ char[] chars = new char[] {
+ '"', 'a',
+ '\\', 't', 'b',
+ '\\', 'r', 'c',
+ '\\', 'n', 'd',
+ '\\'
+ };
+ string s = new String(chars);
+
+ object o1 = ReadFromString(s);
+ }
+
+ [Test]
+ public void UnicodeEscapeInsertsUnicodeCharacter()
+ {
+ char[] chars = new char[] {
+ '"', 'a',
+ '\\', 'u', '1', '2', 'C', '4',
+ 'b', '"'
+ };
+
+ string s = new String(chars);
+
+ object o1 = ReadFromString(s);
+ Expect(o1, EqualTo("a\u12C4b"));
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException))]
+ public void UnicodeEscapeWithBadCharacterFails()
+ {
+ char[] chars = new char[] {
+ '"', 'a',
+ '\\', 'u', '1', '2', 'X', '4',
+ 'b', '"'
+ };
+ string s = new String(chars);
+
+ object o1 = ReadFromString(s);
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException))]
+ public void UnicodeEscapeWithEOFFails()
+ {
+ char[] chars = new char[] {
+ '"', 'a',
+ '\\', 'u', '1', '2', 'A', '"'
+ };
+ string s = new String(chars);
+
+ object o1 = ReadFromString(s);
+ }
+
+
+ [Test]
+ public void OctalEscapeInsertsCharacter()
+ {
+ char[] chars = new char[] {
+ '"', 'a',
+ '\\', '1', '2', '4',
+ 'b', '"'
+ };
+ string s = new String(chars);
+
+ object o1 = ReadFromString(s);
+ Expect(o1, EqualTo("a\x0054b")); // hex/octal conversion
+ }
+
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException))]
+ public void OctalEscapeWithBadDigitFails()
+ {
+ char[] chars = new char[] {
+ '"', 'a',
+ '\\', '1', '8', '4',
+ 'b', '"'
+ };
+ string s = new String(chars);
+
+ object o1 = ReadFromString(s);
+ }
+
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException))]
+ public void OctalEscapeWithEOFFails()
+ {
+ char[] chars = new char[] {
+ '"', 'a',
+ '\\', '1', '8', '"'
+ };
+ string s = new String(chars);
+
+ object o1 = ReadFromString(s);
+ }
+
+ [ExpectedException(typeof(ArgumentException))]
+ public void OctalEscapeOutOfRangeFails()
+ {
+ char[] chars = new char[] {
+ '"', 'a',
+ '\\', '4', '7', '7',
+ 'b', '"'
+ };
+ string s = new String(chars);
+
+ object o1 = ReadFromString(s);
+ }
+
+
+ #endregion
+
+ #region Character tests
+
+ [Test]
+ public void BackslashYieldsNextCharacter()
+ {
+ object o1 = ReadFromString("\\a");
+ Expect(o1, TypeOf(typeof(Char)));
+ Expect(o1, EqualTo('a'));
+ }
+
+ [Test]
+ public void BackslashYieldsNextCharacterStoppingAtTerminator()
+ {
+ object o1 = ReadFromString("\\a b");
+ Expect(o1, TypeOf(typeof(Char)));
+ Expect(o1, EqualTo('a'));
+ }
+
+ [Test]
+ [ExpectedException(typeof(System.IO.EndOfStreamException))]
+ public void BackslashFollowedByEOFFails()
+ {
+ object o1 = ReadFromString("\\");
+ }
+
+ [Test]
+ public void BackslashRecognizesSpecialNames()
+ {
+ object o1 = ReadFromString("\\newline");
+ object o2 = ReadFromString("\\space");
+ object o3 = ReadFromString("\\tab");
+ object o4 = ReadFromString("\\backspace");
+ object o5 = ReadFromString("\\formfeed");
+ object o6 = ReadFromString("\\return");
+
+ Expect(o1, EqualTo('\n'));
+ Expect(o2, EqualTo(' '));
+ Expect(o3, EqualTo('\t'));
+ Expect(o4, EqualTo('\b'));
+ Expect(o5, EqualTo('\f'));
+ Expect(o6, EqualTo('\r'));
+ }
+
+ [Test]
+ public void BackslashRecognizesUnicode()
+ {
+ object o1 = ReadFromString("\\u12C4");
+ Expect(o1, EqualTo('\u12C4'));
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException))]
+ public void BackslashUnicodeWithEOFFails()
+ {
+ object o1 = ReadFromString("\\u12C 4");
+ }
+
+ [Test]
+ [ExpectedException(typeof(Exception))]
+ public void BackslashUnicodeInBadRangeFails()
+ {
+ object o1 = ReadFromString("\\uDAAA");
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException))]
+ public void BackslashUnicodeWithBadDigitFails()
+ {
+ object o1 = ReadFromString("\\u12X4");
+ }
+
+ [Test]
+ public void BackslashRecognizesOctal()
+ {
+ object o1 = ReadFromString("\\o124");
+ Expect(o1, EqualTo('\x54'));
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException))]
+ public void BackslashOctalWithEOFFails()
+ {
+ object o1 = ReadFromString("\\u12 4");
+ }
+
+ [Test]
+ [ExpectedException(typeof(Exception))]
+ public void BackslashOctalInBadRangeFails()
+ {
+ object o1 = ReadFromString("\\o444");
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException))]
+ public void BackslashOctalWithBadDigitFails()
+ {
+ object o1 = ReadFromString("\\o128");
+ }
+
+ [Test]
+ [ExpectedException(typeof(Exception))]
+ public void BackslashOctalWithTooManyDigitsFails()
+ {
+ object o1 = ReadFromString("\\o0012 aa");
+ }
+
+ [Test]
+ [ExpectedException(typeof(Exception))]
+ public void BackslashWithOtherFails()
+ {
+ object o1 = ReadFromString("\\aa");
+ }
+
+ #endregion
+
+ #region comment tests
+
+ [Test]
+ public void SemicolonIgnoresToEndOfLine()
+ {
+ object o1 = ReadFromString(" ; ignore \n 123");
+ Expect(o1, EqualTo(123));
+ }
+
+ [Test]
+ public void SharpBangIgnoresToEndOfLine()
+ {
+ object o1 = ReadFromString(" #! ignore \n 123");
+ Expect(o1, EqualTo(123));
+ }
+
+ #endregion
+
+ #region Discard tests
+
+ [Test]
+ public void SharpUnderscoreIgnoresNextForm()
+ {
+ object o1 = ReadFromString("#_ (1 2 3) 4");
+ Expect(o1, EqualTo(4));
+ }
+
+ [Test]
+ public void SharpUnderscoreIgnoresNextFormInList()
+ {
+ object o1 = ReadFromString("( abc #_ (1 2 3) 12)");
+ Expect(o1, TypeOf(typeof(PersistentList)));
+ PersistentList pl = o1 as PersistentList;
+ Expect(pl.count(), EqualTo(2));
+ Expect(pl.first(), TypeOf(typeof(Symbol)));
+ Expect(((Symbol)pl.first()).Name, EqualTo("abc"));
+ Expect(((Symbol)pl.first()).Namespace, Null);
+ Expect(pl.rest().first(), TypeOf(typeof(int)));
+ Expect(pl.rest().first(), EqualTo(12));
+ Expect(pl.rest().rest(), Null);
+ }
+
+ #endregion
+
+ #region List tests
+
+ [Test]
+ public void CanReadBasicList()
+ {
+ Object o1 = ReadFromString("(abc 12)");
+ Expect(o1, TypeOf(typeof(PersistentList)));
+ PersistentList pl = o1 as PersistentList;
+ Expect(pl.count(), EqualTo(2));
+ Expect(pl.first(), TypeOf(typeof(Symbol)));
+ Expect(((Symbol)pl.first()).Name, EqualTo("abc"));
+ Expect(((Symbol)pl.first()).Namespace, Null);
+ Expect(pl.rest().first(), TypeOf(typeof(int)));
+ Expect(pl.rest().first(), EqualTo(12));
+ Expect(pl.rest().rest(), Null);
+ }
+
+ [Test]
+ public void CanReadEmptyList()
+ {
+ Object o1 = ReadFromString("( )");
+ Expect(o1, InstanceOfType(typeof(IPersistentList)));
+ IPersistentList pl = o1 as IPersistentList;
+ Expect(pl.count(), EqualTo(0));
+ }
+
+ [Test]
+ public void CanReadNestedList()
+ {
+ Object o1 = ReadFromString("(a (b c) d)");
+ Expect(o1, InstanceOfType(typeof(IPersistentList)));
+ IPersistentList pl = o1 as IPersistentList;
+ ISeq seq = pl.seq();
+ Expect(pl.count(), EqualTo(3));
+ Expect(seq.rest().first(), InstanceOfType(typeof(IPersistentList)));
+ IPersistentList sub = seq.rest().first() as IPersistentList;
+ Expect(sub.count(), EqualTo(2));
+ }
+
+ [Test]
+ [ExpectedException(typeof(System.IO.EndOfStreamException))]
+ public void MissingListTerminatorFails()
+ {
+ Object o1 = ReadFromString("(a b 1 2");
+ }
+
+ [Test]
+ public void ListGetsLineNumber()
+ {
+ Object o1 = ReadFromStringNumbering("\n\n(a b \n1 2)");
+ Expect(o1, InstanceOfType(typeof(IObj)));
+ IObj io = o1 as IObj;
+ Expect(io.meta().valAt(Keyword.intern(null,"line")), EqualTo(3));
+ }
+
+ #endregion
+
+ #region VectorTests
+
+ [Test]
+ public void CanReadBasicVector()
+ {
+ Object o1 = ReadFromString("[abc 12]");
+ Expect(o1, TypeOf(typeof(LazilyPersistentVector)));
+ LazilyPersistentVector pl = o1 as LazilyPersistentVector;
+ Expect(pl.count(), EqualTo(2));
+ Expect(pl.nth(0), TypeOf(typeof(Symbol)));
+ Expect(((Symbol)pl.nth(0)).Name, EqualTo("abc"));
+ Expect(((Symbol)pl.nth(0)).Namespace, Null);
+ Expect(pl.nth(1), TypeOf(typeof(int)));
+ Expect(pl.nth(1), EqualTo(12));
+ }
+
+ [Test]
+ public void CanReadEmptyVector()
+ {
+ Object o1 = ReadFromString("[ ]");
+ Expect(o1, InstanceOfType(typeof(IPersistentVector)));
+ IPersistentVector v = o1 as IPersistentVector;
+ Expect(v.count(), EqualTo(0));
+ }
+
+ [Test]
+ public void VectorCanContainNestedList()
+ {
+ Object o1 = ReadFromString("[a (b c) d]");
+ Expect(o1, InstanceOfType(typeof(IPersistentVector)));
+ IPersistentVector v = o1 as IPersistentVector;
+ Expect(v.count(), EqualTo(3));
+ Expect(v.nth(1), InstanceOfType(typeof(IPersistentList)));
+ IPersistentList sub = v.nth(1) as IPersistentList;
+ Expect(sub.count(), EqualTo(2));
+ }
+
+ [Test]
+ public void VectorCanContainNestedVector()
+ {
+ Object o1 = ReadFromString("[a [b c] d]");
+ Expect(o1, InstanceOfType(typeof(IPersistentVector)));
+ IPersistentVector v = o1 as IPersistentVector;
+ Expect(v.count(), EqualTo(3));
+ Expect(v.nth(1), InstanceOfType(typeof(IPersistentVector)));
+ IPersistentVector sub = v.nth(1) as IPersistentVector;
+ Expect(sub.count(), EqualTo(2));
+ }
+
+ [Test]
+ [ExpectedException(typeof(System.IO.EndOfStreamException))]
+ public void MissingVectorTerminatorFails()
+ {
+ Object o1 = ReadFromString("[a b 1 2");
+ }
+
+ #endregion
+
+ #region Map tests
+
+ [Test]
+ public void CanReadBasicMap()
+ {
+ Object o1 = ReadFromString("{:abc 12 14 a}");
+ Expect(o1, InstanceOfType(typeof(IPersistentMap)));
+ IPersistentMap m = o1 as IPersistentMap;
+ Expect(m.count(), EqualTo(2));
+ Expect(m.valAt(Keyword.intern(null, "abc")), EqualTo(12));
+ Expect(m.valAt(14), EqualTo(Symbol.intern("a")));
+ }
+
+ [Test]
+ public void CanReadEmptyMap()
+ {
+ Object o1 = ReadFromString("{ }");
+ Expect(o1, InstanceOfType(typeof(IPersistentMap)));
+ IPersistentMap m = o1 as IPersistentMap;
+ Expect(m.count(), EqualTo(0));
+ }
+
+
+ [Test]
+ [ExpectedException(typeof(System.IO.EndOfStreamException))]
+ public void MissingRightBraceFails()
+ {
+ Object o1 = ReadFromString("{a b 1 2");
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException))]
+ public void MapWithOddNumberOfEntriesFails()
+ {
+ Object o1 = ReadFromString("{a b 1}");
+ }
+
+
+
+ #endregion
+
+ #region Set tests
+
+ [Test]
+ public void CanReadBasicSet()
+ {
+ Object o1 = ReadFromString("#{abc 12}");
+ Expect(o1, InstanceOfType(typeof(IPersistentSet)));
+ IPersistentSet s = o1 as IPersistentSet;
+ Expect(s.count(), EqualTo(2));
+ Expect(s.contains(Symbol.intern("abc")));
+ Expect(s.contains(12));
+ }
+
+ [Test]
+ public void CanReadEmptySet()
+ {
+ Object o1 = ReadFromString("#{ }");
+ Expect(o1, InstanceOfType(typeof(IPersistentSet)));
+ IPersistentSet s = o1 as IPersistentSet;
+ Expect(s.count(), EqualTo(0));
+ }
+
+ [Test]
+ [ExpectedException(typeof(System.IO.EndOfStreamException))]
+ public void MissingSetTerminatorFails()
+ {
+ Object o1 = ReadFromString("#{a b 1 2");
+ }
+
+ #endregion
+
+ #region Unmatched delimiter tests
+
+ [Test]
+ [ExpectedException(typeof(Exception))]
+ public void NakedRightParenIsBad()
+ {
+ Object o1 = ReadFromString("}");
+ }
+
+ [Test]
+ [ExpectedException(typeof(Exception))]
+ public void NakedRightBracketIsBad()
+ {
+ Object o1 = ReadFromString("]");
+ }
+
+
+ [Test]
+ [ExpectedException(typeof(Exception))]
+ public void NakedRightBraceIsBad()
+ {
+ Object o1 = ReadFromString("}");
+ }
+
+ [Test]
+ [ExpectedException(typeof(Exception))]
+ public void MismatchedDelimiterIsBad()
+ {
+ Object o1 = ReadFromString("( a b c }");
+ }
+
+ #endregion
+
+ #region Wrapping forms
+
+ [Test]
+ public void QuoteWraps()
+ {
+ object o1 = ReadFromString("'a");
+ Expect(o1,InstanceOfType(typeof(IPersistentList)));
+ IPersistentList p = o1 as IPersistentList;
+ ISeq s = p.seq();
+ Expect(s.count(),EqualTo(2));
+ Expect(s.first(),EqualTo(Symbol.intern("quote")));
+ Expect(s.rest().first(),TypeOf(typeof(Symbol)));
+ }
+
+ [Test]
+ public void QuoteWraps2()
+ {
+ object o1 = ReadFromString("'(a b c)");
+ Expect(o1, InstanceOfType(typeof(IPersistentList)));
+ IPersistentList p = o1 as IPersistentList;
+ ISeq s = p.seq();
+ Expect(s.count(), EqualTo(2));
+ Expect(s.first(), EqualTo(Symbol.intern("quote")));
+ Expect(s.rest().first(), InstanceOfType(typeof(IPersistentList)));
+ Expect(((IPersistentList)s.rest().first()).count(), EqualTo(3));
+ }
+
+
+ [Test]
+ public void MetaWraps()
+ {
+ object o1 = ReadFromString("^a");
+ Expect(o1, InstanceOfType(typeof(IPersistentList)));
+ IPersistentList p = o1 as IPersistentList;
+ ISeq s = p.seq();
+ Expect(s.count(), EqualTo(2));
+ Expect(s.first(), EqualTo(Symbol.intern("clojure.core","meta")));
+ Expect(s.rest().first(), TypeOf(typeof(Symbol)));
+ }
+
+ [Test]
+ public void MetaWraps2()
+ {
+ object o1 = ReadFromString("^(a b c)");
+ Expect(o1, InstanceOfType(typeof(IPersistentList)));
+ IPersistentList p = o1 as IPersistentList;
+ ISeq s = p.seq();
+ Expect(s.count(), EqualTo(2));
+ Expect(s.first(), EqualTo(Symbol.intern("clojure.core", "meta")));
+ Expect(s.rest().first(), InstanceOfType(typeof(IPersistentList)));
+ Expect(((IPersistentList)s.rest().first()).count(), EqualTo(3));
+ }
+
+ [Test]
+ public void DerefWraps()
+ {
+ object o1 = ReadFromString("@a");
+ Expect(o1, InstanceOfType(typeof(IPersistentList)));
+ IPersistentList p = o1 as IPersistentList;
+ ISeq s = p.seq();
+ Expect(s.count(), EqualTo(2));
+ Expect(s.first(), EqualTo(Symbol.intern("clojure.core", "deref")));
+ Expect(s.rest().first(), TypeOf(typeof(Symbol)));
+ }
+
+ [Test]
+ public void DerefWraps2()
+ {
+ object o1 = ReadFromString("@(a b c)");
+ Expect(o1, InstanceOfType(typeof(IPersistentList)));
+ IPersistentList p = o1 as IPersistentList;
+ ISeq s = p.seq();
+ Expect(s.count(), EqualTo(2));
+ Expect(s.first(), EqualTo(Symbol.intern("clojure.core", "deref")));
+ Expect(s.rest().first(), InstanceOfType(typeof(IPersistentList)));
+ Expect(((IPersistentList)s.rest().first()).count(), EqualTo(3));
+ }
+
+ #endregion
+
+ #region Syntax-quote tests
+
+ [Test]
+ public void SQOnSelfEvaluatingReturnsQuotedThing()
+ {
+ object o1 = ReadFromString("`:abc");
+ object o2 = ReadFromString("`222");
+ object o3 = ReadFromString("`\\a)");
+ object o4 = ReadFromString("`\"abc\"");
+
+ Expect(o1, TypeOf(typeof(Keyword)));
+ Expect(o1, EqualTo(Keyword.intern(null, "abc")));
+ Expect(o2, TypeOf(typeof(int)));
+ Expect(o2, EqualTo(222));
+ Expect(o3, TypeOf(typeof(char)));
+ Expect(o3, EqualTo('a'));
+ Expect(o4, TypeOf(typeof(string)));
+ Expect(o4, EqualTo("abc"));
+ }
+
+ [Test]
+ public void SQOnSpecialFormQuotes()
+ {
+ object o1 = ReadFromString("`def");
+ Expect(o1,InstanceOfType(typeof(ISeq)));
+ ISeq s = o1 as ISeq;
+ Expect(s.count(),EqualTo(2) );
+ Expect(s.first(),EqualTo(Symbol.intern("quote")));
+ Expect(s.rest().first(),InstanceOfType(typeof(Symbol)));
+ Symbol sym = s.rest().first() as Symbol;
+ Expect(sym.Namespace, Null);
+ Expect(sym.Name, EqualTo("def"));
+ }
+
+ [Test]
+ public void SQOnRegularSymbolResolves()
+ {
+ object o1 = ReadFromString("`abc");
+ Expect(o1, InstanceOfType(typeof(ISeq)));
+ ISeq s = o1 as ISeq;
+ Expect(s.count(), EqualTo(2));
+ Expect(s.first(), EqualTo(Symbol.intern("quote")));
+ Expect(s.rest().first(), InstanceOfType(typeof(Symbol)));
+ Symbol sym = s.rest().first() as Symbol;
+ Expect(sym.Namespace, EqualTo(((Namespace)RT.CURRENT_NS.deref()).Name.Name));
+ Expect(sym.Name, EqualTo("abc"));
+ }
+
+ [Test]
+ public void SQOnGensymGenerates()
+ {
+ object o1 = ReadFromString("`abc#");
+ Expect(o1, InstanceOfType(typeof(ISeq)));
+ ISeq s = o1 as ISeq;
+ Expect(s.count(), EqualTo(2));
+ Expect(s.first(), EqualTo(Symbol.intern("quote")));
+ Expect(s.rest().first(), InstanceOfType(typeof(Symbol)));
+ Symbol sym = s.rest().first() as Symbol;
+ Expect(sym.Namespace, Null);
+ Expect(sym.Name.StartsWith("abc_")); ;
+ }
+
+
+ [Test]
+ public void SQOnGensymSeesSameTwice()
+ {
+ object o1 = ReadFromString("`(abc# abc#)");
+ // Return should be
+ // (clojure/concat (clojure/list (quote abc__N))
+ // (clojure/list (quote abc__N))))
+ string str = o1.ToString();
+
+ Expect(o1, InstanceOfType(typeof(ISeq)));
+ ISeq s = o1 as ISeq;
+ Expect(s.count(), EqualTo(3));
+ Expect(s.first(), EqualTo(Symbol.intern("clojure.core","concat")));
+
+ Expect(s.rest().first(), InstanceOfType(typeof(ISeq)));
+ ISeq s2 = s.rest().first() as ISeq;
+ Expect(s2.count(), EqualTo(2));
+
+ Expect(s2.rest().first(), InstanceOfType(typeof(ISeq)));
+ ISeq s2a = s2.rest().first() as ISeq;
+ Expect(s2a.rest().first(), InstanceOfType(typeof(Symbol)));
+ Symbol sym1 = s2a.rest().first() as Symbol;
+
+ Expect(s.rest().rest().first(), InstanceOfType(typeof(ISeq)));
+ ISeq s3 = s.rest().rest().first() as ISeq;
+ Expect(s3.count(), EqualTo(2));
+
+ Expect(s3.rest().first(), InstanceOfType(typeof(ISeq)));
+ ISeq s3a = s3.rest().first() as ISeq;
+ Expect(s3a.rest().first(), InstanceOfType(typeof(Symbol)));
+ Symbol sym2 = s3a.rest().first() as Symbol;
+
+ Expect(sym1.Namespace, Null);
+ Expect(sym1.Name.StartsWith("abc__"));
+ Expect(sym1, EqualTo(sym2));
+ }
+
+ [Test]
+ public void SQOnMapMakesMap()
+ {
+ Object o1 = ReadFromString("`{:a 1 :b 2}");
+ // (clojure/apply
+ // clojure/hash-map
+ // (clojure/concat (clojure/list :a)
+ // (clojure/list 1)
+ // (clojure/list :b)
+ // (clojure/list 2)))
+
+ Expect(o1, InstanceOfType(typeof(ISeq)));
+ ISeq s = o1 as ISeq;
+ Expect(s.count(), EqualTo(3));
+ Expect(s.first(), EqualTo(Symbol.intern("clojure.core/apply")));
+ Expect(s.rest().first(), EqualTo(Symbol.intern("clojure.core/hash-map")));
+ Expect(s.rest().rest().first(), InstanceOfType(typeof(ISeq)));
+
+ ISeq s1 = s.rest().rest().first() as ISeq;
+ ISeq s2;
+
+ Expect(s1.count(), EqualTo(5));
+ Expect(s1.first(), EqualTo(Symbol.intern("clojure.core/concat")));
+
+ s1 = s1.rest();
+ Expect(s1.first(),InstanceOfType(typeof(ISeq)));
+
+ s2 = s1.first() as ISeq;
+ Expect(s2.first(),EqualTo(Symbol.intern("clojure.core/list")));
+ Expect(s2.rest().first(),EqualTo(Keyword.intern(null,"a")));
+
+
+ s1 = s1.rest();
+ Expect(s1.first(), InstanceOfType(typeof(ISeq)));
+
+ s2 = s1.first() as ISeq;
+ Expect(s2.first(), EqualTo(Symbol.intern("clojure.core/list")));
+ Expect(s2.rest().first(), EqualTo(1));
+
+ s1 = s1.rest();
+ Expect(s1.first(), InstanceOfType(typeof(ISeq)));
+
+ s2 = s1.first() as ISeq;
+ Expect(s2.first(), EqualTo(Symbol.intern("clojure.core/list")));
+ Expect(s2.rest().first(), EqualTo(Keyword.intern(null, "b")));
+
+
+ s1 = s1.rest();
+ Expect(s1.first(), InstanceOfType(typeof(ISeq)));
+
+ s2 = s1.first() as ISeq;
+ Expect(s2.first(), EqualTo(Symbol.intern("clojure.core/list")));
+ Expect(s2.rest().first(), EqualTo(2));
+ }
+
+ public void SQOnVectorMakesVector()
+ {
+ Object o1 = ReadFromString("`[:b 2]");
+ // (clojure/apply
+ // clojure/vector
+ // (clojure/concat (clojure/list :b)
+ // (clojure/list 2)))
+
+ Expect(o1, InstanceOfType(typeof(ISeq)));
+ ISeq s = o1 as ISeq;
+ Expect(s.count(), EqualTo(3));
+ Expect(s.first(), EqualTo(Symbol.intern("clojure.core/apply")));
+ Expect(s.rest().first(), EqualTo(Symbol.intern("clojure.core/vector")));
+ Expect(s.rest().rest().first(), InstanceOfType(typeof(ISeq)));
+
+ ISeq s1 = s.rest().rest().first() as ISeq;
+ ISeq s2;
+
+ Expect(s1.count(), EqualTo(3));
+ Expect(s1.first(), EqualTo(Symbol.intern("clojure.core/concat")));
+
+ s1 = s1.rest();
+ Expect(s1.first(), InstanceOfType(typeof(ISeq)));
+
+ s2 = s1.first() as ISeq;
+ Expect(s2.first(), EqualTo(Symbol.intern("clojure.core/list")));
+ Expect(s2.rest().first(), EqualTo(Keyword.intern(null, "b")));
+
+
+ s1 = s1.rest();
+ Expect(s1.first(), InstanceOfType(typeof(ISeq)));
+
+ s2 = s1.first() as ISeq;
+ Expect(s2.first(), EqualTo(Symbol.intern("clojure.core/list")));
+ Expect(s2.rest().first(), EqualTo(2));
+ }
+
+ [Test]
+ public void SQOnSetMakesSet()
+ {
+ Object o1 = ReadFromString("`#{:b 2}");
+ // (clojure/apply
+ // clojure/hash-set
+ // (clojure/concat (clojure/list :b)
+ // (clojure/list 2)))
+
+ Expect(o1, InstanceOfType(typeof(ISeq)));
+ ISeq s = o1 as ISeq;
+ Expect(s.count(), EqualTo(3));
+ Expect(s.first(), EqualTo(Symbol.intern("clojure.core/apply")));
+ Expect(s.rest().first(), EqualTo(Symbol.intern("clojure.core/hash-set")));
+ Expect(s.rest().rest().first(), InstanceOfType(typeof(ISeq)));
+
+ ISeq s1 = s.rest().rest().first() as ISeq;
+
+ Expect(s1.count(), EqualTo(3));
+ Expect(s1.first(), EqualTo(Symbol.intern("clojure.core/concat")));
+
+ s1 = s1.rest();
+ Expect(s1.first(), InstanceOfType(typeof(ISeq)));
+ ISeq s2 = s1.first() as ISeq;
+ s1 = s1.rest();
+ Expect(s1.first(), InstanceOfType(typeof(ISeq)));
+ ISeq s3 = s1.first() as ISeq;
+
+ Expect(s2.first(), EqualTo(Symbol.intern("clojure.core/list")));
+ Expect(s2.first(), EqualTo(Symbol.intern("clojure.core/list")));
+
+
+ object e1 = s2.rest().first();
+ object e2 = s3.rest().first();
+
+ // Set elements can occur in any order
+
+ Expect(e1, EqualTo(Keyword.intern(null, "b")) | EqualTo(2));
+ Expect(e2, EqualTo(Keyword.intern(null, "b")) | EqualTo(2));
+ Expect(e1, Not.EqualTo(e2));
+ }
+
+ [Test]
+ public void SQOnListMakesList()
+ {
+ Object o1 = ReadFromString("`(:b 2)");
+ // (clojure/concat (clojure/list :b)
+ // (clojure/list 2)))
+
+ Expect(o1, InstanceOfType(typeof(ISeq)));
+ ISeq s1 = o1 as ISeq;
+ ISeq s2;
+
+ Expect(s1.count(), EqualTo(3));
+ Expect(s1.first(), EqualTo(Symbol.intern("clojure.core/concat")));
+
+ s1 = s1.rest();
+ Expect(s1.first(), InstanceOfType(typeof(ISeq)));
+
+ s2 = s1.first() as ISeq;
+ Expect(s2.first(), EqualTo(Symbol.intern("clojure.core/list")));
+ Expect(s2.rest().first(), EqualTo(Keyword.intern(null, "b")));
+
+
+ s1 = s1.rest();
+ Expect(s1.first(), InstanceOfType(typeof(ISeq)));
+
+ s2 = s1.first() as ISeq;
+ Expect(s2.first(), EqualTo(Symbol.intern("clojure.core/list")));
+ Expect(s2.rest().first(), EqualTo(2));
+ }
+
+
+ [Test]
+ public void UnquoteStandaloneReturnsUnquoteObject()
+ {
+ object o1 = ReadFromString("~x");
+
+ //Expect(o1, InstanceOfType(typeof(LispReader.Unquote)));
+ //LispReader.Unquote u = o1 as LispReader.Unquote;
+ //Expect(u.Obj, EqualTo(Symbol.intern("x")));
+ Expect(o1, InstanceOfType(typeof(ISeq)));
+ ISeq s = o1 as ISeq;
+ Expect(s.first(), EqualTo(Symbol.intern("clojure.core/unquote")));
+ Expect(s.rest().first(), EqualTo(Symbol.intern("x")));
+ Expect(s.count(), EqualTo(2));
+
+ }
+
+ [Test]
+ public void UnquoteSpliceStandaloneReturnsUnquoteSpliceObject()
+ {
+ object o1 = ReadFromString("~@x");
+
+ Expect(o1, InstanceOfType(typeof(ISeq)));
+ ISeq s = o1 as ISeq;
+ Expect(s.first(), EqualTo(Symbol.intern("clojure.core/unquote-splicing")));
+ Expect(s.rest().first(), EqualTo(Symbol.intern("x")));
+ Expect(s.count(), EqualTo(2));
+ }
+
+ [Test]
+ public void SQonUnquoteDequotes()
+ {
+ object o1 = ReadFromString("`(a ~b)");
+ // (clojure/concat (clojure/list (quote NS/a))
+ // (clojure/list b))
+
+
+ Expect(o1, InstanceOfType(typeof(ISeq)));
+ ISeq s1 = o1 as ISeq;
+ ISeq s2;
+
+ Expect(s1.count(), EqualTo(3));
+ Expect(s1.first(), EqualTo(Symbol.intern("clojure.core/concat")));
+
+ s1 = s1.rest();
+ Expect(s1.first(), InstanceOfType(typeof(ISeq)));
+
+ s2 = s1.first() as ISeq;
+ Expect(s2.first(), EqualTo(Symbol.intern("clojure.core/list")));
+ Expect(s2.rest().first(), InstanceOfType(typeof(ISeq)));
+ ISeq s3 = s2.rest().first() as ISeq;
+
+ Expect(s3.count(), EqualTo(2));
+ Expect(s3.first(), EqualTo(Symbol.intern("quote")));
+ Expect(s3.rest().first(), EqualTo(Symbol.intern(((Namespace)RT.CURRENT_NS.deref()).Name.Name,"a")));
+
+
+ s1 = s1.rest();
+ Expect(s1.first(), InstanceOfType(typeof(ISeq)));
+
+ s2 = s1.first() as ISeq;
+ Expect(s2.first(), EqualTo(Symbol.intern("clojure.core/list")));
+ Expect(s2.rest().first(), EqualTo(Symbol.intern("b")));
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException))]
+ public void SQonUnquoteSpliceNotInListFails()
+ {
+ object o1 = ReadFromString("`~@x");
+ }
+
+ [Test]
+ public void SqOnUnquoteSpliceSplices()
+ {
+ object o1 = ReadFromString("`(a ~@b)");
+ // (clojure/concat (clojure/list (quote user/a)) b)
+
+ Expect(o1, InstanceOfType(typeof(ISeq)));
+ ISeq s1 = o1 as ISeq;
+ ISeq s2;
+
+ Expect(s1.count(), EqualTo(3));
+ Expect(s1.first(), EqualTo(Symbol.intern("clojure.core/concat")));
+
+ s1 = s1.rest();
+ Expect(s1.first(), InstanceOfType(typeof(ISeq)));
+
+ s2 = s1.first() as ISeq;
+ Expect(s2.first(), EqualTo(Symbol.intern("clojure.core/list")));
+ Expect(s2.rest().first(), InstanceOfType(typeof(ISeq)));
+ ISeq s3 = s2.rest().first() as ISeq;
+
+ Expect(s3.count(), EqualTo(2));
+ Expect(s3.first(), EqualTo(Symbol.intern("quote")));
+ Expect(s3.rest().first(), EqualTo(Symbol.intern(((Namespace)RT.CURRENT_NS.deref()).Name.Name, "a")));
+
+
+ s1 = s1.rest();
+ Expect(s1.first(), EqualTo(Symbol.intern("b")));
+ }
+
+ // We should test to see that 'line' meta info is not preserved.
+
+ [Test]
+ public void SQOnLparenRParenReturnsEmptyList()
+ {
+ object o1 = ReadFromString("`()");
+ Expect(o1,EqualTo(PersistentList.EMPTY));
+ }
+
+ #endregion
+
+ #region #-dispatch tests
+
+ [Test]
+ [ExpectedException(typeof(Exception))]
+ public void SharpDispatchOnInvalidCharFails()
+ {
+ object o1 = ReadFromString("#a(1 2)");
+ }
+
+ #endregion
+
+ #region Meta reader tests
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException))]
+ public void MetaOnImproperMetadataFails()
+ {
+ object o1 = ReadFromString("#^1 (a b c");
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException))]
+ public void MetaOnAppliedToNonIObjFails()
+ {
+ object o1 = ReadFromString("#^{:a 1} 7");
+ }
+
+ [Test]
+ public void MetaAppliesHashMetaDataToObject()
+ {
+ object o1 = ReadFromString("#^{a 1} (a b)");
+
+ Expect(o1, InstanceOfType(typeof(ISeq)));
+ ISeq s = o1 as ISeq;
+
+ Expect(s.count(), EqualTo(2));
+ Expect(s.first(), EqualTo(Symbol.intern("a")));
+ Expect(s.rest().first(), EqualTo(Symbol.intern("b")));
+
+ Expect(o1, InstanceOfType(typeof(IObj)));
+ IObj o = o1 as IObj;
+ Expect(o.meta(), InstanceOfType(typeof(IPersistentMap)));
+ IPersistentMap m = o.meta() as IPersistentMap;
+
+ Expect(m.count(), EqualTo(1));
+ Expect(m.valAt(Symbol.intern("a")), EqualTo(1));
+ }
+
+
+ [Test]
+ public void MetaAppliesSymbolAsTagMetaDataToObject()
+ {
+ object o1 = ReadFromString("#^c (a b)");
+
+ Expect(o1, InstanceOfType(typeof(ISeq)));
+ ISeq s = o1 as ISeq;
+
+ Expect(s.count(), EqualTo(2));
+ Expect(s.first(), EqualTo(Symbol.intern("a")));
+ Expect(s.rest().first(), EqualTo(Symbol.intern("b")));
+
+ Expect(o1, InstanceOfType(typeof(IObj)));
+ IObj o = o1 as IObj;
+ Expect(o.meta(), InstanceOfType(typeof(IPersistentMap)));
+ IPersistentMap m = o.meta() as IPersistentMap;
+
+ Expect(m.count(), EqualTo(1));
+ Expect(m.valAt(Keyword.intern(null,"tag")), EqualTo(Symbol.intern("c")));
+ }
+
+ [Test]
+ public void MetaAppliesKeywordAsTagMetaDataToObject()
+ {
+ object o1 = ReadFromString("#^:c (a b)");
+
+ Expect(o1, InstanceOfType(typeof(ISeq)));
+ ISeq s = o1 as ISeq;
+
+ Expect(s.count(), EqualTo(2));
+ Expect(s.first(), EqualTo(Symbol.intern("a")));
+ Expect(s.rest().first(), EqualTo(Symbol.intern("b")));
+
+ Expect(o1, InstanceOfType(typeof(IObj)));
+ IObj o = o1 as IObj;
+ Expect(o.meta(), InstanceOfType(typeof(IPersistentMap)));
+ IPersistentMap m = o.meta() as IPersistentMap;
+
+ Expect(m.count(), EqualTo(1));
+ Expect(m.valAt(Keyword.intern(null, "tag")), EqualTo(Keyword.intern(null,"c")));
+ }
+
+ [Test]
+ public void MetaAppliesStringAsTagMetaDataToObject()
+ {
+ object o1 = ReadFromString("#^\"help\" (a b)");
+
+ Expect(o1, InstanceOfType(typeof(ISeq)));
+ ISeq s = o1 as ISeq;
+
+ Expect(s.count(), EqualTo(2));
+ Expect(s.first(), EqualTo(Symbol.intern("a")));
+ Expect(s.rest().first(), EqualTo(Symbol.intern("b")));
+
+ Expect(o1, InstanceOfType(typeof(IObj)));
+ IObj o = o1 as IObj;
+ Expect(o.meta(), InstanceOfType(typeof(IPersistentMap)));
+ IPersistentMap m = o.meta() as IPersistentMap;
+
+ Expect(m.count(), EqualTo(1));
+ Expect(m.valAt(Keyword.intern(null, "tag")), EqualTo("help"));
+ }
+
+ [Test]
+ public void MetaAddsLineupNumberAsMetaDataIfAvailable()
+ {
+ object o1 = ReadFromStringNumbering("\n\n#^:c (a b)");
+
+ Expect(o1, InstanceOfType(typeof(ISeq)));
+ ISeq s = o1 as ISeq;
+
+ Expect(s.count(), EqualTo(2));
+ Expect(s.first(), EqualTo(Symbol.intern("a")));
+ Expect(s.rest().first(), EqualTo(Symbol.intern("b")));
+
+ Expect(o1, InstanceOfType(typeof(IObj)));
+ IObj o = o1 as IObj;
+ Expect(o.meta(), InstanceOfType(typeof(IPersistentMap)));
+ IPersistentMap m = o.meta() as IPersistentMap;
+
+ Expect(m.count(), EqualTo(2));
+ Expect(m.valAt(Keyword.intern(null, "tag")), EqualTo(Keyword.intern(null,"c")));
+ Expect(m.valAt(Keyword.intern(null, "line")), EqualTo(3));
+ }
+
+ #endregion
+
+ #region Var reader tests
+
+ [Test]
+ public void VarWrapsVar()
+ {
+ Object o1 = ReadFromString("#'abc");
+
+ Expect(o1, InstanceOfType(typeof(ISeq)));
+ ISeq s = o1 as ISeq;
+ Expect(s.count(), EqualTo(2));
+ Expect(s.first(), EqualTo(Symbol.intern("var")));
+ Expect(s.rest().first(), EqualTo(Symbol.intern("abc")));
+ }
+
+ #endregion
+
+ #region Regex reader tests
+
+ [Test]
+ public void SharpDoubleQuoteGeneratesRegex()
+ {
+ object o1 = ReadFromString("#\"abc\"");
+
+ Expect(o1, InstanceOfType(typeof(System.Text.RegularExpressions.Regex)));
+ System.Text.RegularExpressions.Regex r = o1 as System.Text.RegularExpressions.Regex;
+ Expect(r.ToString(), EqualTo("abc"));
+ }
+
+ [Test]
+ [ExpectedException(typeof(System.IO.EndOfStreamException))]
+ public void SharpDQHitsEOFFails()
+ {
+ object o1 = ReadFromString("#\"abc");
+ }
+
+ [Test]
+ public void SharpDQEscapesOnBackslash()
+ {
+ char[] chars = new char[] {
+ '#', '"', 'a', '\\', '"', 'b', 'c', '"'
+ };
+
+ // input = #"a\"bc" -- should go over the "
+
+ string str = new String(chars);
+
+ object o1 = ReadFromString(str);
+
+ Expect(o1, InstanceOfType(typeof(System.Text.RegularExpressions.Regex)));
+ System.Text.RegularExpressions.Regex r = o1 as System.Text.RegularExpressions.Regex;
+ Expect(r.ToString(), EqualTo("a\\\"bc"));
+ }
+
+ #endregion
+
+ #region Fn reader & Arg reader tests
+
+ [Test]
+ public void SharpFnWithNoArgsGeneratesNoArgFn()
+ {
+ object o1 = ReadFromString("#(+ 1 2)");
+ // (fn* [] (+ 1 2))
+
+ Expect(o1, InstanceOfType(typeof(ISeq)));
+ ISeq s = o1 as ISeq;
+
+ Expect(s.first(), EqualTo(Symbol.intern("fn*")));
+ s = s.rest();
+ Expect(s.first(), InstanceOfType(typeof(IPersistentVector)));
+ IPersistentVector arglist = s.first() as IPersistentVector;
+
+ Expect(arglist.count(), EqualTo(0));
+
+ s = s.rest();
+ Expect(s.first(), InstanceOfType(typeof(ISeq)));
+ Expect(s.rest(), Null);
+
+ ISeq form = s.first() as ISeq;
+
+ Expect(form.count(), EqualTo(3));
+ Expect(form.first(), EqualTo(Symbol.intern("+")));
+ Expect(form.rest().first(), EqualTo(1));
+ Expect(form.rest().rest().first(), EqualTo(2));
+ }
+
+ [Test]
+ public void SharpFnWithArgsGeneratesFnWithArgs()
+ {
+ object o1 = ReadFromString("#(+ %2 2)");
+ // (fn* [p1__N p2__M] (+ p2__M 2))
+
+ Expect(o1, InstanceOfType(typeof(ISeq)));
+ ISeq s = o1 as ISeq;
+
+ Expect(s.first(), EqualTo(Symbol.intern("fn*")));
+ s = s.rest();
+ Expect(s.first(), InstanceOfType(typeof(IPersistentVector)));
+ IPersistentVector arglist = s.first() as IPersistentVector;
+
+ Expect(arglist.count(), EqualTo(2));
+ Expect(arglist.nth(0), InstanceOfType(typeof(Symbol)));
+ Expect(arglist.nth(1), InstanceOfType(typeof(Symbol)));
+ Symbol arg1 = arglist.nth(0) as Symbol;
+ Symbol arg2 = arglist.nth(1) as Symbol;
+ Expect(arg1.Name, StartsWith("p1__"));
+ Expect(arg2.Name, StartsWith("p2__"));
+
+ s = s.rest();
+ Expect(s.first(), InstanceOfType(typeof(ISeq)));
+ Expect(s.rest(), Null);
+
+ ISeq form = s.first() as ISeq;
+
+ Expect(form.count(), EqualTo(3));
+ Expect(form.first(), EqualTo(Symbol.intern("+")));
+ Expect(form.rest().first(), EqualTo(arg2));
+ Expect(form.rest().rest().first(), EqualTo(2));
+ }
+
+ [Test]
+ public void SharpFnWithRestArgGeneratesFnWithRestArg()
+ {
+ object o1 = ReadFromString("#(+ %2 %&)");
+ // (fn* [p1__N p2__M & rest__X] (+ p2__M rest__X))
+
+ Expect(o1, InstanceOfType(typeof(ISeq)));
+ ISeq s = o1 as ISeq;
+
+ Expect(s.first(), EqualTo(Symbol.intern("fn*")));
+ s = s.rest();
+ Expect(s.first(), InstanceOfType(typeof(IPersistentVector)));
+ IPersistentVector arglist = s.first() as IPersistentVector;
+
+ Expect(arglist.count(), EqualTo(4));
+ Expect(arglist.nth(0), InstanceOfType(typeof(Symbol)));
+ Expect(arglist.nth(1), InstanceOfType(typeof(Symbol)));
+ Expect(arglist.nth(2), InstanceOfType(typeof(Symbol)));
+ Expect(arglist.nth(3), InstanceOfType(typeof(Symbol)));
+ Symbol arg1 = arglist.nth(0) as Symbol;
+ Symbol arg2 = arglist.nth(1) as Symbol;
+ Symbol arg3 = arglist.nth(2) as Symbol;
+ Symbol arg4 = arglist.nth(3) as Symbol;
+ Expect(arg1.Name, StartsWith("p1__"));
+ Expect(arg2.Name, StartsWith("p2__"));
+ Expect(arg3.Name, EqualTo("&"));
+ Expect(arg4.Name, StartsWith("rest__"));
+
+ s = s.rest();
+ Expect(s.first(), InstanceOfType(typeof(ISeq)));
+ Expect(s.rest(), Null);
+
+ ISeq form = s.first() as ISeq;
+
+ Expect(form.count(), EqualTo(3));
+ Expect(form.first(), EqualTo(Symbol.intern("+")));
+ Expect(form.rest().first(), EqualTo(arg2));
+ Expect(form.rest().rest().first(), EqualTo(arg4));
+ }
+
+ [Test]
+ public void SharpFnWithAnonArgGeneratesFnWithArgs()
+ {
+ object o1 = ReadFromString("#(+ % 2)");
+ // (fn* [p1__N] (+ p1__N 2))
+
+ Expect(o1, InstanceOfType(typeof(ISeq)));
+ ISeq s = o1 as ISeq;
+
+ Expect(s.first(), EqualTo(Symbol.intern("fn*")));
+ s = s.rest();
+ Expect(s.first(), InstanceOfType(typeof(IPersistentVector)));
+ IPersistentVector arglist = s.first() as IPersistentVector;
+
+ Expect(arglist.count(), EqualTo(1));
+ Expect(arglist.nth(0), InstanceOfType(typeof(Symbol)));
+ Symbol arg1 = arglist.nth(0) as Symbol;
+ Expect(arg1.Name, StartsWith("p1__"));
+
+ s = s.rest();
+ Expect(s.first(), InstanceOfType(typeof(ISeq)));
+ Expect(s.rest(), Null);
+
+ ISeq form = s.first() as ISeq;
+
+ Expect(form.count(), EqualTo(3));
+ Expect(form.first(), EqualTo(Symbol.intern("+")));
+ Expect(form.rest().first(), EqualTo(arg1));
+ Expect(form.rest().rest().first(), EqualTo(2));
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException))]
+ public void ArgReaderOutsideSharpFnFails()
+ {
+ object o1 = ReadFromString("(+ %2 2)");
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException))]
+ public void ArgReaderFollowedByNonNumericFails()
+ {
+ object o1 = ReadFromString("#(+ %a 2)");
+ }
+
+
+
+ #endregion
+
+ }
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/LockingTransactionTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/LockingTransactionTests.cs new file mode 100644 index 00000000..23682559 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/LockingTransactionTests.cs @@ -0,0 +1,194 @@ +/**
+ * 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;
+using System.Threading;
+
+namespace Clojure.Tests.LibTests
+{
+ // TODO: Add tests for LockingTransaction
+ [TestFixture]
+ public class LockingTransactionTests : AssertionHelper
+ {
+
+
+ //// TODO: Make this work.
+
+ //// This test is taken from the Java code.
+ //[Test]
+ //public void BigTest()
+ //{
+ // // We have to start the main work unit on its own thread because
+ // // the main during testing is STA and so does not support waiting on multiple handles.
+
+ // BigTester<Incrementer> tester = new BigTester<Incrementer>(5, 10, 2000);
+ // EventWaitHandle h = new EventWaitHandle(false, EventResetMode.ManualReset);
+ // Thread t = new Thread(tester.Work);
+ // t.Start(h);
+ // h.WaitOne();
+ // Console.WriteLine("Done");
+ //}
+
+ //class BigTester<T> where T : LockingTransactionTests.RefTester
+ //{
+ // int _nthreads;
+ // int _niters;
+ // int _nitems;
+
+ // public BigTester(int nthreads, int nitems, int niters)
+ // {
+ // _nthreads = nthreads;
+ // _nitems = nitems;
+ // _niters = niters;
+ // }
+
+ // public void Work(object o)
+ // {
+ // List<Ref> refs = new List<Ref>();
+
+ // for (int i = 0; i < _nitems; i++)
+ // refs.Add(new Ref(0));
+
+ // List<Thread> threads = new List<Thread>(_nthreads);
+ // List<EventWaitHandle> handles = new List<EventWaitHandle>(_nthreads);
+ // List<Incrementer> tasks = new List<Incrementer>(_nthreads);
+
+ // for (int i = 0; i < _nthreads; i++)
+ // {
+ // List<Ref> copy = refs.GetRange(0, refs.Count);
+ // Shuffle(copy);
+ // tasks.Add(new Incrementer(i, _niters, copy));
+ // threads.Add(new Thread(tasks[i].Work));
+ // handles.Add(new EventWaitHandle(false, EventResetMode.ManualReset));
+ // }
+
+
+ // for (int i = 0; i < _nthreads; i++)
+ // {
+ // threads[i].Name = "Thr " + i;
+ // threads[i].Start(handles[i]);
+ // }
+
+ // EventWaitHandle.WaitAll(handles.ToArray());
+
+ // foreach (Incrementer task in tasks)
+ // Console.WriteLine("Task {0}: {1} millisecs", task.Id, task.Nanos / 10000.0);
+
+ // foreach (Ref r in refs)
+ // Console.WriteLine("Ref is {0}", r.get());
+
+ // EventWaitHandle ewh = (EventWaitHandle)o;
+ // ewh.Set();
+
+ // }
+
+
+ // void Shuffle(List<Ref> refs)
+ // {
+ // }
+ //}
+
+ //public abstract class RefTester
+ //{
+ // readonly int _id;
+ // public int Id
+ // {
+ // get { return _id; }
+ // }
+
+ // protected readonly int _niters;
+ // protected readonly List<Ref> _items;
+
+ // long _nanos = 0;
+ // public long Nanos
+ // {
+ // get { return _nanos; }
+ // }
+
+
+ // public RefTester(int id, int niters, List<Ref> items)
+ // {
+ // _id = id;
+ // _niters = niters;
+ // _items = items;
+ // }
+
+ // public void Work(object o)
+ // {
+ // for (int i = 0; i < _niters; i++)
+ // {
+ // long startTime = DateTime.Now.Ticks;
+ // LockingTransaction.runInTransaction(this.TxUnit);
+ // long finishTime = DateTime.Now.Ticks;
+ // _nanos += finishTime - startTime;
+ // }
+
+ // EventWaitHandle h = (EventWaitHandle)o;
+ // h.Set();
+ // }
+
+ // public abstract object TxUnit(object[] args);
+ //}
+
+ //class Incrementer : RefTester
+ //{
+ // public Incrementer(int id, int niters, List<Ref> items)
+ // : base(id, niters, items)
+ // {
+ // }
+
+ // public override object TxUnit(object[] args)
+ // {
+ // foreach (Ref r in _items)
+ // {
+ // int val = (int)r.get();
+ // r.set(val + 1);
+ // }
+ // return null;
+ // }
+ //}
+
+
+ //class Commuter : RefTester
+ //{
+ // public Commuter(int id, int niters, List<Ref> items)
+ // : base(id, niters, items)
+ // {
+ // }
+
+ // public override object TxUnit(object[] args)
+ // {
+ // foreach (Ref r in _items)
+ // {
+ // r.commute(Commuter.Incr,null);
+ // }
+ // return null;
+ // }
+
+ // static object Incr(object[] args)
+ // {
+ // int val = (int)args[0];
+ // return val + 1;
+ // }
+ //}
+
+ }
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/MapEntryTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/MapEntryTests.cs new file mode 100644 index 00000000..2a5253fb --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/MapEntryTests.cs @@ -0,0 +1,369 @@ +/**
+ * 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 MapEntryTests : AssertionHelper
+ {
+ #region C-tor tests
+
+ [Test]
+ public void CtorCreatesEntryWithProperKeyVal()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+
+ Expect(me.key(), EqualTo(1));
+ Expect(me.val(), EqualTo("abc"));
+ }
+
+ #endregion
+
+ #region Object override tests
+
+ [Test]
+ public void HashCodeSameAsPersistentVector()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+ PersistentVector v = PersistentVector.create(1, "abc");
+
+ Expect(me.GetHashCode(), EqualTo(v.GetHashCode()));
+ }
+
+ [Test]
+ public void HashCodeFalseOnDifferentValues()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+ PersistentVector v = PersistentVector.create(1, "abcd");
+
+ Expect(me.GetHashCode(), Not.EqualTo(v.GetHashCode()));
+ }
+
+ [Test]
+ public void EqualsWorksOnPersistentVector()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+ PersistentVector v = PersistentVector.create(1, "abc");
+
+ Expect(me.Equals(v));
+ }
+
+ [Test]
+ public void EqualsWorksFalseOnDifferentValues()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+ PersistentVector v = PersistentVector.create(1, "abcd");
+
+ Expect(me.Equals(v),False);
+ }
+
+
+ #endregion
+
+ #region IMapEntry tests
+
+ #endregion
+
+ #region IPersistentVector tests
+
+ [Test]
+ public void LengthIs2()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+
+ Expect(me.length(), EqualTo(2));
+ }
+
+ [Test]
+ public void NthInRangeWorks()
+ {
+
+ MapEntry me = new MapEntry(1, "abc");
+
+ Expect(me.nth(0), EqualTo(1));
+ Expect(me.nth(1), EqualTo("abc"));
+ }
+
+ [Test]
+ [ExpectedException(typeof(IndexOutOfRangeException))]
+ public void NthOutOfRangeLowFails()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+ object obj = me.nth(-4);
+ }
+
+ [Test]
+ [ExpectedException(typeof(IndexOutOfRangeException))]
+ public void NthOutOfRangeHighFails()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+ object obj = me.nth(4);
+ }
+
+ [Test]
+ public void AssocNInRangeModifies()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+ IPersistentVector v1 = me.assocN(0, 2);
+ IPersistentVector v2 = me.assocN(1, "def");
+ IPersistentVector v3 = me.assocN(2, "ghi");
+
+ Expect(me.count(), EqualTo(2));
+ Expect(me.key(), EqualTo(1));
+ Expect(me.val(), EqualTo("abc"));
+
+ Expect(v1.count(), EqualTo(2));
+ Expect(v1.nth(0), EqualTo(2));
+ Expect(v1.nth(1), EqualTo("abc"));
+
+ Expect(v2.count(), EqualTo(2));
+ Expect(v2.nth(0), EqualTo(1));
+ Expect(v2.nth(1), EqualTo("def"));
+
+ Expect(v3.count(), EqualTo(3));
+ Expect(v3.nth(0), EqualTo(1));
+ Expect(v3.nth(1), EqualTo("abc"));
+ Expect(v3.nth(2), EqualTo("ghi"));
+ }
+
+ [Test]
+ [ExpectedException(typeof(IndexOutOfRangeException))]
+ public void AssocNOutOfRangeLowThrows()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+ IPersistentVector v1 = me.assocN(-4, 2);
+ }
+
+ [Test]
+ [ExpectedException(typeof(IndexOutOfRangeException))]
+ public void AssocNOutOfRangeHighThrows()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+ IPersistentVector v1 = me.assocN(4, 2);
+ }
+
+ [Test]
+ public void ConsWorks()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+ IPersistentVector v1 = me.cons(2);
+
+ Expect(me.count(), EqualTo(2));
+ Expect(me.key(), EqualTo(1));
+ Expect(me.val(), EqualTo("abc"));
+
+
+ Expect(v1.count(), EqualTo(3));
+ Expect(v1.nth(0), EqualTo(1));
+ Expect(v1.nth(1), EqualTo("abc"));
+ Expect(v1.nth(2), EqualTo(2));
+ }
+
+ #endregion
+
+ #region Associative tests
+
+ [Test]
+ public void ContainsKeyOnExistingKeyWorks()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+
+ Expect(me.containsKey(0));
+ Expect(me.containsKey(1));
+ }
+
+ [Test]
+ public void ContainsKeyOutOfRangeIsFalse()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+
+ Expect(me.containsKey(-4),False);
+ Expect(me.containsKey(4), False);
+ }
+
+
+ [Test]
+ public void EntryAtOnExistingKeyWorks()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+ IMapEntry me1 = me.entryAt(0);
+ IMapEntry me2 = me.entryAt(1);
+
+ Expect(me1.key(), EqualTo(0));
+ Expect(me1.val(), EqualTo(1));
+ Expect(me2.key(), EqualTo(1));
+ Expect(me2.val(), EqualTo("abc"));
+ }
+
+ [Test]
+ public void EntryAtOutOfRangeLowReturnsNull()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+ IMapEntry me1 = me.entryAt(-4);
+
+ Expect(me1,Null);
+ }
+
+ [Test]
+ public void EntryAtOutOfRangeHighReturnsNull()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+ IMapEntry me1 = me.entryAt(4);
+
+ Expect(me1, Null);
+ }
+
+ [Test]
+ public void ValAtOnExistingKeyReturnsValue()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+
+ Expect(me.valAt(0), EqualTo(1));
+ Expect(me.valAt(1), EqualTo("abc"));
+ }
+
+ [Test]
+ public void ValAtOnMissingKeyReturnsNull()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+
+ Expect(me.valAt(-4), Null);
+ Expect(me.valAt(4), Null);
+ }
+
+ [Test]
+ public void ValAtWithDefaultOnExistingKeyReturnsValue()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+
+ Expect(me.valAt(0,7), EqualTo(1));
+ Expect(me.valAt(1,7), EqualTo("abc"));
+ }
+
+ [Test]
+ public void ValAtWithDefaultOnMissingKeyReturnsDefault()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+
+ Expect(me.valAt(-4,7), EqualTo(7));
+ Expect(me.valAt(4, 7), EqualTo(7));
+ }
+
+ #endregion
+
+ #region Reversible tests
+
+ [Test]
+ public void RseqReturnReverseSeq()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+
+ ISeq s = me.rseq();
+
+ Expect(s.count(), EqualTo(2));
+ Expect(s.first(), EqualTo("abc"));
+ Expect(s.rest().first(), EqualTo(1));
+ Expect(s.rest().rest(), Null);
+ }
+
+ #endregion
+
+ #region IPersistentCollection tests
+
+ [Test]
+ public void CountIs2()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+ Expect(me.count(), EqualTo(2));
+ }
+
+ [Test]
+ public void SeqReturnsASeq()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+ ISeq s = me.seq();
+
+ Expect(s.count(), EqualTo(2));
+ Expect(s.first(), EqualTo(1));
+ Expect(s.rest().first(), EqualTo("abc"));
+ Expect(s.rest().rest(), Null);
+ }
+
+ [Test]
+ public void EmptyReutrnsNull()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+
+ Expect(me.empty(), Null);
+ }
+
+
+ [Test]
+ public void ExplictIPersistentCollectionConsWorks()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+ IPersistentCollection c = (IPersistentCollection)me;
+ ISeq s = c.cons(2).seq();
+
+ Expect(me.count(), EqualTo(2));
+ Expect(me.key(), EqualTo(1));
+ Expect(me.val(), EqualTo("abc"));
+
+ Expect(s.count(), EqualTo(3));
+ Expect(s.first(), EqualTo(1));
+ Expect(s.rest().first(), EqualTo("abc"));
+ Expect(s.rest().rest().first(), EqualTo(2));
+ Expect(s.rest().rest().rest(), Null);
+ }
+
+ #endregion
+
+ #region IPersistentStack tests
+
+ [Test]
+ public void PeekReturnsVal()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+
+ Expect(me.peek(), EqualTo("abc"));
+ Expect(me.count(), EqualTo(2));
+ Expect(me.key(), EqualTo(1));
+ Expect(me.val(), EqualTo("abc"));
+ }
+
+ [Test]
+ public void PopLosesTheValue()
+ {
+ MapEntry me = new MapEntry(1, "abc");
+ IPersistentVector v = (IPersistentVector)me.pop();
+
+ Expect(v.length(), EqualTo(1));
+ Expect(v.nth(0), EqualTo(1));
+ }
+
+
+
+
+ #endregion
+
+ }
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/NamespaceTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/NamespaceTests.cs new file mode 100644 index 00000000..4e6fcbab --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/NamespaceTests.cs @@ -0,0 +1,257 @@ +/**
+ * 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: NEed to fix NS tests to clear the created namespaces after each test.
+ /*
+ [TestFixture]
+ public class NamespaceTests : AssertionHelper
+ {
+ #region C-tor tests
+
+ [Test]
+ public void FindOrCreateCreatesANewNamespace()
+ {
+ Symbol sym = Symbol.intern("abc");
+ Namespace ns = Namespace.findOrCreate(sym);
+
+ Expect(ns, Not.Null);
+ Expect(ns.Name, EqualTo(sym));
+ }
+
+ [Test]
+ public void FindOrCreateFindsExistingNamespace()
+ {
+ Symbol sym1 = Symbol.intern("abc");
+ Namespace ns1 = Namespace.findOrCreate(sym1);
+ Symbol sym2 = Symbol.intern("abc");
+ Namespace ns2 = Namespace.findOrCreate(sym2);
+
+ Expect(Object.ReferenceEquals(ns1, ns2));
+ }
+
+ [Test]
+ public void FindGivesNullOnMissingNS()
+ {
+ Symbol sym = Symbol.intern("abc");
+ Namespace ns = Namespace.find(sym);
+
+ Expect(ns, Null);
+ }
+
+ [Test]
+ public void FindFindsExistingNS()
+ {
+ Symbol sym1 = Symbol.intern("abc");
+ Namespace ns1 = Namespace.findOrCreate(sym1);
+ Symbol sym2 = Symbol.intern("abc");
+ Namespace ns2 = Namespace.find(sym2);
+
+ Expect(Object.ReferenceEquals(ns1, ns2));
+ }
+
+ [Test]
+ public void RemoveRemovesExisingNamespace()
+ {
+ Symbol sym1 = Symbol.intern("abc");
+ Namespace ns1 = Namespace.findOrCreate(sym1);
+ Symbol sym2 = Symbol.intern("abc");
+ Namespace ns2 = Namespace.remove(sym2);
+ Namespace ns3 = Namespace.find(sym1);
+
+ Expect(object.ReferenceEquals(ns1, ns2));
+ Expect(ns3, Null);
+ }
+
+
+ [Test]
+ public void RemoveReturnsNullOnNonExisingNamespace()
+ {
+ Symbol sym2 = Symbol.intern("abc");
+ Namespace ns2 = Namespace.remove(sym2);
+
+ Expect(ns2, Null);
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException))]
+ public void RemoveFailsRemovingClojureCoreNS()
+ {
+ Symbol sym = Symbol.intern("clojure.core");
+ Namespace ns = Namespace.remove(sym);
+ }
+
+
+ // how to test the thread-safety of findOrCreatea?
+
+ #endregion
+
+ #region object override tests
+
+ [Test]
+ public void ToStringWorks()
+ {
+ // do we care all that much?
+ Namespace ns = Namespace.findOrCreate(Symbol.intern("abc"));
+ Expect(ns.ToString(),EqualTo("#<Namespace: abc>"));
+ }
+
+ #endregion
+
+ #region Interning symbols tests
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException))]
+ public void InterningSymbolWithNamespaceFails()
+ {
+ Symbol sym = Symbol.intern("abc", "def");
+ Namespace ns = Namespace.findOrCreate(Symbol.intern("ghi"));
+ Var v = ns.intern(sym);
+ }
+
+ [Test]
+ public void InterningSymbolCreatesVar()
+ {
+ Symbol sym = Symbol.intern("def");
+ Namespace ns = Namespace.findOrCreate(Symbol.intern("abc"));
+
+ Var v = ns.intern(sym);
+
+ Expect(v, Not.Null);
+ Expect(v.Namespace, EqualTo(ns));
+
+ }
+
+ [Test]
+ public void InterningSymbolEntersVarInMap()
+ {
+ Symbol sym = Symbol.intern("def");
+ Namespace ns = Namespace.findOrCreate(Symbol.intern("abc"));
+
+ Var v = ns.intern(sym);
+
+ Expect(ns.findInternedVar(sym), SameAs(v));
+ }
+
+
+
+ [Test]
+ public void InterningSymbolAgainFindsVar()
+ {
+ Symbol sym = Symbol.intern("def");
+ Namespace ns = Namespace.findOrCreate(Symbol.intern("abc"));
+
+ Var v1 = ns.intern(sym);
+
+ Var v2 = ns.intern(sym);
+
+ Expect(Object.ReferenceEquals(v1, v2));
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException))]
+ public void ReferSymbolToVarInOtherAndThenInterningThrows()
+ {
+ // I don't know why
+
+ Namespace ns1 = Namespace.findOrCreate(Symbol.intern("abc"));
+
+ Symbol sym1 = Symbol.intern("def");
+ Var v1 = ns1.intern(sym1);
+
+ Namespace ns2 = Namespace.findOrCreate(Symbol.intern("d"));
+ Symbol sym2 = Symbol.intern("g");
+
+ ns2.refer(sym2, v1);
+ ns2.intern(sym2);
+ }
+
+
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException))]
+ public void ReferOfSymbolWithNamespaceFails()
+ {
+ Symbol sym = Symbol.intern("abc", "def");
+ Namespace ns = Namespace.findOrCreate(Symbol.intern("ghi"));
+ ns.refer(sym, Var.create());
+ }
+
+ [Test]
+ public void ReferEntersVar()
+ {
+ Namespace ns = Namespace.findOrCreate(Symbol.intern("abc"));
+
+ Symbol sym = Symbol.intern("def");
+ Var v = Var.create();
+ ns.refer(sym, v);
+
+ Expect(ns.getMapping(sym), SameAs(v));
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException))]
+ public void ImportTypeOnSymbolWithNamespaceFails()
+ {
+ Symbol sym = Symbol.intern("abc", "def");
+ Namespace ns = Namespace.findOrCreate(Symbol.intern("ghi"));
+ ns.importType(sym, typeof(Int32));
+ }
+
+ [Test]
+ public void ImportTypeEntersType()
+ {
+ Namespace ns = Namespace.findOrCreate(Symbol.intern("abc"));
+
+ Symbol sym = Symbol.intern("def");
+ ns.importType(sym, typeof(Int32));
+
+ Expect(ns.getMapping(sym), SameAs(typeof(Int32)));
+ }
+
+
+ [Test]
+ public void FindInternedVarFailsIfNonVarValueInMap()
+ {
+ Namespace ns = Namespace.findOrCreate(Symbol.intern("abc"));
+
+ Symbol sym = Symbol.intern("def");
+ ns.importType(sym, typeof(Int32));
+
+ Var v = ns.findInternedVar(sym);
+
+ Expect(v, Null);
+ }
+
+
+ // Don't know how to test the race condition in the loops for
+ // intern(Symbol), reference(Symbol), unmap(Symbol)
+
+ #endregion
+ }
+ */
+
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/NumbersTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/NumbersTests.cs new file mode 100644 index 00000000..e5c869fc --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/NumbersTests.cs @@ -0,0 +1,137 @@ +/**
+ * 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 java.math;
+
+namespace Clojure.Tests.LibTests
+{
+ [TestFixture]
+ public class NumbersTests : AssertionHelper
+ {
+ #region Helpers
+
+ private void ExpectInt32(object x)
+ {
+ Expect(x, TypeOf(typeof(Int32)));
+ }
+
+ private void ExpectSameObject(object x, object y)
+ {
+ Expect(x, SameAs(y));
+ }
+
+ private void ExpectEqualObject(object x, object y)
+ {
+ Expect(x, EqualTo(y));
+ }
+
+ #endregion
+
+ #region reduce tests
+
+ [Test]
+ public void ReduceOnBigIntReducesSmallerValues()
+ {
+ BigInteger b1 = new BigInteger("123");
+ BigInteger b2 = new BigInteger("0");
+ BigInteger b3 = new BigInteger(Int32.MaxValue.ToString());
+ BigInteger b4 = new BigInteger(Int32.MinValue.ToString());
+
+ ExpectInt32(Numbers.reduce(b1));
+ ExpectInt32(Numbers.reduce(b2));
+ ExpectInt32(Numbers.reduce(b3));
+ ExpectInt32(Numbers.reduce(b4));
+ }
+
+ [Test]
+ public void ReduceOnBigIntReturnsLargerValues()
+ {
+ BigInteger b1 = new BigInteger("100000000000000000000", 16);
+ BigInteger b2 = b1.negate();
+ BigInteger b3 = new BigInteger("123456789012345678901234567890");
+ BigInteger b4 = b3.negate();
+
+ ExpectSameObject(b1, Numbers.reduce(b1));
+ ExpectSameObject(b2, Numbers.reduce(b2));
+ ExpectSameObject(b3, Numbers.reduce(b3));
+ ExpectSameObject(b4, Numbers.reduce(b4));
+ }
+
+ [Test]
+ public void ReduceOnLongReducesSmallerValues()
+ {
+ long b1 = 123;
+ long b2 = 0;
+ long b3 = Int32.MaxValue;
+ long b4 = Int32.MinValue;
+
+ ExpectInt32(Numbers.reduce(b1));
+ ExpectInt32(Numbers.reduce(b2));
+ ExpectInt32(Numbers.reduce(b3));
+ ExpectInt32(Numbers.reduce(b4));
+ }
+
+
+ [Test]
+ public void ReduceOnLongReturnsLargerValues()
+ {
+ long b1 = ((long)Int32.MaxValue) + 1;
+ long b2 = ((long)Int32.MinValue) - 1;
+ long b3 = 123456789000;
+ long b4 = -b3;
+
+ ExpectEqualObject(b1, Numbers.reduce(b1));
+ ExpectEqualObject(b2, Numbers.reduce(b2));
+ ExpectEqualObject(b3, Numbers.reduce(b3));
+ ExpectEqualObject(b4, Numbers.reduce(b4));
+ }
+
+ #endregion
+
+ #region divide tests
+
+ [Test]
+ [ExpectedException(typeof(ArithmeticException))]
+ public void DivideByZeroFails()
+ {
+ object o = Numbers.BIDivide(Numbers.BigIntegerOne, Numbers.BigIntegerZero);
+ }
+
+ [Test]
+ public void DivideReducesToIntOnDenomOne()
+ {
+ object o = Numbers.BIDivide(new BigInteger("75"), new BigInteger("25"));
+ Expect(o, EqualTo(3));
+ }
+
+ [Test]
+ public void DivideReturnsReducedRatio()
+ {
+ object o = Numbers.BIDivide(new BigInteger("42"), new BigInteger("30"));
+
+ Expect(o, TypeOf(typeof(Ratio)));
+
+ Ratio r = o as Ratio;
+ Expect(r.Numerator, EqualTo(new BigInteger("7")));
+ Expect(r.Denominator, EqualTo(new BigInteger("5")));
+ }
+
+ #endregion
+ }
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/ObjTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/ObjTests.cs new file mode 100644 index 00000000..bf7423ba --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/ObjTests.cs @@ -0,0 +1,68 @@ +/**
+ * 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
+{
+ [TestFixture]
+ public class ObjTests : IObjTests
+ {
+
+ class MockObj : Obj
+ {
+ public MockObj()
+ {
+ }
+
+ public MockObj(IPersistentMap meta)
+ : base(meta)
+ {
+ }
+
+ public override IObj withMeta(IPersistentMap meta)
+ {
+ return meta == _meta
+ ? this
+ : new MockObj(meta);
+ }
+ }
+
+ MockRepository _mocks;
+
+ [SetUp]
+ public void Setup()
+ {
+ _mocks = new MockRepository();
+ IPersistentMap meta = _mocks.StrictMock<IPersistentMap>();
+ _mocks.ReplayAll();
+
+ _objWithNullMeta = new MockObj();
+ _obj = new MockObj(meta);
+ _expectedType = typeof(MockObj);
+ }
+
+ [TearDown]
+ public void Teardown()
+ {
+ _mocks.VerifyAll();
+ }
+ }
+}
+
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentArrayMapTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentArrayMapTests.cs new file mode 100644 index 00000000..87692146 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentArrayMapTests.cs @@ -0,0 +1,917 @@ +/**
+ * 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 System.Collections;
+
+using NUnit.Framework;
+using Rhino.Mocks;
+
+using clojure.lang;
+
+using RMExpect = Rhino.Mocks.Expect;
+
+namespace Clojure.Tests.LibTests
+{
+ [TestFixture]
+ public class PersistentArrayMapTests : AssertionHelper
+ {
+ #region C-tor tests
+
+ [Test]
+ public void CreateOnEmptyDictionaryReturnsEmptyMap()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ IPersistentMap m = PersistentArrayMap.create(d);
+
+ Expect(m.count(), EqualTo(0));
+ }
+
+ [Test]
+ public void CreateOnDictionaryReturnsMap()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentArrayMap.create(d);
+
+ Expect(m.count(), EqualTo(2));
+ Expect(m.valAt(1), EqualTo("a"));
+ Expect(m.valAt(2), EqualTo("b"));
+ Expect(m.containsKey(3), False);
+ }
+
+ // other c-tors are not public.
+
+
+ #endregion
+
+ #region Associative tests
+
+ [Test]
+ public void ContainsKeyOnMissingKeyIsFalse()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentArrayMap.create(d);
+
+ Expect(m.containsKey(3), False);
+ }
+
+
+ [Test]
+ public void ContainsKeyOnExistingKeyIsTrue()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentArrayMap.create(d);
+
+ Expect(m.containsKey(1));
+ Expect(m.containsKey(2));
+ }
+
+ [Test]
+ public void ContainsKeyNotConfusedByValue()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentArrayMap.create(d);
+
+ Expect(m.containsKey("a"), False);
+ }
+
+ [Test]
+ public void EntryAtReturnsNullOnMissingKey()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentArrayMap.create(d);
+
+ Expect(m.entryAt(3), Null);
+ }
+
+ [Test]
+ public void EntryAtReturnsEntryforKey()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentArrayMap.create(d);
+ IMapEntry me = m.entryAt(1);
+
+ Expect(me.key(), EqualTo(1));
+ Expect(me.val(), EqualTo("a"));
+ }
+
+ [Test]
+ public void ValAt1ReturnsNullOnMissingKey()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentArrayMap.create(d);
+
+ Expect(m.valAt(3), Null);
+ }
+
+ [Test]
+ public void ValAt1ReturnsValueforKey()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentArrayMap.create(d);
+
+ Expect(m.valAt(1), EqualTo("a"));
+ }
+
+
+ [Test]
+ public void ValAt2ReturnsDefaultOnMissingKey()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentArrayMap.create(d);
+
+ Expect(m.valAt(3,99), EqualTo(99));
+ }
+
+ [Test]
+ public void ValAt2ReturnsValueforKey()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentArrayMap.create(d);
+
+ Expect(m.valAt(1,99), EqualTo("a"));
+ }
+
+ #endregion
+
+ #region IPersistentCollection tests
+
+ [Test]
+ public void CountOnEmptyReturns0()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ IPersistentMap m = PersistentArrayMap.create(d);
+
+ Expect(m.count(), EqualTo(0));
+ }
+
+ [Test]
+ public void CountOnNonEmptyReturnsCount()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+ IPersistentMap m = PersistentArrayMap.create(d);
+
+ Expect(m.count(), EqualTo(2));
+ }
+
+ [Test]
+ public void EmptyReturnsEmpty()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+ IPersistentMap m = PersistentArrayMap.create(d);
+ IPersistentCollection c = m.empty();
+
+ Expect(c.count(), EqualTo(0));
+ Expect(c.seq(), Null);
+ }
+
+
+ [Test]
+ public void SeqOnEmptyReturnNull()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ IPersistentMap m = PersistentArrayMap.create(d);
+ ISeq s = m.seq();
+
+ Expect(s, Null);
+ }
+
+ [Test]
+ public void SeqOnNonEmptyIterates()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+ IPersistentMap m = PersistentArrayMap.create(d);
+ ISeq s = m.seq();
+ IMapEntry me1 = (IMapEntry)s.first();
+ IMapEntry me2 = (IMapEntry)s.rest().first();
+ ISeq end = s.rest().rest();
+
+ Expect(s.count(), EqualTo(2));
+ Expect(me1.key(), EqualTo(1) | EqualTo(2));
+ Expect(me1.val(), EqualTo(((int)me1.key()==1 ? "a" : "b")));
+ Expect(me2.key(), EqualTo(1) | EqualTo(2));
+ Expect(me2.val(), EqualTo(((int)me2.key() == 1 ? "a" : "b")));
+ Expect(end, Null);
+ }
+
+ #endregion
+
+ #region IPersistentMap tests
+
+ [Test]
+ public void AssocModifiesOnExistingKey()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m1 = PersistentArrayMap.create(d);
+ IPersistentMap m2 = m1.assoc(2, "c");
+
+ Expect(m1.count(), EqualTo(2));
+ Expect(m1.valAt(2), EqualTo("b"));
+ Expect(m2.count(), EqualTo(2));
+ Expect(m2.valAt(2), EqualTo("c"));
+ }
+
+
+ [Test]
+ public void AssocAddsOnNewKey()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m1 = PersistentArrayMap.create(d);
+ IPersistentMap m2 = m1.assoc(3, "c");
+
+ Expect(m1.count(), EqualTo(2));
+ Expect(m1.containsKey(3), False);
+ Expect(m2.count(), EqualTo(3));
+ Expect(m2.valAt(3), EqualTo("c"));
+ }
+
+
+ [Test]
+ [ExpectedException(typeof(Exception))]
+ public void AssocExFailsOnExistingKey()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m1 = PersistentArrayMap.create(d);
+ IPersistentMap m2 = m1.assocEx(2, "c");
+ }
+
+
+
+ [Test]
+ public void AssocExModifiesOnNewKey()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m1 = PersistentArrayMap.create(d);
+ IPersistentMap m2 = m1.assocEx(3, "c");
+
+ Expect(m1.count(), EqualTo(2));
+ Expect(m1.containsKey(3), False);
+ Expect(m2.count(), EqualTo(3));
+ Expect(m2.valAt(3), EqualTo("c"));
+ }
+
+ [Test]
+ public void WithoutOnExistingKeyRemovesKey()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[3] = "a";
+ d[5] = "b";
+ d[7] = "c";
+
+ IPersistentMap m1 = PersistentArrayMap.create(d);
+ IPersistentMap m2 = m1.without(5);
+
+ Expect(m1.count(), EqualTo(3));
+ Expect(m1.valAt(5), EqualTo("b"));
+ Expect(m2.count(), EqualTo(2));
+ Expect(m2.containsKey(5), False);
+ }
+
+ [Test]
+ public void WithoutOnMissingKeyIsIdentity()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[3] = "a";
+ d[5] = "b";
+ d[7] = "c";
+
+ IPersistentMap m1 = PersistentArrayMap.create(d);
+ IPersistentMap m2 = m1.without(4);
+
+ Expect(m2, SameAs(m1));
+ }
+
+ #endregion
+
+ #region APersistentMap tests
+
+ [Test]
+ public void EqualsOnSimilarDictionaryReturnsTrue()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentArrayMap.create(d);
+
+ Expect(m.equiv(d));
+ }
+
+ [Test]
+ public void EqualsOnDictionaryWIthDifferntValueReturnsFalse()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentArrayMap.create(d);
+
+ d[2] = "c";
+
+ Expect(m.Equals(d),False);
+ }
+
+
+ [Test]
+ public void EqualsOnDictionaryWithExtraValueReturnsFalse()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentArrayMap.create(d);
+
+ d[3] = "c";
+
+ Expect(m.Equals(d), False);
+ }
+
+ [Test]
+ public void HashCodeBasedOnValue()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m1 = PersistentArrayMap.create(d);
+
+ d[3] = "c";
+ IPersistentMap m2 = PersistentArrayMap.create(d);
+
+ Expect(m1.GetHashCode(), Not.EqualTo(m2.GetHashCode()));
+ }
+
+ [Test]
+ public void AssociativeDotAssocWorks()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentArrayMap.create(d);
+ Associative a = (Associative)m;
+
+ Associative a1 = a.assoc(3, "c");
+ Associative a2 = a.assoc(2, "c");
+
+ Expect(a.count(), EqualTo(2));
+ Expect(a.valAt(1), EqualTo("a"));
+ Expect(a.valAt(2), EqualTo("b"));
+ Expect(a.containsKey(3), False);
+
+ Expect(a1.count(), EqualTo(3));
+ Expect(a1.valAt(1), EqualTo("a"));
+ Expect(a1.valAt(2), EqualTo("b"));
+ Expect(a1.valAt(3), EqualTo("c"));
+
+ Expect(a2.count(), EqualTo(2));
+ Expect(a2.valAt(1), EqualTo("a"));
+ Expect(a2.valAt(2), EqualTo("c"));
+ Expect(a2.containsKey(3), False);
+ }
+
+ [Test]
+ public void ConsOnIMapEntryAddsNew()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentArrayMap.create(d);
+ IPersistentMap c = m.cons(new MapEntry(3, "c"));
+
+ Expect(m.count(), EqualTo(2));
+ Expect(m.valAt(1), EqualTo("a"));
+ Expect(m.valAt(2), EqualTo("b"));
+
+ Expect(c.count(), EqualTo(3));
+ Expect(c.valAt(1), EqualTo("a"));
+ Expect(c.valAt(2), EqualTo("b"));
+ Expect(c.valAt(3), EqualTo("c"));
+ }
+
+ [Test]
+ public void ConsOnIMapEntryReplacesExisting()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentArrayMap.create(d);
+ IPersistentMap c = m.cons(new MapEntry(2, "c"));
+
+ Expect(m.count(), EqualTo(2));
+ Expect(m.valAt(1), EqualTo("a"));
+ Expect(m.valAt(2), EqualTo("b"));
+
+ Expect(c.count(), EqualTo(2));
+ Expect(c.valAt(1), EqualTo("a"));
+ Expect(c.valAt(2), EqualTo("c"));
+ }
+
+
+ [Test]
+ public void ConsOnDictionaryEntryAddsNew()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentArrayMap.create(d);
+ IPersistentMap c = m.cons(new DictionaryEntry(3, "c"));
+
+ Expect(m.count(), EqualTo(2));
+ Expect(m.valAt(1), EqualTo("a"));
+ Expect(m.valAt(2), EqualTo("b"));
+
+ Expect(c.count(), EqualTo(3));
+ Expect(c.valAt(1), EqualTo("a"));
+ Expect(c.valAt(2), EqualTo("b"));
+ Expect(c.valAt(3), EqualTo("c"));
+ }
+
+ [Test]
+ public void ConsOnDictionaryEntryReplacesExisting()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentArrayMap.create(d);
+ IPersistentMap c = m.cons(new DictionaryEntry(2, "c"));
+
+ Expect(m.count(), EqualTo(2));
+ Expect(m.valAt(1), EqualTo("a"));
+ Expect(m.valAt(2), EqualTo("b"));
+
+ Expect(c.count(), EqualTo(2));
+ Expect(c.valAt(1), EqualTo("a"));
+ Expect(c.valAt(2), EqualTo("c"));
+ }
+
+ [Test]
+ public void ConsOnKeyValuePairAddsNew()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentArrayMap.create(d);
+ IPersistentMap c = m.cons(new KeyValuePair<int,string>(3, "c"));
+
+ Expect(m.count(), EqualTo(2));
+ Expect(m.valAt(1), EqualTo("a"));
+ Expect(m.valAt(2), EqualTo("b"));
+
+ Expect(c.count(), EqualTo(3));
+ Expect(c.valAt(1), EqualTo("a"));
+ Expect(c.valAt(2), EqualTo("b"));
+ Expect(c.valAt(3), EqualTo("c"));
+ }
+
+ [Test]
+ public void ConsOnKeyValuePairReplacesExisting()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentArrayMap.create(d);
+ IPersistentMap c = m.cons(new KeyValuePair<int,string>(2, "c"));
+
+ Expect(m.count(), EqualTo(2));
+ Expect(m.valAt(1), EqualTo("a"));
+ Expect(m.valAt(2), EqualTo("b"));
+
+ Expect(c.count(), EqualTo(2));
+ Expect(c.valAt(1), EqualTo("a"));
+ Expect(c.valAt(2), EqualTo("c"));
+ }
+
+ [Test]
+ public void ConsOnIPVAddsNew()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentArrayMap.create(d);
+
+ IPersistentVector v = PersistentVector.create(3, "c");
+ IPersistentMap c = m.cons(v);
+
+ Expect(m.count(), EqualTo(2));
+ Expect(m.valAt(1), EqualTo("a"));
+ Expect(m.valAt(2), EqualTo("b"));
+
+ Expect(c.count(), EqualTo(3));
+ Expect(c.valAt(1), EqualTo("a"));
+ Expect(c.valAt(2), EqualTo("b"));
+ Expect(c.valAt(3), EqualTo("c"));
+ }
+
+ [Test]
+ public void ConsOnIPVReplacesExisting()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentArrayMap.create(d);
+
+ IPersistentVector v = PersistentVector.create(2, "c");
+ IPersistentMap c = m.cons(v);
+
+ Expect(m.count(), EqualTo(2));
+ Expect(m.valAt(1), EqualTo("a"));
+ Expect(m.valAt(2), EqualTo("b"));
+
+ Expect(c.count(), EqualTo(2));
+ Expect(c.valAt(1), EqualTo("a"));
+ Expect(c.valAt(2), EqualTo("c"));
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException))]
+ public void ConsOnNon2IPVFails()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentArrayMap.create(d);
+
+ IPersistentVector v = PersistentVector.create(2, "c", 3, "d");
+ IPersistentMap c = m.cons(v);
+
+ }
+
+ [Test]
+ public void ConsOnIPersistentMapAddsOrReplacesMany()
+ {
+ Dictionary<int, string> d1 = new Dictionary<int, string>();
+ d1[1] = "a";
+ d1[2] = "b";
+
+ IPersistentMap m1 = PersistentArrayMap.create(d1);
+
+
+ Dictionary<int, string> d2 = new Dictionary<int, string>();
+ d2[2] = "c";
+ d2[3] = "d";
+
+ IPersistentMap m2 = PersistentArrayMap.create(d2);
+ IPersistentMap m3 = m1.cons(m2);
+
+
+ Expect(m1.count(), EqualTo(2));
+ Expect(m1.valAt(1), EqualTo("a"));
+ Expect(m1.valAt(2), EqualTo("b"));
+
+ Expect(m2.count(), EqualTo(2));
+ Expect(m2.valAt(2), EqualTo("c"));
+ Expect(m2.valAt(3), EqualTo("d"));
+
+ Expect(m3.count(), EqualTo(3));
+ Expect(m3.valAt(1), EqualTo("a"));
+ Expect(m3.valAt(2), EqualTo("c"));
+ Expect(m3.valAt(3), EqualTo("d"));
+ }
+
+ [Test]
+ public void InvokeOn1ArgDoesValAt1()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IFn f = (IFn)PersistentArrayMap.create(d);
+
+ Expect(f.invoke(1), EqualTo("a"));
+ Expect(f.invoke(7),Null);
+
+ }
+ [Test]
+ public void InvokeOn2ArgsDoesValAt2()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IFn f = (IFn)PersistentArrayMap.create(d);
+
+ Expect(f.invoke(1,99), EqualTo("a"));
+ Expect(f.invoke(7,99), EqualTo(99));
+ }
+
+ [Test]
+ [ExpectedException(typeof(NotImplementedException))]
+ public void IDictionary_Add_fails()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IDictionary id = (IDictionary)PersistentArrayMap.create(d);
+ id.Add(1, "c");
+ }
+
+ [Test]
+ [ExpectedException(typeof(NotImplementedException))]
+ public void IDictionary_Clear_fails()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IDictionary id = (IDictionary)PersistentArrayMap.create(d);
+ id.Clear();
+ }
+
+ [Test]
+ [ExpectedException(typeof(NotImplementedException))]
+ public void IDictionary_Remove_fails()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IDictionary id = (IDictionary)PersistentArrayMap.create(d);
+ id.Remove(1);
+ }
+
+ [Test]
+ public void IDictionary_Contains_finds_existing_key()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IDictionary id = (IDictionary)PersistentArrayMap.create(d);
+ Expect(id.Contains(1));
+ }
+
+
+
+ [Test]
+ public void IDictionary_Contains_does_not_find_existing_key()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IDictionary id = (IDictionary)PersistentArrayMap.create(d);
+
+ Expect(id.Contains(3),False);
+ }
+
+ [Test]
+ public void IDictionary_IsFixedSize_is_true()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IDictionary id = (IDictionary)PersistentArrayMap.create(d);
+
+ Expect(id.IsFixedSize);
+ }
+
+ [Test]
+ public void IDictionary_IsReadOnly_is_true()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IDictionary id = (IDictionary)PersistentArrayMap.create(d);
+
+ Expect(id.IsReadOnly);
+ }
+
+ [Test]
+ public void IDictionary_index_acts_like_valAt()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IDictionary id = (IDictionary)PersistentArrayMap.create(d);
+ Expect(id[2], EqualTo("b"));
+ Expect(id[3], Null);
+ }
+
+ [Test]
+ public void IDictionary_Keys_creates_key_collection()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IDictionary id = (IDictionary)PersistentArrayMap.create(d);
+ ICollection keys = id.Keys;
+
+ Expect(keys.Count, EqualTo(2));
+ int[] akeys = new int[2];
+ keys.CopyTo(akeys, 0);
+ Array.Sort(akeys);
+ Expect(akeys[0], EqualTo(1));
+ Expect(akeys[1], EqualTo(2));
+ }
+
+ [Test]
+ public void IDictionary_Values_creates_value_collection()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IDictionary id = (IDictionary)PersistentArrayMap.create(d);
+ ICollection vals = id.Values;
+
+ Expect(vals.Count, EqualTo(2));
+ string[] avals = new string[2];
+ vals.CopyTo(avals, 0);
+ Array.Sort(avals);
+ Expect(avals[0], EqualTo("a"));
+ Expect(avals[1], EqualTo("b"));
+ }
+
+
+
+
+ [Test]
+ public void IDictionary_GetEnumerator_returns_an_enumerator()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IDictionary id = (IDictionary)PersistentArrayMap.create(d);
+ IDictionaryEnumerator e = id.GetEnumerator();
+
+ Expect(e.MoveNext());
+ DictionaryEntry de1 = (DictionaryEntry)e.Current;
+ Expect(e.MoveNext());
+ DictionaryEntry de2 = (DictionaryEntry)e.Current;
+ Expect(e.MoveNext(), False);
+
+ Expect(de1.Key, EqualTo(1) | EqualTo(2));
+ Expect(de2.Key, EqualTo(1) | EqualTo(2));
+ Expect(de1.Value, EqualTo(((int)de1.Key) == 1 ? "a" : "b"));
+ Expect(de2.Value, EqualTo(((int)de2.Key) == 1 ? "a" : "b"));
+ }
+
+ [Test]
+ public void ICollection_CopyTo_Copies()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ ICollection c = (ICollection)PersistentArrayMap.create(d);
+ IMapEntry[] a = new IMapEntry[c.Count];
+ c.CopyTo(a, 0);
+
+ int key0 = (int)a[0].key();
+ int key1 = (int)a[1].key();
+ string val0 = (string)a[0].val();
+ string val1 = (string)a[1].val();
+
+ Expect(key0, EqualTo(1) | EqualTo(2));
+ Expect(key1, EqualTo(key0 == 1 ? 2 : 1));
+ Expect(val0, EqualTo(key0 == 1 ? "a" : "b"));
+ Expect(val1, EqualTo(key1 == 1 ? "a" : "b"));
+ }
+
+
+ [Test]
+ public void ICollection_Count_returns_count_of_items()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ ICollection c = (ICollection)PersistentArrayMap.create(d);
+
+ Expect(c.Count, EqualTo(2));
+ }
+
+ [Test]
+ public void ICollection_IsSynchronized_is_true()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ ICollection c = (ICollection)PersistentArrayMap.create(d);
+
+ Expect(c.IsSynchronized);
+ }
+
+
+ [Test]
+ [ExpectedException(typeof(NotImplementedException))]
+ public void ICollection_SyncRoot_fails()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ ICollection c = (ICollection)PersistentArrayMap.create(d);
+
+ object s = c.SyncRoot;
+ }
+
+
+ #endregion
+ }
+
+ [TestFixture]
+ public class PersistentArrayMap_IObj_Tests : IObjTests
+ {
+ MockRepository _mocks;
+
+ [SetUp]
+ public void Setup()
+ {
+ _mocks = new MockRepository();
+ IPersistentMap meta = _mocks.StrictMock<IPersistentMap>();
+ _mocks.ReplayAll();
+
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "abc";
+
+ _objWithNullMeta = (IObj)PersistentArrayMap.create(d);
+ _obj = _objWithNullMeta.withMeta(meta);
+ _expectedType = typeof(PersistentArrayMap);
+ }
+
+ [TearDown]
+ public void Teardown()
+ {
+ _mocks.VerifyAll();
+ }
+
+ }
+
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentHashMapTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentHashMapTests.cs new file mode 100644 index 00000000..200494b5 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentHashMapTests.cs @@ -0,0 +1,242 @@ +/**
+ * 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;
+using System.Collections;
+
+
+namespace Clojure.Tests.LibTests
+{
+ [TestFixture]
+ public class PersistentHashMapTests : AssertionHelper
+ {
+
+ #region C-tor tests
+
+ [Test]
+ public void CreateOnEmptyDictionaryReturnsEmptyMap()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ IPersistentMap m = PersistentHashMap.create(d);
+
+ Expect(m.count(), EqualTo(0));
+ }
+
+ [Test]
+ public void CreateOnDictionaryReturnsMap()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentHashMap.create(d);
+
+ Expect(m.count(), EqualTo(2));
+ Expect(m.valAt(1), EqualTo("a"));
+ Expect(m.valAt(2), EqualTo("b"));
+ Expect(m.containsKey(3), False);
+ }
+
+ [Test]
+ public void CreateOnEmptyListReturnsEmptyMap()
+ {
+ ArrayList a = new ArrayList();
+ IPersistentMap m = PersistentHashMap.create(a);
+
+ Expect(m.count(), EqualTo(0));
+ }
+
+ [Test]
+ public void CreateOnListReturnsMap()
+ {
+ object[] items = new object[] { 1, "a", 2, "b" };
+ ArrayList a = new ArrayList(items);
+
+ IPersistentMap m = PersistentHashMap.create(a);
+
+ Expect(m.count(), EqualTo(2));
+ Expect(m.valAt(1), EqualTo("a"));
+ Expect(m.valAt(2), EqualTo("b"));
+ Expect(m.containsKey(3), False);
+ }
+
+ [Test]
+ public void CreateOnEmptyISeqReturnsEmptyMap()
+ {
+ object[] items = new object[] {};
+ ArrayList a = new ArrayList(items);
+ ISeq s = PersistentList.create(a).seq();
+ IPersistentMap m = PersistentHashMap.create(s);
+
+ Expect(m.count(), EqualTo(0));
+ }
+
+ [Test]
+ public void CreateOnISeqReturnsMap()
+ {
+ object[] items = new object[] { 1, "a", 2, "b" };
+ ArrayList a = new ArrayList(items);
+ ISeq s = PersistentList.create(a).seq();
+ IPersistentMap m = PersistentHashMap.create(s);
+
+ Expect(m.count(), EqualTo(2));
+ Expect(m.valAt(1), EqualTo("a"));
+ Expect(m.valAt(2), EqualTo("b"));
+ Expect(m.containsKey(3), False);
+ }
+
+ [Test]
+ public void CreateOnNoArgsReturnsEmptyMap()
+ {
+ PersistentHashMap m = PersistentHashMap.create();
+
+ Expect(m.count(), EqualTo(0));
+ Expect(m.meta(), Null);
+ }
+
+ [Test]
+ public void CreateOnNoArgsReturnsMap()
+ {
+ PersistentHashMap m = PersistentHashMap.create(1, "a", 2, "b");
+
+ Expect(m.count(), EqualTo(2));
+ Expect(m.valAt(1), EqualTo("a"));
+ Expect(m.valAt(2), EqualTo("b"));
+ Expect(m.containsKey(3), False);
+ Expect(m.meta(), Null);
+ }
+
+
+ [Test]
+ public void CreateOnMetaNoArgsReturnsEmptyMap()
+ {
+ MockRepository mocks = new MockRepository();
+ IPersistentMap meta = mocks.StrictMock<IPersistentMap>();
+ mocks.ReplayAll();
+
+ PersistentHashMap m = PersistentHashMap.create(meta);
+
+ Expect(m.count(), EqualTo(0));
+ Expect(m.meta(), SameAs(meta));
+ mocks.VerifyAll();
+ }
+
+ [Test]
+ public void CreateOnMetaNoArgsReturnsMap()
+ {
+ MockRepository mocks = new MockRepository();
+ IPersistentMap meta = mocks.StrictMock<IPersistentMap>();
+ mocks.ReplayAll();
+
+ PersistentHashMap m = PersistentHashMap.create(meta,1, "a", 2, "b");
+
+ Expect(m.count(), EqualTo(2));
+ Expect(m.valAt(1), EqualTo("a"));
+ Expect(m.valAt(2), EqualTo("b"));
+ Expect(m.containsKey(3), False);
+ Expect(m.meta(), SameAs(meta));
+ mocks.VerifyAll();
+ }
+
+ #endregion
+
+ #region Associative tests
+
+ #endregion
+
+ #region IPersistentMap tests
+
+ #endregion
+
+ #region IPersistentCollection tests
+
+ #endregion
+
+ #region Big tests
+
+ [Test]
+ public void DoSomeBigTests()
+ {
+ DoBigTest(100);
+ DoBigTest(1000);
+ DoBigTest(10000);
+ DoBigTest(100000);
+ }
+
+ public void DoBigTest(int numEntries)
+ {
+ System.Console.WriteLine("Testing {0} items.", numEntries);
+
+ Random rnd = new Random();
+ Dictionary<int, int> dict = new Dictionary<int, int>(numEntries);
+ for (int i = 0; i < numEntries; i++)
+ {
+ int r = rnd.Next();
+ dict[r] = r;
+ }
+ PersistentHashMap m = (PersistentHashMap) PersistentHashMap.create(dict);
+
+ Expect(m.count(),EqualTo(dict.Count));
+
+ foreach ( int key in dict.Keys )
+ {
+ Expect(m.containsKey(key));
+ Expect(m.valAt(key),EqualTo(key));
+ }
+
+ for ( ISeq s = m.seq(); s != null; s = s.rest() )
+ Expect(dict.ContainsKey((int)((IMapEntry)s.first()).key()));
+
+ }
+
+ #endregion
+
+ }
+
+ [TestFixture]
+ public class PersistentHashMap_IObj_Tests : IObjTests
+ {
+ MockRepository _mocks;
+
+ [SetUp]
+ public void Setup()
+ {
+ _mocks = new MockRepository();
+ IPersistentMap meta = _mocks.StrictMock<IPersistentMap>();
+ _mocks.ReplayAll();
+
+ PersistentHashMap m = PersistentHashMap.create(1, "a", 2, "b");
+
+
+ _objWithNullMeta = (IObj)m;
+ _obj = _objWithNullMeta.withMeta(meta);
+ _expectedType = typeof(PersistentHashMap);
+ }
+
+ [TearDown]
+ public void Teardown()
+ {
+ _mocks.VerifyAll();
+ }
+
+ }
+
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentHashSetTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentHashSetTests.cs new file mode 100644 index 00000000..9e71e14d --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentHashSetTests.cs @@ -0,0 +1,188 @@ +/**
+ * 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;
+using System.Collections;
+
+namespace Clojure.Tests.LibTests
+{
+ [TestFixture]
+ public class PersistentHashSetTests : AssertionHelper
+ {
+
+ #region C-tor tests
+
+ [Test]
+ public void CreateOnEmptyListReturnsEmptySet()
+ {
+ ArrayList a = new ArrayList();
+ IPersistentSet m = PersistentHashSet.create1(a);
+
+ Expect(m.count(), EqualTo(0));
+ }
+
+ [Test]
+ public void CreateOnListReturnsSet()
+ {
+ object[] items = new object[] { 1, "a" };
+ ArrayList a = new ArrayList(items);
+
+ IPersistentSet m = PersistentHashSet.create1(a);
+
+ Expect(m.count(), EqualTo(2));
+ Expect(m.contains(1));
+ Expect(m.contains("a"));
+ Expect(m.contains(3), False);
+ }
+
+ [Test]
+ public void CreateOnEmptyISeqReturnsEmptySet()
+ {
+ object[] items = new object[] { };
+ ArrayList a = new ArrayList(items);
+ ISeq s = PersistentList.create(a).seq();
+ IPersistentSet m = PersistentHashSet.create(s);
+
+ Expect(m.count(), EqualTo(0));
+ }
+
+ [Test]
+ public void CreateOnISeqReturnsSet()
+ {
+ object[] items = new object[] { 1, "a" };
+ ArrayList a = new ArrayList(items);
+ ISeq s = PersistentList.create(a).seq();
+ IPersistentSet m = PersistentHashSet.create(s);
+
+ Expect(m.count(), EqualTo(2));
+ Expect(m.contains(1));
+ Expect(m.contains("a"));
+ Expect(m.contains(3), False);
+ }
+
+ [Test]
+ public void CreateOnNoArgsReturnsEmptySet()
+ {
+ PersistentHashSet m = PersistentHashSet.create();
+
+ Expect(m.count(), EqualTo(0));
+ Expect(m.meta(), Null);
+ }
+
+ [Test]
+ public void CreateOnNoArgsReturnsSet()
+ {
+ PersistentHashSet m = PersistentHashSet.create(1, "a");
+
+ Expect(m.count(), EqualTo(2));
+ Expect(m.contains(1));
+ Expect(m.contains("a"));
+ Expect(m.contains(3), False);
+ Expect(m.meta(), Null);
+ }
+
+
+
+ #endregion
+
+ #region Associative tests
+
+ #endregion
+
+ #region IPersistentMap tests
+
+ #endregion
+
+ #region IPersistentCollection tests
+
+ #endregion
+
+ #region Big tests
+
+ [Test]
+ public void DoSomeBigTests()
+ {
+ DoBigTest(100);
+ DoBigTest(1000);
+ DoBigTest(10000);
+ DoBigTest(100000);
+ }
+
+ public void DoBigTest(int numEntries)
+ {
+ System.Console.WriteLine("Testing {0} items.", numEntries);
+
+ Random rnd = new Random();
+ Dictionary<object, object> dict = new Dictionary<object, object>(numEntries);
+ for (int i = 0; i < numEntries; i++)
+ {
+ int r = rnd.Next();
+ dict[r] = r;
+ }
+
+ object[] items = dict.Keys.ToArray();
+
+ PersistentHashSet m = (PersistentHashSet)PersistentHashSet.create(items);
+
+ Expect(m.count(), EqualTo(dict.Count));
+
+ foreach (int key in dict.Keys)
+ {
+ Expect(m.contains(key));
+ }
+
+ for (ISeq s = m.seq(); s != null; s = s.rest())
+ Expect(dict.ContainsKey((int)s.first()));
+
+ }
+
+ #endregion
+ }
+
+ [TestFixture]
+ public class PersistentHashSet_IObj_Tests : IObjTests
+ {
+ MockRepository _mocks;
+
+ [SetUp]
+ public void Setup()
+ {
+ _mocks = new MockRepository();
+ IPersistentMap meta = _mocks.StrictMock<IPersistentMap>();
+ _mocks.ReplayAll();
+
+ PersistentHashSet m = PersistentHashSet.create(1, "a", 2, "b");
+
+
+ _objWithNullMeta = (IObj)m;
+ _obj = _objWithNullMeta.withMeta(meta);
+ _expectedType = typeof(PersistentHashSet);
+ }
+
+ [TearDown]
+ public void Teardown()
+ {
+ _mocks.VerifyAll();
+ }
+
+ }
+
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentListTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentListTests.cs new file mode 100644 index 00000000..dd4539d4 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentListTests.cs @@ -0,0 +1,245 @@ +/**
+ * 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 PersistentListTests : AssertionHelper
+ {
+ #region C-tor tests
+
+ [Test]
+ public void OneArgCtorConstructsListOfOneElement()
+ {
+ PersistentList p = new PersistentList("abc");
+
+ Expect(p.first(), EqualTo("abc"));
+ Expect(p.rest(), Null);
+ Expect(p.count(), EqualTo(1));
+ }
+
+ [Test]
+ public void ListCtorConstructsListOfSeveralElements()
+ {
+ object[] items = new object[] { 1, "abc", 2, "def" };
+ IPersistentList p = PersistentList.create(items);
+
+ Expect(p.count(), EqualTo(4));
+
+ ISeq s = p.seq();
+ Expect(s.first(), EqualTo(1));
+ Expect(s.rest().first(), EqualTo("abc"));
+ Expect(s.rest().rest().first(), EqualTo(2));
+ Expect(s.rest().rest().rest().first(), EqualTo("def"));
+ Expect(s.rest().rest().rest().rest(), Null);
+ }
+
+
+ #endregion
+
+ #region IPersistentStack tests
+
+ [Test]
+ public void PeekYieldsFirstElementAndListUnchanged()
+ {
+ PersistentList p = (PersistentList)PersistentList.create(new object[] { "abc", 1, "def" });
+
+ Expect(p.peek(), EqualTo("abc"));
+ Expect(p.count(), EqualTo(3));
+ }
+
+ [Test]
+ public void PopLosesfirstElement()
+ {
+ PersistentList p = (PersistentList)PersistentList.create(new object[]{"abc", 1, "def"});
+ PersistentList p2 = (PersistentList)p.pop();
+ Expect(p2.count(), EqualTo(2));
+ Expect(p2.peek(), EqualTo(1));
+ }
+
+ [Test]
+ public void PopOnSingletonListYieldsEmptyList()
+ {
+ PersistentList p = new PersistentList("abc");
+ IPersistentStack s = p.pop();
+ Expect(s.count(), EqualTo(0));
+ }
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException))]
+ public void DoublePopOnSingletonListYieldsException()
+ {
+ PersistentList p = new PersistentList("abc");
+ IPersistentStack s = p.pop().pop();
+ }
+
+ #endregion
+
+ #region IPersistentCollection tests
+
+ [Test]
+ public void EmptyHasNoElements()
+ {
+ PersistentList p = new PersistentList("abc");
+ IPersistentCollection c = p.empty();
+
+ Expect(c.count(), EqualTo(0));
+ }
+
+ [Test]
+ public void EmptyPreservesMeta()
+ {
+ MockRepository mocks = new MockRepository();
+ IPersistentMap meta = mocks.StrictMock<IPersistentMap>();
+ mocks.ReplayAll();
+
+ IPersistentCollection p = (IPersistentCollection)new PersistentList("abc").withMeta(meta);
+ IObj obj = (IObj) p.empty();
+
+ Expect(obj.meta(), SameAs(meta));
+ mocks.VerifyAll();
+ }
+
+ #endregion
+
+ #region IReduce tests
+
+ [Test]
+ public void ReduceWithNoStartIterates()
+ {
+ MockRepository mocks = new MockRepository();
+ IFn fn = mocks.StrictMock<IFn>();
+ RMExpect.Call(fn.invoke(1, 2)).Return(5);
+ RMExpect.Call(fn.invoke(5, 3)).Return(7);
+ mocks.ReplayAll();
+
+ PersistentList p = (PersistentList)PersistentList.create(new object[] { 1, 2, 3 });
+ object ret = p.reduce(fn);
+
+ Expect(ret, EqualTo(7));
+
+ mocks.VerifyAll();
+ }
+
+ [Test]
+ public void ReduceWithStartIterates()
+ {
+ MockRepository mocks = new MockRepository();
+ IFn fn = mocks.StrictMock<IFn>();
+ 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();
+
+ PersistentList p = (PersistentList)PersistentList.create(new object[] { 1, 2, 3 });
+ object ret = p.reduce(fn, 20);
+
+ Expect(ret, EqualTo(7));
+
+ mocks.VerifyAll();
+ }
+
+
+ #endregion
+
+ }
+
+ [TestFixture]
+ public class PersistentList_ISeq_Tests : ISeqTestHelper
+ {
+ PersistentList _pl;
+ PersistentList _plWithMeta;
+ object[] _values;
+
+
+ [SetUp]
+ public void Setup()
+ {
+ PersistentList p1 = new PersistentList("abc");
+ PersistentList p2 = (PersistentList)p1.cons("def");
+ _pl = (PersistentList)p2.cons(7);
+ _values = new object[] { 7, "def", "abc" };
+ _plWithMeta = (PersistentList)_pl.withMeta(PersistentHashMap.create("a", 1));
+ }
+
+ [Test]
+ public void ISeq_has_correct_valuess()
+ {
+ VerifyISeqContents(_pl, _values);
+ }
+
+ [Test]
+ public void ISeq_with_meta_has_correct_valuess()
+ {
+ VerifyISeqContents(_plWithMeta, _values);
+ }
+
+ [Test]
+ public void Rest_has_correct_type()
+ {
+ VerifyISeqRestTypes(_pl, typeof(PersistentList));
+ }
+
+ [Test]
+ public void Cons_works()
+ {
+ VerifyISeqCons(_pl, "pqr", _values);
+ }
+
+ [Test]
+ public void ConsPreservesMeta()
+ {
+ PersistentList p2 = (PersistentList)_plWithMeta.cons("def");
+ Expect(p2.meta(), SameAs(_plWithMeta.meta()));
+ }
+ }
+
+
+ [TestFixture]
+ public class PersistentList_IObj_Tests : IObjTests
+ {
+ MockRepository _mocks;
+
+ [SetUp]
+ public void Setup()
+ {
+ _mocks = new MockRepository();
+ IPersistentMap meta = _mocks.StrictMock<IPersistentMap>();
+ _mocks.ReplayAll();
+
+ PersistentList p1 = (PersistentList)PersistentList.create(new object[] { "abc", "def" });
+
+
+ _objWithNullMeta = (IObj)p1;
+ _obj = _objWithNullMeta.withMeta(meta);
+ _expectedType = typeof(PersistentList);
+ }
+
+ [TearDown]
+ public void Teardown()
+ {
+ _mocks.VerifyAll();
+ }
+
+ }
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentQueueTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentQueueTests.cs new file mode 100644 index 00000000..3281ac44 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentQueueTests.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 PersistentQueue
+ class PersistentQueueTests
+ {
+ }
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentStructMapTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentStructMapTests.cs new file mode 100644 index 00000000..c2db638a --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentStructMapTests.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 PersistentStructMap
+ class PersistentStructMapTests
+ {
+ }
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentTreeMapTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentTreeMapTests.cs new file mode 100644 index 00000000..aebfd478 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentTreeMapTests.cs @@ -0,0 +1,233 @@ +/**
+ * 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;
+using System.Collections;
+
+
+namespace Clojure.Tests.LibTests
+{
+ [TestFixture]
+ public class PersistentTreeMapTests : AssertionHelper
+ {
+ #region C-tor tests
+
+ [Test]
+ public void CreateOnEmptyDictionaryReturnsEmptyMap()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ IPersistentMap m = PersistentTreeMap.create(d);
+
+ Expect(m.count(), EqualTo(0));
+ }
+
+ [Test]
+ public void CreateOnDictionaryReturnsMap()
+ {
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ IPersistentMap m = PersistentTreeMap.create(d);
+
+ Expect(m.count(), EqualTo(2));
+ Expect(m.valAt(1), EqualTo("a"));
+ Expect(m.valAt(2), EqualTo("b"));
+ Expect(m.containsKey(3), False);
+ }
+
+ //[Test]
+ //public void CreateOnEmptyListReturnsEmptyMap()
+ //{
+ // ArrayList a = new ArrayList();
+ // IPersistentMap m = PersistentTreeMap.create(a);
+
+ // Expect(m.count(), EqualTo(0));
+ //}
+
+ //[Test]
+ //public void CreateOnListReturnsMap()
+ //{
+ // object[] items = new object[] { 1, "a", 2, "b" };
+ // ArrayList a = new ArrayList(items);
+
+ // IPersistentMap m = PersistentTreeMap.create(a);
+
+ // Expect(m.count(), EqualTo(2));
+ // Expect(m.valAt(1), EqualTo("a"));
+ // Expect(m.valAt(2), EqualTo("b"));
+ // Expect(m.containsKey(3), False);
+ //}
+
+ [Test]
+ public void CreateOnEmptyISeqReturnsEmptyMap()
+ {
+ object[] items = new object[] { };
+ ArrayList a = new ArrayList(items);
+ ISeq s = PersistentList.create(a).seq();
+ IPersistentMap m = PersistentTreeMap.create(s);
+
+ Expect(m.count(), EqualTo(0));
+ }
+
+ [Test]
+ public void CreateOnISeqReturnsMap()
+ {
+ object[] items = new object[] { 1, "a", 2, "b" };
+ ArrayList a = new ArrayList(items);
+ ISeq s = PersistentList.create(a).seq();
+ IPersistentMap m = PersistentTreeMap.create(s);
+
+ Expect(m.count(), EqualTo(2));
+ Expect(m.valAt(1), EqualTo("a"));
+ Expect(m.valAt(2), EqualTo("b"));
+ Expect(m.containsKey(3), False);
+ }
+
+ [Test]
+ public void DefaultCtorReturnsEmptyMap()
+ {
+ PersistentTreeMap m = new PersistentTreeMap();
+
+ Expect(m.count(), EqualTo(0));
+ Expect(m.meta(), Null);
+ }
+
+
+ //[Test]
+ //public void CreateOnMetaNoArgsReturnsEmptyMap()
+ //{
+ // MockRepository mocks = new MockRepository();
+ // IPersistentMap meta = mocks.StrictMock<IPersistentMap>();
+ // mocks.ReplayAll();
+
+ // PersistentTreeMap m = PersistentTreeMap.create(meta);
+
+ // Expect(m.count(), EqualTo(0));
+ // Expect(m.meta(), SameAs(meta));
+ // mocks.VerifyAll();
+ //}
+
+ //[Test]
+ //public void CreateOnMetaNoArgsReturnsMap()
+ //{
+ // MockRepository mocks = new MockRepository();
+ // IPersistentMap meta = mocks.StrictMock<IPersistentMap>();
+ // mocks.ReplayAll();
+
+ // PersistentTreeMap m = PersistentTreeMap.create(meta, 1, "a", 2, "b");
+
+ // Expect(m.count(), EqualTo(2));
+ // Expect(m.valAt(1), EqualTo("a"));
+ // Expect(m.valAt(2), EqualTo("b"));
+ // Expect(m.containsKey(3), False);
+ // Expect(m.meta(), SameAs(meta));
+ // mocks.VerifyAll();
+ //}
+
+ #endregion
+
+ #region Associative tests
+
+ #endregion
+
+ #region IPersistentMap tests
+
+ #endregion
+
+ #region IPersistentCollection tests
+
+ #endregion
+
+ #region Big tests
+
+ [Test]
+ public void DoSomeBigTests()
+ {
+ DoBigTest(100);
+ DoBigTest(1000);
+ DoBigTest(10000);
+ DoBigTest(100000);
+ }
+
+ public void DoBigTest(int numEntries)
+ {
+ System.Console.WriteLine("Testing {0} items.", numEntries);
+
+ Random rnd = new Random();
+ Dictionary<int, int> dict = new Dictionary<int, int>(numEntries);
+ for (int i = 0; i < numEntries; i++)
+ {
+ int r = rnd.Next();
+ dict[r] = r;
+ }
+ PersistentTreeMap m = (PersistentTreeMap)PersistentTreeMap.create(dict);
+
+ Expect(m.count(), EqualTo(dict.Count));
+
+ foreach (int key in dict.Keys)
+ {
+ Expect(m.containsKey(key));
+ Expect(m.valAt(key), EqualTo(key));
+ }
+
+ for (ISeq s = m.seq(); s != null; s = s.rest())
+ Expect(dict.ContainsKey((int)((IMapEntry)s.first()).key()));
+
+ }
+
+ #endregion
+ }
+
+
+ [TestFixture]
+ public class PersistentTreeMap_IObj_Tests : IObjTests
+ {
+ MockRepository _mocks;
+
+ [SetUp]
+ public void Setup()
+ {
+ _mocks = new MockRepository();
+ IPersistentMap meta = _mocks.StrictMock<IPersistentMap>();
+ _mocks.ReplayAll();
+
+ Dictionary<int, string> d = new Dictionary<int, string>();
+ d[1] = "a";
+ d[2] = "b";
+
+ PersistentTreeMap m = (PersistentTreeMap)PersistentTreeMap.create(d);
+
+
+ _objWithNullMeta = (IObj)m;
+ _obj = _objWithNullMeta.withMeta(meta);
+ _expectedType = typeof(PersistentTreeMap);
+ }
+
+ [TearDown]
+ public void Teardown()
+ {
+ _mocks.VerifyAll();
+ }
+
+ }
+
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentTreeSetTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentTreeSetTests.cs new file mode 100644 index 00000000..77b9a4d4 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentTreeSetTests.cs @@ -0,0 +1,58 @@ +/**
+ * 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 PersistentTreeSet
+ class PersistentTreeSetTests
+ {
+ }
+
+ [TestFixture]
+ public class PersistentTreeSet_IObj_Tests : IObjTests
+ {
+ MockRepository _mocks;
+
+ [SetUp]
+ public void Setup()
+ {
+ _mocks = new MockRepository();
+ IPersistentMap meta = _mocks.StrictMock<IPersistentMap>();
+ _mocks.ReplayAll();
+
+ PersistentTreeSet m = PersistentTreeSet.create("a", "b");
+
+
+ _objWithNullMeta = (IObj)m;
+ _obj = _objWithNullMeta.withMeta(meta);
+ _expectedType = typeof(PersistentTreeSet);
+ }
+
+ [TearDown]
+ public void Teardown()
+ {
+ _mocks.VerifyAll();
+ }
+
+ }
+
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentVectorTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentVectorTests.cs new file mode 100644 index 00000000..bde46e9f --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/PersistentVectorTests.cs @@ -0,0 +1,330 @@ +/**
+ * 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 PersistentVectorTests : AssertionHelper
+ {
+
+ #region C-tor tests
+
+ [Test]
+ public void CreateOnISeqReturnsCorrectCount()
+ {
+ Range r = new Range(2,5);
+ PersistentVector v = PersistentVector.create(r);
+
+ Expect(v.count(),EqualTo(r.count()));
+ }
+
+ [Test]
+ public void CreateOnISeqHasItems()
+ {
+ Range r = new Range(2, 5);
+ PersistentVector v = PersistentVector.create(r);
+
+ Expect(v.nth(0), EqualTo(2));
+ Expect(v.nth(1), EqualTo(3));
+ Expect(v.nth(2), EqualTo(4));
+ }
+
+ [Test]
+ public void CreateOnISeqWithManyItemsWorks()
+ {
+ // Want to bust out of the first tail, so need to insert more than 32 elements.
+ Range r = new Range(2, 1000);
+ PersistentVector v = PersistentVector.create(r);
+
+ Expect(v.count(), EqualTo(r.count()));
+ for (int i = 0; i < v.count(); ++i)
+ Expect(v.nth(i), EqualTo(i + 2));
+ }
+
+ [Test]
+ public void CreateOnISeqWithManyManyItemsWorks()
+ {
+ // Want to bust out of the first tail, so need to insert more than 32 elements.
+ // Let's get out of the second level, too.
+
+ Range r = new Range(2, 100000);
+ PersistentVector v = PersistentVector.create(r);
+
+ Expect(v.count(), EqualTo(r.count()));
+ for (int i = 0; i < v.count(); ++i)
+ Expect(v.nth(i), EqualTo(i + 2));
+ }
+
+ [Test]
+ public void CreateOnMultipleItemsWorks()
+ {
+ PersistentVector v = PersistentVector.create(2,3,4);
+
+ Expect(v.count(),EqualTo(3));
+ Expect(v.nth(0), EqualTo(2));
+ Expect(v.nth(1), EqualTo(3));
+ Expect(v.nth(2), EqualTo(4));
+ }
+
+ #endregion
+
+ #region IPersistentVector tests
+
+
+ // nth - tested in c-tor tests
+
+
+ [Test]
+ public void CountYieldsLength()
+ {
+ PersistentVector v = PersistentVector.create(1, 2, 3);
+
+ Expect(v.length(), EqualTo(3));
+ }
+
+ [Test]
+ [ExpectedException(typeof(IndexOutOfRangeException))]
+ public void NthOutOfRangeLowFails()
+ {
+ PersistentVector v = PersistentVector.create(1, 2, 3);
+ object obj = v.nth(-4);
+ }
+
+ [Test]
+ [ExpectedException(typeof(IndexOutOfRangeException))]
+ public void NthOutOfRangeHighFails()
+ {
+ PersistentVector v = PersistentVector.create(1, 2, 3);
+ object obj = v.nth(4);
+ }
+
+ [Test]
+ public void AssocNReplacesInRangeForSmall()
+ {
+ Range r = new Range(2, 5);
+ PersistentVector v1 = PersistentVector.create(r);
+ IPersistentVector v2 = v1.assocN(1,10);
+
+ Expect(v1.nth(0), EqualTo(2));
+ Expect(v1.nth(1), EqualTo(3));
+ Expect(v1.nth(2), EqualTo(4));
+ Expect(v1.count(), EqualTo(3));
+ Expect(v2.nth(0), EqualTo(2));
+ Expect(v2.nth(1), EqualTo(10));
+ Expect(v2.nth(2), EqualTo(4));
+ Expect(v2.count(), EqualTo(3));
+ }
+
+ [Test]
+ public void AssocNAddsAtEndForSmall()
+ {
+ Range r = new Range(2, 5);
+ PersistentVector v1 = PersistentVector.create(r);
+ IPersistentVector v2 = v1.assocN(3, 10);
+
+ Expect(v1.nth(0), EqualTo(2));
+ Expect(v1.nth(1), EqualTo(3));
+ Expect(v1.nth(2), EqualTo(4));
+ Expect(v1.count(), EqualTo(3));
+ Expect(v2.nth(0), EqualTo(2));
+ Expect(v2.nth(1), EqualTo(3));
+ Expect(v2.nth(2), EqualTo(4));
+ Expect(v2.nth(3), EqualTo(10));
+ Expect(v2.count(), EqualTo(4));
+ }
+
+ [Test]
+ [ExpectedException(typeof(IndexOutOfRangeException))]
+ public void AssocNOutOfRangeLowThrowsException()
+ {
+ Range r = new Range(2, 5);
+ PersistentVector v1 = PersistentVector.create(r);
+ IPersistentVector v2 = v1.assocN(-4, 10);
+ }
+
+ [Test]
+ [ExpectedException(typeof(IndexOutOfRangeException))]
+ public void AssocNOutOfRangeHighThrowsException()
+ {
+ Range r = new Range(2, 5);
+ PersistentVector v1 = PersistentVector.create(r);
+ IPersistentVector v2 = v1.assocN(4, 10);
+ }
+
+ [Test]
+ public void AssocNAddsAtEndForEmpty()
+ {
+ PersistentVector v1 = PersistentVector.create();
+ IPersistentVector v2 = v1.assocN(0, "abc");
+
+ Expect(v1.count(), EqualTo(0));
+ Expect(v2.count(), EqualTo(1));
+ Expect(v2.nth(0), EqualTo("abc"));
+ }
+
+ [Test]
+ public void AssocNChangesForBig()
+ {
+ Range r = new Range(2, 100000);
+ PersistentVector v1 = PersistentVector.create(r);
+ IPersistentVector v2 = v1;
+
+ for (int i = 0; i < 110000; i++)
+ v2 = v2.assocN(i, i + 20);
+
+ for ( int i=0; i<v1.count(); ++i )
+ Expect(v1.nth(i),EqualTo(i+2));
+
+ for (int i = 0; i < v2.count(); ++i)
+ Expect(v2.nth(i), EqualTo(i + 20));
+ }
+
+ [Test]
+ public void ConsWorks()
+ {
+ PersistentVector v1 = PersistentVector.create(2,3,4);
+ IPersistentVector v2 = v1;
+
+ for (int i = 3; i < 100000; i++)
+ v2 = v2.cons(i+2);
+
+ Expect(v1.count(), EqualTo(3));
+ Expect(v2.count(), EqualTo(100000));
+
+ for (int i = 0; i < v2.count(); ++i)
+ Expect(v2.nth(i), EqualTo(i + 2));
+ }
+
+ #endregion
+
+ #region IPersistentCollection tests
+
+ [Test]
+ public void EmptyReturnsEmptyCollection()
+ {
+ PersistentVector v = PersistentVector.create(1, 2, 3);
+ IPersistentCollection e = v.empty();
+
+ Expect(e.count(), EqualTo(0));
+ }
+
+ [Test]
+ public void EmptyCopiesMeta()
+ {
+ MockRepository mocks = new MockRepository();
+ IPersistentMap meta = mocks.StrictMock<IPersistentMap>();
+ mocks.ReplayAll();
+
+ PersistentVector v1 = PersistentVector.create(1, 2, 3);
+ IPersistentCollection e1 = v1.empty();
+
+ PersistentVector v2 = (PersistentVector) v1.withMeta(meta);
+ IPersistentCollection e2 = v2.empty();
+
+ Expect(((IObj)e1).meta(), Null);
+ Expect(((IObj)e2).meta(), SameAs(meta));
+
+ mocks.VerifyAll();
+ }
+
+
+ #endregion
+
+ #region IPersistentStack tests
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException))]
+ public void PopOnEmptyThrowsException()
+ {
+ PersistentVector v = PersistentVector.create();
+ IPersistentStack s = v.pop();
+ }
+
+ [Test]
+ public void PopOnSizeOneReturnsEmpty()
+ {
+ PersistentVector v = PersistentVector.create(1);
+ IPersistentStack s = v.pop();
+
+ Expect(s.count(), EqualTo(0));
+ }
+
+ [Test]
+ public void PopOnSmallReturnsOneLess()
+ {
+ Range r = new Range(2, 20);
+ PersistentVector v = PersistentVector.create(r);
+ IPersistentStack s = v.pop();
+
+ Expect(v.count(),EqualTo(r.count()));
+ Expect(s.count(),EqualTo(v.count()-1));
+ }
+
+ [Test]
+ public void PopOnBigWorks()
+ {
+ Range r = new Range(0, 100000);
+ PersistentVector v = PersistentVector.create(r);
+ IPersistentStack s = v;
+ for (int i = 16; i < 100000; i++)
+ s = s.pop();
+
+ Expect(v.count(), EqualTo(r.count()));
+ Expect(s.count(), EqualTo(16));
+ }
+
+
+ #endregion
+
+ #region IFn tests
+
+ #endregion
+ }
+
+ [TestFixture]
+ public class PersistentVector_IObj_Tests : IObjTests
+ {
+ MockRepository _mocks;
+
+ [SetUp]
+ public void Setup()
+ {
+ _mocks = new MockRepository();
+ IPersistentMap meta = _mocks.StrictMock<IPersistentMap>();
+ _mocks.ReplayAll();
+
+ PersistentVector v = PersistentVector.create(2, 3, 4);
+
+ _objWithNullMeta = (IObj)v;
+ _obj = _objWithNullMeta.withMeta(meta);
+ _expectedType = typeof(PersistentVector);
+ }
+
+ [TearDown]
+ public void Teardown()
+ {
+ _mocks.VerifyAll();
+ }
+
+ }
+
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/RangeTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/RangeTests.cs new file mode 100644 index 00000000..7948a681 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/RangeTests.cs @@ -0,0 +1,182 @@ +/**
+ * 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 RangeTests : AssertionHelper
+ {
+ #region C-tor tests
+
+ [Test]
+ public void Basic_ctor_has_no_meta()
+ {
+ Range r = new Range(2, 5);
+ Expect(r.meta(), Null);
+ }
+
+ [Test]
+ public void Meta_ctor_has_meta()
+ {
+ MockRepository mocks = new MockRepository();
+ IPersistentMap meta = mocks.StrictMock<IPersistentMap>();
+ mocks.ReplayAll();
+
+ Range r = new Range(meta, 2, 5);
+
+ Expect(r.meta(), EqualTo(meta));
+
+ mocks.VerifyAll();
+ }
+
+ #endregion
+
+ #region IPersistentCollection tests
+
+ [Test]
+ public void Range_has_correct_count()
+ {
+ Range r = new Range(2, 20);
+
+ Expect(r.count(), EqualTo(18));
+ }
+
+
+ #endregion
+
+ #region IReduce tests
+
+ [Test]
+ public void ReduceWithNoStartIterates()
+ {
+ MockRepository mocks = new MockRepository();
+ IFn fn = mocks.StrictMock<IFn>();
+ RMExpect.Call(fn.invoke(2, 3)).Return(5);
+ RMExpect.Call(fn.invoke(5, 4)).Return(7);
+ mocks.ReplayAll();
+
+ Range r = new Range(2, 5);
+ object ret = r.reduce(fn);
+
+ Expect(ret, EqualTo(7));
+
+ mocks.VerifyAll();
+ }
+
+ [Test]
+ public void ReduceWithStartIterates()
+ {
+ MockRepository mocks = new MockRepository();
+ IFn fn = mocks.StrictMock<IFn>();
+ 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();
+
+ Range r = new Range(2, 5);
+ object ret = r.reduce(fn, 20);
+
+ Expect(ret, EqualTo(7));
+
+ mocks.VerifyAll();
+ }
+
+ #endregion
+
+ // TODO: test stream capability of Range
+ }
+
+ [TestFixture]
+ public class Range_ISeq_Tests : ISeqTestHelper
+ {
+ Range _r;
+ Range _rWithMeta;
+ object[] _values;
+
+ [SetUp]
+ public void Setup()
+ {
+ IPersistentMap meta = PersistentHashMap.create("a", 1, "b", 2);
+
+ _r = new Range(2, 5);
+ _rWithMeta = new Range(meta, 2, 5);
+ _values = new object[] { 2, 3, 4 };
+ }
+
+ [Test]
+ public void Range_has_correct_values()
+ {
+ VerifyISeqContents(_r, _values);
+ }
+
+ [Test]
+ public void Range_with_meta_has_correct_values()
+ {
+ VerifyISeqContents(_rWithMeta, _values);
+ }
+
+ [Test]
+ public void Rest_preserves_meta()
+ {
+ VerifyISeqRestMaintainsMeta(_rWithMeta);
+ }
+
+ [Test]
+ public void Rest_preserves_type()
+ {
+ VerifyISeqRestTypes(_r, typeof(Range));
+ }
+
+ [Test]
+ public void Cons_works()
+ {
+ VerifyISeqCons(_r, 12, _values);
+ }
+ }
+
+ [TestFixture]
+ public class Range_IObj_Tests : IObjTests
+ {
+ MockRepository _mocks;
+
+ [SetUp]
+ public void Setup()
+ {
+ _mocks = new MockRepository();
+ IPersistentMap meta = _mocks.StrictMock<IPersistentMap>();
+ _mocks.ReplayAll();
+
+ Range r = new Range(2, 5);
+
+ _objWithNullMeta = (IObj)r;
+ _obj = _objWithNullMeta.withMeta(meta);
+ _expectedType = typeof(Range);
+ }
+
+ [TearDown]
+ public void Teardown()
+ {
+ _mocks.VerifyAll();
+ }
+
+ }
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/RefTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/RefTests.cs new file mode 100644 index 00000000..efc67335 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/RefTests.cs @@ -0,0 +1,23 @@ +/**
+ * 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 Ref
+
+ class RefTests
+ {
+ }
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/RestFnImplTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/RestFnImplTests.cs new file mode 100644 index 00000000..3d9870e4 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/RestFnImplTests.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 RestFnImpl tests
+ class RestFnImplTests
+ {
+ }
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/RestFnTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/RestFnTests.cs new file mode 100644 index 00000000..90ef2168 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/RestFnTests.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 RestFn tests
+ class RestFnTests
+ {
+ }
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/StreamSeqTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/StreamSeqTests.cs new file mode 100644 index 00000000..7f4c4f61 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/StreamSeqTests.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 StreamSeq
+ class StreamSeqTests
+ {
+ }
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/StringSeqTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/StringSeqTests.cs new file mode 100644 index 00000000..b17280b2 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/StringSeqTests.cs @@ -0,0 +1,163 @@ +/**
+ * 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 StringSeqTests : AssertionHelper
+ {
+
+ #region C-tor tests
+
+ [Test]
+ public void Create_on_empty_string_yields_null()
+ {
+ StringSeq s = StringSeq.create(String.Empty);
+
+ Expect(s, Null);
+ }
+
+ [Test]
+ public void Create_on_nonempty_string_yields_a_StringSeq()
+ {
+ StringSeq s = StringSeq.create("abcde");
+
+ Expect(s, Not.Null);
+ }
+
+ #endregion
+
+ #region IPersistentCollection tests
+
+ [Test]
+ public void Count_is_string_length()
+ {
+ StringSeq s = StringSeq.create("abcde");
+
+ Expect(s.count(),EqualTo(5));
+ }
+
+ #endregion
+
+ #region IndexedSeq tests
+
+ [Test]
+ public void Initial_index_is_zero()
+ {
+ StringSeq s = StringSeq.create("abc");
+
+ Expect(s.index(), EqualTo(0));
+ }
+
+ [Test]
+ public void Index_of_rest_is_one()
+ {
+ StringSeq s = StringSeq.create("abc");
+ IndexedSeq i = (IndexedSeq)s.rest();
+
+ Expect(i.index(), EqualTo(1));
+ }
+
+ #endregion
+
+ }
+
+ [TestFixture]
+ public class StringSeq_ISeq_Tests : ISeqTestHelper
+ {
+ StringSeq _s;
+ StringSeq _sWithMeta;
+ object[] _values;
+
+ [SetUp]
+ public void Setup()
+ {
+ IPersistentMap meta = PersistentHashMap.create("a", 1, "b", 2);
+
+ _s = StringSeq.create("abcde");
+ _sWithMeta = (StringSeq)((IObj)StringSeq.create("abcde")).withMeta(meta);
+ _values = new object[] { 'a', 'b', 'c', 'd', 'e' };
+ }
+
+ [Test]
+ public void StringSeq_has_correct_ISeq_values()
+ {
+ VerifyISeqContents(_s, _values);
+ }
+
+ [Test]
+ public void StringSeq_with_meta_has_correct_ISeq_values()
+ {
+ VerifyISeqContents(_sWithMeta, _values);
+ }
+
+ [Test]
+ public void StringSeq_ISeq_rest_preserves_meta()
+ {
+ VerifyISeqRestMaintainsMeta(_sWithMeta);
+ }
+
+ [Test]
+ public void StringSeq_ISeq_rest_preserves_type()
+ {
+ VerifyISeqRestTypes(_s,typeof(StringSeq));
+ }
+
+ [Test]
+ public void StringSeq_ISeq_cons_works()
+ {
+ VerifyISeqCons(_s, 12, _values);
+ }
+
+ }
+
+ [TestFixture]
+ public class StringSeq_IObj_Tests : IObjTests
+ {
+ MockRepository _mocks;
+
+ [SetUp]
+ public void Setup()
+ {
+ _mocks = new MockRepository();
+ IPersistentMap meta = _mocks.StrictMock<IPersistentMap>();
+ _mocks.ReplayAll();
+
+ StringSeq s = StringSeq.create("abcde");
+
+
+ _objWithNullMeta = (IObj)s;
+ _obj = _objWithNullMeta.withMeta(meta);
+ _expectedType = typeof(StringSeq);
+ }
+
+ [TearDown]
+ public void Teardown()
+ {
+ _mocks.VerifyAll();
+ }
+
+ }
+
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/SymbolTests.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/SymbolTests.cs new file mode 100644 index 00000000..3cc32821 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/SymbolTests.cs @@ -0,0 +1,326 @@ +/**
+ * 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;
+using System.Collections;
+
+
+
+namespace Clojure.Tests.LibTests
+{
+ [TestFixture]
+ public class SymbolTests : AssertionHelper
+ {
+
+ #region c-tor tests
+
+ [Test]
+ public void Intern2CreatesSymbolWithNoNS()
+ {
+ Symbol sym = Symbol.intern(null, "abc");
+
+ Expect(sym.Name, EqualTo("abc"));
+ Expect(sym.Namespace, Null);
+ Expect(sym.meta(), Null);
+ }
+
+ [Test]
+ public void Intern2CreatesSymbolWithNS()
+ {
+ Symbol sym = Symbol.intern("def", "abc");
+
+ Expect(sym.Name, EqualTo("abc"));
+ Expect(sym.Namespace, EqualTo("def"));
+ Expect(sym.meta(), Null);
+ }
+
+ [Test]
+ public void Intern2InternsStrings()
+ {
+ String symname = new StringBuilder().Append("ab").Append("c").ToString();
+ String nsname = new StringBuilder().Append("ab").Append("c").ToString();
+
+ Symbol sym1 = Symbol.intern(nsname,symname);
+ Symbol sym2 = Symbol.intern(nsname,symname);
+
+ Expect(String.IsInterned(sym1.Name),Not.Null);
+ Expect(String.IsInterned(sym1.Namespace), Not.Null);
+ Expect(Object.ReferenceEquals(sym1.Name, sym2.Name));
+ Expect(Object.ReferenceEquals(sym1.Namespace, sym2.Namespace));
+ Expect(object.ReferenceEquals(sym1.Name, symname), False);
+ }
+
+
+
+ [Test]
+ public void Intern1CreatesSymbolWithNoNS()
+ {
+ Symbol sym = Symbol.intern("abc");
+
+ Expect(sym.Name, EqualTo("abc"));
+ Expect(sym.Namespace, Null);
+ Expect(sym.meta(), Null);
+ }
+
+ [Test]
+ public void Intern1CreatesSymbolWithNS()
+ {
+ Symbol sym = Symbol.intern("def/abc");
+
+ Expect(sym.Name, EqualTo("abc"));
+ Expect(sym.Namespace, EqualTo("def"));
+ Expect(sym.meta(), Null);
+ }
+
+
+ [Test]
+ public void Intern1CreatesSymbolWithNSFromLastSlash()
+ {
+ Symbol sym = Symbol.intern("ghi/def/abc");
+
+ Expect(sym.Name, EqualTo("abc"));
+ Expect(sym.Namespace, EqualTo("ghi/def"));
+ Expect(sym.meta(), Null);
+ }
+
+ [Test]
+ public void Intern1InternsStrings()
+ {
+ String name = new StringBuilder().Append("def/").Append("abc").ToString();
+
+ Symbol sym1 = Symbol.intern(name);
+ Symbol sym2 = Symbol.intern(name);
+
+ Expect(String.IsInterned(sym1.Name), Not.Null);
+ Expect(String.IsInterned(sym1.Namespace), Not.Null);
+ Expect(Object.ReferenceEquals(sym1.Name, sym2.Name));
+ Expect(Object.ReferenceEquals(sym1.Namespace, sym2.Namespace));
+ }
+
+ #endregion
+
+ #region Object overrides
+
+ [Test]
+ public void SymToStringWithNoNSIsJustName()
+ {
+ Symbol sym = Symbol.intern("abc");
+ Expect(sym.ToString(), EqualTo("abc"));
+ }
+
+ [Test]
+ public void SymToStringWithNsConcatenatesNames()
+ {
+ Symbol sym = Symbol.intern("def", "abc");
+ Expect(sym.ToString(), EqualTo("def/abc"));
+ }
+
+ [Test]
+ public void EqualsOnIdentityIsTrue()
+ {
+ Symbol sym = Symbol.intern("abc");
+ Expect(sym.Equals(sym));
+ }
+
+ [Test]
+ public void EqualsOnNonSymbolIsFalse()
+ {
+ Symbol sym = Symbol.intern("abc");
+ Expect(sym.Equals("abc"), False);
+ }
+
+ [Test]
+ public void EqualsOnDissimilarSymbolIsFalse()
+ {
+ Symbol sym1 = Symbol.intern("abc");
+ Symbol sym2 = Symbol.intern("ab");
+ Symbol sym3 = Symbol.intern("def", "abc");
+ Symbol sym4 = Symbol.intern("de","abc");
+
+ Expect(sym1.Equals(sym2), False);
+ Expect(sym1.Equals(sym3), False);
+ Expect(sym3.Equals(sym4), False);
+ }
+
+ [Test]
+ public void EqualsOnSimilarSymbolIsTrue()
+ {
+
+ Symbol sym1 = Symbol.intern("abc");
+ Symbol sym2 = Symbol.intern("abc");
+ Symbol sym3 = Symbol.intern("def", "abc");
+ Symbol sym4 = Symbol.intern("def", "abc");
+
+ Expect(sym1.Equals(sym2));
+ Expect(sym3.Equals(sym4));
+ }
+
+ [Test]
+ public void HashCodeDependsOnNames()
+ {
+ Symbol sym1 = Symbol.intern("abc");
+ Symbol sym2 = Symbol.intern("abc");
+ Symbol sym3 = Symbol.intern("def", "abc");
+ Symbol sym4 = Symbol.intern("def", "abc");
+ Symbol sym5 = Symbol.intern("ab");
+ Symbol sym6 = Symbol.intern("de", "abc");
+
+ Expect(sym1.GetHashCode(), EqualTo(sym2.GetHashCode()));
+ Expect(sym3.GetHashCode(), EqualTo(sym4.GetHashCode()));
+ Expect(sym1.GetHashCode(), Not.EqualTo(sym3.GetHashCode()));
+ Expect(sym1.GetHashCode(), Not.EqualTo(sym5.GetHashCode()));
+ Expect(sym3.GetHashCode(), Not.EqualTo(sym6.GetHashCode()));
+ }
+
+ #endregion
+
+ #region Named tests
+
+ // We've been testing these all along.
+
+ #endregion
+
+ #region IFn tests
+
+ [Test]
+ public void Invoke2IndexesIntoItsFirstArg()
+ {
+ Symbol sym1 = Symbol.intern("abc");
+ Symbol sym2 = Symbol.intern("abc");
+ Symbol sym3 = Symbol.intern("ab");
+
+ IDictionary dict = new Hashtable();
+ dict[sym1] = 7;
+ dict["abc"] = 8;
+
+ Expect(sym1.invoke(dict), EqualTo(7));
+ Expect(sym2.invoke(dict), EqualTo(7));
+ Expect(sym3.invoke(dict), Null);
+ }
+
+ [Test]
+ public void Invoke3IndexesIntoItsFirstArg()
+ {
+ Symbol sym1 = Symbol.intern("abc");
+ Symbol sym2 = Symbol.intern("abc");
+ Symbol sym3 = Symbol.intern("ab");
+
+ IDictionary dict = new Hashtable();
+ dict[sym1] = 7;
+ dict["abc"] = 8;
+
+ Expect(sym1.invoke(dict,20), EqualTo(7));
+ Expect(sym2.invoke(dict,20), EqualTo(7));
+ Expect(sym3.invoke(dict,20), EqualTo(20));
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException))]
+ public void InvokeOnNoArgsFails()
+ {
+ Symbol sym1 = Symbol.intern("abc");
+ object o = sym1.invoke();
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentException))]
+ public void InvokeOnTooManyArgsFails()
+ {
+ Symbol sym1 = Symbol.intern("abc");
+ IDictionary dict = new Hashtable();
+ dict[sym1] = 7;
+ dict["abc"] = 8;
+
+ object o = sym1.invoke(dict,20,null);
+ }
+
+ #endregion
+
+ #region IComparable tests
+
+ [Test]
+ [ExpectedException(typeof(InvalidOperationException))]
+ public void CompareToNonSymbolFails()
+ {
+ Symbol sym1 = Symbol.intern("abc");
+ int c = sym1.CompareTo("abc");
+ }
+
+ [Test]
+ public void CompareToEqualSymbolIsZero()
+ {
+ Symbol sym1 = Symbol.intern("abc");
+ Symbol sym2 = Symbol.intern("abc");
+
+ Expect(sym1.CompareTo(sym2), EqualTo(0));
+ }
+
+ [Test]
+ public void NullNSIsLessThanNonNullNS()
+ {
+ Symbol sym1 = Symbol.intern("abc");
+ Symbol sym2 = Symbol.intern("a", "abc");
+
+ Expect(sym1.CompareTo(sym2), LessThan(0));
+ Expect(sym2.CompareTo(sym1), GreaterThan(0));
+ }
+
+ [Test]
+ public void DissimilarNSCompareOnNS()
+ {
+ Symbol sym1 = Symbol.intern("a", "abc");
+ Symbol sym2 = Symbol.intern("b", "abc");
+
+ Expect(sym1.CompareTo(sym2), LessThan(0));
+ Expect(sym2.CompareTo(sym1), GreaterThan(0));
+ }
+
+ #endregion
+
+ }
+
+ [TestFixture]
+ public class Symbol_IObj_Tests : IObjTests
+ {
+ MockRepository _mocks;
+
+ [SetUp]
+ public void Setup()
+ {
+ _mocks = new MockRepository();
+ IPersistentMap meta = _mocks.StrictMock<IPersistentMap>();
+ _mocks.ReplayAll();
+
+ Symbol sym1 = Symbol.intern("def", "abc");
+
+ _objWithNullMeta = (IObj)sym1;
+ _obj = _objWithNullMeta.withMeta(meta);
+ _expectedType = typeof(Symbol);
+ }
+
+ [TearDown]
+ public void Teardown()
+ {
+ _mocks.VerifyAll();
+ }
+
+ }
+
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/LibTests/TestTest.cs b/ClojureCLR/Clojure/Clojure.Tests/LibTests/TestTest.cs new file mode 100644 index 00000000..3013a348 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/LibTests/TestTest.cs @@ -0,0 +1,62 @@ +/**
+ * 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;
+
+
+namespace Clojure.Tests.LibTests
+{
+
+
+ //public class BaseTest : AssertionHelper
+ //{
+ // [Test]
+ // public void Test1()
+ // {
+ // Console.WriteLine("T1");
+ // }
+
+ // [Test]
+ // public void Test2()
+ // {
+ // Console.WriteLine("T2");
+ // }
+
+ //}
+
+ //[TestFixture]
+ //public class TestTest : BaseTest
+ //{
+ // [Test]
+ // public void Test3()
+ // {
+ // Console.WriteLine("T3");
+ // }
+ //}
+
+
+
+ //[TestFixture]
+ //public class TestTest2 : BaseTest
+ //{
+ // [Test]
+ // public void Test4()
+ // {
+ // Console.WriteLine("T4");
+ // }
+ //}
+}
diff --git a/ClojureCLR/Clojure/Clojure.Tests/Properties/AssemblyInfo.cs b/ClojureCLR/Clojure/Clojure.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..648f8405 --- /dev/null +++ b/ClojureCLR/Clojure/Clojure.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Clojure.Tests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Clojure.Tests")]
+[assembly: AssemblyCopyright("Copyright © 2009")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("6741a194-da64-4dd1-8fcf-6ed1248acd29")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
|