blob: 2c24f143e32e5e5fbcfe8bb59a35efce3daf9dd0 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "AbstractListTest.h"
#include <decaf/lang/Integer.h>
#include <decaf/util/AbstractList.h>
#include <vector>
using namespace std;
using namespace decaf;
using namespace decaf::util;
using namespace decaf::lang;
using namespace decaf::lang::exceptions;
////////////////////////////////////////////////////////////////////////////////
namespace {
template<typename E>
class SimpleList : public AbstractList<E> {
private:
std::vector<E> array;
public:
using AbstractList<E>::add;
public:
SimpleList() : AbstractList<E>(), array() {
}
virtual ~SimpleList() {}
virtual E get( int index ) const {
if( index < 0 || index >= (int)array.size() ) {
throw IndexOutOfBoundsException();
}
return this->array[index];
}
virtual void add( int i, const E& value ) {
if( i < 0 || i > (int)array.size() ) {
throw IndexOutOfBoundsException();
}
this->array.insert( this->array.begin() + i, value );
}
virtual E removeAt( int i ) {
if( i < 0 || i >= (int)array.size() ) {
throw IndexOutOfBoundsException();
}
E oldValue = this->array[i];
this->array.erase( this->array.begin() + i );
return oldValue;
}
virtual int size() const {
return (int)this->array.size();
}
};
template<typename E>
class MockArrayList : public AbstractList<E> {
public:
std::vector<E> array;
public:
using AbstractList<E>::add;
public:
MockArrayList() : AbstractList<E>(), array() {
}
virtual ~MockArrayList() {}
virtual E get( int index ) const {
if( index < 0 || index >= (int)array.size() ) {
throw IndexOutOfBoundsException();
}
return this->array[index];
}
virtual void add( int i, const E& value ) {
if( i < 0 || i > (int)array.size() ) {
throw IndexOutOfBoundsException();
}
this->modCount += 10;
this->array.insert( this->array.begin() + i, value );
}
virtual E removeAt( int i ) {
if( i < 0 || i >= (int)array.size() ) {
throw IndexOutOfBoundsException();
}
this->modCount++;
E oldValue = this->array[i];
this->array.erase( this->array.begin() + i );
return oldValue;
}
virtual int size() const {
return (int)this->array.size();
}
};
template<typename E>
class MockRemoveFailureArrayList : public AbstractList<E> {
public:
virtual ~MockRemoveFailureArrayList() {}
virtual E get( int index ) const {
return E();
}
virtual int size() const {
return 0;
}
virtual E removeAt( int i ) {
this->modCount += 2;
return E();
}
int getModCount() const {
return this->modCount;
}
};
template<typename E>
class MockList : public AbstractList<E> {
private:
std::vector<E> array;
public:
using AbstractList<E>::add;
public:
MockList() : AbstractList<E>(), array() {}
virtual ~MockList() {}
virtual E get( int index ) const {
if( index < 0 || index >= (int)array.size() ) {
throw IndexOutOfBoundsException();
}
return array[index];
}
virtual int size() const {
return (int)array.size();
}
};
}
////////////////////////////////////////////////////////////////////////////////
AbstractListTest::AbstractListTest() {
}
////////////////////////////////////////////////////////////////////////////////
AbstractListTest::~AbstractListTest() {
}
////////////////////////////////////////////////////////////////////////////////
void AbstractListTest::testIterator() {
SimpleList<int> list;
list.add( 10 );
list.add( 20 );
std::auto_ptr< Iterator<int> > iter( list.iterator() );
CPPUNIT_ASSERT_EQUAL( 10, iter->next() );
iter->remove();
CPPUNIT_ASSERT_EQUAL( 20, iter->next() );
}
////////////////////////////////////////////////////////////////////////////////
void AbstractListTest::testListIterator() {
int tempValue;
SimpleList<int> list;
list.add( 3 );
list.add( 15 );
list.add( 5 );
list.add( 1 );
list.add( 7 );
std::auto_ptr< ListIterator<int> > iter( list.listIterator() );
CPPUNIT_ASSERT_MESSAGE( "Should not have previous", !iter->hasPrevious() );
CPPUNIT_ASSERT_MESSAGE( "Should have next", iter->hasNext() );
tempValue = iter->next();
CPPUNIT_ASSERT_MESSAGE( std::string( "next returned wrong value. Wanted 3, got: " ) +
Integer::toString( tempValue ), tempValue == 3 );
tempValue = iter->previous();
SimpleList<std::string> list2;
list2.add( std::string("1") );
std::auto_ptr< ListIterator<std::string> > iter2( list2.listIterator() );
iter2->add( std::string("2") );
iter2->next();
CPPUNIT_ASSERT_MESSAGE( "Should contain two elements", list2.size() == 2 );
SimpleList<int> list3;
std::auto_ptr< ListIterator<int> > it( list3.listIterator() );
it->add( 1 );
it->add( 2 );
CPPUNIT_ASSERT_MESSAGE( "Should contain two elements", list3.size() == 2 );
}
////////////////////////////////////////////////////////////////////////////////
void AbstractListTest::testIteratorNext() {
MockArrayList<std::string> t;
t.array.push_back( "a" );
t.array.push_back( "b" );
std::auto_ptr< Iterator<std::string> > it( t.iterator() );
while( it->hasNext() ) {
it->next();
}
try {
it->next();
CPPUNIT_FAIL( "Should throw NoSuchElementException" );
} catch( NoSuchElementException& cme ) {
// expected
}
t.add( "c" );
try {
it->remove();
CPPUNIT_FAIL( "Should throw ConcurrentModificationException" );
} catch( ConcurrentModificationException& cme ) {
// expected
}
it.reset( t.iterator() );
try {
it->remove();
CPPUNIT_FAIL( "Should throw IllegalStateException" );
} catch( IllegalStateException& ise ) {
// expected
}
std::string value = it->next();
CPPUNIT_ASSERT_EQUAL( std::string("a"), value );
}
////////////////////////////////////////////////////////////////////////////////
void AbstractListTest::testRemove() {
MockRemoveFailureArrayList<std::string> list;
std::auto_ptr< Iterator<std::string> > iter( list.iterator() );
iter->next();
iter->remove();
try {
iter->remove();
} catch( ConcurrentModificationException& e ) {
CPPUNIT_FAIL("Excepted to catch IllegalStateException not ConcurrentModificationException");
} catch( IllegalStateException& e ) {
//Excepted to catch IllegalStateException here
}
}
////////////////////////////////////////////////////////////////////////////////
void AbstractListTest::testIndexOf() {
SimpleList<int> array;
for( int i = 1; i < 6; i++ ) {
array.add(i);
}
MockArrayList<int> list;
list.addAll( array );
CPPUNIT_ASSERT_EQUAL_MESSAGE( "find 0 in the list do not contain 0", -1, list.indexOf( 0 ) );
CPPUNIT_ASSERT_EQUAL_MESSAGE( "did not return the right location of element 3", 2, list.indexOf( 3 ) );
}
////////////////////////////////////////////////////////////////////////////////
void AbstractListTest::testLastIndexOf() {
SimpleList<int> array;
for( int i = 1; i < 6; i++ ) {
array.add(i);
}
for( int i = 5; i > 0; i-- ) {
array.add(i);
}
CPPUNIT_ASSERT( array.size() == 10 );
MockArrayList<int> list;
list.addAll( array );
CPPUNIT_ASSERT( list.size() == 10 );
CPPUNIT_ASSERT_EQUAL_MESSAGE( "find 6 in the list do not contain 6",
-1, list.lastIndexOf( 6 ) );
CPPUNIT_ASSERT_EQUAL_MESSAGE( "did not return the right location of element 4",
6, list.lastIndexOf( 4 ) );
}
////////////////////////////////////////////////////////////////////////////////
void AbstractListTest::testRemoveAt() {
MockList<int> list;
try {
list.removeAt( 0 );
CPPUNIT_FAIL("should throw UnsupportedOperationException");
} catch( UnsupportedOperationException& e ) {
// expected
}
try {
list.set( 0, 1 );
CPPUNIT_FAIL("should throw UnsupportedOperationException");
} catch( UnsupportedOperationException& e ) {
// expected
}
}