public void testCycList() {
    System.out.println("\n*** testCycList ***");

    try {

      // Simple empty list constructor.
      ArrayList arrayList = new ArrayList();
      CycList cycList = new CycList<CycObject>(arrayList);
      assertNotNull(cycList);
      assertEquals("()", cycList.toString());

      // Construct list of one element.
      ArrayList arrayList2 = new ArrayList();
      CycObjectFactory.addCycConstantCache(BRAZIL);
      arrayList2.add(BRAZIL);
      CycList cycList2 = new CycList<CycObject>(arrayList2);
      assertEquals("(Brazil)", cycList2.toString());
      assertEquals("(#$Brazil)", cycList2.cyclify());

      // Construct list with embedded sublist.
      ArrayList arrayList3 = new ArrayList();
      arrayList3.add(BRAZIL);
      arrayList3.add(cycList);
      arrayList3.add(cycList2);
      CycList cycList3 = new CycList<CycObject>(arrayList3);
      assertEquals("(Brazil () (Brazil))", cycList3.toString());
      assertEquals("(#$Brazil () (#$Brazil))", cycList3.cyclify());

      // isValid()
      assertTrue(cycList.isValid());
      assertTrue(cycList2.isValid());
      assertTrue(cycList3.isValid());
      CycList cycList4 = new CycList(new Hashtable());
      assertFalse(cycList4.isValid());

      // first(), rest()
      ArrayList arrayList5 = new ArrayList();
      arrayList5.add(BRAZIL);
      CycList cycList5 = new CycList<CycObject>(arrayList5);
      assertEquals("(Brazil)", cycList5.toString());
      assertEquals("(#$Brazil)", cycList5.cyclify());
      assertEquals(cycList5.first(), BRAZIL);
      assertTrue(((CycList) (cycList5.rest())).size() == 0);
      CycList cycList5a = new CycList<CycObject>();
      cycList5a.add("a");
      cycList5a.setDottedElement("b");
      assertEquals("b", cycList5a.rest());

      // reverse()
      assertEquals(cycList5.toString(), cycList5.reverse().toString());
      assertEquals("((#$Brazil) () #$Brazil)", cycList3.reverse().cyclify());

      // reverse of strings.
      ArrayList arrayList6 = new ArrayList();
      arrayList6.add("z");
      arrayList6.add("y");
      arrayList6.add("x");
      CycList cycList6 = new CycList(arrayList6);
      assertEquals("(\"z\" \"y\" \"x\")", cycList6.toString());
      assertEquals("(\"x\" \"y\" \"z\")", cycList6.reverse().toString());

      // Improper lists.
      ArrayList arrayList7 = new ArrayList();
      arrayList7.add(Integer.valueOf(10));
      CycList cycList7 = new CycList(arrayList7);
      cycList7.setDottedElement(BRAZIL);
      assertTrue(cycList7.size() == 2);
      assertEquals("(10 . Brazil)", cycList7.toString());
      //CycListParser.verbosity = 10;

      CycListParser cycListParser = new CycListParser(null);
      CycList cycList7_1 = cycListParser.read("(a b c)");
      assertEquals("(A B C)", cycList7_1.toString());

      CycList cycList7a = getCyc().makeCycList("(a . (b . (c . (d))))");
      assertEquals("(A B C D)", cycList7a.toString());
      CycList cycList7b = getCyc().makeCycList("((a . b) . (c . d))");
      assertEquals("((A . B) C . D)", cycList7b.toString());
      CycList cycList7c = getCyc().makeCycList("((a . (b)) . (c . (d)))");
      assertEquals("((A B) C D)", cycList7c.toString());
      CycList cycList7d = getCyc().makeCycList("(a b . c)");
      assertEquals("(A B . C)", cycList7d.toString());
      CycList cycList7e = getCyc().makeCycList("(a b c . d)");
      assertEquals("(A B C . D)", cycList7e.toString());
      // construct
      Object object1 = CycList.construct(BRAZIL, CycObjectFactory.nil);
      assertNotNull(object1);
      assertTrue(object1 instanceof CycList);
      assertEquals("(Brazil)", object1.toString());
      // makeDottedPair
      CycList cycList8 = CycList.makeDottedPair(BRAZIL, "Atlantic");
      assertEquals("(Brazil . \"Atlantic\")", cycList8.toString());

      CycList cycList9 = CycList.makeDottedPair(BRAZIL, Integer.valueOf(1));
      assertEquals("(Brazil . 1)", cycList9.toString());

      CycList cycList10 = CycList.makeDottedPair(BRAZIL, CycObjectFactory.makeCycSymbol("foo"));
      assertEquals("(Brazil . FOO)", cycList10.toString());

      // Parse strings to make CycLists.
      String listAsString = "()";
      CycList cycList11 = getCyc().makeCycList(listAsString);
      assertEquals(listAsString, cycList11.toString());
      listAsString = "(1)";
      CycList cycList12 = getCyc().makeCycList(listAsString);
      assertEquals(listAsString, cycList12.toString());
      listAsString = "(1 2 3 4 5)";
      CycList cycList13 = getCyc().makeCycList(listAsString);
      assertEquals(listAsString, cycList13.toString());
      listAsString = "(\"1\" \"bar\" A #$Brazil Z 4.25 :KEYWORD ?COLLECTION NIL)";
      CycList cycList14 = getCyc().makeCycList(listAsString);
      assertEquals(listAsString, cycList14.cyclify());
      listAsString = "((A))";
      CycList cycList15 = getCyc().makeCycList(listAsString);
      assertEquals(listAsString, cycList15.toString());
      listAsString = "((A) (B C) (((D))))";
      CycList cycList16 = getCyc().makeCycList(listAsString);
      assertEquals(listAsString, cycList16.toString());
      CycList cycList17 = getCyc().makeCycList(listAsString);
      assertEquals(cycList17.toString(), cycList16.toString());
      assertEquals(cycList17.toString(), cycList16.toString());
      assertEquals(getCyc().makeCycList("(A)"), cycList17.first());
      assertEquals(getCyc().makeCycList("(B C)"), cycList17.second());
      assertEquals(getCyc().makeCycList("(((D)))"), cycList17.third());
      listAsString = "(apply #'+ '(1 2 3))";
      CycList cycList18 = getCyc().makeCycList(listAsString);
      assertEquals("(APPLY (FUNCTION +) (QUOTE (1 2 3)))",
              cycList18.toString());
      listAsString = "(1 2 \n"
              + " ;; a comment \n"
              + " 3 4 5)";
      CycList cycList19 = getCyc().makeCycList(listAsString);
      assertEquals(cycList13, cycList19);
      listAsString = "(" + Double.toString(1.0E-05) + ")";
      CycList cycList19a = getCyc().makeCycList(listAsString);
      assertEquals(listAsString, cycList19a.cyclify());
      cycListParser = new CycListParser(getCyc());
      listAsString = "(1 2 3) 4 \"5 6\" 7 (8 9 10) 11 test";
      CycList cycList19b = cycListParser.read(listAsString);
      assertEquals("(1 2 3)", cycList19b.toString());
      assertEquals(" 4 \"5 6\" 7 (8 9 10) 11 test", cycListParser.remainingString());
      listAsString =
              "(#$ist-Asserted \n"
              + "  (#$totalInvestmentEarningsForStockTypeBoughtDuring  \n"
              + "    #$TechStock  \n"
              + "    (#$MinusFn (#$Pound-GreatBritain 330000000000))  \n"
              + "    (#$EarlyPartFn (#$YearFn 2000)))  \n"
              + "  #$TheMotleyFoolUKCorpusMt))";
      final CycList cycList19c = cycListParser.read(listAsString);
      assertTrue(cycList19c.cyclify().indexOf("330000000000") > -1);
      assertTrue(DefaultCycObject.cyclify(cycList19c).indexOf("330000000000") > -1);
      testCycListAdd();

      // subst
      cycList18 = getCyc().makeCycList("(b)");
      cycList19 = cycList18.subst(CycObjectFactory.makeCycSymbol("x"), CycObjectFactory.makeCycSymbol("a"));
      assertEquals(getCyc().makeCycList("(b)"), cycList19);
      CycList cycList20 = getCyc().makeCycList("(a)");
      CycList cycList21 = cycList20.subst(CycObjectFactory.makeCycSymbol("x"), CycObjectFactory.makeCycSymbol("a"));
      assertEquals(getCyc().makeCycList("(x)"), cycList21);
      CycList cycList22 = getCyc().makeCycList("((a))");
      CycList cycList23 = cycList22.subst(CycObjectFactory.makeCycSymbol("x"), CycObjectFactory.makeCycSymbol("a"));
      assertEquals(getCyc().makeCycList("((x))"), cycList23);
      CycList cycList24 = getCyc().makeCycList("((a) (b c) (((d))))");
      CycList cycList25 = cycList24.subst(CycObjectFactory.makeCycSymbol("x"), CycObjectFactory.makeCycSymbol("a"));
      assertEquals(getCyc().makeCycList("((x) (b c) (((d))))"), cycList25);

      // containsDuplicates
      CycList cycList26 = getCyc().makeCycList("(a b c d)");
      assertFalse(cycList26.containsDuplicates());
      CycList cycList27 = getCyc().makeCycList("(a a c d)");
      assertTrue(cycList27.containsDuplicates());
      CycList cycList28 = getCyc().makeCycList("(a b c c)");
      assertTrue(cycList28.containsDuplicates());
      CycList cycList29 = getCyc().makeCycList("(a (b) (b) c)");
      assertTrue(cycList29.containsDuplicates());

      // list
      CycList cycList30 = CycList.list(CycObjectFactory.makeCycSymbol("a"));
      assertEquals("(A)", cycList30.toString());
      CycList cycList31 = CycList.list(CycObjectFactory.makeCycSymbol("a"),
              CycObjectFactory.makeCycSymbol("b"));
      assertEquals("(A B)", cycList31.toString());
      CycList cycList32 = CycList.list(CycObjectFactory.makeCycSymbol("a"),
              CycObjectFactory.makeCycSymbol("b"),
              CycObjectFactory.makeCycSymbol("c"));
      assertEquals("(A B C)", cycList32.toString());

      // combinationsOf
      CycList cycList33 = getCyc().makeCycList("(1 2 3 4)");
      assertEquals("((1) (2) (3) (4))", cycList33.combinationsOf(1).toString());
      assertEquals("((1 2) (1 3) (1 4) (2 3) (2 4) (3 4))",
              cycList33.combinationsOf(2).toString());
      assertEquals("((1 2 3 4))",
              cycList33.combinationsOf(4).toString());
      assertEquals("()",
              cycList33.combinationsOf(0).toString());
      assertEquals("()",
              (new CycList()).combinationsOf(4).toString());

      // randomPermutation
      CycList cycList34 = getCyc().makeCycList("(1 2 3 4 5 6 7 8 9 10)");
      CycList permutedCycList = cycList34.randomPermutation();
      assertEquals(10, permutedCycList.size());
      assertTrue(permutedCycList.contains(Integer.valueOf(2)));
      assertFalse(permutedCycList.containsDuplicates());

      // doesElementPrecedeOthers
      CycList cycList35 = getCyc().makeCycList("(1 2 3 4 5 6 7 8 9 10)");
      assertTrue(cycList35.doesElementPrecedeOthers(Integer.valueOf(1),
              getCyc().makeCycList("(8 7 6)")));
      assertTrue(cycList35.doesElementPrecedeOthers(Integer.valueOf(9),
              getCyc().makeCycList("(10)")));
      assertTrue(cycList35.doesElementPrecedeOthers(Integer.valueOf(10),
              getCyc().makeCycList("(18 17 16)")));
      assertFalse(cycList35.doesElementPrecedeOthers(Integer.valueOf(12),
              getCyc().makeCycList("(1 2 10)")));
      assertFalse(cycList35.doesElementPrecedeOthers(Integer.valueOf(9),
              getCyc().makeCycList("(8 7 6)")));

      // clone
      CycList cycList36 = getCyc().makeCycList("(1 2 3 4 5)");
      CycList cycList37 = (CycList) cycList36.clone();
      assertEquals(cycList36, cycList37);
      assertTrue(cycList36 != cycList37);
      CycList cycList38 = getCyc().makeCycList("(1 2 3 4 5 . 6)");
      CycList cycList39 = (CycList) cycList38.clone();

      assertEquals(cycList38, cycList39);
      assertTrue(cycList38 != cycList39);

      // deepCopy
      CycList cycList40 = getCyc().makeCycList("(1 2 3 4 5)");
      CycList cycList41 = (CycList) cycList40.deepCopy();
      assertEquals(cycList40, cycList41);
      assertTrue(cycList40 != cycList41);
      CycList cycList42 = getCyc().makeCycList("(1 2 3 4 5 . 6)");
      CycList cycList43 = (CycList) cycList42.deepCopy();
      assertEquals(cycList42, cycList43);
      assertTrue(cycList42 != cycList43);
      CycList cycList44 = getCyc().makeCycList("(1 (2 3) (4 5) ((6)))");
      CycList cycList45 = (CycList) cycList44.deepCopy();
      assertEquals(cycList44, cycList45);
      assertTrue(cycList44 != cycList45);
      assertEquals(cycList44.first(), cycList45.first());
      assertTrue(cycList44.first() == cycList45.first());
      assertEquals(cycList44.second(), cycList45.second());
      assertTrue(cycList44.second() != cycList45.second());
      assertEquals(cycList44.fourth(), cycList45.fourth());
      assertTrue(cycList44.fourth() != cycList45.fourth());
      assertEquals(((CycList) cycList44.fourth()).first(),
              ((CycList) cycList45.fourth()).first());
      assertTrue(((CycList) cycList44.fourth()).first()
              != ((CycList) cycList45.fourth()).first());

      // addNew
      CycList cycList46 = getCyc().makeCycList("(1 2 3 4 5)");
      assertEquals(5, cycList46.size());
      cycList46.addNew(Integer.valueOf(6));
      assertEquals(6, cycList46.size());
      cycList46.addNew(Integer.valueOf(2));
      assertEquals(6, cycList46.size());
      // addAllNew
      CycList cycList47 = getCyc().makeCycList("(1 2 3 4 5)");
      assertEquals(5, cycList47.size());
      CycList cycList48 = getCyc().makeCycList("(6 7 8 9 10)");
      assertEquals(5, cycList48.size());
      cycList47.addAllNew(cycList48);
      assertEquals(10, cycList47.size());
      CycList cycList49 = getCyc().makeCycList("(2 5 8 9 11)");
      assertEquals(5, cycList49.size());
      cycList47.addAllNew(cycList49);
      assertEquals(11, cycList47.size());

      // last
      cycList46 = getCyc().makeCycList("(8 7 6)");
      assertEquals(Integer.valueOf(6), cycList46.last());
      // toXML, toXMLString
      listAsString = "(\"1\" A (#$Brazil . Z) 4.25 :KEYWORD ?collection NIL . #$Dog)";
      cycList47 = getCyc().makeCycList(listAsString);
      XMLStringWriter xmlStringWriter = new XMLStringWriter();
      String cycListXMLString = cycList47.toXMLString();
      Object object = CycObjectFactory.unmarshall(cycListXMLString);
      assertTrue(object instanceof CycList);
      assertEquals(cycList47, (CycList) object);
      cycList48 =
              getCyc().makeCycList("(T (#$BiologicalTaxon "
              + "#$BiologicalSpecies "
              + "#$OrganismClassificationType "
              + "#$CycLTerm "
              + "#$CollectionType))");
      cycListXMLString = Marshaller.marshall(cycList48);
//      System.out.println(cycListXMLString);
      object = CycObjectFactory.unmarshall(cycListXMLString);
      assertTrue(object instanceof CycList);
      assertEquals(cycList48, (CycList) object);
      cycListXMLString =
              "\n<list>\n"
              + "  <symbol>QUOTE</symbol>\n"
              + "  <list>\n"
              + "    <symbol>A</symbol>\n"
              + "    <dotted-element>\n"
              + "      <symbol>B</symbol>\n"
              + "    </dotted-element>\n"
              + "  </list>\n"
              + "</list>\n";
      object = CycObjectFactory.unmarshall(cycListXMLString);
      assertTrue(object instanceof CycList);
      cycList49 = getCyc().makeCycList("(QUOTE (A . B))");
      assertEquals(cycList49, object);
      testCycList50();

      // addQuoted
      CycList cycList51 = new CycList();
      cycList51.add(Integer.valueOf(1));
      cycList51.addQuoted(CycObjectFactory.makeCycSymbol("quote-me"));
      assertEquals("(1 (QUOTE QUOTE-ME))", cycList51.toString());

      // toString (with null element)
      CycList cycList52 = new CycList();
      cycList52.add(null);
      assertNull(cycList52.first());
      assertEquals("(null)", cycList52.toString());

      // treeConstants
      CycList cycList54 =
              getCyc().makeCycList("(T (#$BiologicalTaxon "
              + "#$BiologicalSpecies "
              + "#$OrganismClassificationType "
              + "#$CycLTerm "
              + "#$CollectionType))");
      cycList54.add(new CycNart(getCyc().getKnownConstantByName("FruitFn"), getCyc().getKnownConstantByName("PumpkinPlant")));
      CycList cycList55 = cycList54.treeConstants();
      assertEquals(7, cycList55.size());

      // stringApiValue()
      CycConstant ontario = null;
      ontario =
              getCyc().getKnownConstantByGuid(
              CycObjectFactory.makeGuid("bd58b6d5-9c29-11b1-9dad-c379636f7270"));
      CycList cycList56 = new CycList(ontario);
      Object result56 = CycUtils.evalSubLWithWorker(getCyc(), cycList56.stringApiValue());
      assertTrue(result56 instanceof CycList);
      assertEquals(cycList56, (CycList) result56);
      // Check whether stringApiValue works properly on a CycList with a CycNart element
      CycConstant cityNamedFn =
              getCyc().getKnownConstantByGuid(
              CycObjectFactory.makeGuid("bd6870a6-9c29-11b1-9dad-c379636f7270"));
      CycNart attawapiskat = new CycNart(cityNamedFn, "Attawapiskat", ontario);
      CycList cycListWithNart = new CycList(ontario, attawapiskat);
      Object resultObj = CycUtils.evalSubLWithWorker(getCyc(), cycListWithNart.stringApiValue());
      assertTrue(resultObj instanceof CycList);
      assertEquals(cycListWithNart.cyclify(), ((CycList) resultObj).cyclify());
      // stringApiValue() on a CycList containing a String containing a double-quote
      CycList cycListWithString = new CycList(new String("How much \"wood\" would a \"woodchuck\" \"chuck\"?"));
      resultObj = CycUtils.evalSubLWithWorker(getCyc(), cycListWithString.stringApiValue());
      assertTrue(resultObj instanceof CycList);
      assertEquals(cycListWithString, (CycList) resultObj);

      // stringApiValue() on a dotted CycList
      CycList dottedCycList = new CycList("first element", "second element");
      dottedCycList.setDottedElement("dotted element");
      resultObj = CycUtils.evalSubLWithWorker(getCyc(), dottedCycList.stringApiValue());
      assertTrue(resultObj instanceof CycList);
      assertEquals(dottedCycList, (CycList) resultObj);
      // Parse a list containing a string with a backslash
      String script = "(identity \"abc\")";
      resultObj = CycUtils.evalSubLWithWorker(getCyc(), script);
      assertTrue(resultObj instanceof String);
      script = "(identity \"abc\\\\\")";
      resultObj = CycUtils.evalSubLWithWorker(getCyc(), script);
      assertTrue(resultObj instanceof String);
      CycList command = new CycList();
      command.add(CycObjectFactory.makeCycSymbol("identity"));
      command.add("abc\\");
      script = command.cyclifyWithEscapeChars();
      resultObj = CycUtils.evalSubLWithWorker(getCyc(), script);
      assertTrue(resultObj instanceof String);

    } catch (Exception e) {
      failWithException(e);
    }

    testUnmodifiableCycList();

    System.out.println("*** testCycList OK ***");
  }