diff options
Diffstat (limited to 'basic/qa/cppunit')
-rw-r--r-- | basic/qa/cppunit/basic_coverage.cxx | 161 | ||||
-rw-r--r-- | basic/qa/cppunit/basictest.cxx | 125 | ||||
-rw-r--r-- | basic/qa/cppunit/basictest.hxx | 55 | ||||
-rw-r--r-- | basic/qa/cppunit/test_append.cxx | 80 | ||||
-rw-r--r-- | basic/qa/cppunit/test_compiler_checks.cxx | 36 | ||||
-rw-r--r-- | basic/qa/cppunit/test_language_conditionals.cxx | 173 | ||||
-rw-r--r-- | basic/qa/cppunit/test_nested_struct.cxx | 303 | ||||
-rw-r--r-- | basic/qa/cppunit/test_scanner.cxx | 1166 | ||||
-rw-r--r-- | basic/qa/cppunit/test_vba.cxx | 256 |
9 files changed, 2355 insertions, 0 deletions
diff --git a/basic/qa/cppunit/basic_coverage.cxx b/basic/qa/cppunit/basic_coverage.cxx new file mode 100644 index 000000000..0dfc7d94e --- /dev/null +++ b/basic/qa/cppunit/basic_coverage.cxx @@ -0,0 +1,161 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "basictest.hxx" +#include <osl/file.hxx> +#include <i18nlangtag/languagetag.hxx> +#include <unotools/syslocaleoptions.hxx> + +namespace +{ + +class Coverage : public test::BootstrapFixture +{ +private: + int m_nb_tests_ok; + OUString m_sCurrentTest; + void process_directory(const OUString& sDirName); + void run_test(const OUString& sFileName); + void test_failed(); + void test_success(); + std::vector< OUString > get_subdirnames( const OUString& sDirName ); + +public: + Coverage(); + virtual ~Coverage() override; + + void Coverage_Iterator(); + + // Adds code needed to register the test suite + CPPUNIT_TEST_SUITE(Coverage); + + // Declares the method as a test to call + CPPUNIT_TEST(Coverage_Iterator); + + // End of test suite definition + CPPUNIT_TEST_SUITE_END(); +}; + +Coverage::Coverage() + : BootstrapFixture(true, false) + , m_nb_tests_ok(0) +{ +} + +Coverage::~Coverage() +{ + fprintf(stderr,"basic coverage Summary : pass:%d\n", m_nb_tests_ok ); +} + +void Coverage::test_failed() +{ + CPPUNIT_FAIL( + OUStringToOString(m_sCurrentTest, RTL_TEXTENCODING_UTF8).getStr()); +} + +void Coverage::test_success() +{ + m_nb_tests_ok += 1; + fprintf(stderr,"%s,PASS\n", OUStringToOString( m_sCurrentTest, RTL_TEXTENCODING_UTF8 ).getStr() ); +} + +void Coverage::run_test(const OUString& sFileURL) +{ + m_sCurrentTest = sFileURL; + bool bResult = false; + MacroSnippet testMacro; + testMacro.LoadSourceFromFile( sFileURL ); + testMacro.Compile(); + if( !testMacro.HasError() ) + { + SbxVariableRef pResult = testMacro.Run(); + if( pResult.is() && pResult->GetInteger() == 1 ) + { + bResult = true; + } + } + if(bResult) + { + test_success(); + } + else + { + test_failed(); + } +} + +std::vector< OUString > Coverage::get_subdirnames( const OUString& sDirName ) +{ + std::vector< OUString > sSubDirNames; + osl::Directory aDir(sDirName); + osl::DirectoryItem aItem; + osl::FileStatus aFileStatus(osl_FileStatus_Mask_FileURL|osl_FileStatus_Mask_Type); + + if(aDir.open() == osl::FileBase::E_None) + { + while (aDir.getNextItem(aItem) == osl::FileBase::E_None) + { + aItem.getFileStatus(aFileStatus); + if(aFileStatus.isDirectory()) + sSubDirNames.push_back( aFileStatus.getFileURL() ); + } + } + return sSubDirNames; +} +void Coverage::process_directory(const OUString& sDirName) +{ + osl::Directory aDir(sDirName); + osl::DirectoryItem aItem; + osl::FileStatus aFileStatus(osl_FileStatus_Mask_FileURL|osl_FileStatus_Mask_Type); + + if(aDir.open() == osl::FileBase::E_None) + { + while (aDir.getNextItem(aItem) == osl::FileBase::E_None) + { + aItem.getFileStatus(aFileStatus); + if(aFileStatus.isRegular()) + { + run_test(aFileStatus.getFileURL()); + } + } + } + fprintf(stderr,"end process directory\n"); +} + +void Coverage::Coverage_Iterator() +{ + OUString sDirName = m_directories.getURLFromSrc("/basic/qa/basic_coverage/"); + + CPPUNIT_ASSERT(!sDirName.isEmpty()); + process_directory(sDirName); // any files in the root test dir are run in test harness default locale ( en-US ) + std::vector< OUString > sLangDirs = get_subdirnames( sDirName ); + + for (auto const& langDir : sLangDirs) + { + sal_Int32 nSlash = langDir.lastIndexOf('/'); + if ( nSlash != -1 ) + { + OUString sLangISO = langDir.copy( nSlash + 1 ); + LanguageTag aLocale( sLangISO ); + if ( aLocale.isValidBcp47() ) + { + SvtSysLocaleOptions aLocalOptions; + // set locale for test dir + aLocalOptions.SetLocaleConfigString( sLangISO ); + process_directory(langDir); + } + } + } +} + + CPPUNIT_TEST_SUITE_REGISTRATION(Coverage); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basic/qa/cppunit/basictest.cxx b/basic/qa/cppunit/basictest.cxx new file mode 100644 index 000000000..635da6e5e --- /dev/null +++ b/basic/qa/cppunit/basictest.cxx @@ -0,0 +1,125 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "basictest.hxx" +#include <cppunit/plugin/TestPlugIn.h> +#include <basic/sbstar.hxx> +#include <basic/sbmod.hxx> +#include <basic/sbmeth.hxx> +#include <basic/sbuno.hxx> +#include <osl/file.hxx> + +void MacroSnippet::InitSnippet() +{ + mpBasic = new StarBASIC(); + StarBASIC::SetGlobalErrorHdl( LINK( this, MacroSnippet, BasicErrorHdl ) ); +} + +void MacroSnippet::MakeModule( const OUString& sSource ) +{ + mpMod = mpBasic->MakeModule( "TestModule", sSource ); +} + +MacroSnippet::MacroSnippet( const OUString& sSource ) + : mbError(false) +{ + InitSnippet(); + MakeModule( sSource ); +} + +MacroSnippet::MacroSnippet() + : mbError(false) +{ + InitSnippet(); +} + +void MacroSnippet::LoadSourceFromFile( const OUString& sMacroFileURL ) +{ + OUString sSource; + fprintf(stderr,"loadSource opening macro file %s\n", OUStringToOString( sMacroFileURL, RTL_TEXTENCODING_UTF8 ).getStr() ); + + osl::File aFile(sMacroFileURL); + if(aFile.open(osl_File_OpenFlag_Read) == osl::FileBase::E_None) + { + sal_uInt64 size; + sal_uInt64 size_read; + if(aFile.getSize(size) == osl::FileBase::E_None) + { + void* buffer = calloc(1, size+1); + CPPUNIT_ASSERT(buffer); + if(aFile.read( buffer, size, size_read) == osl::FileBase::E_None) + { + if(size == size_read) + { + OUString sCode(static_cast<char*>(buffer), size, RTL_TEXTENCODING_UTF8); + sSource = sCode; + } + } + + free(buffer); + } + } + CPPUNIT_ASSERT_MESSAGE( "Source is empty", ( sSource.getLength() > 0 ) ); + MakeModule( sSource ); +} + +SbxVariableRef MacroSnippet::Run( const css::uno::Sequence< css::uno::Any >& rArgs ) +{ + SbxVariableRef pReturn; + if ( !Compile() ) + return pReturn; + SbMethod* pMeth = mpMod.is() ? static_cast<SbMethod*>(mpMod->Find( "doUnitTest", SbxClassType::Method )) : nullptr; + if ( pMeth ) + { + if ( rArgs.hasElements() ) + { + SbxArrayRef aArgs = new SbxArray; + for ( int i=0; i < rArgs.getLength(); ++i ) + { + SbxVariable* pVar = new SbxVariable(); + unoToSbxValue( pVar, rArgs[ i ] ); + aArgs->Put32( pVar, i + 1 ); + } + pMeth->SetParameters( aArgs.get() ); + } + pReturn = new SbxMethod( *static_cast<SbxMethod*>(pMeth)); + } + return pReturn; +} + +SbxVariableRef MacroSnippet::Run() +{ + css::uno::Sequence< css::uno::Any > aArgs; + return Run( aArgs ); +} + +bool MacroSnippet::Compile() +{ + CPPUNIT_ASSERT_MESSAGE("module is NULL", mpMod.get() != nullptr ); + mpMod->Compile(); + return !mbError; +} + +bool MacroSnippet::HasError() const { return mbError; } + +const ErrCode& MacroSnippet::getError() const { return maErrCode; } + +IMPL_LINK( MacroSnippet, BasicErrorHdl, StarBASIC *, /*pBasic*/, bool) +{ + fprintf(stderr,"(%d:%d)\n", + StarBASIC::GetLine(), StarBASIC::GetCol1()); + fprintf(stderr,"Basic error: %s\n", OUStringToOString( StarBASIC::GetErrorText(), RTL_TEXTENCODING_UTF8 ).getStr() ); + mbError = true; + maErrCode = StarBASIC::GetErrorCode(); + return false; +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basic/qa/cppunit/basictest.hxx b/basic/qa/cppunit/basictest.hxx new file mode 100644 index 000000000..c8d262ee6 --- /dev/null +++ b/basic/qa/cppunit/basictest.hxx @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef INCLUDED_BASIC_QA_CPPUNIT_BASICTEST_HXX +#define INCLUDED_BASIC_QA_CPPUNIT_BASICTEST_HXX + +#include <sal/types.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/plugin/TestPlugIn.h> +#include <test/bootstrapfixture.hxx> +#include <basic/sbstar.hxx> +#include <basic/basrdll.hxx> +#include <basic/sbmod.hxx> +#include <basic/sbmeth.hxx> +#include <basic/sbuno.hxx> + +class MacroSnippet +{ +private: + bool mbError; + ErrCode maErrCode; + BasicDLL maDll; // we need a dll instance for resource manager etc. + SbModuleRef mpMod; + StarBASICRef mpBasic; + + void InitSnippet(); + void MakeModule( const OUString& sSource ); + +public: + explicit MacroSnippet( const OUString& sSource ); + MacroSnippet(); + + void LoadSourceFromFile( const OUString& sMacroFileURL ); + + SbxVariableRef Run( const css::uno::Sequence< css::uno::Any >& rArgs ); + + SbxVariableRef Run(); + + bool Compile(); + + DECL_LINK( BasicErrorHdl, StarBASIC *, bool ); + + bool HasError() const; + const ErrCode& getError() const; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basic/qa/cppunit/test_append.cxx b/basic/qa/cppunit/test_append.cxx new file mode 100644 index 000000000..7ff58012b --- /dev/null +++ b/basic/qa/cppunit/test_append.cxx @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "basictest.hxx" + +namespace +{ + class EnableTest : public test::BootstrapFixture + { + public: + EnableTest() : BootstrapFixture(true, false) {}; + void testDimEnable(); + void testWin64(); + void testEnableRuntime(); + // Adds code needed to register the test suite + CPPUNIT_TEST_SUITE(EnableTest); + + // Declares the method as a test to call + CPPUNIT_TEST(testDimEnable); + CPPUNIT_TEST(testWin64); + CPPUNIT_TEST(testEnableRuntime); + + // End of test suite definition + CPPUNIT_TEST_SUITE_END(); + }; + +OUString sTestEnableRuntime( + "Function doUnitTest as Integer\n" + "Dim Enable as Integer\n" + "Enable = 1\n" + "Enable = Enable + 2\n" + "doUnitTest = Enable\n" + "End Function\n" +); + +OUString sTestDimEnable( + "Sub doUnitTest\n" + "Dim Enable as String\n" + "End Sub\n" +); + +void EnableTest::testEnableRuntime() +{ + MacroSnippet myMacro(sTestEnableRuntime); + myMacro.Compile(); + CPPUNIT_ASSERT_MESSAGE("testEnableRuntime fails with compile error",!myMacro.HasError() ); + SbxVariableRef pNew = myMacro.Run(); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(3), pNew->GetInteger()); +} + +void EnableTest::testDimEnable() +{ + MacroSnippet myMacro(sTestDimEnable); + myMacro.Compile(); + CPPUNIT_ASSERT_MESSAGE("Dim causes compile error", !myMacro.HasError() ); +} + +void EnableTest::testWin64() +{ + OUString aSource1 = " #If Win64\n" + "Declare PtrSafe Function aht_apiGetOpenFileName Lib \"comdlg32.dll\"" + "\n" + "#End if\n"; + + MacroSnippet myMacro(aSource1); + myMacro.Compile(); + CPPUNIT_ASSERT_MESSAGE("#if Win64 Declare PtrSafe causes compile error", !myMacro.HasError() ); +} + + // Put the test suite in the registry + CPPUNIT_TEST_SUITE_REGISTRATION(EnableTest); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basic/qa/cppunit/test_compiler_checks.cxx b/basic/qa/cppunit/test_compiler_checks.cxx new file mode 100644 index 000000000..24b380ed2 --- /dev/null +++ b/basic/qa/cppunit/test_compiler_checks.cxx @@ -0,0 +1,36 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/config.h> +#include "basictest.hxx" +#include <basic/sberrors.hxx> +#include <unotest/bootstrapfixturebase.hxx> + +CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testRedefineArgument) +{ + MacroSnippet aMacro("Sub doUnitTest(argName)\n" + " If False Then\n" + " Dim argName\n" + " End If\n" + "End Sub\n"); + aMacro.Compile(); + CPPUNIT_ASSERT(aMacro.HasError()); + CPPUNIT_ASSERT_EQUAL(ERRCODE_BASIC_VAR_DEFINED, aMacro.getError().StripDynamic()); +} + +CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testDoubleArgument) +{ + MacroSnippet aMacro("Sub doUnitTest(argName, argName)\n" + "End Sub\n"); + aMacro.Compile(); + CPPUNIT_ASSERT(aMacro.HasError()); + CPPUNIT_ASSERT_EQUAL(ERRCODE_BASIC_VAR_DEFINED, aMacro.getError().StripDynamic()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/basic/qa/cppunit/test_language_conditionals.cxx b/basic/qa/cppunit/test_language_conditionals.cxx new file mode 100644 index 000000000..53d6b6ec4 --- /dev/null +++ b/basic/qa/cppunit/test_language_conditionals.cxx @@ -0,0 +1,173 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "basictest.hxx" +#include <rtl/ustring.hxx> + +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> + +namespace +{ +class Language_Conditionals : public CppUnit::TestFixture +{ +public: + void testIfNot(); + void testIfAndNot(); + void testNENot(); + + CPPUNIT_TEST_SUITE(Language_Conditionals); + + CPPUNIT_TEST(testIfNot); + CPPUNIT_TEST(testIfAndNot); + CPPUNIT_TEST(testNENot); + + CPPUNIT_TEST_SUITE_END(); +}; + +void Language_Conditionals::testIfNot() +{ + { // need a block to ensure MacroSnippet is cleaned properly + const OUString aSnippet("Option VBASupport 1\n" + "Option Explicit\n" + "\n" + "Function doUnitTest() As Integer\n" + "Dim op1 As Boolean\n" + "op1 = False\n" + "If Not op1 Then\n" + "doUnitTest = 1\n" + "Else\n" + "doUnitTest = 0\n" + "End If\n" + "End Function\n"); + MacroSnippet myMacro(aSnippet); + myMacro.Compile(); + CPPUNIT_ASSERT(!myMacro.HasError()); + SbxVariableRef pNew = myMacro.Run(); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(1), pNew->GetInteger()); + } + { // need a block to ensure MacroSnippet is cleaned properly + const OUString aSnippet("Option VBASupport 0\n" + "Option Explicit\n" + "\n" + "Function doUnitTest() As Integer\n" + "Dim op1 As Boolean\n" + "op1 = False\n" + "If Not op1 Then\n" + "doUnitTest = 1\n" + "Else\n" + "doUnitTest = 0\n" + "End If\n" + "End Function\n"); + MacroSnippet myMacro(aSnippet); + myMacro.Compile(); + CPPUNIT_ASSERT(!myMacro.HasError()); + SbxVariableRef pNew = myMacro.Run(); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(1), pNew->GetInteger()); + } +} + +void Language_Conditionals::testIfAndNot() +{ + { // need a block to ensure MacroSnippet is cleaned properly + const OUString aSnippet("Option VBASupport 1\n" + "Option Explicit\n" + "\n" + "Function doUnitTest() As Integer\n" + "Dim op1 As Boolean\n" + "Dim op2 As Boolean\n" + "op1 = True\n" + "op2 = False\n" + "If op1 And Not op2 Then\n" + "doUnitTest = 1\n" + "Else\n" + "doUnitTest = 0\n" + "End If\n" + "End Function\n"); + MacroSnippet myMacro(aSnippet); + myMacro.Compile(); + CPPUNIT_ASSERT(!myMacro.HasError()); + SbxVariableRef pNew = myMacro.Run(); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(1), pNew->GetInteger()); + } + { // need a block to ensure MacroSnippet is cleaned properly + const OUString aSnippet("Option VBASupport 0\n" + "Option Explicit\n" + "\n" + "Function doUnitTest() As Integer\n" + "Dim op1 As Boolean\n" + "Dim op2 As Boolean\n" + "op1 = True\n" + "op2 = False\n" + "If op1 And Not op2 Then\n" + "doUnitTest = 1\n" + "Else\n" + "doUnitTest = 0\n" + "End If\n" + "End Function\n"); + MacroSnippet myMacro(aSnippet); + myMacro.Compile(); + CPPUNIT_ASSERT(!myMacro.HasError()); + SbxVariableRef pNew = myMacro.Run(); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(1), pNew->GetInteger()); + } +} + +void Language_Conditionals::testNENot() +{ + { // need a block to ensure MacroSnippet is cleaned properly + const OUString aSnippet("Option VBASupport 1\n" + "Option Explicit\n" + "\n" + "Function doUnitTest() As Integer\n" + "Dim op1 As Boolean\n" + "Dim op2 As Boolean\n" + "op1 = False\n" + "op2 = False\n" + "If op1 <> Not op2 Then\n" + "doUnitTest = 1\n" + "Else\n" + "doUnitTest = 0\n" + "End If\n" + "End Function\n"); + MacroSnippet myMacro(aSnippet); + myMacro.Compile(); + CPPUNIT_ASSERT(!myMacro.HasError()); + SbxVariableRef pNew = myMacro.Run(); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(1), pNew->GetInteger()); + } + { // need a block to ensure MacroSnippet is cleaned properly + const OUString aSnippet("Option VBASupport 0\n" + "Option Explicit\n" + "\n" + "Function doUnitTest() As Integer\n" + "Dim op1 As Boolean\n" + "Dim op2 As Boolean\n" + "op1 = False\n" + "op2 = False\n" + "If op1 <> Not op2 Then\n" + "doUnitTest = 1\n" + "Else\n" + "doUnitTest = 0\n" + "End If\n" + "End Function\n"); + MacroSnippet myMacro(aSnippet); + myMacro.Compile(); + CPPUNIT_ASSERT(!myMacro.HasError()); + SbxVariableRef pNew = myMacro.Run(); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(1), pNew->GetInteger()); + } +} + +CPPUNIT_TEST_SUITE_REGISTRATION(Language_Conditionals); + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/basic/qa/cppunit/test_nested_struct.cxx b/basic/qa/cppunit/test_nested_struct.cxx new file mode 100644 index 000000000..009d832b1 --- /dev/null +++ b/basic/qa/cppunit/test_nested_struct.cxx @@ -0,0 +1,303 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#include "basictest.hxx" + +#include <com/sun/star/awt/WindowDescriptor.hpp> +#include <com/sun/star/table/TableBorder.hpp> +#include <basic/sbuno.hxx> + +namespace +{ + using namespace com::sun::star; + class Nested_Struct : public test::BootstrapFixture + { + public: + Nested_Struct(): BootstrapFixture(true, false) {}; + void testAssign1(); + void testAssign1Alt(); // result is uno-ised and tested + void testOldAssign(); + void testOldAssignAlt(); // result is uno-ised and tested + void testUnfixedVarAssign(); + void testUnfixedVarAssignAlt(); // result is uno-ised and tested + void testFixedVarAssign(); + void testFixedVarAssignAlt(); // result is uno-ised and tested + void testUnoAccess(); // fdo#60117 specific test + + // Adds code needed to register the test suite + CPPUNIT_TEST_SUITE(Nested_Struct); + + // Declares the method as a test to call + CPPUNIT_TEST(testAssign1); + CPPUNIT_TEST(testAssign1Alt); + CPPUNIT_TEST(testOldAssign); + CPPUNIT_TEST(testOldAssignAlt); + CPPUNIT_TEST(testUnfixedVarAssign); + CPPUNIT_TEST(testUnfixedVarAssignAlt); + CPPUNIT_TEST(testFixedVarAssign); + CPPUNIT_TEST(testFixedVarAssignAlt); + CPPUNIT_TEST(testUnoAccess); + + // End of test suite definition + CPPUNIT_TEST_SUITE_END(); + }; + +// tests the new behaviour, we should be able to +// directly modify the value of the nested 'HorizontalLine' struct +OUString sTestSource1( + "Function doUnitTest() as Integer\n" + "Dim b0 as new \"com.sun.star.table.TableBorder\"\n" + "b0.HorizontalLine.OuterLineWidth = 9\n" + "doUnitTest = b0.HorizontalLine.OuterLineWidth\n" + "End Function\n" +); + +OUString sTestSource1Alt( + "Function doUnitTest() as Object\n" + "Dim b0 as new \"com.sun.star.table.TableBorder\"\n" + "b0.HorizontalLine.OuterLineWidth = 9\n" + "doUnitTest = b0\n" + "End Function\n" +); + +// tests the old behaviour, we should still be able +// to use the old workaround of +// a) creating a new instance BorderLine, +// b) cloning the new instance with the value of b0.HorizontalLine +// c) modifying the new instance +// d) setting b0.HorizontalLine with the value of the new instance +OUString sTestSource2( + "Function doUnitTest()\n" + "Dim b0 as new \"com.sun.star.table.TableBorder\", l as new \"com.sun.star.table.BorderLine\"\n" + "l = b0.HorizontalLine\n" + "l.OuterLineWidth = 9\n" + "b0.HorizontalLine = l\n" + "doUnitTest = b0.HorizontalLine.OuterLineWidth\n" +"End Function\n" +); + +OUString sTestSource2Alt( + "Function doUnitTest()\n" + "Dim b0 as new \"com.sun.star.table.TableBorder\", l as new \"com.sun.star.table.BorderLine\"\n" + "l = b0.HorizontalLine\n" + "l.OuterLineWidth = 9\n" + "b0.HorizontalLine = l\n" + "doUnitTest = b0\n" +"End Function\n" +); +// it should be legal to assign a variant to a struct ( and copy by val ) +// make sure we aren't copying by reference, we make sure that l is not +// a reference copy of b0.HorizontalLine, each one should have an +// OuterLineWidth of 4 & 9 respectively and we should be returning +// 13 the sum of the two ( hopefully unique values if we haven't copied by reference ) +OUString sTestSource3( + "Function doUnitTest()\n" + "Dim b0 as new \"com.sun.star.table.TableBorder\"\n" + "l = b0.HorizontalLine\n" + "l.OuterLineWidth = 9\n" + "b0.HorizontalLine = l\n" + "l.OuterLineWidth = 4\n" + "doUnitTest = b0.HorizontalLine.OuterLineWidth + l.OuterLineWidth\n" +"End Function\n" +); + +OUString sTestSource3Alt( + "Function doUnitTest()\n" + "Dim b0 as new \"com.sun.star.table.TableBorder\"\n" + "l = b0.HorizontalLine\n" + "l.OuterLineWidth = 9\n" + "b0.HorizontalLine = l\n" + "l.OuterLineWidth = 4\n" + "Dim result(1)\n" + "result(0) = b0\n" + "result(1) = l\n" + "doUnitTest = result\n" +"End Function\n" +); + +// nearly the same as above but this time for a fixed type +// variable +OUString sTestSource4( + "Function doUnitTest()\n" + "Dim b0 as new \"com.sun.star.table.TableBorder\", l as new \"com.sun.star.table.BorderLine\"\n" + "l = b0.HorizontalLine\n" + "l.OuterLineWidth = 9\n" + "b0.HorizontalLine = l\n" + "l.OuterLineWidth = 4\n" + "doUnitTest = b0.HorizontalLine.OuterLineWidth + l.OuterLineWidth\n" +"End Function\n" +); + +OUString sTestSource4Alt( + "Function doUnitTest()\n" + "Dim b0 as new \"com.sun.star.table.TableBorder\", l as new \"com.sun.star.table.BorderLine\"\n" + "l = b0.HorizontalLine\n" + "l.OuterLineWidth = 9\n" + "b0.HorizontalLine = l\n" + "l.OuterLineWidth = 4\n" + "Dim result(1)\n" + "result(0) = b0\n" + "result(1) = l\n" + "doUnitTest = result\n" +"End Function\n" +); + +// Although basic might appear to correctly change nested struct elements +// fdo#60117 shows that basic can be fooled ( and even the watch(ed) variable +// in the debugger shows the expected values ) +// We need to additionally check the actual uno struct to see if the +// changes made are *really* reflected in the object +OUString sTestSource5( + "Function doUnitTest() as Object\n" + "Dim aWinDesc as new \"com.sun.star.awt.WindowDescriptor\"\n" + "Dim aRect as new \"com.sun.star.awt.Rectangle\"\n" + "aRect.X = 200\n" + "aWinDesc.Bounds = aRect\n" + "doUnitTest = aWinDesc\n" +"End Function\n" +); + + +void Nested_Struct::testAssign1() +{ + MacroSnippet myMacro( sTestSource1 ); + myMacro.Compile(); + CPPUNIT_ASSERT_MESSAGE("testAssign1 fails with compile error",!myMacro.HasError() ); + SbxVariableRef pNew = myMacro.Run(); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(9), pNew->GetInteger()); +} + +void Nested_Struct::testAssign1Alt() +{ + MacroSnippet myMacro( sTestSource1Alt ); + myMacro.Compile(); + CPPUNIT_ASSERT_MESSAGE("testAssign1Alt fails with compile error",!myMacro.HasError() ); + SbxVariableRef pNew = myMacro.Run(); + uno::Any aRet = sbxToUnoValue( pNew.get() ); + table::TableBorder aBorder; + aRet >>= aBorder; + + int result = aBorder.HorizontalLine.OuterLineWidth; + CPPUNIT_ASSERT_EQUAL( 9, result ); +} + +void Nested_Struct::testOldAssign() +{ + MacroSnippet myMacro( sTestSource2 ); + myMacro.Compile(); + CPPUNIT_ASSERT_MESSAGE("testOldAssign fails with compile error",!myMacro.HasError() ); + SbxVariableRef pNew = myMacro.Run(); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(9), pNew->GetInteger()); +} + +void Nested_Struct::testOldAssignAlt() +{ + MacroSnippet myMacro( sTestSource2Alt ); + myMacro.Compile(); + CPPUNIT_ASSERT_MESSAGE("testOldAssign fails with compile error",!myMacro.HasError() ); + SbxVariableRef pNew = myMacro.Run(); + uno::Any aRet = sbxToUnoValue( pNew.get() ); + table::TableBorder aBorder; + aRet >>= aBorder; + + int result = aBorder.HorizontalLine.OuterLineWidth; + CPPUNIT_ASSERT_EQUAL( 9, result ); +} + +void Nested_Struct::testUnfixedVarAssign() +{ + MacroSnippet myMacro( sTestSource3 ); + myMacro.Compile(); + CPPUNIT_ASSERT_MESSAGE("testUnfixedVarAssign fails with compile error",!myMacro.HasError() ); + // forces a broadcast + SbxVariableRef pNew = myMacro.Run(); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(13), pNew->GetInteger()); +} + +void Nested_Struct::testUnfixedVarAssignAlt() +{ + MacroSnippet myMacro( sTestSource3Alt ); + myMacro.Compile(); + CPPUNIT_ASSERT_MESSAGE("testUnfixedVarAssignAlt fails with compile error",!myMacro.HasError() ); + SbxVariableRef pNew = myMacro.Run(); + uno::Any aRet = sbxToUnoValue( pNew.get() ); + + uno::Sequence< uno::Any > aResult; + bool bRes = aRet >>= aResult; + CPPUNIT_ASSERT_EQUAL(true, bRes ); + + int result = aResult.getLength(); + // should have 2 elements in a sequence returned + CPPUNIT_ASSERT_EQUAL(2, result ); + + table::TableBorder aBorder; + aResult[0] >>= aBorder; + + table::BorderLine aBorderLine; + aResult[1] >>= aBorderLine; + result = aBorder.HorizontalLine.OuterLineWidth; + CPPUNIT_ASSERT_EQUAL(9, result ); + result = aBorderLine.OuterLineWidth; + CPPUNIT_ASSERT_EQUAL(4, result ); +} + +void Nested_Struct::testFixedVarAssign() +{ + MacroSnippet myMacro( sTestSource4 ); + myMacro.Compile(); + CPPUNIT_ASSERT_MESSAGE("testFixedVarAssign fails with compile error",!myMacro.HasError() ); + SbxVariableRef pNew = myMacro.Run(); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(13), pNew->GetInteger()); +} + +void Nested_Struct::testFixedVarAssignAlt() +{ + MacroSnippet myMacro( sTestSource4Alt ); + myMacro.Compile(); + CPPUNIT_ASSERT_MESSAGE("testFixedVarAssignAlt fails with compile error",!myMacro.HasError() ); + SbxVariableRef pNew = myMacro.Run(); + uno::Any aRet = sbxToUnoValue( pNew.get() ); + + uno::Sequence< uno::Any > aResult; + bool bRes = aRet >>= aResult; + CPPUNIT_ASSERT_EQUAL(true, bRes ); + + int result = aResult.getLength(); + // should have 2 elements in a sequence returned + CPPUNIT_ASSERT_EQUAL(2, result ); + + table::TableBorder aBorder; + aResult[0] >>= aBorder; + + table::BorderLine aBorderLine; + aResult[1] >>= aBorderLine; + result = aBorder.HorizontalLine.OuterLineWidth; + CPPUNIT_ASSERT_EQUAL(9, result ); + result = aBorderLine.OuterLineWidth; + CPPUNIT_ASSERT_EQUAL(4, result ); +} + +void Nested_Struct::testUnoAccess() +{ + MacroSnippet myMacro( sTestSource5 ); + myMacro.Compile(); + CPPUNIT_ASSERT_MESSAGE("testUnoAccess fails with compile error",!myMacro.HasError() ); + SbxVariableRef pNew = myMacro.Run(); + uno::Any aRet = sbxToUnoValue( pNew.get() ); + awt::WindowDescriptor aWinDesc; + aRet >>= aWinDesc; + + int result = aWinDesc.Bounds.X; + CPPUNIT_ASSERT_EQUAL(200, result ); +} + + // Put the test suite in the registry + CPPUNIT_TEST_SUITE_REGISTRATION(Nested_Struct); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basic/qa/cppunit/test_scanner.cxx b/basic/qa/cppunit/test_scanner.cxx new file mode 100644 index 000000000..068006128 --- /dev/null +++ b/basic/qa/cppunit/test_scanner.cxx @@ -0,0 +1,1166 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/types.h> +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/plugin/TestPlugIn.h> + +#include <rtl/math.hxx> + +#include <scanner.hxx> + +namespace +{ + struct Symbol + { + sal_uInt16 line; + sal_uInt16 col1; + OUString text; + double number; + SbxDataType type; + bool ws; + }; + + /** + * Perform tests on Scanner. + */ + class ScannerTest : public CppUnit::TestFixture + { + private: + void testBlankLines(); + void testOperators(); + void testAlphanum(); + void testComments(); + void testGoto(); + void testGotoCompatible(); + void testExclamation(); + void testNumbers(); + void testDataType(); + void testHexOctal(); + void testTdf103104(); + void testTdf136032(); + + // Adds code needed to register the test suite + CPPUNIT_TEST_SUITE(ScannerTest); + + // Declares the method as a test to call + CPPUNIT_TEST(testBlankLines); + CPPUNIT_TEST(testOperators); + CPPUNIT_TEST(testAlphanum); + CPPUNIT_TEST(testComments); + CPPUNIT_TEST(testGoto); + CPPUNIT_TEST(testGotoCompatible); + CPPUNIT_TEST(testExclamation); + CPPUNIT_TEST(testNumbers); + CPPUNIT_TEST(testDataType); + CPPUNIT_TEST(testHexOctal); + CPPUNIT_TEST(testTdf103104); + CPPUNIT_TEST(testTdf136032); + + // End of test suite definition + CPPUNIT_TEST_SUITE_END(); + }; + + static const OUString cr = "\n"; + static const OUString rem = "REM"; + static const OUString asdf = "asdf"; + static const OUString dot = "."; + static const OUString goto_ = "goto"; + static const OUString excl = "!"; + + std::vector<Symbol> getSymbols(const OUString& source, sal_Int32& errors, bool bCompatible = false) + { + std::vector<Symbol> symbols; + SbiScanner scanner(source); + scanner.EnableErrors(); + scanner.SetCompatible(bCompatible); + while(scanner.NextSym()) + { + Symbol symbol; + symbol.line = scanner.GetLine(); + symbol.col1 = scanner.GetCol1(); + symbol.text = scanner.GetSym(); + symbol.number = scanner.GetDbl(); + symbol.type = scanner.GetType(); + symbol.ws = scanner.WhiteSpace(); + symbols.push_back(symbol); + } + errors = scanner.GetErrors(); + return symbols; + } + + std::vector<Symbol> getSymbols(const OUString& source, bool bCompatible = false) + { + sal_Int32 i; + return getSymbols(source, i, bCompatible); + } + + void ScannerTest::testBlankLines() + { + const OUString source1(""); + const OUString source2("\r\n"); + const OUString source3("\n"); + const OUString source4("\r"); + const OUString source5("\r\n\r\n"); + const OUString source6("\n\r"); + const OUString source7("\n\r\n"); + const OUString source8("\r\n\r"); + const OUString source9(" "); + + std::vector<Symbol> symbols; + symbols = getSymbols(source1); + CPPUNIT_ASSERT(symbols.empty()); + + symbols = getSymbols(source2); + CPPUNIT_ASSERT_EQUAL(size_t(1), symbols.size()); + CPPUNIT_ASSERT_EQUAL(cr, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + + symbols = getSymbols(source3); + CPPUNIT_ASSERT_EQUAL(size_t(1), symbols.size()); + CPPUNIT_ASSERT_EQUAL(cr, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + + symbols = getSymbols(source4); + CPPUNIT_ASSERT_EQUAL(size_t(1), symbols.size()); + CPPUNIT_ASSERT_EQUAL(cr, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + + symbols = getSymbols(source5); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(cr, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + + symbols = getSymbols(source6); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(cr, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + + symbols = getSymbols(source7); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(cr, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + + symbols = getSymbols(source8); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(cr, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + + symbols = getSymbols(source9); + CPPUNIT_ASSERT_EQUAL(size_t(1), symbols.size()); + CPPUNIT_ASSERT_EQUAL(cr, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + } + + void ScannerTest::testOperators() + { + const OUString sourceE("="); + const OUString sourceLT("<"); + const OUString sourceGT(">"); + const OUString sourceLTE("<="); + const OUString sourceGTE(">="); + const OUString sourceEE("=="); + const OUString sourceNE("<>"); + const OUString sourceA(":="); + const OUString sourceNot("Not"); + + std::vector<Symbol> symbols; + + symbols = getSymbols(sourceE); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(sourceE, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + + symbols = getSymbols(sourceLT); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(sourceLT, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + + symbols = getSymbols(sourceGT); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(sourceGT, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + + symbols = getSymbols(sourceLTE); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(sourceLTE, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + + symbols = getSymbols(sourceGTE); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(sourceGTE, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + + symbols = getSymbols(sourceEE); + CPPUNIT_ASSERT_EQUAL(size_t(3), symbols.size()); + CPPUNIT_ASSERT_EQUAL(sourceE, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(sourceE, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[2].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[2].type); + + symbols = getSymbols(sourceNE); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(sourceNE, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + + symbols = getSymbols(sourceA); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(sourceA, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + + symbols = getSymbols(sourceNot); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(sourceNot, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + } + + void ScannerTest::testAlphanum() + { + const OUString source1("asdfghefg"); + const OUString source2("1asfdasfd"); + const OUString source3("AdfsaAUdsl10987"); + const OUString source4("asdfa_mnvcnm"); + const OUString source5("_asdf1"); + const OUString source6("_6"); + const OUString source7("joxclk_"); + const OUString source8(" asdf "); + const OUString source9(" 19395 asdfa "); + const OUString source10("\n1\n2\na sdf"); + const OUString source11("asdf.asdf"); + const OUString source12(".."); + + std::vector<Symbol> symbols; + + symbols = getSymbols(source1); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(source1, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + + symbols = getSymbols(source2); + CPPUNIT_ASSERT_EQUAL(size_t(3), symbols.size()); + CPPUNIT_ASSERT(symbols[0].text.isEmpty()); // Can't start symbol with a digit + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(OUString("asfdasfd"), symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[2].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[2].type); + + symbols = getSymbols(source3); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(source3, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + + symbols = getSymbols(source4); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(source4, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + + symbols = getSymbols(source5); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(source5, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + + symbols = getSymbols(source6); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(source6, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + + symbols = getSymbols(source7); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(OUString("joxclk_"), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(OUString("joxclk "), source7); // Change the trailing '_' to a ' ' + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + + symbols = getSymbols(source8); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(OUString("asdf"), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + + symbols = getSymbols(source9); + CPPUNIT_ASSERT_EQUAL(size_t(3), symbols.size()); + CPPUNIT_ASSERT(symbols[0].text.isEmpty()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(19395.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(OUString("asdfa"), symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[2].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[2].type); + + symbols = getSymbols(source10); + CPPUNIT_ASSERT_EQUAL(size_t(8), symbols.size()); + CPPUNIT_ASSERT_EQUAL(cr, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT(symbols[1].text.isEmpty()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, symbols[1].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[1].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[2].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[2].type); + CPPUNIT_ASSERT(symbols[3].text.isEmpty()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0, symbols[3].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[3].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[4].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[4].type); + CPPUNIT_ASSERT_EQUAL(1u, static_cast<unsigned int>(symbols[5].text.getLength())); + CPPUNIT_ASSERT_EQUAL('a', static_cast<char>(symbols[5].text[0])); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[5].type); + CPPUNIT_ASSERT_EQUAL(OUString("sdf"), symbols[6].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[6].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[7].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[7].type); + + symbols = getSymbols(source11); + CPPUNIT_ASSERT_EQUAL(size_t(4), symbols.size()); + CPPUNIT_ASSERT_EQUAL(asdf, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(dot, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + CPPUNIT_ASSERT_EQUAL(asdf, symbols[2].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[2].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[3].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[3].type); + + symbols = getSymbols(source12); + CPPUNIT_ASSERT_EQUAL(size_t(3), symbols.size()); + CPPUNIT_ASSERT_EQUAL(dot, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(dot, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[2].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[2].type); + } + + void ScannerTest::testComments() + { + const OUString source1("REM asdf"); + const OUString source2("REMasdf"); + const OUString source3("'asdf"); + const OUString source4("asdf _\n'100"); + const OUString source5("'asdf _\n100"); + const OUString source6("'asdf _\n'100"); + const OUString source7("'asdf _\n 1234 _\n asdf'"); + + std::vector<Symbol> symbols; + + symbols = getSymbols(source1); + CPPUNIT_ASSERT_EQUAL(size_t(1), symbols.size()); + CPPUNIT_ASSERT_EQUAL(rem, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + + symbols = getSymbols(source2); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(OUString("REMasdf"), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + + symbols = getSymbols(source3); + CPPUNIT_ASSERT_EQUAL(size_t(1), symbols.size()); + CPPUNIT_ASSERT_EQUAL(rem, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + + symbols = getSymbols(source4); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(asdf, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(rem, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + + symbols = getSymbols(source5); + CPPUNIT_ASSERT_EQUAL(size_t(3), symbols.size()); + CPPUNIT_ASSERT_EQUAL(rem, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT(symbols[1].text.isEmpty()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(100.0, symbols[1].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[1].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[2].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[2].type); + + symbols = getSymbols(source6); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(rem, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(rem, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + + symbols = getSymbols(source7); + CPPUNIT_ASSERT_EQUAL(size_t(4), symbols.size()); + CPPUNIT_ASSERT_EQUAL(rem, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT(symbols[1].text.isEmpty()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1234.0, symbols[1].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[1].type); + CPPUNIT_ASSERT_EQUAL(asdf, symbols[2].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[2].type); + CPPUNIT_ASSERT_EQUAL(rem, symbols[3].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[3].type); + } + + void ScannerTest::testGoto() + { + const OUString source1("goto"); + const OUString source2("go to"); + const OUString source3("go\nto"); + + std::vector<Symbol> symbols; + + symbols = getSymbols(source1); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(goto_, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + + symbols = getSymbols(source2); + CPPUNIT_ASSERT_EQUAL(size_t(3), symbols.size()); + CPPUNIT_ASSERT_EQUAL(OUString("go"), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(OUString("to"), symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[2].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[2].type); + + symbols = getSymbols(source3); + CPPUNIT_ASSERT_EQUAL(size_t(4), symbols.size()); + CPPUNIT_ASSERT_EQUAL(OUString("go"), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + CPPUNIT_ASSERT_EQUAL(OUString("to"), symbols[2].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[2].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[3].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[3].type); + } + + void ScannerTest::testGotoCompatible() + { + const OUString source1("goto"); + const OUString source2("go to"); + const OUString source3("go\nto"); + + std::vector<Symbol> symbols; + + symbols = getSymbols(source1, true); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(goto_, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + symbols = getSymbols(source2, true); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(goto_, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + symbols = getSymbols(source3, true); + CPPUNIT_ASSERT_EQUAL(size_t(4), symbols.size()); + CPPUNIT_ASSERT_EQUAL(OUString("go"), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(OUString("to"), symbols[2].text); + CPPUNIT_ASSERT_EQUAL(cr, symbols[3].text); + } + + void ScannerTest::testExclamation() + { + const OUString source1("asdf!asdf"); + const OUString source2("!1234"); + const OUString source3("!_3"); + const OUString source4("!$"); + const OUString source5("!%"); + const OUString source6("!\n"); + + std::vector<Symbol> symbols; + + symbols = getSymbols(source1); + CPPUNIT_ASSERT_EQUAL(size_t(4), symbols.size()); + CPPUNIT_ASSERT_EQUAL(asdf, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(excl, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(asdf, symbols[2].text); + CPPUNIT_ASSERT_EQUAL(cr, symbols[3].text); + + symbols = getSymbols(source2); + CPPUNIT_ASSERT_EQUAL(size_t(3), symbols.size()); + CPPUNIT_ASSERT_EQUAL(excl, symbols[0].text); + CPPUNIT_ASSERT(symbols[1].text.isEmpty()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1234.0, symbols[1].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(cr, symbols[2].text); + + symbols = getSymbols(source3); + CPPUNIT_ASSERT_EQUAL(size_t(3), symbols.size()); + CPPUNIT_ASSERT_EQUAL(excl, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(OUString("_3"), symbols[1].text); + CPPUNIT_ASSERT_EQUAL(cr, symbols[2].text); + + symbols = getSymbols(source4); + CPPUNIT_ASSERT_EQUAL(size_t(3), symbols.size()); + CPPUNIT_ASSERT_EQUAL(excl, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(OUString("$"), symbols[1].text); + CPPUNIT_ASSERT_EQUAL(cr, symbols[2].text); + + symbols = getSymbols(source5); + CPPUNIT_ASSERT_EQUAL(size_t(3), symbols.size()); + CPPUNIT_ASSERT_EQUAL(excl, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(OUString("%"), symbols[1].text); + CPPUNIT_ASSERT_EQUAL(cr, symbols[2].text); + + symbols = getSymbols(source6); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(excl, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + } + + void ScannerTest::testNumbers() + { + const OUString source1("12345"); + const OUString source2("1.2.3"); + const OUString source3("123.4"); + const OUString source4("0.5"); + const OUString source5("5.0"); + const OUString source6("0.0"); + const OUString source7("-3"); + const OUString source8("-0.0"); + const OUString source9("12dE3"); + const OUString source10("12e3"); + const OUString source11("12D+3"); + const OUString source12("12e++3"); + const OUString source13("12e-3"); + const OUString source14("12e-3+"); + const OUString source15("1,2,3"); + const OUString source16("1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); + const OUString source17("10e308"); + + std::vector<Symbol> symbols; + sal_Int32 errors; + + symbols = getSymbols(source1, errors); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(12345.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(0u, static_cast<unsigned int>(errors)); + + symbols = getSymbols(source2, errors); + CPPUNIT_ASSERT_EQUAL(size_t(3), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.2, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxDOUBLE, symbols[0].type); + CPPUNIT_ASSERT_DOUBLES_EQUAL(.3, symbols[1].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxDOUBLE, symbols[1].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[2].text); + CPPUNIT_ASSERT_EQUAL(1u, static_cast<unsigned int>(errors)); + + symbols = getSymbols(source3, errors); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(123.4, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxDOUBLE, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(0u, static_cast<unsigned int>(errors)); + + symbols = getSymbols(source4, errors); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(.5, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxDOUBLE, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(0u, static_cast<unsigned int>(errors)); + + symbols = getSymbols(source5, errors); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(5.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxDOUBLE, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(0u, static_cast<unsigned int>(errors)); + + symbols = getSymbols(source6, errors); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxDOUBLE, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(0u, static_cast<unsigned int>(errors)); + + symbols = getSymbols(source7, errors); + CPPUNIT_ASSERT_EQUAL(size_t(3), symbols.size()); + CPPUNIT_ASSERT_EQUAL(OUString("-"), symbols[0].text); + CPPUNIT_ASSERT_DOUBLES_EQUAL(3.0, symbols[1].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[1].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[2].text); + CPPUNIT_ASSERT_EQUAL(0u, static_cast<unsigned int>(errors)); + + symbols = getSymbols(source8, errors); + CPPUNIT_ASSERT_EQUAL(size_t(3), symbols.size()); + CPPUNIT_ASSERT_EQUAL(OUString("-"), symbols[0].text); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, symbols[1].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxDOUBLE, symbols[1].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[2].text); + CPPUNIT_ASSERT_EQUAL(0u, static_cast<unsigned int>(errors)); + + symbols = getSymbols(source9, errors); + CPPUNIT_ASSERT_EQUAL(size_t(3), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(12.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxDOUBLE, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(OUString("dE3"), symbols[1].text); + CPPUNIT_ASSERT_EQUAL(cr, symbols[2].text); + CPPUNIT_ASSERT_EQUAL(1u, static_cast<unsigned int>(errors)); + + symbols = getSymbols(source10, errors); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(12000.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxDOUBLE, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(0u, static_cast<unsigned int>(errors)); + + symbols = getSymbols(source11, errors); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(12000.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxDOUBLE, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(0u, static_cast<unsigned int>(errors)); + + symbols = getSymbols(source12, errors); + CPPUNIT_ASSERT_EQUAL(size_t(6), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(12.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxDOUBLE, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(OUString("e"), symbols[1].text); + CPPUNIT_ASSERT_EQUAL(OUString("+"), symbols[2].text); + CPPUNIT_ASSERT_EQUAL(OUString("+"), symbols[3].text); + CPPUNIT_ASSERT_DOUBLES_EQUAL(3.0, symbols[4].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[4].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[5].text); + CPPUNIT_ASSERT_EQUAL(1u, static_cast<unsigned int>(errors)); + + symbols = getSymbols(source13, errors); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(.012, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxDOUBLE, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(0u, static_cast<unsigned int>(errors)); + + symbols = getSymbols(source14, errors); + CPPUNIT_ASSERT_EQUAL(size_t(3), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(.012, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxDOUBLE, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(OUString("+"), symbols[1].text); + CPPUNIT_ASSERT_EQUAL(cr, symbols[2].text); + CPPUNIT_ASSERT_EQUAL(0u, static_cast<unsigned int>(errors)); + + symbols = getSymbols(source15, errors); + CPPUNIT_ASSERT_EQUAL(size_t(6), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(OUString(","), symbols[1].text); + CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0, symbols[2].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[2].type); + CPPUNIT_ASSERT_EQUAL(OUString(","), symbols[3].text); + CPPUNIT_ASSERT_DOUBLES_EQUAL(3.0, symbols[4].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[4].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[5].text); + CPPUNIT_ASSERT_EQUAL(0u, static_cast<unsigned int>(errors)); + + symbols = getSymbols(source16, errors); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxDOUBLE, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + // This error is from a "buffer overflow" which is stupid because + // the buffer is artificially constrained by the scanner. + CPPUNIT_ASSERT_EQUAL(1u, static_cast<unsigned int>(errors)); // HACK + + double fInf = 0.0; + rtl::math::setInf( &fInf, false); + symbols = getSymbols(source17, errors); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(fInf, symbols[0].number); + CPPUNIT_ASSERT_EQUAL(SbxDOUBLE, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(1u, static_cast<unsigned int>(errors)); // math error, overflow + + // trailing data type character % = SbxINTEGER + symbols = getSymbols("1.23%"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.23, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + // trailing data type character & = SbxLONG + symbols = getSymbols("1.23&"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.23, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxLONG, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + // trailing data type character ! = SbxSINGLE + symbols = getSymbols("1.23!"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.23, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxSINGLE, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + // trailing data type character # = SbxDOUBLE + symbols = getSymbols("1.23#"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.23, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxDOUBLE, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + // trailing data type character @ = SbxCURRENCY + symbols = getSymbols("1.23@"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.23, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxCURRENCY, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + // trailing data type character $ = SbxSTRING + symbols = getSymbols("1.23$", errors); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.23, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxSTRING, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + // ERRCODE_BASIC_SYNTAX + CPPUNIT_ASSERT_EQUAL(1u, static_cast<unsigned int>(errors)); + } + + void ScannerTest::testDataType() + { + const OUString source1("asdf%"); + const OUString source2("asdf&"); + const OUString source3("asdf!"); + const OUString source4("asdf#"); + const OUString source5("asdf@"); + const OUString source6("asdf$"); + const OUString source7("asdf "); + + std::vector<Symbol> symbols; + + symbols = getSymbols(source1); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + symbols = getSymbols(source2); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(SbxLONG, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + symbols = getSymbols(source3); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(SbxSINGLE, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + symbols = getSymbols(source4); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(SbxDOUBLE, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + symbols = getSymbols(source5); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(SbxCURRENCY, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + symbols = getSymbols(source6); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(SbxSTRING, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + symbols = getSymbols(source7); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + } + + void ScannerTest::testHexOctal() + { + const OUString source1("&HA"); + const OUString source2("&HASDF"); + const OUString source3("&H10"); + const OUString source4("&&H&1H1&H1"); + const OUString source5("&O&O12"); + const OUString source6("&O10"); + const OUString source7("&HO"); + const OUString source8("&O123000000000000000000000"); + const OUString source9("&H1.23"); + + sal_Int32 errors; + std::vector<Symbol> symbols; + + symbols = getSymbols(source1); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(10.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + symbols = getSymbols(source2); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(2783.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + symbols = getSymbols(source3); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(16.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + symbols = getSymbols(source4); + CPPUNIT_ASSERT_EQUAL(size_t(6), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString("&"), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, symbols[1].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxLONG, symbols[1].type); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, symbols[2].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[2].text); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[2].type); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, symbols[3].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString("H1"), symbols[3].text); + CPPUNIT_ASSERT_EQUAL(SbxLONG, symbols[3].type); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, symbols[4].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString("H1"), symbols[4].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[4].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[5].text); + + symbols = getSymbols(source5); + CPPUNIT_ASSERT_EQUAL(size_t(3), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxLONG, symbols[0].type); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, symbols[1].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString("O12"), symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[2].text); + + symbols = getSymbols(source6); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(8.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + symbols = getSymbols(source7); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + symbols = getSymbols(source8); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + // TODO: this line fails on 64 bit systems!!! + // CPPUNIT_ASSERT_EQUAL(symbols[0].number, -1744830464); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + symbols = getSymbols(source9); + CPPUNIT_ASSERT_EQUAL(size_t(3), symbols.size()); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[0].type); + CPPUNIT_ASSERT_DOUBLES_EQUAL(.23, symbols[1].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxDOUBLE, symbols[1].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[2].text); + + /* tdf#62323, tdf#62326 - conversion of Hex literals to basic signed Integers */ + + // &H0 = 0 + symbols = getSymbols("&H0"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + // &H8000 = -32768 + symbols = getSymbols("&H8000"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(SbxMININT, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + // &H80000000 = -2147483648 + symbols = getSymbols("&H80000000"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(SbxMINLNG, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxLONG, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + // &HFFFF = -1 + symbols = getSymbols("&HFFFF"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-1.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + // &HFFFFFFFF = -1 + symbols = getSymbols("&HFFFFFFFF"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-1.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + // &H7FFF = 32767 + symbols = getSymbols("&H7FFF"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(SbxMAXINT, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + // &H7FFFFFFF = 2147483647 + symbols = getSymbols("&H7FFFFFFF"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(SbxMAXLNG, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxLONG, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + /* tdf#130476 - trailing data type characters */ + + // % = SbxINTEGER + symbols = getSymbols("&H0%"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + // & = SbxLONG + symbols = getSymbols("&H0&"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxLONG, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + // ! = SbxSINGLE + symbols = getSymbols("&H0!"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxSINGLE, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + // # = SbxDOUBLE + symbols = getSymbols("&H0#"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxDOUBLE, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + // @ = SbxCURRENCY + symbols = getSymbols("&H0@"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxCURRENCY, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + // $ = SbxSTRING + symbols = getSymbols("&H0$", errors); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxSTRING, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + // ERRCODE_BASIC_SYNTAX + CPPUNIT_ASSERT_EQUAL(1u, static_cast<unsigned int>(errors)); + + // % = SbxINTEGER + symbols = getSymbols("&O0%"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + // & = SbxLONG + symbols = getSymbols("&O0&"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxLONG, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + // ! = SbxSINGLE + symbols = getSymbols("&O0!"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxSINGLE, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + // # = SbxDOUBLE + symbols = getSymbols("&O0#"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxDOUBLE, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + // @ = SbxCURRENCY + symbols = getSymbols("&O0@"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxCURRENCY, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + // $ = SbxSTRING + symbols = getSymbols("&O0$", errors); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxSTRING, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + // ERRCODE_BASIC_SYNTAX + CPPUNIT_ASSERT_EQUAL(1u, static_cast<unsigned int>(errors)); + + // maximum for Hex % = SbxINTEGER + symbols = getSymbols("&HFFFF%"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-1.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + // overflow for Hex % = SbxINTEGER + symbols = getSymbols("&H10000%", errors); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + // ERRCODE_BASIC_MATH_OVERFLOW + CPPUNIT_ASSERT_EQUAL(1u, static_cast<unsigned int>(errors)); + + // maximum for Octal % = SbxINTEGER + symbols = getSymbols("&O177777%"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-1.0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + // overflow for Octal % = SbxINTEGER + symbols = getSymbols("&O200000%", errors); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0, symbols[0].number, 1E-12); + CPPUNIT_ASSERT_EQUAL(OUString(), symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + // ERRCODE_BASIC_MATH_OVERFLOW + CPPUNIT_ASSERT_EQUAL(1u, static_cast<unsigned int>(errors)); + } + + void ScannerTest::testTdf103104() + { + const OUString source1("asdf _\n asdf"); + const OUString source2("asdf. _\n asdf"); + const OUString source3("asdf _\n .asdf"); + + std::vector<Symbol> symbols; + + symbols = getSymbols(source1); + CPPUNIT_ASSERT_EQUAL(size_t(3), symbols.size()); + CPPUNIT_ASSERT_EQUAL(asdf, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(asdf, symbols[1].text); + CPPUNIT_ASSERT(symbols[1].ws); + CPPUNIT_ASSERT_EQUAL(cr, symbols[2].text); + + symbols = getSymbols(source2); + CPPUNIT_ASSERT_EQUAL(size_t(4), symbols.size()); + CPPUNIT_ASSERT_EQUAL(asdf, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(dot, symbols[1].text); + CPPUNIT_ASSERT(!symbols[1].ws); + CPPUNIT_ASSERT_EQUAL(asdf, symbols[2].text); + CPPUNIT_ASSERT(symbols[2].ws); + CPPUNIT_ASSERT_EQUAL(cr, symbols[3].text); + + symbols = getSymbols(source3); + CPPUNIT_ASSERT_EQUAL(size_t(4), symbols.size()); + CPPUNIT_ASSERT_EQUAL(asdf, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(dot, symbols[1].text); + CPPUNIT_ASSERT(!symbols[1].ws); + CPPUNIT_ASSERT_EQUAL(asdf, symbols[2].text); + CPPUNIT_ASSERT(!symbols[2].ws); + CPPUNIT_ASSERT_EQUAL(cr, symbols[3].text); + } + + void ScannerTest::testTdf136032() + { + std::vector<Symbol> symbols; + sal_Int32 errors; + + // tdf#136032 - abort scan of a string beginning with a hashtag, + // if a comma/whitespace is found. Otherwise, the compiler raises a syntax error. + symbols = getSymbols("Print #i,\"A#B\"", errors); + CPPUNIT_ASSERT_EQUAL(size_t(5), symbols.size()); + CPPUNIT_ASSERT_EQUAL(0u, static_cast<unsigned int>(errors)); + symbols = getSymbols("Print #i, \"A#B\"", errors); + CPPUNIT_ASSERT_EQUAL(size_t(5), symbols.size()); + CPPUNIT_ASSERT_EQUAL(0u, static_cast<unsigned int>(errors)); + } + + // Put the test suite in the registry + CPPUNIT_TEST_SUITE_REGISTRATION(ScannerTest); +} // namespace +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basic/qa/cppunit/test_vba.cxx b/basic/qa/cppunit/test_vba.cxx new file mode 100644 index 000000000..235bcc2cf --- /dev/null +++ b/basic/qa/cppunit/test_vba.cxx @@ -0,0 +1,256 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#include "basictest.hxx" +#include <unotools/syslocaleoptions.hxx> + +#ifdef _WIN32 +#include <string.h> +#include <comphelper/processfactory.hxx> +#include <o3tl/char16_t2wchar_t.hxx> + +#if !defined WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include <windows.h> +#include <odbcinst.h> +#endif + +using namespace ::com::sun::star; + +namespace +{ + class VBATest : public test::BootstrapFixture + { + public: + VBATest() : BootstrapFixture(true, false) {} + void testMiscVBAFunctions(); + void testMiscOLEStuff(); + // Adds code needed to register the test suite + CPPUNIT_TEST_SUITE(VBATest); + + // Declares the method as a test to call + CPPUNIT_TEST(testMiscVBAFunctions); + CPPUNIT_TEST(testMiscOLEStuff); + + // End of test suite definition + CPPUNIT_TEST_SUITE_END(); + + }; + +void VBATest::testMiscVBAFunctions() +{ + const char* macroSource[] = { + "bytearraystring.vb", +#ifdef _WIN32 + "cdec.vb", // currently CDec is implemented only on Windows +#endif + "constants.vb", +// datevalue test seems to depend on both locale and language +// settings, should try and rewrite the test to deal with that +// for some reason tinderboxes don't seem to complain leaving enabled +// for the moment + "datevalue.vb", + "partition.vb", + "strconv.vb", + "dateserial.vb", + "format.vb", + "replace.vb", + "stringplusdouble.vb", + "chr.vb", + "abs.vb", + "array.vb", + "asc.vb", + "atn.vb", + "cbool.vb", + "cdate.vb", + "cdbl.vb", + "choose.vb", + "cos.vb", + "cint.vb", + "clng.vb", + "csng.vb", + "cstr.vb", + "cvdate.vb", + "cverr.vb", + "dateadd.vb", + "datediff.vb", + "datepart.vb", + "day.vb", + "enum.vb", + "error.vb", + "Err.Raise.vb", + "exp.vb", + "fix.vb", + "hex.vb", + "hour.vb", + "formatnumber.vb", + "iif.vb", + "instr.vb", + "instrrev.vb", + "int.vb", + "iserror.vb", + "ismissing.vb", + "isnull.vb", + "isobject.vb", + "join.vb", + "lbound.vb", + "isarray.vb", + "isdate.vb", + "isempty.vb", + "isnumeric.vb", + "lcase.vb", + "left.vb", + "len.vb", + "log.vb", + "ltrim.vb", + "mid.vb", + "minute.vb", + "month.vb", + "monthname.vb", + "oct.vb", + "optional_paramters.vb", + "qbcolor.vb", + "rgb.vb", + "rtrim.vb", + "right.vb", + "second.vb", + "sgn.vb", + "sin.vb", + "space.vb", + "sqr.vb", + "str.vb", + "strcomp.vb", + "string.vb", + "strreverse.vb", + "switch.vb", + "timeserial.vb", + "timevalue.vb", + "trim.vb", + "typename.vb", + "ubound.vb", + "ucase.vb", + "val.vb", + "vartype.vb", + "weekday.vb", + "weekdayname.vb", + "year.vb", +#ifndef _WIN32 // missing 64bit Currency marshalling. + "win32compat.vb", // windows compatibility hooks. +#endif + "win32compatb.vb" // same methods, different signatures. + }; + OUString sMacroPathURL = m_directories.getURLFromSrc("/basic/qa/vba_tests/"); + // Some test data expects the uk locale + LanguageTag aLocale(LANGUAGE_ENGLISH_UK); + SvtSysLocaleOptions aLocalOptions; + aLocalOptions.SetLocaleConfigString( aLocale.getBcp47() ); + + for ( size_t i=0; i<SAL_N_ELEMENTS( macroSource ); ++i ) + { + OUString sMacroURL = sMacroPathURL + + OUString::createFromAscii( macroSource[ i ] ); + + MacroSnippet myMacro; + myMacro.LoadSourceFromFile( sMacroURL ); + SbxVariableRef pReturn = myMacro.Run(); + CPPUNIT_ASSERT_MESSAGE("No return variable huh?", pReturn.is()); + fprintf(stderr, "macro result for %s\n", macroSource[i]); + fprintf(stderr, "macro returned:\n%s\n", + OUStringToOString(pReturn->GetOUString(), RTL_TEXTENCODING_UTF8).getStr()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Result not as expected", OUString("OK"), + pReturn->GetOUString()); + } +} + +void VBATest::testMiscOLEStuff() +{ +// Not much point even trying to run except on Windows. +// (Without Excel doesn't really do anything anyway, +// see "so skip test" below.) + +// Since some time, on a properly updated Windows 10, this works +// only with a 64-bit LibreOffice + +#if defined(_WIN64) + // test if we have the necessary runtime environment + // to run the OLE tests. + uno::Reference< lang::XMultiServiceFactory > xOLEFactory; + uno::Reference< uno::XComponentContext > xContext( + comphelper::getProcessComponentContext() ); + if( xContext.is() ) + { + uno::Reference<lang::XMultiComponentFactory> xSMgr = xContext->getServiceManager(); + xOLEFactory.set( xSMgr->createInstanceWithContext( "com.sun.star.bridge.OleObjectFactory", xContext ), + uno::UNO_QUERY ); + } + bool bOk = false; + if( xOLEFactory.is() ) + { + uno::Reference< uno::XInterface > xADODB = xOLEFactory->createInstance( "ADODB.Connection" ); + bOk = xADODB.is(); + } + if ( !bOk ) + return; // can't do anything, skip test + + const int nBufSize = 1024 * 4; + wchar_t sBuf[nBufSize]; + SQLGetInstalledDriversW( sBuf, nBufSize, nullptr ); + + const wchar_t *pODBCDriverName = sBuf; + bool bFound = false; + for (; wcslen( pODBCDriverName ) != 0; pODBCDriverName += wcslen( pODBCDriverName ) + 1 ) { + if( wcscmp( pODBCDriverName, L"Microsoft Excel Driver (*.xls)" ) == 0 || + wcscmp( pODBCDriverName, L"Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)" ) == 0 ) { + bFound = true; + break; + } + } + if ( !bFound ) + return; // can't find ODBC driver needed test, so skip test + + const char* macroSource[] = { + "ole_ObjAssignNoDflt.vb", + "ole_ObjAssignToNothing.vb", + }; + + OUString sMacroPathURL = m_directories.getURLFromSrc("/basic/qa/vba_tests/"); + + uno::Sequence< uno::Any > aArgs(2); + // path to test document + OUString sPath = m_directories.getPathFromSrc("/basic/qa/vba_tests/data/ADODBdata.xls"); + sPath = sPath.replaceAll( "/", "\\" ); + + aArgs[ 0 ] <<= sPath; + aArgs[ 1 ] <<= OUString(o3tl::toU(pODBCDriverName)); + + for ( sal_uInt32 i=0; i<SAL_N_ELEMENTS( macroSource ); ++i ) + { + OUString sMacroURL = sMacroPathURL + + OUString::createFromAscii( macroSource[ i ] ); + MacroSnippet myMacro; + myMacro.LoadSourceFromFile( sMacroURL ); + SbxVariableRef pReturn = myMacro.Run( aArgs ); + CPPUNIT_ASSERT_MESSAGE("No return variable huh?", pReturn.is()); + fprintf(stderr, "macro result for %s\n", macroSource[i]); + fprintf(stderr, "macro returned:\n%s\n", + OUStringToOString(pReturn->GetOUString(), RTL_TEXTENCODING_UTF8).getStr()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Result not as expected", OUString("OK"), + pReturn->GetOUString()); + } +#else + // Avoid "this method is empty and should be removed" warning + (void) 42; +#endif +} + + // Put the test suite in the registry + CPPUNIT_TEST_SUITE_REGISTRATION(VBATest); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |