Skip to content

Commit

Permalink
Adds basic tests and patterns for type inference
Browse files Browse the repository at this point in the history
Issue: #92
  • Loading branch information
kpp committed Aug 13, 2016
1 parent 63f134e commit 9cfb35d
Show file tree
Hide file tree
Showing 4 changed files with 254 additions and 4 deletions.
4 changes: 4 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure)
macro(cxx_test pretty_name bin_name sources libs)
add_executable(${bin_name} ${sources})
target_link_libraries(${bin_name} supc++ -pthread ${libs} ${GTEST_BOTH_LIBRARIES} ${READLINE_LIBS_TO_LINK})
if (USE_LLVM)
target_link_libraries(${bin_name} jit trampoline ${LLVM_LIBS} ${LLVM_LD_FLAGS})
endif()
set_target_properties(${bin_name} PROPERTIES COMPILE_DEFINITIONS TESTS_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}/\")
add_test(${pretty_name} ${bin_name})
add_dependencies(check ${bin_name})
Expand All @@ -22,3 +25,4 @@ cxx_test(StackSemantics test_stack_semantics "${CMAKE_CURRENT_SOURCE_DIR}/stack_
# TODO cxx_test(StackUnderflow test_stack_underflow "${CMAKE_CURRENT_SOURCE_DIR}/stack_underflow.cpp" "stapi")
cxx_test(DecodeAllMethods test_decode_all_methods "${CMAKE_CURRENT_SOURCE_DIR}/decode_all_methods.cpp" "stapi;memory_managers;standard_set")
cxx_test("VM::primitives" test_vm_primitives "${CMAKE_CURRENT_SOURCE_DIR}/vm_primitives.cpp" "memory_managers;standard_set")
cxx_test(Inference test_inference "${CMAKE_CURRENT_SOURCE_DIR}/inference.cpp" "stapi;memory_managers;standard_set")
Binary file added tests/data/Inference.image
Binary file not shown.
232 changes: 232 additions & 0 deletions tests/inference.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
#include <gtest/gtest.h>
#include "patterns/InitVMImage.h"
#include <inference.h>

class P_Inference : public P_InitVM_Image
{
public:
type::TypeSystem* m_type_system;

P_Inference() : P_InitVM_Image(), m_type_system(0) {}
virtual ~P_Inference() {}

virtual void SetUp()
{
P_InitVM_Image::SetUp();
m_type_system = new type::TypeSystem(*m_vm);
}
virtual void TearDown() {
P_InitVM_Image::TearDown();
delete m_type_system;
}

type::InferContext* inferMessage(
TClass* const objectClass,
const std::string& methodName,
const type::Type& args,
type::TContextStack* parent,
bool sendToSuper = false
) {
EXPECT_NE(static_cast<TClass*>(0), objectClass) << "Class is null";
TMethod* const method = objectClass->methods->find<TMethod>(methodName.c_str());
EXPECT_NE(static_cast<TMethod*>(0), method) << "Method is null";

TSymbol* const selector = method->name;
return m_type_system->inferMessage(selector, args, parent, sendToSuper);
}

type::InferContext* inferMessage(
const std::string& className,
const std::string& methodName,
const type::Type& args,
type::TContextStack* parent,
bool sendToSuper = false
) {
TClass* const objectClass = m_image->getGlobal<TClass>(className.c_str());
return this->inferMessage(objectClass, methodName, args, parent, sendToSuper);
}

};

INSTANTIATE_TEST_CASE_P(_, P_Inference, ::testing::Values(std::string("Inference")) );

TEST_P(P_Inference, SmallInt)
{
{
SCOPED_TRACE("SmallInt>>asSmallInt");
type::Type args(globals.arrayClass, type::Type::tkArray);
args.pushSubType(type::Type(TInteger(42)));

type::InferContext* const inferContext = this->inferMessage("SmallInt", "asSmallInt", args, 0);
ASSERT_EQ( type::Type(TInteger(42)), inferContext->getReturnType() );
}
{
SCOPED_TRACE("SmallInt>>+ SmallInt");
type::Type args(globals.arrayClass, type::Type::tkArray);
args.pushSubType(type::Type(TInteger(40)));
args.pushSubType(type::Type(TInteger(2)));

type::InferContext* const inferContext = this->inferMessage("SmallInt", "+", args, 0);
ASSERT_EQ( type::Type(TInteger(42)), inferContext->getReturnType() );
}
}

TEST_P(P_Inference, Number)
{
{
SCOPED_TRACE("Number::new");
type::Type args(globals.arrayClass, type::Type::tkArray);
TClass* const metaNumberClass = m_image->getGlobal<TClass>("Number")->getClass();
args.pushSubType(type::Type(metaNumberClass));

type::InferContext* const inferContext = this->inferMessage(metaNumberClass, "new", args, 0);
ASSERT_EQ( type::Type(TInteger(0)), inferContext->getReturnType() );
}
{
SCOPED_TRACE("Number>>factorial");
type::Type args(globals.arrayClass, type::Type::tkArray);
args.pushSubType(type::Type(TInteger(4)));

type::InferContext* const inferContext = this->inferMessage("Number", "factorial", args, 0);
ASSERT_EQ( type::Type(TInteger(24)), inferContext->getReturnType() );
}
{
SCOPED_TRACE("Number>>negative");
{
SCOPED_TRACE("-SmallInt");
type::Type args(globals.arrayClass, type::Type::tkArray);
args.pushSubType(type::Type(TInteger(-1)));

type::InferContext* const inferContext = this->inferMessage("Number", "negative", args, 0);
ASSERT_EQ( type::Type(globals.trueObject), inferContext->getReturnType() );
}
{
SCOPED_TRACE("+SmallInt");
type::Type args(globals.arrayClass, type::Type::tkArray);
args.pushSubType(type::Type(TInteger(1)));

type::InferContext* const inferContext = this->inferMessage("Number", "negative", args, 0);
ASSERT_EQ( type::Type(globals.falseObject), inferContext->getReturnType() );
}
}
{
SCOPED_TRACE("Number>>negated");
{
SCOPED_TRACE("-SmallInt");
type::Type args(globals.arrayClass, type::Type::tkArray);
args.pushSubType(type::Type(TInteger(-1)));

type::InferContext* const inferContext = this->inferMessage("Number", "negated", args, 0);
ASSERT_EQ( type::Type(TInteger(1)), inferContext->getReturnType() );
}
{
SCOPED_TRACE("+SmallInt");
type::Type args(globals.arrayClass, type::Type::tkArray);
args.pushSubType(type::Type(TInteger(1)));

type::InferContext* const inferContext = this->inferMessage("Number", "negated", args, 0);
ASSERT_EQ( type::Type(TInteger(-1)), inferContext->getReturnType() );
}
}
{
SCOPED_TRACE("Number>>absolute");
{
SCOPED_TRACE("-SmallInt");
type::Type args(globals.arrayClass, type::Type::tkArray);
args.pushSubType(type::Type(TInteger(-1)));

type::InferContext* const inferContext = this->inferMessage("Number", "absolute", args, 0);
ASSERT_EQ( type::Type(TInteger(1)), inferContext->getReturnType() );
}
{
SCOPED_TRACE("+SmallInt");
type::Type args(globals.arrayClass, type::Type::tkArray);
args.pushSubType(type::Type(TInteger(1)));

type::InferContext* const inferContext = this->inferMessage("Number", "absolute", args, 0);
ASSERT_EQ( type::Type(TInteger(1)), inferContext->getReturnType() );
}
}
}

TEST_P(P_Inference, True)
{
{
SCOPED_TRACE("True>>not");
type::Type args(globals.arrayClass, type::Type::tkArray);
args.pushSubType(type::Type(globals.trueObject));

type::InferContext* const inferContext = this->inferMessage("True", "not", args, 0);
ASSERT_EQ( type::Type(globals.falseObject), inferContext->getReturnType() );
}
{
SCOPED_TRACE("True>>and:");
type::Type args(globals.arrayClass, type::Type::tkArray);
args.pushSubType(type::Type(globals.trueObject));
args.pushSubType(type::Type(globals.blockClass));

type::InferContext* const inferContext = this->inferMessage("True", "and:", args, 0);
ASSERT_EQ( type::Type(type::Type::tkPolytype), inferContext->getReturnType() ); // FIXME: expect Boolean type
}
{
SCOPED_TRACE("True>>or:");
type::Type args(globals.arrayClass, type::Type::tkArray);
args.pushSubType(type::Type(globals.trueObject));
args.pushSubType(type::Type(globals.blockClass));

type::InferContext* const inferContext = this->inferMessage("True", "or:", args, 0);
ASSERT_EQ( type::Type(globals.trueObject), inferContext->getReturnType() );
}
}

TEST_P(P_Inference, False)
{
{
SCOPED_TRACE("False>>not");
type::Type args(globals.arrayClass, type::Type::tkArray);
args.pushSubType(type::Type(globals.falseObject));

type::InferContext* const inferContext = this->inferMessage("False", "not", args, 0);
ASSERT_EQ( type::Type(globals.trueObject), inferContext->getReturnType() );
}
{
SCOPED_TRACE("False>>and:");
type::Type args(globals.arrayClass, type::Type::tkArray);
args.pushSubType(type::Type(globals.falseObject));
args.pushSubType(type::Type(globals.blockClass));

type::InferContext* const inferContext = this->inferMessage("False", "and:", args, 0);
ASSERT_EQ( type::Type(globals.falseObject), inferContext->getReturnType() );
}
{
SCOPED_TRACE("False>>or:");
type::Type args(globals.arrayClass, type::Type::tkArray);
args.pushSubType(type::Type(globals.falseObject));
args.pushSubType(type::Type(globals.blockClass));

type::InferContext* const inferContext = this->inferMessage("False", "or:", args, 0);
ASSERT_EQ( type::Type(type::Type::tkPolytype), inferContext->getReturnType() ); // FIXME: expect Boolean type
}
}

TEST_P(P_Inference, Array)
{
{
SCOPED_TRACE("Array>>sort:");
type::Type args(globals.arrayClass, type::Type::tkArray);
args.pushSubType(type::Type(globals.arrayClass));
args.pushSubType(type::Type(globals.blockClass));

type::InferContext* const inferContext = this->inferMessage("Array", "sort:", args, 0);
ASSERT_EQ( type::Type(globals.arrayClass), inferContext->getReturnType() );
}
{
SCOPED_TRACE("Array::new");
type::Type args(globals.arrayClass, type::Type::tkArray);
TClass* const metaArrayClass = m_image->getGlobal<TClass>("Array")->getClass();
args.pushSubType(type::Type(metaArrayClass));

type::InferContext* const inferContext = this->inferMessage(metaArrayClass, "new", args, 0);
ASSERT_EQ( type::Type(globals.arrayClass), inferContext->getReturnType() );
}
}
22 changes: 18 additions & 4 deletions tests/patterns/InitVMImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@
#define LLST_PATTERN_INIT_VM_IMAGE_INCLUDED

#include <gtest/gtest.h>
#include "../helpers/VMImage.h"
#include <vm.h>

class P_InitVM_Image : public ::testing::TestWithParam<std::string /*image name*/>
{
protected:
H_VMImage* m_image;
std::auto_ptr<IMemoryManager> m_memoryManager;
public:
std::auto_ptr<Image> m_image;
std::auto_ptr<SmalltalkVM> m_vm;
P_InitVM_Image() : m_memoryManager(), m_image(), m_vm() {}
virtual ~P_InitVM_Image() {}

virtual void SetUp()
Expand All @@ -19,10 +22,21 @@ class P_InitVM_Image : public ::testing::TestWithParam<std::string /*image name*
abort();
}
ParamType image_name = GetParam();
m_image = new H_VMImage(image_name);

#if defined(LLVM)
m_memoryManager.reset(new LLVMMemoryManager());
#else
m_memoryManager.reset(new BakerMemoryManager()),
#endif
m_memoryManager->initializeHeap(1024*1024, 1024*1024);
m_image.reset(new Image(m_memoryManager.get()));
m_image->loadImage(TESTS_DIR "./data/" + image_name + ".image");
m_vm.reset(new SmalltalkVM(m_image.get(), m_memoryManager.get()));
}
virtual void TearDown() {
delete m_image;
m_vm.reset();
m_image.reset();
m_memoryManager.reset();
}
};

Expand Down

0 comments on commit 9cfb35d

Please sign in to comment.