diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
commit | 267c6f2ac71f92999e969232431ba04678e7437e (patch) | |
tree | 358c9467650e1d0a1d7227a21dac2e3d08b622b2 /basic/qa/cppunit | |
parent | Initial commit. (diff) | |
download | libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip |
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'basic/qa/cppunit')
-rw-r--r-- | basic/qa/cppunit/_test_asserts.bas | 72 | ||||
-rw-r--r-- | basic/qa/cppunit/_test_asserts.vb | 73 | ||||
-rw-r--r-- | basic/qa/cppunit/basic_coverage.cxx | 126 | ||||
-rw-r--r-- | basic/qa/cppunit/basictest.cxx | 125 | ||||
-rw-r--r-- | basic/qa/cppunit/basictest.hxx | 52 | ||||
-rw-r--r-- | basic/qa/cppunit/test_append.cxx | 78 | ||||
-rw-r--r-- | basic/qa/cppunit/test_compiler_checks.cxx | 117 | ||||
-rw-r--r-- | basic/qa/cppunit/test_global_array.cxx | 86 | ||||
-rw-r--r-- | basic/qa/cppunit/test_global_as_new.cxx | 83 | ||||
-rw-r--r-- | basic/qa/cppunit/test_language_conditionals.cxx | 166 | ||||
-rw-r--r-- | basic/qa/cppunit/test_nested_struct.cxx | 323 | ||||
-rw-r--r-- | basic/qa/cppunit/test_scanner.cxx | 1165 | ||||
-rw-r--r-- | basic/qa/cppunit/test_vba.cxx | 267 |
13 files changed, 2733 insertions, 0 deletions
diff --git a/basic/qa/cppunit/_test_asserts.bas b/basic/qa/cppunit/_test_asserts.bas new file mode 100644 index 0000000000..0c3e0b371f --- /dev/null +++ b/basic/qa/cppunit/_test_asserts.bas @@ -0,0 +1,72 @@ +' +' 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/. +' + +Option Explicit + +Dim passCount As Integer +Dim failCount As Integer +Dim result As String + +Function GetResult() + If passCount <> 0 and failCount = 0 Then + GetResult = "OK" + Else + GetResult = result & Chr$(10) & "Tests passed: " & passCount & Chr$(10) & "Tests failed: " & failCount & Chr$(10) + End If +End Function + +Sub TestInit() + passCount = 0 + failCount = 0 + result = result & "Test Results" & Chr$(10) & "============" & Chr$(10) +End Sub + +Sub Assert(Assertion As Boolean, Optional testId As String, Optional testComment As String) + If Assertion = True Then + passCount = passCount + 1 + Else + Dim testMsg As String + If Not IsMissing(testId) Then + testMsg = " " + testId + End If + If Not IsMissing(testComment) Then + If Not (testComment = "") Then testMsg = testMsg + " (" + testComment + ")" + End If + + result = result & Chr$(10) & " Failed:" & testMsg + failCount = failCount + 1 + End If +End Sub + +Sub AssertEqual(actual As Variant, expected As Variant, testName As String) + If expected = actual Then + passCount = passCount + 1 + Else + result = result & Chr$(10) & " Failed: " & testName & " returned " & actual & ", expected " & expected + failCount = failCount + 1 + End If +End Sub + +' Same as AssertEqual, but also checks actual and expected types +Sub AssertEqualStrict(actual As Variant, expected As Variant, testName As String) + AssertEqual actual, expected, testName + AssertEqual TypeName(actual), TypeName(expected), testName & " type mismatch:" +End Sub + +Sub AssertEqualApprox(actual, expected, epsilon, testName As String) + If Abs(expected - actual) <= epsilon Then + passCount = passCount + 1 + Else + result = result & Chr$(10) & " Failed: " & testName & " returned " & actual & ", expected " & expected & ", epsilon " & epsilon + failCount = failCount + 1 + End If +End Sub + +Sub ReportErrorHandler(testName As String, aErr, sError, nErl) + Assert False, testName, "hit error handler - " & aErr & ": " & sError & " line : " & nErl +End Sub diff --git a/basic/qa/cppunit/_test_asserts.vb b/basic/qa/cppunit/_test_asserts.vb new file mode 100644 index 0000000000..2130ce02f4 --- /dev/null +++ b/basic/qa/cppunit/_test_asserts.vb @@ -0,0 +1,73 @@ +' +' 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/. +' + +Option VBASupport 1 +Option Explicit + +Dim passCount As Integer +Dim failCount As Integer +Dim result As String + +Function GetResult() + If passCount <> 0 and failCount = 0 Then + GetResult = "OK" + Else + GetResult = result & Chr$(10) & "Tests passed: " & passCount & Chr$(10) & "Tests failed: " & failCount & Chr$(10) + End If +End Function + +Sub TestInit() + passCount = 0 + failCount = 0 + result = result & "Test Results" & Chr$(10) & "============" & Chr$(10) +End Sub + +Sub Assert(Assertion As Boolean, Optional testId As String, Optional testComment As String) + If Assertion = True Then + passCount = passCount + 1 + Else + Dim testMsg As String + If Not IsMissing(testId) Then + testMsg = " " + testId + End If + If Not IsMissing(testComment) Then + If Not (testComment = "") Then testMsg = testMsg + " (" + testComment + ")" + End If + + result = result & Chr$(10) & " Failed:" & testMsg + failCount = failCount + 1 + End If +End Sub + +Sub AssertEqual(actual As Variant, expected As Variant, testName As String) + If expected = actual Then + passCount = passCount + 1 + Else + result = result & Chr$(10) & " Failed: " & testName & " returned " & actual & ", expected " & expected + failCount = failCount + 1 + End If +End Sub + +' Same as AssertEqual, but also checks actual and expected types +Sub AssertEqualStrict(actual As Variant, expected As Variant, testName As String) + AssertEqual actual, expected, testName + AssertEqual TypeName(actual), TypeName(expected), testName & " type mismatch:" +End Sub + +Sub AssertEqualApprox(actual, expected, epsilon, testName As String) + If Abs(expected - actual) <= epsilon Then + passCount = passCount + 1 + Else + result = result & Chr$(10) & " Failed: " & testName & " returned " & actual & ", expected " & expected & ", epsilon " & epsilon + failCount = failCount + 1 + End If +End Sub + +Sub ReportErrorHandler(testName As String, aErr, sError, nErl) + Assert False, testName, "hit error handler - " & aErr & ": " & sError & " line : " & nErl +End Sub diff --git a/basic/qa/cppunit/basic_coverage.cxx b/basic/qa/cppunit/basic_coverage.cxx new file mode 100644 index 0000000000..0f07229172 --- /dev/null +++ b/basic/qa/cppunit/basic_coverage.cxx @@ -0,0 +1,126 @@ +/* -*- 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: + void process_directory(const OUString& sDirName); + std::vector< OUString > get_subdirnames( const OUString& sDirName ); + +public: + Coverage(); + + 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) +{ +} + +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); + OUString sMacroUtilsURL = m_directories.getURLFromSrc(u"basic/qa/cppunit/_test_asserts.bas"); + + if(aDir.open() == osl::FileBase::E_None) + { + while (aDir.getNextItem(aItem) == osl::FileBase::E_None) + { + aItem.getFileStatus(aFileStatus); + if(aFileStatus.isRegular()) + { + OUString sFileURL = aFileStatus.getFileURL(); + if (sFileURL.endsWith(".bas")) + { + MacroSnippet testMacro; + testMacro.LoadSourceFromFile("TestUtil", sMacroUtilsURL); + testMacro.LoadSourceFromFile("TestModule", sFileURL); + SbxVariableRef pReturn = testMacro.Run(); + CPPUNIT_ASSERT_MESSAGE("No return variable huh?", pReturn.is()); + fprintf(stderr, "macro result for %s\n", OUStringToOString(sFileURL,RTL_TEXTENCODING_UTF8).getStr()); + 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()); + } + } + } + } + fprintf(stderr,"end process directory\n"); +} + +void Coverage::Coverage_Iterator() +{ + OUString sDirName = m_directories.getURLFromSrc(u"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 0000000000..13dc8c72e4 --- /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& sName, const OUString& sSource) +{ + mpMod = mpBasic->MakeModule(sName, sSource); +} + +MacroSnippet::MacroSnippet( const OUString& sSource ) + : mbError(false) +{ + InitSnippet(); + MakeModule("TestModule", sSource); +} + +MacroSnippet::MacroSnippet() + : mbError(false) +{ + InitSnippet(); +} + +void MacroSnippet::LoadSourceFromFile(const OUString& sModuleName, 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; + if(aFile.getSize(size) == osl::FileBase::E_None) + { + void* buffer = calloc(1, size+1); + CPPUNIT_ASSERT(buffer); + sal_uInt64 size_read; + 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(sModuleName, 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->Put(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 ); + mpMod->Compile(); + return !mbError; +} + +bool MacroSnippet::HasError() const { return mbError; } + +const ErrCodeMsg& 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 0000000000..46af3542b8 --- /dev/null +++ b/basic/qa/cppunit/basictest.hxx @@ -0,0 +1,52 @@ +/* -*- 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/. + */ +#pragma once + +#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; + ErrCodeMsg maErrCode; + BasicDLL maDll; // we need a dll instance for resource manager etc. + SbModuleRef mpMod; + StarBASICRef mpBasic; + + void InitSnippet(); + void MakeModule(const OUString& sName, const OUString& sSource); + +public: + explicit MacroSnippet(const OUString& sSource); + MacroSnippet(); + + void LoadSourceFromFile(const OUString& sName, 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 ErrCodeMsg& getError() const; +}; + +/* 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 0000000000..aa3280a4ad --- /dev/null +++ b/basic/qa/cppunit/test_append.cxx @@ -0,0 +1,78 @@ +/* -*- 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() +{ + MacroSnippet myMacro(" #If Win64\n" + "Declare PtrSafe Function aht_apiGetOpenFileName Lib \"comdlg32.dll\"" + "\n" + "#End if\n"); + 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 0000000000..773719e9fd --- /dev/null +++ b/basic/qa/cppunit/test_compiler_checks.cxx @@ -0,0 +1,117 @@ +/* -*- 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().GetCode()); +} + +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().GetCode()); +} + +CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testTdf149157) +{ + MacroSnippet aMacro("Function extentComment() As Integer\n" + " ' _\n" + " If Not extentComment Then\n" + " extentComment = 1\n" + " End If\n" + "End Function\n"); + aMacro.Compile(); + CPPUNIT_ASSERT(!aMacro.HasError()); +} + +CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testTdf149157_compatible) +{ + MacroSnippet aMacro("Option Compatible\n" + "Function extentComment() As Integer\n" + " ' _\n" + "\n" + " If Not extentComment Then\n" + " extentComment = 1\n" + " End If\n" + "End Function\n"); + aMacro.Compile(); + CPPUNIT_ASSERT(!aMacro.HasError()); +} + +CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testTdf149157_vba) +{ + MacroSnippet aMacro("Option VBASupport 1\n" + "Function extentComment() As Integer\n" + " ' _\n" + "\n" + " If Not extentComment Then\n" + " extentComment = 1\n" + " End If\n" + "End Function\n"); + aMacro.Compile(); + CPPUNIT_ASSERT(!aMacro.HasError()); +} + +CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testTdf149402) +{ + MacroSnippet aMacro("Function extentComment() As Integer\n" + " ' _ \n" + " If Not extentComment Then\n" + " extentComment = 1\n" + " Else\n" + " End If\n" + "End Function\n"); + aMacro.Compile(); + CPPUNIT_ASSERT(!aMacro.HasError()); +} + +CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testTdf149402_compatible) +{ + MacroSnippet aMacro("Option Compatible\n" + "Function extentComment() As Integer\n" + " ' _ \n" + " If Not extentComment Then\n" + " extentComment = 1\n" + " Else\n" + " End If\n" + "End Function\n"); + aMacro.Compile(); + CPPUNIT_ASSERT(!aMacro.HasError()); +} + +CPPUNIT_TEST_FIXTURE(CppUnit::TestFixture, testTdf149402_vba) +{ + MacroSnippet aMacro("Option VBASupport 1\n" + "Function extentComment() As Integer\n" + " ' _ \n" + " If Not extentComment Then\n" + " extentComment = 1\n" + " Else\n" + " End If\n" + "End Function\n"); + aMacro.Compile(); + CPPUNIT_ASSERT(!aMacro.HasError()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/basic/qa/cppunit/test_global_array.cxx b/basic/qa/cppunit/test_global_array.cxx new file mode 100644 index 0000000000..d2dafcfbda --- /dev/null +++ b/basic/qa/cppunit/test_global_array.cxx @@ -0,0 +1,86 @@ +/* -*- 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 <basic/sbstar.hxx> +#include <basic/sbmeth.hxx> +#include <basic/basrdll.hxx> +#include <cppunit/extensions/HelperMacros.h> + +namespace +{ +class GlobalArrayTest : public CppUnit::TestFixture +{ + void testMaintainsValueAcrossCalls(); + + CPPUNIT_TEST_SUITE(GlobalArrayTest); + CPPUNIT_TEST(testMaintainsValueAcrossCalls); + CPPUNIT_TEST_SUITE_END(); + + BasicDLL lib; + StarBASICRef interpreter; + + SbModuleRef Module() + { + interpreter = new StarBASIC(); + auto mod = interpreter->MakeModule("GlobalArray", R"BAS( + +Type testType + iNr As Integer + sType As String +End Type + +Global aTestTypes(2) As New testType + +Function Macro1 As String + aTestTypes(0).iNr = 1 + aTestTypes(0).sType = "A" + Macro1 = aTestTypes(0).iNr & aTestTypes(0).sType +End Function + +Function Macro2 As String + aTestTypes(1).iNr = 2 + aTestTypes(1).sType = "B" + Macro2 = aTestTypes(0).iNr & aTestTypes(0).sType & aTestTypes(1).iNr & aTestTypes(1).sType +End Function + + )BAS"); + CPPUNIT_ASSERT(mod->Compile()); + CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, StarBASIC::GetErrBasic()); + CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, SbxBase::GetError()); + CPPUNIT_ASSERT(mod->IsCompiled()); + return mod; + } +}; + +void GlobalArrayTest::testMaintainsValueAcrossCalls() +{ + auto m = Module(); + auto Macro1 = m->FindMethod("Macro1", SbxClassType::Method); + CPPUNIT_ASSERT_MESSAGE("Could not Find Macro1 in module", Macro1 != nullptr); + + // There is no SbxMethod::call(), the basic code is exercised here in the copy ctor + SbxVariableRef returned = new SbxMethod{ *Macro1 }; + CPPUNIT_ASSERT(returned->IsString()); + CPPUNIT_ASSERT_EQUAL(OUString{ "1A" }, returned->GetOUString()); + + auto Macro2 = m->FindMethod("Macro2", SbxClassType::Method); + CPPUNIT_ASSERT_MESSAGE("Could not Find Macro2 in module", Macro2 != nullptr); + returned = new SbxMethod{ *Macro2 }; + CPPUNIT_ASSERT(returned->IsString()); + // tdf#145371 - check if the global array has maintained its state + // Without the fix in place, this test would have failed with: + // - Expected: 1A2B + // - Actual : 02B + CPPUNIT_ASSERT_EQUAL(OUString("1A2B"), returned->GetOUString()); +} + +// Put the test suite in the registry +CPPUNIT_TEST_SUITE_REGISTRATION(GlobalArrayTest); + +} // namespace diff --git a/basic/qa/cppunit/test_global_as_new.cxx b/basic/qa/cppunit/test_global_as_new.cxx new file mode 100644 index 0000000000..868f62d3ec --- /dev/null +++ b/basic/qa/cppunit/test_global_as_new.cxx @@ -0,0 +1,83 @@ +/* -*- 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 <basic/sbstar.hxx> +#include <basic/sbmeth.hxx> +#include <basic/basrdll.hxx> +#include <cppunit/extensions/HelperMacros.h> + +namespace +{ +class GlobalAsNewTest : public CppUnit::TestFixture +{ + void testMaintainsValueAcrossCalls(); + + CPPUNIT_TEST_SUITE(GlobalAsNewTest); + CPPUNIT_TEST(testMaintainsValueAcrossCalls); + CPPUNIT_TEST_SUITE_END(); + + BasicDLL lib; + StarBASICRef interpreter; + + SbModuleRef Module() + { + interpreter = new StarBASIC(); + auto mod = interpreter->MakeModule("GlobalAsNew", R"BAS( +Global aDate As New "com.sun.star.util.Date" + +Function GetDateAsString As String + DIM local_Date As New "com.sun.star.util.Date" + GetDateAsString = TRIM(STR(aDate.Year)) + "-" + TRIM(STR(local_Date.Year)) + TRIM(STR(aDate.Month)) + "-" + TRIM(STR(aDate.Day)) +End Function + +Function SetDate + aDate.Month = 6 + aDate.Day = 30 + aDate.Year = 2019 + SetDate = GetDateAsString() +End Function + + )BAS"); + CPPUNIT_ASSERT(mod->Compile()); + CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, StarBASIC::GetErrBasic()); + CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, SbxBase::GetError()); + CPPUNIT_ASSERT(mod->IsCompiled()); + return mod; + } +}; + +void GlobalAsNewTest::testMaintainsValueAcrossCalls() +{ + auto m = Module(); + auto GetDateAsString = m->FindMethod("GetDateAsString", SbxClassType::Method); + CPPUNIT_ASSERT_MESSAGE("Could not Find GetDateAsString in module", GetDateAsString != nullptr); + + // There is no SbxMethod::call(), the basic code is exercised here in the copy ctor + SbxVariableRef returned = new SbxMethod{ *GetDateAsString }; + CPPUNIT_ASSERT(returned->IsString()); + //0-00-0 is the result of reading the default-initialized date + CPPUNIT_ASSERT_EQUAL(OUString{ "0-00-0" }, returned->GetOUString()); + + auto SetDate = m->FindMethod("SetDate", SbxClassType::Method); + CPPUNIT_ASSERT_MESSAGE("Could not Find SetDate in module", SetDate != nullptr); + returned = new SbxMethod{ *SetDate }; + CPPUNIT_ASSERT(returned->IsString()); + OUString set_val("2019-06-30"); + CPPUNIT_ASSERT_EQUAL(set_val, returned->GetOUString()); + + returned = new SbxMethod{ *GetDateAsString }; + CPPUNIT_ASSERT(returned->IsString()); + //tdf#88442 The global should have maintained its state! + CPPUNIT_ASSERT_EQUAL(set_val, returned->GetOUString()); +} + +// Put the test suite in the registry +CPPUNIT_TEST_SUITE_REGISTRATION(GlobalAsNewTest); + +} // namespace diff --git a/basic/qa/cppunit/test_language_conditionals.cxx b/basic/qa/cppunit/test_language_conditionals.cxx new file mode 100644 index 0000000000..c35d5571e9 --- /dev/null +++ b/basic/qa/cppunit/test_language_conditionals.cxx @@ -0,0 +1,166 @@ +/* -*- 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 <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 + MacroSnippet myMacro("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"); + 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 + MacroSnippet myMacro("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"); + 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 + MacroSnippet myMacro("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"); + 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 + MacroSnippet myMacro("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"); + 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 + MacroSnippet myMacro("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"); + 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 + MacroSnippet myMacro("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"); + 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 0000000000..daced48ba2 --- /dev/null +++ b/basic/qa/cppunit/test_nested_struct.cxx @@ -0,0 +1,323 @@ +/* -*- 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 + void testTdf134576(); + + // 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); + CPPUNIT_TEST(testTdf134576); + + // 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 ); +} + +void Nested_Struct::testTdf134576() +{ + MacroSnippet myMacro("Function doUnitTest()\n" + " On Error Resume Next\n" + " For Each a In b\n" + " c.d\n" + " Next\n" + " doUnitTest = 1\n" + "End Function\n"); + + myMacro.Compile(); + CPPUNIT_ASSERT(!myMacro.HasError()); + + // Without the fix in place, it would have crashed here + SbxVariableRef pNew = myMacro.Run(); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(1), pNew->GetInteger()); +} + + // 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 0000000000..f17750c89a --- /dev/null +++ b/basic/qa/cppunit/test_scanner.cxx @@ -0,0 +1,1165 @@ +/* -*- 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 <limits> + +#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(); +}; + +constexpr OUString cr = u"\n"_ustr; +constexpr OUString rem = u"REM"_ustr; +constexpr OUString asdf = u"asdf"_ustr; +constexpr OUString dot = u"."_ustr; +constexpr OUString goto_ = u"goto"_ustr; +constexpr OUString excl = u"!"_ustr; + +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() +{ + std::vector<Symbol> symbols; + symbols = getSymbols(""); + CPPUNIT_ASSERT(symbols.empty()); + + symbols = getSymbols("\r\n"); + CPPUNIT_ASSERT_EQUAL(size_t(1), symbols.size()); + CPPUNIT_ASSERT_EQUAL(cr, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + + symbols = getSymbols("\n"); + CPPUNIT_ASSERT_EQUAL(size_t(1), symbols.size()); + CPPUNIT_ASSERT_EQUAL(cr, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + + symbols = getSymbols("\r"); + CPPUNIT_ASSERT_EQUAL(size_t(1), symbols.size()); + CPPUNIT_ASSERT_EQUAL(cr, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + + symbols = getSymbols("\r\n\r\n"); + 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("\n\r"); + 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("\n\r\n"); + 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("\r\n\r"); + 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(" "); + 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() +{ + constexpr OUString sourceE(u"="_ustr); + constexpr OUString sourceLT(u"<"_ustr); + constexpr OUString sourceGT(u">"_ustr); + constexpr OUString sourceLTE(u"<="_ustr); + constexpr OUString sourceGTE(u">="_ustr); + constexpr OUString sourceNE(u"<>"_ustr); + constexpr OUString sourceA(u":="_ustr); + constexpr OUString sourceNot(u"Not"_ustr); + + 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("=="); + 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() +{ + constexpr OUString source1(u"asdfghefg"_ustr); + constexpr OUString source3(u"AdfsaAUdsl10987"_ustr); + constexpr OUString source4(u"asdfa_mnvcnm"_ustr); + constexpr OUString source5(u"_asdf1"_ustr); + constexpr OUString source6(u"_6"_ustr); + constexpr OUString source7(u"joxclk_"_ustr); + + 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("1asfdasfd"); + 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); + // tdf#125637 - don't change underscore to space + CPPUNIT_ASSERT_EQUAL(OUString("joxclk_"), source7); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[1].type); + + symbols = getSymbols(" asdf "); + 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(" 19395 asdfa "); + 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("\n1\n2\na sdf"); + 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("asdf.asdf"); + 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(".."); + 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() +{ + std::vector<Symbol> symbols; + + symbols = getSymbols("REM asdf"); + CPPUNIT_ASSERT_EQUAL(size_t(1), symbols.size()); + CPPUNIT_ASSERT_EQUAL(rem, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + + symbols = getSymbols("REMasdf"); + 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("'asdf"); + CPPUNIT_ASSERT_EQUAL(size_t(1), symbols.size()); + CPPUNIT_ASSERT_EQUAL(rem, symbols[0].text); + CPPUNIT_ASSERT_EQUAL(SbxVARIANT, symbols[0].type); + + symbols = getSymbols("asdf _\n'100"); + 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("'asdf _\n100"); + 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("'asdf _\n'100"); + 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("'asdf _\n 1234 _\n asdf'"); + 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() +{ + std::vector<Symbol> symbols; + + symbols = getSymbols("goto"); + 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("go to"); + 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("go\nto"); + 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() +{ + std::vector<Symbol> symbols; + + symbols = getSymbols("goto", 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("go to", 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("go\nto", 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() +{ + std::vector<Symbol> symbols; + + symbols = getSymbols("asdf!asdf"); + 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("!1234"); + 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("!_3"); + 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("!$"); + 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("!%"); + 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("!\n"); + 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() +{ + std::vector<Symbol> symbols; + sal_Int32 errors; + + symbols = getSymbols("12345", 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("1.2.3", 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("123.4", 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("0.5", 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("5.0", 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("0.0", 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("-3", 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("-0.0", 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("12dE3", 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("12e3", 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("12D+3", 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("12e++3", 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("12e-3", 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("12e-3+", 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("1,2,3", 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("1." + "0000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000", + 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 + + symbols = getSymbols("10e308", errors); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(std::numeric_limits<double>::infinity(), 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() +{ + std::vector<Symbol> symbols; + + symbols = getSymbols("asdf%"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(SbxINTEGER, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + symbols = getSymbols("asdf&"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(SbxLONG, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + symbols = getSymbols("asdf!"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(SbxSINGLE, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + symbols = getSymbols("asdf#"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(SbxDOUBLE, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + symbols = getSymbols("asdf@"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(SbxCURRENCY, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + symbols = getSymbols("asdf$"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_EQUAL(SbxSTRING, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + + symbols = getSymbols("asdf "); + 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() +{ + sal_Int32 errors; + std::vector<Symbol> symbols; + + symbols = getSymbols("&HA"); + 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("&HASDF"); + 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("&H10"); + 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("&&H&1H1&H1"); + 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("&O&O12"); + 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("&O10"); + 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("&HO"); + 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("&O123000000000000000000000"); + 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("&H1.23"); + 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)); + + // maximum for Hex & = SbxLONG + symbols = getSymbols("&H7FFFFFFF&"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(2147483647.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); + + // minimum for Hex & = SbxLONG + symbols = getSymbols("&H80000000&"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-2147483648.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); + + // overflow for Hex & = SbxLONG + symbols = getSymbols("&H100000000&", 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(SbxLONG, 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 & = SbxLONG + symbols = getSymbols("&O17777777777&"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(2147483647.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); + + // minimum for Octal & = SbxLONG + symbols = getSymbols("&O20000000000&", errors); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-2147483648.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); + + // overflow for Octal & = SbxLONG + symbols = getSymbols("&O40000000000&", 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(SbxLONG, symbols[0].type); + CPPUNIT_ASSERT_EQUAL(cr, symbols[1].text); + // ERRCODE_BASIC_MATH_OVERFLOW + CPPUNIT_ASSERT_EQUAL(1u, static_cast<unsigned int>(errors)); + + /* test for leading zeros */ + + // &H0000000FFFF = 65535 + symbols = getSymbols("&H0000000FFFF"); + 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); + + // &O00000123 = 83 + symbols = getSymbols("&O00000123"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(83.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("&O7777777"); + CPPUNIT_ASSERT_EQUAL(size_t(2), symbols.size()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(2097151.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); +} + +void ScannerTest::testTdf103104() +{ + std::vector<Symbol> symbols; + + symbols = getSymbols("asdf _\n asdf"); + 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("asdf. _\n asdf"); + 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("asdf _\n .asdf"); + 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 0000000000..8a15ba7234 --- /dev/null +++ b/basic/qa/cppunit/test_vba.cxx @@ -0,0 +1,267 @@ +/* -*- 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> + +#include <systools/win32/odbccp32.hxx> +#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", + "chrw.vb", + "abs.vb", + "array.vb", + "asc.vb", + "atn.vb", + "booltypename.vb", + "cbool.vb", + "cdate.vb", + "cdbl.vb", + "choose.vb", + "cos.vb", + "cint.vb", + "clng.vb", + "collection.vb", + "csng.vb", + "cstr.vb", + "cvdate.vb", + "cverr.vb", + "dateadd.vb", + "datediff.vb", + "datepart.vb", + "day.vb", + "enum.vb", + "error.vb", + "error_message.vb", + "Err.Raise.vb", + "exp.vb", + "fix.vb", + "hex.vb", + "hour.vb", + "formatnumber.vb", + "formatpercent.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", + "like.vb", + "oct.vb", + "optional_paramters.vb", + "qbcolor.vb", + "rgb.vb", + "rtrim.vb", + "right.vb", + "second.vb", + "sgn.vb", + "sin.vb", + "space.vb", + "split.vb", + "sqr.vb", + "str.vb", + "strcomp.vb", + "string.vb", + "strreverse.vb", + "switch.vb", + "tdf147089_idiv.vb", + "tdf147529_optional_parameters_msgbox.vb", + "tdf148358_non_ascii_names.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(u"/basic/qa/vba_tests/"); + OUString sMacroUtilsURL = m_directories.getURLFromSrc(u"/basic/qa/cppunit/_test_asserts.vb"); + // Some test data expects the uk locale + LanguageTag aLocale(LANGUAGE_ENGLISH_UK); + SvtSysLocaleOptions aLocalOptions; + aLocalOptions.SetLocaleConfigString( aLocale.getBcp47() ); + + for ( size_t i=0; i<std::size( macroSource ); ++i ) + { + OUString sMacroURL = sMacroPathURL + + OUString::createFromAscii( macroSource[ i ] ); + + MacroSnippet myMacro; + myMacro.LoadSourceFromFile("TestUtil", sMacroUtilsURL); + myMacro.LoadSourceFromFile("TestModule", 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]; + if (!sal::systools::odbccp32().SQLGetInstalledDrivers(sBuf, nBufSize)) + return; + + 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(u"/basic/qa/vba_tests/"); + + // path to test document + OUString sPath = m_directories.getPathFromSrc(u"/basic/qa/vba_tests/data/ADODBdata.xls"); + sPath = sPath.replaceAll( "/", "\\" ); + + uno::Sequence< uno::Any > aArgs + { + uno::Any(sPath), + uno::Any(OUString(o3tl::toU(pODBCDriverName))) + }; + + for ( sal_uInt32 i=0; i<std::size( macroSource ); ++i ) + { + OUString sMacroURL = sMacroPathURL + + OUString::createFromAscii( macroSource[ i ] ); + MacroSnippet myMacro; + myMacro.LoadSourceFromFile("TestModule", 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: */ |