diff options
Diffstat (limited to 'ClojureCLR/Clojure/Clojure.Tests/LibTests/LispReaderTests.cs')
-rw-r--r-- | ClojureCLR/Clojure/Clojure.Tests/LibTests/LispReaderTests.cs | 1789 |
1 files changed, 1789 insertions, 0 deletions
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")));
|