summaryrefslogtreecommitdiffstats
path: root/basic/qa/cppunit
diff options
context:
space:
mode:
Diffstat (limited to 'basic/qa/cppunit')
-rw-r--r--basic/qa/cppunit/basic_coverage.cxx161
-rw-r--r--basic/qa/cppunit/basictest.cxx125
-rw-r--r--basic/qa/cppunit/basictest.hxx55
-rw-r--r--basic/qa/cppunit/test_append.cxx80
-rw-r--r--basic/qa/cppunit/test_compiler_checks.cxx36
-rw-r--r--basic/qa/cppunit/test_language_conditionals.cxx173
-rw-r--r--basic/qa/cppunit/test_nested_struct.cxx303
-rw-r--r--basic/qa/cppunit/test_scanner.cxx1166
-rw-r--r--basic/qa/cppunit/test_vba.cxx256
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: */