summaryrefslogtreecommitdiffstats
path: root/sal/qa/osl
diff options
context:
space:
mode:
Diffstat (limited to 'sal/qa/osl')
-rw-r--r--sal/qa/osl/condition/osl_Condition.cxx327
-rw-r--r--sal/qa/osl/condition/osl_Condition_Const.h47
-rw-r--r--sal/qa/osl/file/osl_File.cxx4980
-rw-r--r--sal/qa/osl/file/osl_File_Const.h206
-rw-r--r--sal/qa/osl/file/osl_old_test_file.cxx115
-rw-r--r--sal/qa/osl/file/test_cpy_wrt_file.cxx76
-rw-r--r--sal/qa/osl/getsystempathfromfileurl/test-getsystempathfromfileurl.cxx243
-rw-r--r--sal/qa/osl/module/osl_Module.cxx376
-rw-r--r--sal/qa/osl/module/osl_Module_Const.h46
-rw-r--r--sal/qa/osl/module/osl_Module_DLL.cxx32
-rw-r--r--sal/qa/osl/mutex/osl_Mutex.cxx905
-rw-r--r--sal/qa/osl/mutex/osl_Mutex_Const.h37
-rw-r--r--sal/qa/osl/pipe/osl_Pipe.cxx894
-rwxr-xr-xsal/qa/osl/process/batch.bat19
-rwxr-xr-xsal/qa/osl/process/batch.sh2
-rw-r--r--sal/qa/osl/process/osl_Thread.cxx2005
-rw-r--r--sal/qa/osl/process/osl_Thread.xsce18
-rw-r--r--sal/qa/osl/process/osl_process.cxx450
-rw-r--r--sal/qa/osl/process/osl_process_child.cxx101
-rw-r--r--sal/qa/osl/profile/osl_old_testprofile.cxx62
-rw-r--r--sal/qa/osl/security/TODO.h8
-rw-r--r--sal/qa/osl/security/osl_Security.cxx624
-rw-r--r--sal/qa/osl/security/osl_Security_Const.h58
-rw-r--r--sal/qa/osl/setthreadname/test-setthreadname.cxx79
-rw-r--r--sal/qa/osl/socket.cxx58
-rw-r--r--sal/qa/osl/thread/test_thread.cxx80
26 files changed, 11848 insertions, 0 deletions
diff --git a/sal/qa/osl/condition/osl_Condition.cxx b/sal/qa/osl/condition/osl_Condition.cxx
new file mode 100644
index 000000000..05b7fc661
--- /dev/null
+++ b/sal/qa/osl/condition/osl_Condition.cxx
@@ -0,0 +1,327 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "osl_Condition_Const.h"
+#include <stdlib.h>
+
+using namespace osl;
+
+namespace {
+
+enum ConditionType
+{
+ thread_type_set,
+ thread_type_reset,
+ thread_type_wait
+};
+
+/** thread for testing Condition.
+ */
+class ConditionThread : public Thread
+{
+public:
+ //get the Condition to operate
+ ConditionThread( ::osl::Condition& Con, ConditionType tType): m_MyCon( Con ), m_MyType( tType ) { }
+
+protected:
+ ::osl::Condition& m_MyCon;
+ ConditionType m_MyType;
+
+ void SAL_CALL run() override
+ {
+ switch ( m_MyType )
+ {
+ case thread_type_wait:
+ m_MyCon.wait(); break;
+ case thread_type_set:
+ m_MyCon.set(); break;
+ case thread_type_reset:
+ m_MyCon.reset(); break;
+ default:
+ break;
+ }
+ }
+};
+
+}
+
+namespace osl_Condition
+{
+ /** testing the method:
+ Condition()
+ */
+ class ctors : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ void ctors_create()
+ {
+ ::osl::Condition aCond;
+ bRes = aCond.check();
+
+ CPPUNIT_ASSERT_MESSAGE("#test comment#: create a condition its initial check state should be sal_False.",
+ !bRes );
+ }
+
+ void ctors_createAndSet()
+ {
+ ::osl::Condition aCond;
+ aCond.set();
+ bRes = aCond.check();
+
+ CPPUNIT_ASSERT_MESSAGE("#test comment#: create a condition and set it.",
+ bRes );
+ }
+
+ CPPUNIT_TEST_SUITE(ctors);
+ CPPUNIT_TEST(ctors_create);
+ CPPUNIT_TEST(ctors_createAndSet);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ /** testing the method:
+ void set()
+ */
+ class set : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1, bRes2;
+
+ void set_createAndSet()
+ {
+ ::osl::Condition aCond;
+ aCond.set();
+ bRes = aCond.check();
+
+ CPPUNIT_ASSERT_MESSAGE("#test comment#: check state should be sal_True after set.",
+ bRes );
+ }
+
+ void set_threadWaitRelease()
+ {
+ ::osl::Condition aCond;
+ ConditionThread myThread1(aCond, thread_type_wait);
+ myThread1.create();
+ bRes = myThread1.isRunning();
+
+ ConditionThread myThread2(aCond, thread_type_set);
+ myThread2.create();
+
+ myThread1.join();
+ bRes1 = myThread1.isRunning();
+ bRes2 = aCond.check();
+ myThread2.join();
+
+ CPPUNIT_ASSERT_MESSAGE("#test comment#: use one thread to set the condition in order to release another thread.",
+ bRes);
+ CPPUNIT_ASSERT_MESSAGE("#test comment#: use one thread to set the condition in order to release another thread.",
+ !bRes1);
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: use one thread to set the condition in order to release another thread.",
+ bRes2);
+ }
+
+ CPPUNIT_TEST_SUITE(set);
+ CPPUNIT_TEST(set_createAndSet);
+ CPPUNIT_TEST(set_threadWaitRelease);
+ CPPUNIT_TEST_SUITE_END( );
+ };
+
+ /** testing the method:
+ void reset()
+ */
+ class reset : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1, bRes2;
+
+ void reset_resetWaitAndSet()
+ {
+ ::osl::Condition aCond;
+ aCond.reset();
+
+ ConditionThread myThread(aCond, thread_type_wait);
+ myThread.create();
+ bRes = myThread.isRunning();
+ bRes2 = aCond.check();
+
+ aCond.set();
+ myThread.join();
+ bRes1 = myThread.isRunning();
+
+ CPPUNIT_ASSERT_MESSAGE("#test comment#: wait will cause a reset thread block, use set to release it.",
+ bRes);
+ CPPUNIT_ASSERT_MESSAGE("#test comment#: wait will cause a reset thread block, use set to release it.",
+ !bRes1);
+ CPPUNIT_ASSERT_MESSAGE("#test comment#: wait will cause a reset thread block, use set to release it.",
+ !bRes2);
+ }
+
+ void reset_resetAndSet()
+ {
+ ::osl::Condition aCond;
+ aCond.reset();
+ bRes = aCond.check();
+ aCond.set();
+ bRes1 = aCond.check();
+
+ CPPUNIT_ASSERT_MESSAGE("#test comment#: create a condition and reset/set it.",
+ !bRes );
+ CPPUNIT_ASSERT_MESSAGE("#test comment#: create a condition and reset/set it.",
+ bRes1 );
+ }
+
+ CPPUNIT_TEST_SUITE(reset);
+ CPPUNIT_TEST(reset_resetWaitAndSet);
+ CPPUNIT_TEST(reset_resetAndSet);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ /** testing the method:
+ Result wait(const TimeValue *pTimeout = 0)
+ */
+ class wait : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1, bRes2;
+ std::unique_ptr<TimeValue> tv1;
+
+ void setUp() override
+ {
+ tv1.reset(new TimeValue);
+ tv1->Seconds = 1;
+ tv1->Nanosec = 0;
+ }
+
+ void tearDown() override
+ {
+ tv1.reset();
+ }
+
+ void wait_testAllCombos( )
+ {
+ ::osl::Condition cond1;
+ ::osl::Condition cond2;
+ ::osl::Condition cond3;
+
+ cond1.set();
+ cond2.set();
+
+ osl::Condition::Result r1=cond1.wait(tv1.get());
+ osl::Condition::Result r2=cond2.wait();
+ osl::Condition::Result r3=cond3.wait(tv1.get());
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "#test comment#: test three types of wait.",
+ ::osl::Condition::result_ok, r1 );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "#test comment#: test three types of wait.",
+ ::osl::Condition::result_ok, r2 );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "#test comment#: test three types of wait.",
+ ::osl::Condition::result_timeout, r3 );
+ }
+
+ void wait_timeoutWaits()
+ {
+ ::osl::Condition aCond;
+ ::osl::Condition::Result wRes, wRes1;
+
+ aCond.reset();
+ bRes = aCond.check();
+ wRes = aCond.wait(tv1.get());
+
+ aCond.set();
+ wRes1 = aCond.wait(tv1.get());
+ bRes1 = aCond.check();
+
+ CPPUNIT_ASSERT_MESSAGE("#test comment#: wait a condition after set/reset.",
+ !bRes );
+ CPPUNIT_ASSERT_MESSAGE("#test comment#: wait a condition after set/reset.",
+ bRes1 );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("#test comment#: wait a condition after set/reset.",
+ ::osl::Condition::result_timeout, wRes );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("#test comment#: wait a condition after set/reset.",
+ ::osl::Condition::result_ok, wRes1 );
+ }
+
+ CPPUNIT_TEST_SUITE(wait);
+ CPPUNIT_TEST(wait_testAllCombos);
+ CPPUNIT_TEST(wait_timeoutWaits);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ /** testing the method:
+ sal_Bool check()
+ */
+ class check : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1, bRes2;
+
+ void check_checkStates()
+ {
+ ::osl::Condition aCond;
+
+ aCond.reset();
+ bRes = aCond.check();
+ aCond.set();
+ bRes1 = aCond.check();
+
+ CPPUNIT_ASSERT_MESSAGE("#test comment#: check the condition states.",
+ !bRes );
+ CPPUNIT_ASSERT_MESSAGE("#test comment#: check the condition states.",
+ bRes1 );
+ }
+
+ void check_threadedCheckStates( )
+ {
+ ::osl::Condition aCond;
+ aCond.reset();
+
+ ConditionThread myThread(aCond, thread_type_set);
+ myThread.create();
+ myThread.join();
+ bRes = aCond.check();
+
+ ConditionThread myThread1(aCond, thread_type_reset);
+ myThread1.create();
+ myThread1.join();
+ bRes1 = aCond.check();
+
+ CPPUNIT_ASSERT_MESSAGE("#test comment#: use threads to set/reset Condition and check it in main routine.",
+ bRes );
+ CPPUNIT_ASSERT_MESSAGE("#test comment#: use threads to set/reset Condition and check it in main routine.",
+ !bRes1 );
+ }
+
+ CPPUNIT_TEST_SUITE(check);
+ CPPUNIT_TEST(check_checkStates);
+ CPPUNIT_TEST(check_threadedCheckStates);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_Condition::ctors);
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_Condition::set);
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_Condition::reset);
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_Condition::wait);
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_Condition::check);
+
+} // namespace osl_Condition
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/osl/condition/osl_Condition_Const.h b/sal/qa/osl/condition/osl_Condition_Const.h
new file mode 100644
index 000000000..89b26121b
--- /dev/null
+++ b/sal/qa/osl/condition/osl_Condition_Const.h
@@ -0,0 +1,47 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SAL_QA_OSL_CONDITION_OSL_CONDITION_CONST_H
+#define INCLUDED_SAL_QA_OSL_CONDITION_OSL_CONDITION_CONST_H
+
+#include <sal/types.h>
+#include <rtl/ustring.hxx>
+#include <osl/thread.hxx>
+#include <osl/mutex.hxx>
+#include <osl/pipe.hxx>
+#include <osl/conditn.hxx>
+#include <osl/time.h>
+
+#ifdef UNX
+#include <unistd.h>
+#endif
+
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+// condition names
+
+OUString aTestCon("testcondition");
+
+const char pTestString[17] = "Sun Microsystems";
+
+#endif // INCLUDED_SAL_QA_OSL_CONDITION_OSL_CONDITION_CONST_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/osl/file/osl_File.cxx b/sal/qa/osl/file/osl_File.cxx
new file mode 100644
index 000000000..718fb6542
--- /dev/null
+++ b/sal/qa/osl/file/osl_File.cxx
@@ -0,0 +1,4980 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/types.h>
+#include <rtl/byteseq.hxx>
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+
+#include <osl/thread.h>
+#include <osl/file.hxx>
+#include "osl_File_Const.h"
+
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <tools/urlobj.hxx>
+
+#include <memory>
+
+#ifdef _WIN32
+#include <prewin.h>
+#include <postwin.h>
+#include <o3tl/char16_t2wchar_t.hxx>
+#endif
+
+using namespace osl;
+
+/** detailed wrong message.
+*/
+static OString errorToString(const osl::FileBase::RC _nError)
+{
+ OString sResult;
+ switch (_nError) {
+ case osl::FileBase::E_None:
+ sResult = "Success";
+ break;
+ case osl::FileBase::E_PERM:
+ sResult = "Operation not permitted";
+ break;
+ case osl::FileBase::E_NOENT:
+ sResult = "No such file or directory";
+ break;
+ case osl::FileBase::E_EXIST:
+ sResult = "Already Exist";
+ break;
+ case osl::FileBase::E_ACCES:
+ sResult = "Permission denied";
+ break;
+ case osl::FileBase::E_INVAL:
+ sResult = "The format of the parameters was not valid";
+ break;
+ case osl::FileBase::E_NOTDIR:
+ sResult = "Not a directory";
+ break;
+ case osl::FileBase::E_ISDIR:
+ sResult = "Is a directory";
+ break;
+ case osl::FileBase::E_BADF:
+ sResult = "Bad file";
+ break;
+ case osl::FileBase::E_NOTEMPTY:
+ sResult = "The directory is not empty";
+ break;
+ default:
+ sResult = "Unknown Error";
+ break;
+ }
+ return sResult;
+}
+
+static OString errorToStr(osl::FileBase::RC const& nError)
+{
+ OString suBuf = "The returned error is: " +
+ errorToString(nError) +
+ "!\n";
+ return suBuf;
+}
+
+/** compare two TimeValue, unit is "ms", since Windows time precision is better than UNX.
+*/
+/* FIXME: the above assertion is bogus */
+
+#if (defined UNX) // precision of time in Windows is better than UNX
+# define delta 2000 // time precision, 2000ms
+#else
+# define delta 1800 // time precision, 1.8s
+#endif
+
+static bool t_compareTime(TimeValue *m_aEndTime, TimeValue *m_aStartTime, sal_Int32 nDelta)
+{
+ sal_Int32 nDeltaSeconds = m_aEndTime->Seconds - m_aStartTime->Seconds;
+ sal_Int32 nDeltaNanoSec = sal_Int32(m_aEndTime->Nanosec) - sal_Int32(m_aStartTime->Nanosec);
+ if (nDeltaNanoSec < 0)
+ {
+ nDeltaNanoSec = 1000000000 + nDeltaNanoSec;
+ nDeltaSeconds--;
+ }
+
+ sal_Int32 nDeltaMilliSec = (nDeltaSeconds * 1000) + (nDeltaNanoSec / 1000000);
+ return (nDeltaMilliSec < nDelta);
+}
+
+/** compare two OUString file name.
+*/
+static bool compareFileName(const OUString & ustr1, const OUString & ustr2)
+{
+ bool bOk;
+// on Windows, the separator is '\', so here change to '/', then compare
+#if defined(_WIN32)
+ OUString ustr1new,ustr2new;
+ sal_Unicode reverseSlash = '\\';
+
+ if (ustr1.lastIndexOf(reverseSlash) != -1)
+ ustr1new = ustr1.replace(reverseSlash,'/');
+ else
+ ustr1new = ustr1;
+ if (ustr2.lastIndexOf(reverseSlash) != -1)
+ ustr2new = ustr2.replace(reverseSlash,'/');
+ else
+ ustr2new = ustr2;
+ bOk = ustr1new.equalsIgnoreAsciiCase(ustr2new);
+#else
+ bOk = ustr1.equalsIgnoreAsciiCase(ustr2);
+#endif
+ return bOk;
+}
+
+/** simple version to judge if a file name or directory name is a URL or a system path, just to see if it
+ is start with "file:///";.
+*/
+static bool isURL(const OUString& pathname)
+{
+ return pathname.startsWith(aPreURL);
+}
+
+/** concat two part to form a URL or system path, add PATH_SEPARATOR between them if necessary, add "file:///" to beginning if necessary.
+*/
+static void concatURL(OUString & pathname1, const OUString & pathname2)
+{
+ // check if pathname1 is full qualified URL;
+ if (!isURL(pathname1))
+ {
+ OUString aPathName = pathname1.copy(0);
+ osl::FileBase::getFileURLFromSystemPath(pathname1, aPathName); // convert if not full qualified URL
+ pathname1 = aPathName.copy(0);
+ }
+
+ // check if '/' is in the end of pathname1 or at the begin of pathname2;
+ if (!pathname1.endsWith(aSlashURL) && !pathname2.startsWith(aSlashURL))
+ pathname1 += aSlashURL;
+ pathname1 += pathname2;
+}
+
+/** create a temp test file using OUString name of full qualified URL or system path.
+*/
+static void createTestFile(const OUString& filename)
+{
+ OUString aPathURL = filename.copy(0);
+ osl::FileBase::RC nError;
+
+ if (!isURL(filename))
+ osl::FileBase::getFileURLFromSystemPath(filename, aPathURL); // convert if not full qualified URL
+
+ File aFile(aPathURL);
+ nError = aFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_Write | osl_File_OpenFlag_Create);
+ if ((nError != osl::FileBase::E_None) && (nError != osl::FileBase::E_EXIST))
+ printf("createTestFile failed!\n");
+
+ aFile.close();
+
+}
+
+/** create a temp test file using OUString name of full qualified URL or system path in a base directory.
+*/
+static void createTestFile(const OUString& basename, const OUString& filename)
+{
+ OUString aBaseURL = basename.copy(0);
+
+ concatURL(aBaseURL, filename);
+ createTestFile(aBaseURL);
+}
+
+/** delete a temp test file using OUString name.
+*/
+static void deleteTestFile(const OUString& filename)
+{
+ OUString aPathURL = filename.copy(0);
+ osl::FileBase::RC nError;
+
+ if (!isURL(filename))
+ osl::FileBase::getFileURLFromSystemPath(filename, aPathURL); // convert if not full qualified URL
+
+ nError = File::setAttributes(aPathURL, osl_File_Attribute_GrpWrite| osl_File_Attribute_OwnWrite| osl_File_Attribute_OthWrite); // if readonly, make writable.
+ CPPUNIT_ASSERT_MESSAGE("In deleteTestFile Function: set writable ", (osl::FileBase::E_None == nError) || (osl::FileBase::E_NOENT == nError));
+
+ nError = File::remove(aPathURL);
+ CPPUNIT_ASSERT_MESSAGE("In deleteTestFile Function: remove ", (osl::FileBase::E_None == nError) || (nError == osl::FileBase::E_NOENT));
+}
+
+/** delete a temp test file using OUString name of full qualified URL or system path in a base directory.
+*/
+static void deleteTestFile(const OUString& basename, const OUString& filename)
+{
+ OUString aBaseURL = basename.copy(0);
+
+ concatURL(aBaseURL, filename);
+ deleteTestFile(aBaseURL);
+}
+
+/** create a temp test directory using OUString name of full qualified URL or system path.
+*/
+static void createTestDirectory(const OUString& dirname)
+{
+ OUString aPathURL = dirname.copy(0);
+ osl::FileBase::RC nError;
+
+ if (!isURL(dirname))
+ osl::FileBase::getFileURLFromSystemPath(dirname, aPathURL); // convert if not full qualified URL
+ nError = Directory::create(aPathURL);
+ if ((nError != osl::FileBase::E_None) && (nError != osl::FileBase::E_EXIST))
+ printf("createTestDirectory failed: %d!\n", int(nError));
+}
+
+/** create a temp test directory using OUString name of full qualified URL or system path in a base directory.
+*/
+static void createTestDirectory(const OUString& basename, const OUString& dirname)
+{
+ OUString aBaseURL = basename.copy(0);
+
+ concatURL(aBaseURL, dirname);
+ createTestDirectory(aBaseURL);
+}
+
+/** delete a temp test directory using OUString name of full qualified URL or system path.
+*/
+static void deleteTestDirectory(const OUString& dirname)
+{
+ OUString aPathURL = dirname.copy(0);
+ if (!isURL(dirname))
+ osl::FileBase::getFileURLFromSystemPath(dirname, aPathURL); // convert if not full qualified URL
+
+ Directory testDir(aPathURL);
+ if (testDir.isOpen())
+ testDir.close(); // close if still open.
+
+ osl::FileBase::RC nError = Directory::remove(aPathURL);
+
+ OString strError = "In deleteTestDirectory function: remove Directory " +
+ OUStringToOString(aPathURL, RTL_TEXTENCODING_ASCII_US) + " -> result: " + OString::number(nError);
+ CPPUNIT_ASSERT_MESSAGE(strError.getStr(), (osl::FileBase::E_None == nError) || (nError == osl::FileBase::E_NOENT));
+}
+
+/** delete a temp test directory using OUString name of full qualified URL or system path in a base directory.
+*/
+static void deleteTestDirectory(const OUString& basename, const OUString& dirname)
+{
+ OUString aBaseURL = basename.copy(0);
+
+ concatURL(aBaseURL, dirname);
+ deleteTestDirectory(aBaseURL);
+}
+
+namespace {
+
+/** Check for the file and directory access right.
+*/
+enum class oslCheckMode {
+ Exist,
+ OpenAccess,
+ ReadAccess,
+ WriteAccess
+};
+
+}
+
+/** check if the file exist
+*/
+static bool ifFileExist(const OUString & str)
+{
+ File testFile(str);
+ return (testFile.open(osl_File_OpenFlag_Read) == osl::FileBase::E_None);
+}
+
+/** check if the file can be written
+*/
+static bool ifFileCanWrite(const OUString & str)
+{
+ // on Windows, the file has no write right, but can be written
+#ifdef _WIN32
+ bool bCheckResult = false;
+ OUString aUStr = str.copy(0);
+ if (isURL(str))
+ osl::FileBase::getSystemPathFromFileURL(str, aUStr);
+
+ OString aString = OUStringToOString(aUStr, RTL_TEXTENCODING_ASCII_US);
+ const char *path = aString.getStr();
+ if ((_access(path, 2)) != -1)
+ bCheckResult = true;
+ // on UNX, just test if open success with osl_File_OpenFlag_Write
+#else
+ File testFile(str);
+ bool bCheckResult = (testFile.open(osl_File_OpenFlag_Write) == osl::FileBase::E_None);
+#endif
+ return bCheckResult;
+}
+
+static bool checkDirectory(const OUString& str, oslCheckMode nCheckMode)
+{
+ OUString aUString;
+ DirectoryItem rItem;
+ osl::FileBase::RC rc;
+ bool bCheckResult= false;
+
+ Directory aDir(str);
+ rc = aDir.open();
+
+ if ((rc != osl::FileBase::E_NOENT) && (rc != osl::FileBase::E_ACCES))
+ {
+ switch (nCheckMode)
+ {
+ case oslCheckMode::Exist:
+ if (rc == ::osl::FileBase::E_None)
+ bCheckResult = true;
+ break;
+ case oslCheckMode::OpenAccess:
+ if (rc == osl::FileBase::E_None)
+ bCheckResult = true;
+ break;
+ case oslCheckMode::ReadAccess:
+ rc = aDir.getNextItem(rItem);
+ bCheckResult = (rc == osl::FileBase::E_None) || (rc == osl::FileBase::E_NOENT);
+ break;
+ case oslCheckMode::WriteAccess:
+ ((aUString += str) += aSlashURL) += aTmpName2;
+ if (Directory::create(aUString) == osl::FileBase::E_None)
+ {
+ bCheckResult = true;
+ rc = Directory::remove(aUString);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, rc);
+ }
+ else
+ {
+ bCheckResult = false;
+ }
+ break;
+
+ default:
+ bCheckResult = false;
+ }
+
+ rc = aDir.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, rc);
+ }
+
+ return bCheckResult;
+}
+
+/** construct error message
+*/
+static OString outputError(const OString & returnVal, const OString & rightVal, const char * msg = "")
+{
+ if (returnVal == rightVal)
+ return OString();
+
+ OString aString = msg +
+ OString::Concat(": the returned value is '") +
+ returnVal +
+ "', but the value should be '" +
+ rightVal +
+ "'.";
+ return aString;
+}
+
+#if (defined UNX) /* chmod() method is different in Windows */
+/** Change file mode, two version in UNIX and Windows;.
+*/
+static void changeFileMode(OUString & filepath, sal_Int32 mode)
+{
+ OString aString;
+ OUString aUStr = filepath.copy(0);
+
+ if (isURL(filepath))
+ osl::FileBase::getSystemPathFromFileURL(filepath, aUStr);
+
+ aString = OUStringToOString(aUStr, RTL_TEXTENCODING_ASCII_US);
+ int ret = chmod(aString.getStr(), mode);
+ CPPUNIT_ASSERT_EQUAL(0, ret);
+}
+#else
+static void hideFile(const OUString& filepath)
+{
+ OUString aSysPath(filepath);
+
+ if (isURL(filepath))
+ osl::FileBase::getSystemPathFromFileURL(filepath, aSysPath);
+
+ bool ret = SetFileAttributesW(o3tl::toW(aSysPath.getStr()), FILE_ATTRIBUTE_HIDDEN);
+ CPPUNIT_ASSERT(ret);
+}
+#endif
+
+#if 0
+#if defined UNX
+static OUString getCurrentPID();
+#endif
+#endif
+
+// Beginning of the test cases for osl::FileBase class
+
+namespace osl_FileBase
+{
+ // testing the method
+ // static inline RC getAbsoluteFileURL(const OUString& ustrBaseDirectoryURL,
+ // const OUString& ustrRelativeFileURL,
+ // OUString& ustrAbsoluteFileURL)
+
+ class getAbsoluteFileURL : public CppUnit::TestFixture
+ {
+ public:
+ void check_getAbsoluteFileURL(OUString const& _suBaseURL,
+ OString const& _sRelativeURL,
+ osl::FileBase::RC _nAssumeError,
+ OUString const& _suAssumeResultStr);
+
+ void getAbsoluteFileURL_001_1();
+ void getAbsoluteFileURL_001_2();
+ void getAbsoluteFileURL_001_3();
+ void getAbsoluteFileURL_001_4();
+ void getAbsoluteFileURL_001_5();
+ void getAbsoluteFileURL_001_6();
+ void getAbsoluteFileURL_001_7();
+ void getAbsoluteFileURL_001_8();
+ void getAbsoluteFileURL_002();
+ void getAbsoluteFileURL_003();
+ void getAbsoluteFileURL_004();
+
+ CPPUNIT_TEST_SUITE(getAbsoluteFileURL);
+ CPPUNIT_TEST(getAbsoluteFileURL_001_1);
+ CPPUNIT_TEST(getAbsoluteFileURL_001_2);
+ CPPUNIT_TEST(getAbsoluteFileURL_001_3);
+ CPPUNIT_TEST(getAbsoluteFileURL_001_4);
+ CPPUNIT_TEST(getAbsoluteFileURL_001_5);
+ CPPUNIT_TEST(getAbsoluteFileURL_001_6);
+ CPPUNIT_TEST(getAbsoluteFileURL_001_7);
+ CPPUNIT_TEST(getAbsoluteFileURL_001_8);
+ CPPUNIT_TEST(getAbsoluteFileURL_002);
+ CPPUNIT_TEST(getAbsoluteFileURL_003);
+ CPPUNIT_TEST(getAbsoluteFileURL_004);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ void getAbsoluteFileURL::check_getAbsoluteFileURL(OUString const& _suBaseURL,
+ OString const& _sRelativeURL,
+ osl::FileBase::RC _nAssumeError,
+ OUString const& _suAssumeResultStr)
+ {
+ OUString suRelativeURL = OStringToOUString(_sRelativeURL, RTL_TEXTENCODING_UTF8);
+ OString sBaseURL = OUStringToOString(_suBaseURL, RTL_TEXTENCODING_UTF8);
+ OUString suResultURL;
+ osl::FileBase::RC nError = osl::FileBase::getAbsoluteFileURL(_suBaseURL, suRelativeURL, suResultURL);
+ OString sResultURL = OUStringToOString(suResultURL, RTL_TEXTENCODING_UTF8);
+ OString sError = errorToString(nError);
+ printf("getAbsoluteFileURL('%s','%s') deliver absolute URL: '%s', error '%s'\n",
+ sBaseURL.getStr(), _sRelativeURL.getStr(),sResultURL.getStr(), sError.getStr());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Assumption is wrong: error number is wrong", _nAssumeError, nError);
+
+ if (nError == osl::FileBase::E_None)
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Assumption is wrong: ResultURL is not equal to expected URL ", _suAssumeResultStr, suResultURL);
+ }
+ }
+
+ void getAbsoluteFileURL::getAbsoluteFileURL_001_1()
+ {
+ OUString suAssume = aUserDirectoryURL + "/relative/file1";
+ check_getAbsoluteFileURL(aUserDirectoryURL, "relative/file1",osl::FileBase::E_None, suAssume);
+ }
+
+ void getAbsoluteFileURL::getAbsoluteFileURL_001_2()
+ {
+ OUString suAssume = aUserDirectoryURL + "/relative/file2";
+ check_getAbsoluteFileURL(aUserDirectoryURL, "relative/./file2",osl::FileBase::E_None, suAssume);
+ }
+
+ void getAbsoluteFileURL::getAbsoluteFileURL_001_3()
+ {
+ OUString suAssume = aUserDirectoryURL + "/file3";
+ check_getAbsoluteFileURL(aUserDirectoryURL, "relative/../file3",osl::FileBase::E_None, suAssume);
+ }
+
+ void getAbsoluteFileURL::getAbsoluteFileURL_001_4()
+ {
+ OUString suAssume = aUserDirectoryURL + "/file4";
+ check_getAbsoluteFileURL(aUserDirectoryURL, "././relative/../file4",osl::FileBase::E_None, suAssume);
+ }
+
+ void getAbsoluteFileURL::getAbsoluteFileURL_001_5()
+ {
+ OUString suAssume;
+ suAssume = aUserDirectoryURL + "/relative/";
+ check_getAbsoluteFileURL(aUserDirectoryURL, "././relative/.",osl::FileBase::E_None, suAssume);
+ }
+
+ void getAbsoluteFileURL::getAbsoluteFileURL_001_6()
+ {
+ OUString suAssume = aUserDirectoryURL + "/.relative";
+ check_getAbsoluteFileURL(aUserDirectoryURL, "./.relative",osl::FileBase::E_None, suAssume);
+ }
+
+ void getAbsoluteFileURL::getAbsoluteFileURL_001_7()
+ {
+ OUString suAssume;
+ suAssume = aUserDirectoryURL + "/.a/";
+ check_getAbsoluteFileURL(aUserDirectoryURL, "./.a/mydir/..",osl::FileBase::E_None, suAssume);
+ }
+
+ void getAbsoluteFileURL::getAbsoluteFileURL_001_8()
+ {
+ OUString suAssume = aUserDirectoryURL + "/tmp/ok";
+ check_getAbsoluteFileURL(aUserDirectoryURL, "tmp//ok",osl::FileBase::E_None, suAssume);
+ }
+
+ void getAbsoluteFileURL::getAbsoluteFileURL_002()
+ {
+#if 0
+#if (defined UNX) // Link is not defined in Windows
+ OUString aUStr_LnkFileSys(aTempDirectorySys), aUStr_SrcFileSys(aTempDirectorySys);
+ aUStr_LnkFileSys += aSlashURL + getCurrentPID() + "/link.file";
+ aUStr_SrcFileSys += aSlashURL + getCurrentPID() + "/canonical.name";
+
+ OString strLinkFileName, strSrcFileName;
+ strLinkFileName = OUStringToOString(aUStr_LnkFileSys, RTL_TEXTENCODING_ASCII_US);
+ strSrcFileName = OUStringToOString(aUStr_SrcFileSys, RTL_TEXTENCODING_ASCII_US);
+
+ createTestFile(aCanURL1);
+ sal_Int32 fd = symlink(strSrcFileName.getStr(), strLinkFileName.getStr());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), fd);
+ OString sLnkURL = OUStringToOString(aLnkURL1, RTL_TEXTENCODING_ASCII_US);
+ OUString suAssume = aUserDirectoryURL + "/canonical.name";
+ check_getAbsoluteFileURL(aUserDirectoryURL, sLnkURL, osl::FileBase::E_None, suAssume);
+ deleteTestFile(aCanURL1);
+ fd = remove(strLinkFileName.getStr());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), fd);
+#endif
+#endif
+ }
+
+ // please see line# 930
+ void getAbsoluteFileURL::getAbsoluteFileURL_003()
+ {
+ }
+
+ void getAbsoluteFileURL::getAbsoluteFileURL_004()
+ {
+ // create two level directories under $Temp/PID/
+ OUString aUStrUpBase = aUserDirectoryURL + "/test1";
+ createTestDirectory(aUStrUpBase);
+ OUString aUStrBase = aUserDirectoryURL + "/test1/dir1";
+ createTestDirectory(aUStrBase);
+
+ OUString suAssume = aUserDirectoryURL + "/mytestfile";
+ check_getAbsoluteFileURL(aUStrBase, "../../mytestfile" , osl::FileBase::E_None, suAssume);
+ deleteTestDirectory(aUStrBase);
+ deleteTestDirectory(aUStrUpBase);
+ }
+
+ // testing two methods:
+ // static inline RC getSystemPathFromFileURL(const OUString& ustrFileURL,
+ // OUString& ustrSystemPath)
+ // static RC getFileURLFromSystemPath(const OUString & ustrSystemPath,
+ // OUString & ustrFileURL);
+
+ class SystemPath_FileURL : public CppUnit::TestFixture
+ {
+ public:
+ void getSystemPathFromFileURL_001_1();
+ void getSystemPathFromFileURL_001_2();
+ void getSystemPathFromFileURL_001_21();
+ void getSystemPathFromFileURL_001_22();
+ void getSystemPathFromFileURL_001_3();
+ void getSystemPathFromFileURL_001_31();
+ void getSystemPathFromFileURL_001_4();
+ void getSystemPathFromFileURL_001_41();
+ void getSystemPathFromFileURL_001_5();
+ void getSystemPathFromFileURL_001_51();
+ void getSystemPathFromFileURL_001_52();
+ void getSystemPathFromFileURL_001_53();
+ void getSystemPathFromFileURL_001_6();
+ void getSystemPathFromFileURL_001_61();
+ void getSystemPathFromFileURL_001_7();
+ void getSystemPathFromFileURL_001_71();
+ void getSystemPathFromFileURL_001_8();
+ void getSystemPathFromFileURL_001_81();
+ void getSystemPathFromFileURL_001_9();
+ void getSystemPathFromFileURL_001_91();
+ void getSystemPathFromFileURL_001_92();
+ void getSystemPathFromFileURL_004();
+ void getSystemPathFromFileURL_005();
+
+ // test case for getFileURLFromSystemPath
+ void getFileURLFromSystemPath_001();
+ void getFileURLFromSystemPath_002();
+ void getFileURLFromSystemPath_003();
+ void getFileURLFromSystemPath_004();
+ void getFileURLFromSystemPath_004_1();
+ void getFileURLFromSystemPath_005();
+
+ CPPUNIT_TEST_SUITE(SystemPath_FileURL);
+ CPPUNIT_TEST(getSystemPathFromFileURL_001_1);
+ CPPUNIT_TEST(getSystemPathFromFileURL_001_2);
+ CPPUNIT_TEST(getSystemPathFromFileURL_001_21);
+ CPPUNIT_TEST(getSystemPathFromFileURL_001_22);
+ CPPUNIT_TEST(getSystemPathFromFileURL_001_3);
+ CPPUNIT_TEST(getSystemPathFromFileURL_001_31);
+ CPPUNIT_TEST(getSystemPathFromFileURL_001_4);
+ CPPUNIT_TEST(getSystemPathFromFileURL_001_41);
+ CPPUNIT_TEST(getSystemPathFromFileURL_001_5);
+ CPPUNIT_TEST(getSystemPathFromFileURL_001_51);
+ CPPUNIT_TEST(getSystemPathFromFileURL_001_52);
+ CPPUNIT_TEST(getSystemPathFromFileURL_001_53);
+ CPPUNIT_TEST(getSystemPathFromFileURL_001_6);
+ CPPUNIT_TEST(getSystemPathFromFileURL_001_61);
+ CPPUNIT_TEST(getSystemPathFromFileURL_001_7);
+ CPPUNIT_TEST(getSystemPathFromFileURL_001_71);
+ CPPUNIT_TEST(getSystemPathFromFileURL_001_8);
+ CPPUNIT_TEST(getSystemPathFromFileURL_001_81);
+ CPPUNIT_TEST(getSystemPathFromFileURL_001_9);
+ CPPUNIT_TEST(getSystemPathFromFileURL_001_91);
+ CPPUNIT_TEST(getSystemPathFromFileURL_001_92);
+ CPPUNIT_TEST(getSystemPathFromFileURL_004);
+ CPPUNIT_TEST(getSystemPathFromFileURL_005);
+ CPPUNIT_TEST(getFileURLFromSystemPath_001);
+ CPPUNIT_TEST(getFileURLFromSystemPath_002);
+ CPPUNIT_TEST(getFileURLFromSystemPath_003);
+ CPPUNIT_TEST(getFileURLFromSystemPath_004);
+ CPPUNIT_TEST(getFileURLFromSystemPath_004_1);
+ CPPUNIT_TEST(getFileURLFromSystemPath_005);
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ void check_SystemPath_FileURL(
+ OString const& _sSource,
+ osl::FileBase::RC _nAssumeError,
+ OString const& _sAssumeResultStr,
+ bool bDirection = true);
+
+ void checkWNTBehaviour_getSystemPathFromFileURL(
+ OString const& _sURL,
+ osl::FileBase::RC _nAssumeError,
+ OString const& _sWNTAssumeResultString);
+
+ void checkUNXBehaviour_getSystemPathFromFileURL(
+ OString const& _sURL,
+ osl::FileBase::RC _nAssumeError,
+ OString const& _sUnixAssumeResultString);
+
+ void checkWNTBehaviour_getFileURLFromSystemPath(OString const& _sSysPath,
+ osl::FileBase::RC _nAssumeError,
+ OString const& _sWNTAssumeResultString);
+
+ void checkUNXBehaviour_getFileURLFromSystemPath(
+ OString const& _sSysPath,
+ osl::FileBase::RC _nAssumeError,
+ OString const& _sUnixAssumeResultString);
+
+ };
+
+ // if bDirection==sal_True, check getSystemPathFromFileURL
+ // if bDirection==sal_False, check getFileURLFromSystemPath
+ void SystemPath_FileURL::check_SystemPath_FileURL(
+ OString const& _sSource,
+ osl::FileBase::RC _nAssumeError,
+ OString const& _sAssumeResultStr,
+ bool bDirection)
+ {
+ // PRE: URL as String
+ OUString suSource;
+ OUString suStr;
+ suSource = OStringToOUString(_sSource, RTL_TEXTENCODING_UTF8);
+ osl::FileBase::RC nError;
+
+ if (bDirection)
+ nError = osl::FileBase::getSystemPathFromFileURL(suSource, suStr);
+ else
+ nError = osl::FileBase::getFileURLFromSystemPath(suSource, suStr);
+
+ // if the given string is gt length 0,
+ // we check also this string
+ OString sStr = OUStringToOString(suStr, RTL_TEXTENCODING_UTF8);
+ OString sError = errorToString(nError);
+
+ if (bDirection)
+ printf("getSystemPathFromFileURL('%s') deliver system path: '%s', error '%s'\n",
+ _sSource.getStr(), sStr.getStr(), sError.getStr());
+ else
+ printf("getFileURLFromSystemPath('%s') deliver File URL: '%s', error '%s'\n",
+ _sSource.getStr(), sStr.getStr(), sError.getStr());
+
+ if (!_sAssumeResultStr.isEmpty())
+ {
+ bool bStrAreEqual = _sAssumeResultStr == sStr;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Assumption is wrong",
+ _nAssumeError, nError);
+ CPPUNIT_ASSERT_MESSAGE("Assumption is wrong",
+ bStrAreEqual);
+ }
+ else
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Assumption is wrong", _nAssumeError, nError);
+ }
+ }
+
+ void SystemPath_FileURL::checkWNTBehaviour_getSystemPathFromFileURL(
+ OString const& _sURL,
+ osl::FileBase::RC _nAssumeError,
+ OString const& _sWNTAssumeResultString)
+ {
+#if defined(_WIN32)
+ check_SystemPath_FileURL(_sURL, _nAssumeError, _sWNTAssumeResultString);
+#else
+ (void)_sURL;
+ (void)_nAssumeError;
+ (void)_sWNTAssumeResultString;
+#endif
+ }
+
+ void SystemPath_FileURL::checkUNXBehaviour_getSystemPathFromFileURL(
+ OString const& _sURL,
+ osl::FileBase::RC _nAssumeError,
+ OString const& _sUnixAssumeResultString)
+ {
+#if (defined UNX)
+ check_SystemPath_FileURL(_sURL, _nAssumeError, _sUnixAssumeResultString);
+#else
+ (void)_sURL;
+ (void)_nAssumeError;
+ (void)_sUnixAssumeResultString;
+#endif
+ }
+
+ void SystemPath_FileURL::checkWNTBehaviour_getFileURLFromSystemPath(
+ OString const& _sSysPath,
+ osl::FileBase::RC _nAssumeError,
+ OString const& _sWNTAssumeResultString)
+ {
+#if defined(_WIN32)
+ check_SystemPath_FileURL(_sSysPath, _nAssumeError, _sWNTAssumeResultString, false);
+#else
+ (void)_sSysPath;
+ (void)_nAssumeError;
+ (void)_sWNTAssumeResultString;
+#endif
+ }
+
+ void SystemPath_FileURL::checkUNXBehaviour_getFileURLFromSystemPath(
+ OString const& _sSysPath,
+ osl::FileBase::RC _nAssumeError,
+ OString const& _sUnixAssumeResultString)
+ {
+#if (defined UNX)
+ check_SystemPath_FileURL(_sSysPath, _nAssumeError, _sUnixAssumeResultString, false);
+#else
+ (void)_sSysPath;
+ (void)_nAssumeError;
+ (void)_sUnixAssumeResultString;
+#endif
+ }
+
+ /** Test for getSystemPathFromFileURL()
+ this test is split into 2 different OS tests,
+ the first function checkUNXBehaviour... runs only on Unix based Systems,
+ the second only on windows based systems
+ the first parameter are a file URL where we want to get the system path of,
+ the second parameter is the assumed error of the osl_getSystemPathFromFileURL() function,
+ the third parameter is the assumed result string, the string will only test, if its length is greater than 0
+ */
+
+ void SystemPath_FileURL::getSystemPathFromFileURL_001_1()
+ {
+ OString sURL("");
+ checkUNXBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_INVAL, "");
+ checkWNTBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_INVAL, "");
+ }
+
+ void SystemPath_FileURL::getSystemPathFromFileURL_001_2()
+ {
+ OString sURL("/");
+ checkUNXBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_INVAL, "");
+ checkWNTBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_None, "\\");
+ }
+
+ void SystemPath_FileURL::getSystemPathFromFileURL_001_21()
+ {
+ /* From RFC3986, "2.2. Reserved Characters":
+
+ "The purpose of reserved characters is to provide a set of delimiting
+ characters that are distinguishable from other data within a URI.
+ URIs that differ in the replacement of a reserved character with its
+ corresponding percent-encoded octet are not equivalent. Percent-
+ encoding a reserved character, or decoding a percent-encoded octet
+ that corresponds to a reserved character, will change how the URI is
+ interpreted by most applications. Thus, characters in the reserved
+ set are protected from normalization and are therefore safe to be
+ used by scheme-specific and producer-specific algorithms for
+ delimiting data subcomponents within a URI."
+
+ In other words, %2F ("/") is NOT the same as /.
+ */
+ OString sURL("%2F");
+ checkUNXBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_INVAL, "");
+ checkWNTBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_INVAL, "");
+ }
+
+ void SystemPath_FileURL::getSystemPathFromFileURL_001_22()
+ {
+ OString sURL("file:///tmp%2Fmydir");
+ checkUNXBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_INVAL, "");
+ checkWNTBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_INVAL, "");
+ }
+
+ void SystemPath_FileURL::getSystemPathFromFileURL_001_3()
+ {
+ OString sURL("a");
+ checkUNXBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_None, "a");
+ checkWNTBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_None, "a");
+ }
+
+ void SystemPath_FileURL::getSystemPathFromFileURL_001_31()
+ {
+ OString sURL("tmpname");
+ checkUNXBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_None, "tmpname");
+ checkWNTBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_None, "tmpname");
+ }
+
+ void SystemPath_FileURL::getSystemPathFromFileURL_001_4()
+ {
+ OString sURL("file://");
+ checkUNXBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_None, "");
+ checkWNTBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_INVAL, "");
+ }
+
+ void SystemPath_FileURL::getSystemPathFromFileURL_001_41()
+ {
+ OString sURL("file://localhost/tmp");
+ checkUNXBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_None, "");
+ checkWNTBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_INVAL, "");
+ }
+
+ void SystemPath_FileURL::getSystemPathFromFileURL_001_5()
+ {
+ OString sURL("file:///tmp");
+ checkUNXBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_None, "/tmp");
+ checkWNTBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_INVAL, "");
+ }
+
+ void SystemPath_FileURL::getSystemPathFromFileURL_001_51()
+ {
+ OString sURL("file://c:/tmp");
+ checkUNXBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_INVAL, "");
+ checkWNTBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_INVAL, "");
+ }
+
+ void SystemPath_FileURL::getSystemPathFromFileURL_001_52()
+ {
+ OString sURL("file:///c:/tmp");
+ checkUNXBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_None, "/c:/tmp");
+ checkWNTBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_None, "c:\\tmp");
+ }
+
+ void SystemPath_FileURL::getSystemPathFromFileURL_001_53()
+ {
+ OString sURL("file:///c|/tmp");
+ checkUNXBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_None, "/c|/tmp");
+ checkWNTBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_None, "c:\\tmp");
+ }
+
+ void SystemPath_FileURL::getSystemPathFromFileURL_001_6()
+ {
+ OString sURL("file:///tmp/first");
+ checkUNXBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_None, "/tmp/first");
+ checkWNTBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_INVAL, "");
+ }
+
+ void SystemPath_FileURL::getSystemPathFromFileURL_001_61()
+ {
+ OString sURL("file:///c:/tmp/first");
+ checkUNXBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_None, "/c:/tmp/first");
+ checkWNTBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_None, "c:\\tmp\\first");
+ }
+
+ void SystemPath_FileURL::getSystemPathFromFileURL_001_7()
+ {
+ OString sURL("file:///tmp/../second");
+ checkUNXBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_None, "/tmp/../second");
+ checkWNTBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_INVAL, "");
+ }
+
+ void SystemPath_FileURL::getSystemPathFromFileURL_001_71()
+ {
+ OString sURL("file:///c:/tmp/../second");
+ checkUNXBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_None, "/c:/tmp/../second");
+ checkWNTBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_None, "c:\\tmp\\..\\second");
+ }
+
+ void SystemPath_FileURL::getSystemPathFromFileURL_001_8()
+ {
+ OString sURL("../tmp");
+ checkUNXBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_None, "../tmp");
+ checkWNTBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_None, "..\\tmp");
+ }
+
+ void SystemPath_FileURL::getSystemPathFromFileURL_001_81()
+ {
+#if 0
+ OString sURL("file://~/tmp");
+ char* home_path;
+ home_path = getenv("HOME");
+ OString expResult(home_path ? home_path : "");
+ expResult += "/tmp";
+ checkUNXBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_None, expResult);
+#endif
+ }
+
+ void SystemPath_FileURL::getSystemPathFromFileURL_001_9()
+ {
+ OString sURL("file:///tmp/first%20second");
+ checkUNXBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_None, "/tmp/first second");
+ checkWNTBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_INVAL, "");
+ }
+
+ void SystemPath_FileURL::getSystemPathFromFileURL_001_91()
+ {
+ OString sURL("file:///c:/tmp/first%20second");
+ checkUNXBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_None, "/c:/tmp/first second");
+ checkWNTBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_None, "c:\\tmp\\first second");
+ }
+
+ void SystemPath_FileURL::getSystemPathFromFileURL_001_92()
+ {
+ OString sURL("ca@#;+.,$///78no%01ni..name");
+ checkUNXBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_INVAL, "");
+ checkWNTBehaviour_getSystemPathFromFileURL(sURL, osl::FileBase::E_INVAL, "");
+ }
+
+ // normal legal case
+ void SystemPath_FileURL::getSystemPathFromFileURL_004()
+ {
+ OUString aUStr;
+ OUString aUNormalURL(aTmpName6);
+ OUString aUResultURL (aSysPath4);
+ osl::FileBase::RC nError = osl::FileBase::getSystemPathFromFileURL(aUNormalURL, aUStr);
+
+ bool bOk = compareFileName(aUStr, aUResultURL);
+
+ OString sError =
+ "test for getSystemPathFromFileURL(' " +
+ OUStringToOString(aUNormalURL, RTL_TEXTENCODING_ASCII_US) +
+ " ') function:use an absolute file URL, " +
+ outputError(OUStringToOString(aUStr, RTL_TEXTENCODING_ASCII_US),
+ OUStringToOString(aUResultURL, RTL_TEXTENCODING_ASCII_US));
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sError.getStr(), osl::FileBase::E_None, nError);
+ CPPUNIT_ASSERT_MESSAGE(sError.getStr(), bOk);
+
+ }
+
+ // CJK characters case
+ void SystemPath_FileURL::getSystemPathFromFileURL_005()
+ {
+ OUString aUStr;
+ createTestDirectory(aTmpName10);
+ OUString aUNormalURL(aTmpName10);
+ OUString aUResultURL (aSysPath5);
+
+ osl::FileBase::RC nError = osl::FileBase::getSystemPathFromFileURL(aUNormalURL, aUStr);
+
+ bool bOk = compareFileName(aUStr, aUResultURL);
+
+ OString sError =
+ "test for getSystemPathFromFileURL(' " +
+ OUStringToOString(aUNormalURL, RTL_TEXTENCODING_ASCII_US) +
+ " ') function:use a CJK coded absolute URL, " +
+ outputError(OUStringToOString(aUStr, RTL_TEXTENCODING_ASCII_US),
+ OUStringToOString(aUResultURL, RTL_TEXTENCODING_ASCII_US));
+ deleteTestDirectory(aTmpName10);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sError.getStr(), osl::FileBase::E_None, nError);
+ CPPUNIT_ASSERT_MESSAGE(sError.getStr(), bOk);
+ }
+
+ void SystemPath_FileURL::getFileURLFromSystemPath_001()
+ {
+ OString sSysPath("~/tmp");
+ char* home_path;
+ home_path = getenv("HOME");
+ OString expResult(home_path ? home_path : "");
+ expResult = "file://"+ expResult + "/tmp";
+ checkUNXBehaviour_getFileURLFromSystemPath(sSysPath, osl::FileBase::E_None, expResult);
+ checkWNTBehaviour_getFileURLFromSystemPath(sSysPath, osl::FileBase::E_None, "~/tmp");
+ }
+
+ void SystemPath_FileURL::getFileURLFromSystemPath_002()
+ {
+ OString sSysPath("c:/tmp");
+ checkUNXBehaviour_getFileURLFromSystemPath(sSysPath, osl::FileBase::E_None, "c:/tmp");
+ checkWNTBehaviour_getFileURLFromSystemPath(sSysPath, osl::FileBase::E_None, "file:///c:/tmp");
+ }
+
+ void SystemPath_FileURL::getFileURLFromSystemPath_003()
+ {
+ OString sSysPath("file:///temp");
+ checkUNXBehaviour_getFileURLFromSystemPath(sSysPath, osl::FileBase::E_INVAL, "");
+ checkWNTBehaviour_getFileURLFromSystemPath(sSysPath, osl::FileBase::E_INVAL, "");
+ }
+
+ void SystemPath_FileURL::getFileURLFromSystemPath_004()
+ {
+ OString sSysPath("//tmp//first start");
+ checkUNXBehaviour_getFileURLFromSystemPath(sSysPath, osl::FileBase::E_None, "file:///tmp/first%20start");
+ checkWNTBehaviour_getFileURLFromSystemPath(sSysPath, osl::FileBase::E_INVAL, "");
+ }
+
+ void SystemPath_FileURL::getFileURLFromSystemPath_004_1()
+ {
+ OString sSysPath("/tmp///first start");
+ checkUNXBehaviour_getFileURLFromSystemPath(sSysPath, osl::FileBase::E_None, "file:///tmp/first%20start");
+ checkWNTBehaviour_getFileURLFromSystemPath(sSysPath, osl::FileBase::E_INVAL, "");
+ }
+
+ void SystemPath_FileURL::getFileURLFromSystemPath_005()
+ {
+ OString sSysPath("");
+ checkUNXBehaviour_getFileURLFromSystemPath(sSysPath, osl::FileBase::E_INVAL, "");
+ checkWNTBehaviour_getFileURLFromSystemPath(sSysPath, osl::FileBase::E_INVAL, "");
+ }
+
+ // testing the method
+ // static inline RC searchFileURL( const OUString& ustrFileName,
+ // const OUString& ustrSearchPath,
+ // OUString& ustrFileURL)
+
+ class searchFileURL : public CppUnit::TestFixture
+ {
+ private:
+ OUString aUStr;
+
+ public:
+ void searchFileURL_001()
+ {
+ /* search file is passed by system filename */
+ auto nError1 = osl::FileBase::searchFileURL(aTmpName1, aUserDirectorySys, aUStr);
+ /* search file is passed by full qualified file URL */
+ auto nError2 = osl::FileBase::searchFileURL(aCanURL1, aUserDirectorySys, aUStr);
+ /* search file is passed by relative file path */
+ auto nError3 = osl::FileBase::searchFileURL(aRelURL4, aUserDirectorySys, aUStr);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for searchFileURL function: system filename/URL filename/relative path, system directory, searched files that is not exist, but it reply invalid error, did not pass in (W32) ",
+ osl::FileBase::E_NOENT, nError1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for searchFileURL function: system filename/URL filename/relative path, system directory, searched files that is not exist, but it reply invalid error, did not pass in (W32) ",
+ osl::FileBase::E_NOENT, nError2);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for searchFileURL function: system filename/URL filename/relative path, system directory, searched files that is not exist, but it reply invalid error, did not pass in (W32) ",
+ osl::FileBase::E_NOENT, nError3);
+ }
+
+ void searchFileURL_002()
+ {
+#ifndef UNX
+ /* search file is passed by system filename */
+ OUString strRootSys = INetURLObject(aTempDirectoryURL).GetLastName();
+ auto nError1 = osl::FileBase::searchFileURL(aTempDirectorySys, strRootSys, aUStr);
+ bool bOk1 = compareFileName(aUStr, aTempDirectoryURL);
+ /* search file is passed by full qualified file URL */
+ auto nError2 = osl::FileBase::searchFileURL(aTempDirectoryURL, strRootSys, aUStr);
+ bool bOk2 = compareFileName(aUStr, aTempDirectoryURL);
+#ifndef _WIN32
+ /* search file is passed by relative file path */
+ auto nError3 = osl::FileBase::searchFileURL(aRelURL5, strRootSys, aUStr);
+ bool bOk3 = compareFileName(aUStr, aTempDirectoryURL);
+#endif
+ /* search file is passed by an exist file */
+ createTestFile(aCanURL1);
+ auto nError4 = osl::FileBase::searchFileURL(aCanURL4, aUserDirectorySys, aUStr);
+ bool bOk4 = compareFileName(aUStr, aCanURL1);
+ deleteTestFile(aCanURL1);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for searchFileURL function: system filename, system directory, searched file already exist.",
+ osl::FileBase::E_None, nError1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for searchFileURL function: URL filename, system directory, searched file already exist.",
+ osl::FileBase::E_None, nError2);
+#ifndef _WIN32
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for searchFileURL function: relative path, system directory, searched file already exist.",
+ osl::FileBase::E_None, nError3);
+#endif
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for searchFileURL function: system filename/URL filename/relative path, system directory, searched file already exist.",
+ osl::FileBase::E_None, nError4);
+ CPPUNIT_ASSERT_MESSAGE("test for searchFileURL function: system filename, system directory, searched file already exist.",
+ bOk1);
+ CPPUNIT_ASSERT_MESSAGE("test for searchFileURL function: URL filename, system directory, searched file already exist.",
+ bOk2);
+#ifndef _WIN32
+ CPPUNIT_ASSERT_MESSAGE("test for searchFileURL function: relative path, system directory, searched file already exist.",
+ bOk3);
+#endif
+ CPPUNIT_ASSERT_MESSAGE("test for searchFileURL function: system filename/URL filename/relative path, system directory, searched file already exist.",
+ bOk4);
+#endif
+ }
+
+ void searchFileURL_003()
+ {
+ OUString aSystemPathList(aRootSys + PATH_LIST_DELIMITER + aTempDirectorySys + PATH_LIST_DELIMITER + aRootSys + "system/path");
+ auto nError1 = osl::FileBase::searchFileURL(aUserDirectoryURL, aSystemPathList, aUStr);
+ bool bOk = compareFileName(aUStr, aUserDirectoryURL);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for searchFileURL function: search directory is a list of system paths",
+ osl::FileBase::E_None, nError1);
+ CPPUNIT_ASSERT_MESSAGE("test for searchFileURL function: search directory is a list of system paths",
+ bOk);
+ }
+
+ void searchFileURL_004()
+ {
+ OUString aSystemPathList(aRootSys + PATH_LIST_DELIMITER + aTempDirectorySys + PATH_LIST_DELIMITER + aRootSys + "system/path/../name");
+ auto nError1 = osl::FileBase::searchFileURL(aUserDirectoryURL, aSystemPathList, aUStr);
+ bool bOk = compareFileName(aUStr, aUserDirectoryURL);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for searchFileURL function: search directory is a list of system paths",
+ osl::FileBase::E_None, nError1);
+ CPPUNIT_ASSERT_MESSAGE("test for searchFileURL function: search directory is a list of system paths",
+ bOk);
+ }
+
+ void searchFileURL_005()
+ {
+ auto nError1 = osl::FileBase::searchFileURL(aUserDirectoryURL, aNullURL, aUStr);
+ bool bOk = compareFileName(aUStr, aUserDirectoryURL);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for searchFileURL function: search directory is NULL",
+ osl::FileBase::E_None, nError1);
+ CPPUNIT_ASSERT_MESSAGE("test for searchFileURL function: search directory is NULL",
+ bOk);
+ }
+
+ CPPUNIT_TEST_SUITE(searchFileURL);
+ CPPUNIT_TEST(searchFileURL_001);
+ CPPUNIT_TEST(searchFileURL_002);
+ CPPUNIT_TEST(searchFileURL_003);
+ CPPUNIT_TEST(searchFileURL_004);
+ CPPUNIT_TEST(searchFileURL_005);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // static inline RC getTempDirURL(OUString& ustrTempDirURL)
+
+ class getTempDirURL : public CppUnit::TestFixture
+ {
+ private:
+ OUString aUStr;
+
+ public:
+ void setUp() override
+ {
+ osl::FileBase::RC nError = osl::FileBase::getTempDirURL(aUStr);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for getTempDirURL function: execution",
+ osl::FileBase::E_None, nError);
+ }
+
+ void getTempDirURL_002()
+ {
+ CPPUNIT_ASSERT_MESSAGE("test for getTempDirURL function: test for open and write access rights",
+ checkDirectory(aUStr, oslCheckMode::OpenAccess));
+ CPPUNIT_ASSERT_MESSAGE("test for getTempDirURL function: test for open and write access rights",
+ checkDirectory(aUStr, oslCheckMode::ReadAccess));
+ CPPUNIT_ASSERT_MESSAGE("test for getTempDirURL function: test for open and write access rights",
+ checkDirectory(aUStr, oslCheckMode::WriteAccess));
+ }
+
+ CPPUNIT_TEST_SUITE(getTempDirURL);
+ CPPUNIT_TEST(getTempDirURL_002);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // static inline RC createTempFile(OUString* pustrDirectoryURL,
+ // oslFileHandle* pHandle,
+ // OUString* pustrTempFileURL)
+
+ class createTempFile : public CppUnit::TestFixture
+ {
+ private:
+ std::unique_ptr<oslFileHandle> pHandle;
+ std::unique_ptr<OUString> pUStr_DirURL;
+ std::unique_ptr<OUString> pUStr_FileURL;
+
+ public:
+ void setUp() override
+ {
+ pHandle.reset(new oslFileHandle());
+ pUStr_DirURL.reset(new OUString(aUserDirectoryURL));
+ pUStr_FileURL.reset(new OUString());
+ }
+
+ void tearDown() override
+ {
+ pUStr_DirURL.reset();
+ pUStr_FileURL.reset();
+ pHandle.reset();
+ }
+
+ void createTempFile_001()
+ {
+ auto nError1 = osl::FileBase::createTempFile(pUStr_DirURL.get(), pHandle.get(), pUStr_FileURL.get());
+ File testFile(*pUStr_FileURL);
+ auto nError2 = testFile.open(osl_File_OpenFlag_Create);
+
+ if (nError2 == osl::FileBase::E_EXIST)
+ {
+ osl_closeFile(*pHandle);
+ deleteTestFile(*pUStr_FileURL);
+ }
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for createTempFile function: create temp file and test the existence",
+ osl::FileBase::E_None, nError1);
+ CPPUNIT_ASSERT_MESSAGE("test for createTempFile function: create temp file and test the existence",
+ (pHandle != nullptr));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for createTempFile function: create temp file and test the existence",
+ osl::FileBase::E_EXIST, nError2);
+ }
+
+ void createTempFile_002()
+ {
+ bool bOK = false;
+ auto nError1 = osl::FileBase::createTempFile(pUStr_DirURL.get(), pHandle.get(), pUStr_FileURL.get());
+ File testFile(*pUStr_FileURL);
+ auto nError2 = testFile.open(osl_File_OpenFlag_Create);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("createTempFile function: create a temp file, but it does not exist",
+ osl::FileBase::E_None, nError1);
+ CPPUNIT_ASSERT_MESSAGE("createTempFile function: create a temp file, but it does not exist",
+ (pHandle != nullptr));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("createTempFile function: create a temp file, but it does not exist",
+ osl::FileBase::E_EXIST, nError2);
+
+ // check file if have the write permission
+ if (nError2 == osl::FileBase::E_EXIST)
+ {
+ bOK = ifFileCanWrite(*pUStr_FileURL);
+ osl_closeFile(*pHandle);
+ deleteTestFile(*pUStr_FileURL);
+ }
+
+ CPPUNIT_ASSERT_MESSAGE("test for open and write access rights, in (W32), it did not have write access right, but it should be writable.",
+ bOK);
+ }
+
+ void createTempFile_003()
+ {
+ auto nError1 = osl::FileBase::createTempFile(pUStr_DirURL.get(), pHandle.get(), nullptr);
+ // the temp file will be removed when return from createTempFile
+ bool bOK = (pHandle != nullptr && nError1 == osl::FileBase::E_None);
+ if (bOK)
+ osl_closeFile(*pHandle);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for createTempFile function: set pUStrFileURL to 0 to let it remove the file after call.",
+ osl::FileBase::E_None, nError1);
+ CPPUNIT_ASSERT_MESSAGE("test for createTempFile function: set pUStrFileURL to 0 to let it remove the file after call.",
+ bOK);
+ }
+
+ void createTempFile_004()
+ {
+ auto nError1 = osl::FileBase::createTempFile(pUStr_DirURL.get(), nullptr, pUStr_FileURL.get());
+ bool bOK = (pUStr_FileURL != nullptr);
+ CPPUNIT_ASSERT(bOK);
+ File testFile(*pUStr_FileURL);
+ auto nError2 = testFile.open(osl_File_OpenFlag_Create);
+ deleteTestFile(*pUStr_FileURL);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("createTempFile function: create a temp file, but it does not exist",
+ osl::FileBase::E_None, nError1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("createTempFile function: create a temp file, but it does not exist",
+ osl::FileBase::E_EXIST, nError2);
+ CPPUNIT_ASSERT_MESSAGE("createTempFile function: create a temp file, but it does not exist",
+ bOK);
+
+ }
+
+ CPPUNIT_TEST_SUITE(createTempFile);
+ CPPUNIT_TEST(createTempFile_001);
+ CPPUNIT_TEST(createTempFile_002);
+ CPPUNIT_TEST(createTempFile_003);
+ CPPUNIT_TEST(createTempFile_004);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // FIXME: remove the _disabled to enable:
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_FileBase::getAbsoluteFileURL, "osl_osl::FileBase");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_FileBase::SystemPath_FileURL, "osl_osl::FileBase");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_FileBase::searchFileURL, "osl_osl::FileBase");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_FileBase::getTempDirURL, "osl_osl::FileBase");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_FileBase::createTempFile, "osl_osl::FileBase");
+
+ CPPUNIT_REGISTRY_ADD_TO_DEFAULT("osl_osl::FileBase");
+}
+
+namespace osl_FileStatus
+{
+ // testing the method
+ // FileStatus(sal_uInt32 nMask): _nMask(nMask)
+ class ctors : public CppUnit::TestFixture
+ {
+ private:
+ OUString aUStr;
+ DirectoryItem rItem;
+
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpdir/tmpname.
+ createTestDirectory(aTmpName3);
+ createTestFile(aTmpName4);
+
+ Directory aDir(aTmpName3);
+ auto nError1 = aDir.open();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = aDir.getNextItem(rItem);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ aDir.close();
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpdir/tmpname.
+ deleteTestFile(aTmpName4);
+ deleteTestDirectory(aTmpName3);
+ }
+
+ void ctors_001()
+ {
+ FileStatus rFileStatus(osl_FileStatus_Mask_All);
+ auto nError1 = rItem.getFileStatus(rFileStatus);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ aUStr = rFileStatus.getFileName();
+
+ CPPUNIT_ASSERT_MESSAGE("test for ctors function: mask all and see the file name",
+ compareFileName(aUStr, aTmpName2));
+ }
+
+ void ctors_002()
+ {
+ FileStatus rFileStatus(0);
+ auto nError1 = rItem.getFileStatus(rFileStatus);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ aUStr = rFileStatus.getFileName();
+
+ CPPUNIT_ASSERT_MESSAGE("test for ctors function: mask is empty",
+ compareFileName(aUStr, aNullURL));
+ }
+
+ CPPUNIT_TEST_SUITE(ctors);
+ CPPUNIT_TEST(ctors_001);
+ CPPUNIT_TEST(ctors_002);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline sal_Bool isValid(sal_uInt32 nMask) const
+
+ class isValid : public CppUnit::TestFixture
+ {
+ private:
+ std::unique_ptr<Directory> pDir;
+ DirectoryItem rItem_file, rItem_link;
+
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpdir/tmpname.
+ createTestDirectory(aTmpName3);
+ createTestFile(aTmpName4);
+
+ pDir.reset(new Directory(aTmpName3));
+ osl::FileBase::RC nError1 = pDir->open();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = pDir->getNextItem(rItem_file, 1);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ }
+
+ void tearDown() override
+ {
+ osl::FileBase::RC nError1 = pDir->close();
+ pDir.reset();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(errorToStr(nError1).getStr(), osl::FileBase::E_None, nError1);
+
+ // remove the tempfile in $TEMP/tmpdir/tmpname.
+ deleteTestFile(aTmpName4);
+ deleteTestDirectory(aTmpName3);
+ }
+
+ void isValid_001()
+ {
+ sal_uInt32 mask = 0;
+ FileStatus rFileStatus(mask);
+ osl::FileBase::RC nError1 = rItem_file.getFileStatus(rFileStatus);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ bool bOk = rFileStatus.isValid(mask);
+
+ CPPUNIT_ASSERT_MESSAGE("test for isValid function: no fields specified", bOk);
+ }
+
+ void check_FileStatus(FileStatus const& _aStatus)
+ {
+ OString sStat;
+ if (_aStatus.isValid(osl_FileStatus_Mask_Type))
+ sStat += "type ";
+ if (_aStatus.isValid(osl_FileStatus_Mask_Attributes))
+ sStat += "attributes ";
+ if (_aStatus.isValid(osl_FileStatus_Mask_CreationTime))
+ sStat += "ctime ";
+ if (_aStatus.isValid(osl_FileStatus_Mask_AccessTime))
+ sStat += "atime ";
+ if (_aStatus.isValid(osl_FileStatus_Mask_ModifyTime))
+ sStat += "mtime ";
+ if (_aStatus.isValid(osl_FileStatus_Mask_FileSize))
+ sStat += "filesize ";
+ if (_aStatus.isValid(osl_FileStatus_Mask_FileName))
+ sStat += "filename ";
+ if (_aStatus.isValid(osl_FileStatus_Mask_FileURL))
+ sStat += "fileurl ";
+ printf("mask: %s\n", sStat.getStr());
+ }
+
+ void isValid_002()
+ {
+ createTestFile(aTmpName6);
+ sal_uInt32 mask_file = osl_FileStatus_Mask_Type |
+ osl_FileStatus_Mask_Attributes |
+ osl_FileStatus_Mask_CreationTime |
+ osl_FileStatus_Mask_AccessTime |
+ osl_FileStatus_Mask_ModifyTime |
+ osl_FileStatus_Mask_FileSize |
+ osl_FileStatus_Mask_FileName |
+ osl_FileStatus_Mask_FileURL;
+
+ FileStatus rFileStatus(mask_file);
+ DirectoryItem::get(aTmpName6, rItem_file);
+ osl::FileBase::RC nError1 = rItem_file.getFileStatus(rFileStatus);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(errorToStr(nError1).getStr(), osl::FileBase::E_None, nError1);
+
+ check_FileStatus(rFileStatus);
+ deleteTestFile(aTmpName6);
+
+ }
+
+ /** Check if is a valid linked file.
+
+ Link is not defined in Windows, and on Linux, we can not get the directory item of the linked file.
+ We have to defer to filesystems, normal filesystems support links (EXT2, ...), castrated filesystems
+ don't have links (FAT, FAT32) and Windows NT NTFS support links, but the Windows API doesn't :-(
+ */
+ void isValid_003()
+ {
+#if 0
+#if defined (UNX)
+ sal_Int32 fd;
+
+ OUString aUStr_LnkFileSys(aTempDirectorySys), aUStr_SrcFileSys(aTempDirectorySys);
+ aUStr_LnkFileSys += aSlashURL + getCurrentPID() + "/tmpdir/link.file";
+ aUStr_SrcFileSys += aSlashURL + getCurrentPID() + "/tmpdir/tmpname";
+
+ OString strLinkFileName;
+ OString strSrcFileName;
+ strLinkFileName = OUStringToOString(aUStr_LnkFileSys, RTL_TEXTENCODING_ASCII_US);
+ strSrcFileName = OUStringToOString(aUStr_SrcFileSys, RTL_TEXTENCODING_ASCII_US);
+
+ // create a link file and link it to file "/tmp/PID/tmpdir/tmpname"
+ fd = symlink(strSrcFileName.getStr(), strLinkFileName.getStr());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), fd);
+
+ // testDirectory is "/tmp/PID/tmpdir/"
+ Directory testDirectory(aTmpName3);
+ testDirectory.open();
+ OUString aFileName ("link.file");
+ bool bOk = false;
+ while (true)
+ {
+ osl::FileBase::RC nError1 = testDirectory.getNextItem(rItem_link, 4);
+
+ if (nError1 == osl::FileBase::E_None)
+ {
+ sal_uInt32 mask_link = osl_FileStatus_Mask_FileName | osl_FileStatus_Mask_LinkTargetURL;
+ FileStatus rFileStatus(mask_link);
+ rItem_link.getFileStatus(rFileStatus);
+
+ if (compareFileName(rFileStatus.getFileName(), aFileName))
+ {
+ if (rFileStatus.isValid(osl_FileStatus_Mask_LinkTargetURL))
+ {
+ bOk = true;
+ break;
+ }
+ }
+ }
+ else
+ {
+ break;
+ }
+ };
+
+ fd = remove(strLinkFileName.getStr());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), fd);
+
+ CPPUNIT_ASSERT_MESSAGE("test for isValid function: link file, check for LinkTargetURL", bOk);
+#endif
+#endif
+ }
+
+ void isValid_004()
+ {
+ sal_uInt32 mask_file_all = osl_FileStatus_Mask_All;
+ FileStatus rFileStatus_all(mask_file_all);
+ osl::FileBase::RC nError1 = rItem_file.getFileStatus(rFileStatus_all);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ check_FileStatus(rFileStatus_all);
+
+ sal_uInt32 mask_file_val = osl_FileStatus_Mask_Validate;
+ FileStatus rFileStatus_val(mask_file_val);
+ nError1 = rItem_file.getFileStatus(rFileStatus_val);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ check_FileStatus(rFileStatus_val);
+ }
+
+ CPPUNIT_TEST_SUITE(isValid);
+ CPPUNIT_TEST(isValid_001);
+ CPPUNIT_TEST(isValid_002);
+ CPPUNIT_TEST(isValid_003);
+ CPPUNIT_TEST(isValid_004);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline Type getFileType() const
+
+ class getFileType : public CppUnit::TestFixture
+ {
+ private:
+ DirectoryItem m_aItem_1, m_aItem_2, m_aVolumeItem, m_aFifoItem;
+ DirectoryItem m_aLinkItem, m_aSocketItem, m_aSpecialItem;
+
+ public:
+ void setUp() override
+ {
+ // create a tempfile: $TEMP/tmpdir/tmpname.
+ // a tempdirectory: $TEMP/tmpdir/tmpdir.
+ // use $ROOT/staroffice as volume ---> use dev/fd as volume.
+ // and get their directory item.
+ createTestDirectory(aTmpName3);
+ createTestFile(aTmpName3, aTmpName2);
+ createTestDirectory(aTmpName3, aTmpName1);
+
+ std::unique_ptr<Directory> xDir(new Directory(aTmpName3));
+ auto nError1 = xDir->open();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("open aTmpName3 failed!", osl::FileBase::E_None, nError1);
+ // getNextItem can not assure which item retrieved
+ nError1 = xDir->getNextItem(m_aItem_1, 1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("get first item failed!", osl::FileBase::E_None, nError1);
+
+ nError1 = xDir->getNextItem(m_aItem_2);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("get second item failed!", osl::FileBase::E_None, nError1);
+ xDir->close();
+ // FIXME mindy: failed on my RH9, so removed temporarily
+ // nError1 = DirectoryItem::get(aVolURL2, m_aVolumeItem);
+ // CPPUNIT_ASSERT_MESSAGE("get volume item failed!", osl::FileBase::E_None == nError1);
+ }
+
+ void tearDown() override
+ {
+ // remove all in $TEMP/tmpdir.
+ deleteTestDirectory(aTmpName3, aTmpName1);
+ deleteTestFile(aTmpName3, aTmpName2);
+ deleteTestDirectory(aTmpName3);
+ }
+
+ void getFileType_001()
+ {
+ FileStatus rFileStatus(osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName);
+ auto nError1 = m_aItem_1.getFileStatus(rFileStatus);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("getFileStatus failed", osl::FileBase::E_None, nError1);
+
+ check_FileType(rFileStatus);
+ }
+
+ void check_FileType(osl::FileStatus const& _rFileStatus)
+ {
+ if (_rFileStatus.isValid(osl_FileStatus_Mask_FileName))
+ {
+ OUString suFilename = _rFileStatus.getFileName();
+
+ if (_rFileStatus.isValid(osl_FileStatus_Mask_Type))
+ {
+ osl::FileStatus::Type eType = _rFileStatus.getFileType();
+ bool bOK = false;
+
+ if (compareFileName(suFilename, aTmpName2))
+ bOK = (eType == osl::FileStatus::Regular);
+
+ if (compareFileName(suFilename, aTmpName1))
+ bOK = (eType == FileStatus::Directory);
+
+ CPPUNIT_ASSERT_MESSAGE("test for getFileType function: ", bOK);
+ }
+ }
+ // LLA: it's not a bug, if a FileStatus not exist, so no else
+ }
+
+ void getFileType_002()
+ {
+ FileStatus rFileStatus(osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName);
+ auto nError1 = m_aItem_2.getFileStatus(rFileStatus);
+
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ check_FileType(rFileStatus);
+ }
+
+ void getFileType_003()
+ {
+ }
+
+ void getFileType_007()
+ {
+#if defined(__sun) // Special file is different in Windows
+ auto nError1 = DirectoryItem::get(aTypeURL2, m_aSpecialItem);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ // check for File type
+ FileStatus rFileStatus(osl_FileStatus_Mask_Type);
+ nError1 = m_aSpecialItem.getFileStatus(rFileStatus);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ if (rFileStatus.isValid(osl_FileStatus_Mask_Type))
+ {
+ osl::FileStatus::Type eType = rFileStatus.getFileType();
+
+ CPPUNIT_ASSERT_MESSAGE("test for getFileType function: Special, Solaris version ",
+ (eType == FileStatus::Special));
+ }
+#endif
+ }
+
+ CPPUNIT_TEST_SUITE(getFileType);
+ CPPUNIT_TEST(getFileType_001);
+ CPPUNIT_TEST(getFileType_002);
+ CPPUNIT_TEST(getFileType_003);
+ CPPUNIT_TEST(getFileType_007);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline sal_uInt64 getAttributes() const
+
+ class getAttributes : public CppUnit::TestFixture
+ {
+ private:
+ OUString aTypeURL, aTypeURL_Hid;
+ DirectoryItem rItem, rItem_hidden;
+
+ public:
+ void setUp() override
+ {
+ aTypeURL = aUserDirectoryURL.copy(0);
+ concatURL(aTypeURL, aTmpName2);
+ createTestFile(aTypeURL);
+ osl::FileBase::RC nError = DirectoryItem::get(aTypeURL, rItem);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError);
+
+ aTypeURL_Hid = aUserDirectoryURL.copy(0);
+ concatURL(aTypeURL_Hid, aHidURL1);
+ createTestFile(aTypeURL_Hid);
+#ifdef _WIN32
+ hideFile(aTypeURL_Hid);
+#endif
+ nError = DirectoryItem::get(aTypeURL_Hid, rItem_hidden);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError);
+ }
+
+ void tearDown() override
+ {
+ deleteTestFile(aTypeURL);
+ deleteTestFile(aTypeURL_Hid);
+ }
+
+#if (defined UNX)
+// windows only has 3 file attributes: normal, readonly and hidden
+ void getAttributes_001()
+ {
+ changeFileMode(aTypeURL, S_IRUSR | S_IRGRP | S_IROTH);
+
+ FileStatus rFileStatus(osl_FileStatus_Mask_Attributes);
+ osl::FileBase::RC nError = rItem.getFileStatus(rFileStatus);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError);
+
+ if (geteuid() == 0) // as root, access(W_OK) may be true despite mode
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for getAttributes function: (not ReadOnly,) GrpRead, OwnRead, OthRead(UNX version) ",
+ static_cast<sal_uInt64>(osl_File_Attribute_GrpRead | osl_File_Attribute_OwnRead | osl_File_Attribute_OthRead),
+ rFileStatus.getAttributes());
+ }
+ else
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for getAttributes function: ReadOnly, GrpRead, OwnRead, OthRead(UNX version) ",
+ static_cast<sal_uInt64>(osl_File_Attribute_ReadOnly | osl_File_Attribute_GrpRead | osl_File_Attribute_OwnRead | osl_File_Attribute_OthRead),
+ rFileStatus.getAttributes());
+ }
+ }
+#else // Windows version
+ void getAttributes_001()
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for getAttributes function: ReadOnly, GrpRead, OwnRead, OthRead(Windows version)",
+ 1, 1);
+ }
+#endif
+
+ void getAttributes_002()
+ {
+#if (defined UNX)
+ changeFileMode(aTypeURL, S_IXUSR | S_IXGRP | S_IXOTH);
+
+ FileStatus rFileStatus(osl_FileStatus_Mask_Attributes);
+ osl::FileBase::RC nError = rItem.getFileStatus(rFileStatus);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError);
+
+ if (geteuid() == 0) // as root, access(W_OK) may be true despite mode
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for getAttributes function: Executable, GrpExe, OwnExe, OthExe, the result is (not Readonly,) Executable, GrpExe, OwnExe, OthExe, it partly not pass(Solaris version)",
+ static_cast<sal_uInt64>(osl_File_Attribute_Executable | osl_File_Attribute_GrpExe | osl_File_Attribute_OwnExe | osl_File_Attribute_OthExe),
+ rFileStatus.getAttributes());
+ }
+ else
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for getAttributes function: Executable, GrpExe, OwnExe, OthExe, the result is Readonly, Executable, GrpExe, OwnExe, OthExe, it partly not pass(Solaris version)",
+ static_cast<sal_uInt64>(osl_File_Attribute_ReadOnly | osl_File_Attribute_Executable | osl_File_Attribute_GrpExe | osl_File_Attribute_OwnExe | osl_File_Attribute_OthExe),
+ rFileStatus.getAttributes());
+ }
+#endif
+ }
+
+#if (defined UNX)
+ void getAttributes_003()
+ {
+ changeFileMode(aTypeURL, S_IWUSR | S_IWGRP | S_IWOTH);
+
+ FileStatus rFileStatus(osl_FileStatus_Mask_Attributes);
+ osl::FileBase::RC nError = rItem.getFileStatus(rFileStatus);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for getAttributes function: GrpWrite, OwnWrite, OthWrite(Solaris version)",
+ static_cast<sal_uInt64>(osl_File_Attribute_GrpWrite | osl_File_Attribute_OwnWrite | osl_File_Attribute_OthWrite),
+ rFileStatus.getAttributes());
+ }
+#else // Windows version
+ void getAttributes_003()
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for getAttributes function: GrpWrite, OwnWrite, OthWrite(Windows version)",
+ 1, 1);
+ }
+#endif
+
+ void getAttributes_004()
+ {
+ sal_Int32 test_Attributes = osl_File_Attribute_Hidden;
+ FileStatus rFileStatus(osl_FileStatus_Mask_Attributes);
+ osl::FileBase::RC nError = rItem_hidden.getFileStatus(rFileStatus);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError);
+ test_Attributes &= rFileStatus.getAttributes();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for getAttributes function: Hidden files",
+ static_cast<sal_Int32>(osl_File_Attribute_Hidden), test_Attributes);
+ }
+
+ CPPUNIT_TEST_SUITE(getAttributes);
+ CPPUNIT_TEST(getAttributes_001);
+ CPPUNIT_TEST(getAttributes_002);
+ CPPUNIT_TEST(getAttributes_003);
+ CPPUNIT_TEST(getAttributes_004);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline TimeValue getAccessTime() const
+
+ class getAccessTime : public CppUnit::TestFixture
+ {
+ private:
+ OUString aTypeURL;
+ DirectoryItem rItem;
+
+ public:
+ void setUp() override
+ {
+ aTypeURL = aUserDirectoryURL.copy(0);
+ concatURL(aTypeURL, aTmpName2);
+ createTestFile(aTypeURL);
+ osl::FileBase::RC nError = DirectoryItem::get(aTypeURL, rItem);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError);
+
+ }
+
+ void tearDown() override
+ {
+ deleteTestFile(aTypeURL);
+ }
+
+ void getAccessTime_001()
+ {
+ TimeValue *pTV_current = nullptr;
+ CPPUNIT_ASSERT((pTV_current = static_cast<TimeValue*>(malloc(sizeof(TimeValue)))) != nullptr);
+ TimeValue *pTV_access = nullptr;
+ CPPUNIT_ASSERT((pTV_access = static_cast<TimeValue*>(malloc(sizeof(TimeValue)))) != nullptr);
+
+ FileStatus rFileStatus(osl_FileStatus_Mask_AccessTime);
+ osl::FileBase::RC nError = rItem.getFileStatus(rFileStatus);
+ bool bOk = osl_getSystemTime(pTV_current);
+ CPPUNIT_ASSERT(bOk);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError);
+
+ *pTV_access = rFileStatus.getAccessTime();
+
+ bool bOK = t_compareTime(pTV_access, pTV_current, delta);
+ free(pTV_current);
+ free(pTV_access);
+
+ CPPUNIT_ASSERT_MESSAGE("test for getAccessTime function: This test turns out that UNX precision is no more than 1 sec, don't know how to test this function, in Windows test, it lost hour min sec, only have date time. ",
+ bOK);
+ }
+
+ CPPUNIT_TEST_SUITE(getAccessTime);
+ CPPUNIT_TEST(getAccessTime_001);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline TimeValue getModifyTime() const
+
+ class getModifyTime : public CppUnit::TestFixture
+ {
+ private:
+ OUString aTypeURL;
+ DirectoryItem rItem;
+
+ public:
+ void getModifyTime_001()
+ {
+ TimeValue *pTV_current = nullptr;
+ CPPUNIT_ASSERT((pTV_current = static_cast<TimeValue*>(malloc(sizeof(TimeValue)))) != nullptr);
+
+ // create file
+ aTypeURL = aUserDirectoryURL.copy(0);
+ concatURL(aTypeURL, aTmpName2);
+ createTestFile(aTypeURL);
+
+ // get current time
+ bool bOk = osl_getSystemTime(pTV_current);
+ CPPUNIT_ASSERT(bOk);
+
+ // get instance item and filestatus
+ osl::FileBase::RC nError = DirectoryItem::get(aTypeURL, rItem);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError);
+ FileStatus rFileStatus(osl_FileStatus_Mask_ModifyTime);
+ nError = rItem.getFileStatus(rFileStatus);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError);
+
+ // get modify time
+ TimeValue* pTV_modify = nullptr;
+ CPPUNIT_ASSERT((pTV_modify = static_cast<TimeValue*>(malloc(sizeof(TimeValue)))) != nullptr);
+ *pTV_modify = rFileStatus.getModifyTime();
+
+ bool bOK = t_compareTime(pTV_modify, pTV_current, delta);
+ // delete file
+ deleteTestFile(aTypeURL);
+ free(pTV_current);
+ free(pTV_modify);
+
+ CPPUNIT_ASSERT_MESSAGE("test for getModifyTime function: This test turns out that UNX precision is no more than 1 sec, don't know how to improve this function. ",
+ bOK);
+ }
+
+ CPPUNIT_TEST_SUITE(getModifyTime);
+ CPPUNIT_TEST(getModifyTime_001);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline sal_uInt64 getFileSize() const
+
+ class getFileSize : public CppUnit::TestFixture
+ {
+ private:
+ OUString aTypeURL;
+ DirectoryItem rItem;
+
+ public:
+ void setUp() override
+ {
+ aTypeURL = aUserDirectoryURL.copy(0);
+ concatURL(aTypeURL, aTmpName2);
+ createTestFile(aTypeURL);
+ osl::FileBase::RC nError = DirectoryItem::get(aTypeURL, rItem);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError);
+ }
+
+ void tearDown() override
+ {
+ deleteTestFile(aTypeURL);
+ }
+
+ void getFileSize_001()
+ {
+ FileStatus rFileStatus(osl_FileStatus_Mask_FileSize);
+ osl::FileBase::RC nError = rItem.getFileStatus(rFileStatus);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError);
+
+ sal_uInt64 uFileSize = rFileStatus.getFileSize();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for getFileSize function: empty file ",
+ static_cast<sal_uInt64>(0), uFileSize);
+ }
+
+ void getFileSize_002()
+ {
+ File testfile(aTypeURL);
+ osl::FileBase::RC nError = testfile.open(osl_File_OpenFlag_Write | osl_File_OpenFlag_Read);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError);
+ nError = testfile.setSize(TEST_FILE_SIZE);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError);
+
+ nError = DirectoryItem::get(aTypeURL, rItem);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError);
+ FileStatus rFileStatus(osl_FileStatus_Mask_FileSize);
+ nError = rItem.getFileStatus(rFileStatus);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError);
+ sal_uInt64 uFileSize = rFileStatus.getFileSize();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for getFileSize function: file with size of TEST_FILE_SIZE, did not pass in (W32). ",
+ static_cast<sal_uInt64>(TEST_FILE_SIZE), uFileSize);
+ }
+
+ CPPUNIT_TEST_SUITE(getFileSize);
+ CPPUNIT_TEST(getFileSize_001);
+ CPPUNIT_TEST(getFileSize_002);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline OUString getFileName() const
+
+ class getFileName : public CppUnit::TestFixture
+ {
+ private:
+ OUString aTypeURL;
+ DirectoryItem rItem;
+
+ public:
+ void setUp() override
+ {
+ aTypeURL = aUserDirectoryURL.copy(0);
+ concatURL(aTypeURL, aTmpName2);
+ createTestFile(aTypeURL);
+ osl::FileBase::RC nError = DirectoryItem::get(aTypeURL, rItem);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError);
+ }
+
+ void tearDown() override
+ {
+ deleteTestFile(aTypeURL);
+ }
+
+
+ void getFileName_001()
+ {
+ FileStatus rFileStatus(osl_FileStatus_Mask_FileName);
+ osl::FileBase::RC nError = rItem.getFileStatus(rFileStatus);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError);
+
+ OUString aFileName = rFileStatus.getFileName();
+
+ CPPUNIT_ASSERT_MESSAGE("test for getFileName function: name compare with specify",
+ compareFileName(aFileName, aTmpName2));
+ }
+
+ CPPUNIT_TEST_SUITE(getFileName);
+ CPPUNIT_TEST(getFileName_001);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline OUString getFileURL() const
+
+ class getFileURL : public CppUnit::TestFixture
+ {
+ DirectoryItem rItem;
+
+ public:
+ void setUp() override
+ {
+ createTestFile(aTmpName6);
+ osl::FileBase::RC nError = DirectoryItem::get(aTmpName6, rItem);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError);
+ }
+
+ void tearDown() override
+ {
+ deleteTestFile(aTmpName6);
+ }
+
+
+ void getFileURL_001()
+ {
+ FileStatus rFileStatus(osl_FileStatus_Mask_FileURL);
+ osl::FileBase::RC nError = rItem.getFileStatus(rFileStatus);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError);
+
+ OUString aFileURL = rFileStatus.getFileURL();
+
+ CPPUNIT_ASSERT_MESSAGE("test for getFileURL function: ",
+ compareFileName(aFileURL, aTmpName6));
+ }
+
+ CPPUNIT_TEST_SUITE(getFileURL);
+ CPPUNIT_TEST(getFileURL_001);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline OUString getLinkTargetURL() const
+
+ class getLinkTargetURL : public CppUnit::TestFixture
+ {
+ private:
+ OUString aTypeURL;
+ DirectoryItem rItem;
+
+ public:
+ void setUp() override
+ {
+ aTypeURL = aUserDirectoryURL.copy(0);
+ concatURL(aTypeURL, aTmpName2);
+ createTestFile(aTypeURL);
+ }
+
+ void tearDown() override
+ {
+ deleteTestFile(aTypeURL);
+ }
+
+ void getLinkTargetURL_001()
+ {
+#if 0
+#if (defined UNX) // Link file is not defined in Windows
+ // create a link file;
+ OUString aUStr_LnkFileSys(aTempDirectorySys), aUStr_SrcFileSys(aTempDirectorySys);
+ aUStr_LnkFileSys += aSlashURL + getCurrentPID() + "/link.file";
+ aUStr_SrcFileSys += aSlashURL + getCurrentPID() + "/tmpname";
+
+ OString strLinkFileName, strSrcFileName;
+ strLinkFileName = OUStringToOString(aUStr_LnkFileSys, RTL_TEXTENCODING_ASCII_US);
+ strSrcFileName = OUStringToOString(aUStr_SrcFileSys, RTL_TEXTENCODING_ASCII_US);
+
+ sal_Int32 fd;
+ fd = symlink(strSrcFileName.getStr(), strLinkFileName.getStr());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("in creating link file", static_cast<sal_Int32>(0), fd);
+
+ // get linkTarget URL
+ auto nError = DirectoryItem::get(aLnkURL1, rItem);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("in getting link file item", osl::FileBase::E_None, nError);
+
+ FileStatus rFileStatus(osl_FileStatus_Mask_LinkTargetURL);
+ nError = rItem.getFileStatus(rFileStatus);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("in getting link file status", osl::FileBase::E_None, nError);
+ OUString aFileURL = rFileStatus.getLinkTargetURL();
+
+ // remove link file
+ fd = remove(strLinkFileName.getStr());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("in deleting link file", static_cast<sal_Int32>(0), fd);
+
+ CPPUNIT_ASSERT_MESSAGE("test for getLinkTargetURL function: Solaris version, create a file, and a link file link to it, get its LinkTargetURL and compare",
+ compareFileName(aFileURL, aTypeURL));
+#endif
+#endif
+ }
+
+ CPPUNIT_TEST_SUITE(getLinkTargetURL);
+ CPPUNIT_TEST(getLinkTargetURL_001);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_FileStatus::ctors, "osl_FileStatus");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_FileStatus::isValid, "osl_FileStatus");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_FileStatus::getFileType, "osl_FileStatus");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_FileStatus::getAttributes, "osl_FileStatus");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_FileStatus::getAccessTime, "osl_FileStatus");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_FileStatus::getModifyTime, "osl_FileStatus");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_FileStatus::getFileSize, "osl_FileStatus");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_FileStatus::getFileName, "osl_FileStatus");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_FileStatus::getFileURL, "osl_FileStatus");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_FileStatus::getLinkTargetURL, "osl_FileStatus");
+
+ CPPUNIT_REGISTRY_ADD_TO_DEFAULT("osl_FileStatus");
+}
+
+namespace osl_File
+{
+
+ // testing the method
+ // File(const OUString& ustrFileURL)
+
+ class ctors : public CppUnit::TestFixture
+ {
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpdir/tmpname.
+ createTestDirectory(aTmpName3);
+ createTestFile(aTmpName4);
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpdir/tmpname.
+ deleteTestFile(aTmpName4);
+ deleteTestDirectory(aTmpName3);
+ }
+
+ void ctors_001()
+ {
+ File testFile(aTmpName4);
+
+ osl::FileBase::RC nError1 = testFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
+ osl::FileBase::RC nError2 = testFile.close();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for ctors function: initialize a File and test its open and close",
+ osl::FileBase::E_None, nError1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for ctors function: initialize a File and test its open and close",
+ osl::FileBase::E_None, nError2);
+ }
+
+ void ctors_002()
+ {
+ File testFile(aTmpName5);
+ char buffer[30] = "Test for File constructor";
+ sal_uInt64 nCount;
+
+ osl::FileBase::RC nError1 = testFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
+ osl::FileBase::RC nError2 = testFile.write(buffer, 30, nCount);
+ testFile.close();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for ctors function: test relative file URL, this test show that relative file URL is also acceptable",
+ osl::FileBase::E_None, nError1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for ctors function: test relative file URL, this test show that relative file URL is also acceptable",
+ osl::FileBase::E_None, nError2);
+ }
+
+ CPPUNIT_TEST_SUITE(ctors);
+ CPPUNIT_TEST(ctors_001);
+ CPPUNIT_TEST(ctors_002);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline RC open(sal_uInt32 uFlags)
+
+ class open : public CppUnit::TestFixture
+ {
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpdir/tmpname.
+ createTestDirectory(aTmpName3);
+ createTestFile(aTmpName4);
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpdir/tmpname.
+ deleteTestFile(aTmpName4);
+ deleteTestDirectory(aTmpName3);
+ }
+
+
+ void open_001()
+ {
+ File testFile(aTmpName4);
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
+ auto nError2 = testFile.close();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("close error", osl::FileBase::E_None, nError2);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for open function: open a regular file",
+ osl::FileBase::E_None, nError1);
+ }
+
+ void open_002()
+ {
+ File testFile(aTmpName3);
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Read);
+
+ CPPUNIT_ASSERT_MESSAGE("test for open function: open a directory",
+ (File::E_INVAL == nError1) || (File::E_ACCES == nError1));
+ }
+
+ void open_003()
+ {
+ File testFile(aCanURL1);
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for open function: open a non-exist file",
+ File::E_NOENT, nError1);
+ }
+
+ void open_005()
+ {
+ File testFile(aTmpName4);
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Create);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for open function: create an exist file",
+ File::E_EXIST, nError1);
+ }
+
+ void open_006()
+ {
+ File testFile(aCanURL1);
+ char buffer_write[30] = "Test for File open";
+ char buffer_read[30];
+ sal_uInt64 nCount_write, nCount_read;
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_Write | osl_File_OpenFlag_Create);
+ auto nError2 = testFile.write(buffer_write, 30, nCount_write);
+ osl::FileBase::RC nError4 = testFile.setPos(osl_Pos_Absolut, 0);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError4);
+ auto nError3 = testFile.read(buffer_read, 10, nCount_read);
+
+ osl::FileBase::RC nError5 = testFile.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError5);
+ osl::FileBase::RC nError6 = osl::File::remove(aCanURL1);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError6);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for open function: test for osl_File_OpenFlag_Read, osl_File_OpenFlag_Write and osl_File_OpenFlag_Create",
+ osl::FileBase::E_None, nError1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for open function: test for osl_File_OpenFlag_Read, osl_File_OpenFlag_Write and osl_File_OpenFlag_Create",
+ osl::FileBase::E_None, nError2);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for open function: test for osl_File_OpenFlag_Read, osl_File_OpenFlag_Write and osl_File_OpenFlag_Create",
+ osl::FileBase::E_None, nError3);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for open function: test for osl_File_OpenFlag_Read, osl_File_OpenFlag_Write and osl_File_OpenFlag_Create",
+ sal_uInt64(30), nCount_write);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for open function: test for osl_File_OpenFlag_Read, osl_File_OpenFlag_Write and osl_File_OpenFlag_Create",
+ sal_uInt64(10), nCount_read);
+ }
+
+ CPPUNIT_TEST_SUITE(open);
+ CPPUNIT_TEST(open_001);
+ CPPUNIT_TEST(open_002);
+ CPPUNIT_TEST(open_003);
+ CPPUNIT_TEST(open_005);
+ CPPUNIT_TEST(open_006);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline RC close()
+
+ class close : public CppUnit::TestFixture
+ {
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpdir/tmpname.
+ createTestDirectory(aTmpName3);
+ createTestFile(aTmpName4);
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpdir/tmpname.
+ deleteTestFile(aTmpName4);
+ deleteTestDirectory(aTmpName3);
+ }
+
+
+ void close_001()
+ {
+ File testFile(aTmpName4);
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ auto nError2 = testFile.close();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for close function: close a regular file",
+ osl::FileBase::E_None, nError2);
+ }
+
+ void close_002()
+ {
+ File testFile(aTmpName4);
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ auto nError2 = testFile.close();
+
+ auto nError3 = testFile.setPos(osl_Pos_Absolut, 0);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for close function: manipulate a file after it has been closed",
+ osl::FileBase::E_None, nError2);
+ CPPUNIT_ASSERT_MESSAGE("test for close function: manipulate a file after it has been closed",
+ (osl::FileBase::E_None != nError3));
+ }
+
+ CPPUNIT_TEST_SUITE(close);
+ CPPUNIT_TEST(close_001);
+ CPPUNIT_TEST(close_002);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline RC setPos(sal_uInt32 uHow, sal_Int64 uPos)
+
+ class setPos : public CppUnit::TestFixture
+ {
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpdir/tmpname.
+ createTestDirectory(aTmpName3);
+ createTestFile(aTmpName4);
+
+ // write chars into the file.
+ File testFile(aTmpName4);
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ sal_uInt64 nCount_write = 0;
+ nError1 = testFile.write(pBuffer_Char, sizeof(pBuffer_Char), nCount_write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = testFile.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpdir/tmpname.
+ deleteTestFile(aTmpName4);
+ deleteTestDirectory(aTmpName3);
+ }
+
+ void setPos_001()
+ {
+ File testFile(aTmpName4);
+ char buffer_read[2];
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = testFile.setPos(osl_Pos_Absolut, 26);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ sal_uInt64 nCount_read = 0;
+ nError1 = testFile.read(buffer_read, 1, nCount_read);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = testFile.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for setPos function: test for osl_Pos_Absolut, set the position to 26, test if the 26th char in file is correct",
+ pBuffer_Char[26], buffer_read[0]);
+ }
+
+ void setPos_002()
+ {
+ File testFile(aTmpName4);
+ char buffer_read[2];
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = testFile.setPos(osl_Pos_Absolut, sizeof(pBuffer_Char) - 2);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = testFile.setPos(osl_Pos_Current, 0);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ sal_uInt64 nCount_read = 0;
+ nError1 = testFile.read(buffer_read, 1, nCount_read);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = testFile.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for setPos function: test for osl_Pos_Current, set the position to end, test if the (end -1) char in file is correct",
+ pBuffer_Char[sizeof(pBuffer_Char) - 2], buffer_read[0]);
+ }
+
+ void setPos_003()
+ {
+ File testFile(aTmpName4);
+ char buffer_read[2];
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ // the file size is smaller than 100
+ nError1 = testFile.setPos(osl_Pos_End, -100);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("should return error", osl::FileBase::E_INVAL, nError1);
+
+ nError1 = testFile.setPos(osl_Pos_End, -53);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ sal_uInt64 nCount_read = 0;
+ nError1 = testFile.read(buffer_read, 1, nCount_read);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = testFile.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for setPos function: test for osl_Pos_End, set the position to end, test if the first char in file is correct",
+ pBuffer_Char[0], buffer_read[0]);
+ }
+
+ CPPUNIT_TEST_SUITE(setPos);
+ CPPUNIT_TEST(setPos_001);
+ CPPUNIT_TEST(setPos_002);
+ CPPUNIT_TEST(setPos_003);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline RC getPos(sal_uInt64& uPos)
+
+ class getPos : public CppUnit::TestFixture
+ {
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpdir/tmpname.
+ createTestDirectory(aTmpName3);
+ createTestFile(aTmpName4);
+
+ // write chars into the file.
+ File testFile(aTmpName4);
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ sal_uInt64 nCount_write = 0;
+ nError1 = testFile.write(pBuffer_Char, sizeof(pBuffer_Char), nCount_write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = testFile.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpdir/tmpname.
+ deleteTestFile(aTmpName4);
+ deleteTestDirectory(aTmpName3);
+ }
+
+
+ void getPos_001()
+ {
+ File testFile(aTmpName4);
+ sal_uInt64 nFilePointer;
+
+ auto nError1 = testFile.getPos(nFilePointer);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_INVAL, nError1);
+
+ nError1 = testFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ nError1 = testFile.setPos(osl_Pos_Absolut, 26);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = testFile.getPos(nFilePointer);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ nError1 = testFile.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for getPos function: set the position to 26, get position and check if it is right",
+ static_cast<sal_uInt64>(26), nFilePointer);
+ }
+
+ CPPUNIT_TEST_SUITE(getPos);
+ CPPUNIT_TEST(getPos_001);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline RC isEndOfFile(sal_Bool *pIsEOF)
+
+ class isEndOfFile : public CppUnit::TestFixture
+ {
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpdir/tmpname.
+ createTestDirectory(aTmpName3);
+ createTestFile(aTmpName4);
+
+ // write chars into the file.
+ File testFile(aTmpName4);
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ sal_uInt64 nCount_write = 0;
+ nError1 = testFile.write(pBuffer_Char, sizeof(pBuffer_Char), nCount_write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = testFile.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpdir/tmpname.
+ deleteTestFile(aTmpName4);
+ deleteTestDirectory(aTmpName3);
+ }
+
+
+ void isEndOfFile_001()
+ {
+ File testFile(aTmpName4);
+ sal_Bool bEOF = false;
+ sal_Bool *pEOF = &bEOF;
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ nError1 = testFile.setPos(osl_Pos_End, 0);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = testFile.isEndOfFile(pEOF);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ nError1 = testFile.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ CPPUNIT_ASSERT_MESSAGE("test for isEndOfFile function: set the position to end, check if reach end",
+ *pEOF);
+ }
+
+ void isEndOfFile_002()
+ {
+ File testFile(aTmpName4);
+ sal_Bool bEOF = false;
+ sal_Bool *pEOF = &bEOF;
+ sal_uInt64 nFilePointer = 0;
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ nError1 = testFile.setPos(osl_Pos_Absolut, 0);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ *pEOF = false;
+
+ while (!(*pEOF))
+ {
+ nError1 = testFile.isEndOfFile(pEOF);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = testFile.setPos(osl_Pos_Current, 1);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ }
+
+ nError1 = testFile.getPos(nFilePointer);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ nError1 = testFile.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for isEndOfFile function: use isEndOfFile to move pointer step by step",
+ static_cast<sal_uInt64>(sizeof(pBuffer_Char) + 1), nFilePointer);
+ }
+ CPPUNIT_TEST_SUITE(isEndOfFile);
+ CPPUNIT_TEST(isEndOfFile_001);
+ CPPUNIT_TEST(isEndOfFile_002);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline RC setSize(sal_uInt64 uSize)
+
+ class setSize : public CppUnit::TestFixture
+ {
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpdir/tmpname.
+ createTestDirectory(aTmpName3);
+ createTestFile(aTmpName4);
+
+ // write chars into the file.
+ File testFile(aTmpName4);
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ sal_uInt64 nCount_write = 0;
+ nError1 = testFile.write(pBuffer_Char, sizeof(pBuffer_Char), nCount_write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = testFile.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpdir/tmpname.
+ deleteTestFile(aTmpName4);
+ deleteTestDirectory(aTmpName3);
+ }
+
+
+ void setSize_001()
+ {
+ File testFile(aTmpName4);
+ sal_uInt64 nFilePointer;
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ // enlarge the file to size of 100;
+ nError1 = testFile.setSize(100);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ // get the file size;
+ nError1 = testFile.setPos(osl_Pos_End, 0);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = testFile.getPos(nFilePointer);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ nError1 = testFile.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for setSize function: enlarge the file ",
+ static_cast<sal_uInt64>(100), nFilePointer);
+ }
+
+ void setSize_002()
+ {
+ File testFile(aTmpName4);
+ sal_uInt64 nFilePointer;
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ // enlarge the file to size of 100;
+ nError1 = testFile.setSize(10);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ // get the file size;
+ nError1 = testFile.setPos(osl_Pos_End, 0);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = testFile.getPos(nFilePointer);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ nError1 = testFile.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for setSize function: truncate the file ",
+ static_cast<sal_uInt64>(10), nFilePointer);
+ }
+
+ CPPUNIT_TEST_SUITE(setSize);
+ CPPUNIT_TEST(setSize_001);
+ CPPUNIT_TEST(setSize_002);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline RC read(void *pBuffer, sal_uInt64 uBytesRequested, sal_uInt64& rBytesRead)
+
+ class read : public CppUnit::TestFixture
+ {
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpdir/tmpname.
+ createTestDirectory(aTmpName3);
+ createTestFile(aTmpName4);
+
+ // write chars into the file.
+ File testFile(aTmpName4);
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ sal_uInt64 nCount_write = 0;
+ nError1 = testFile.write(pBuffer_Char, sizeof(pBuffer_Char), nCount_write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = testFile.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpdir/tmpname.
+ deleteTestFile(aTmpName4);
+ deleteTestDirectory(aTmpName3);
+ }
+
+
+ void read_001()
+ {
+ File testFile(aTmpName4);
+ sal_uInt64 nFilePointer;
+ char buffer_read[10];
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ sal_uInt64 nCount_read = 0;
+ nError1 = testFile.read(buffer_read, 10, nCount_read);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = testFile.getPos(nFilePointer);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ nError1 = testFile.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for read function: read whole content in the file to a buffer",
+ sal_uInt64(10), nFilePointer);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for read function: read whole content in the file to a buffer",
+ 0, strncmp(buffer_read, pBuffer_Char, 10));
+ }
+
+ void read_002()
+ {
+ File testFile(aTmpName4);
+ sal_uInt64 nFilePointer;
+ char buffer_read[26];
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ nError1 = testFile.setPos(osl_Pos_Absolut, 26);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ sal_uInt64 nCount_read = 0;
+ nError1 = testFile.read(buffer_read, 26, nCount_read);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = testFile.getPos(nFilePointer);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ nError1 = testFile.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for read function: read from a special position in the file",
+ sal_uInt64(52), nFilePointer);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for read function: read from a special position in the file",
+ sal_uInt64(26), nCount_read);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for read function: read from a special position in the file",
+ 0, strncmp(buffer_read, &pBuffer_Char[26], 26));
+ }
+
+ CPPUNIT_TEST_SUITE(read);
+ CPPUNIT_TEST(read_001);
+ CPPUNIT_TEST(read_002);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline RC write(const void *pBuffer, sal_uInt64 uBytesToWrite, sal_uInt64& rBytesWritten)
+
+ class write : public CppUnit::TestFixture
+ {
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpname.
+ createTestFile(aTmpName6);
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpname.
+ deleteTestFile(aTmpName6);
+ }
+
+
+ void write_001()
+ {
+ File testFile(aTmpName6);
+ sal_uInt64 nFilePointer;
+ char buffer_read[10];
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ sal_uInt64 nCount_write = 0, nCount_read = 0;
+ // write chars into the file.
+ nError1 = testFile.write(pBuffer_Char, 10, nCount_write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ // get the current pointer;
+ nError1 = testFile.getPos(nFilePointer);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ // reset pointer to the beginning;
+ nError1 = testFile.setPos(osl_Pos_Absolut, 0);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = testFile.read(buffer_read, 10, nCount_read);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ nError1 = testFile.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for write function: read whole content in the file to a buffer. Note, buffer size can not smaller than the read size",
+ sal_uInt64(10), nFilePointer);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for write function: read whole content in the file to a buffer. Note, buffer size can not smaller than the read size",
+ 0, strncmp(buffer_read, pBuffer_Char, 10));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for write function: read whole content in the file to a buffer. Note, buffer size can not smaller than the read size",
+ sal_uInt64(10), nCount_write);
+ }
+
+ CPPUNIT_TEST_SUITE(write);
+ CPPUNIT_TEST(write_001);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline RC readLine(::ByteSequence& aSeq)
+
+ class readLine : public CppUnit::TestFixture
+ {
+ rtl::ByteSequence aSequence;
+
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpname.
+ createTestFile(aTmpName6);
+
+ // write some strings into the file.
+ File testFile(aTmpName6);
+ char ppStrSeq[3][27] = { "abcde\n",
+ "1234567890\n",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ };
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ sal_uInt64 nCount_write = 0;
+ for (int nCount = 0; nCount < 3; nCount++)
+ {
+ nError1 = testFile.write(ppStrSeq[nCount], strlen(ppStrSeq[nCount]), nCount_write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ }
+
+ nError1 = testFile.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpname.
+ deleteTestFile(aTmpName6);
+ }
+
+
+ void readLine_001()
+ {
+ File testFile(aTmpName6);
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = testFile.readLine(aSequence);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for readLine function: read the first line of the file.",
+ osl::FileBase::E_None, nError1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for readLine function: read the first line of the file.",
+ 0, strncmp(reinterpret_cast<char *>(aSequence.getArray()), pBuffer_Char, 5));
+ }
+
+ void readLine_002()
+ {
+ File testFile(aTmpName6);
+ sal_Bool bEOF = false;
+ sal_Bool *pEOF = &bEOF;
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ for (int nCount = 0; nCount < 3; nCount++)
+ {
+ nError1 = testFile.readLine(aSequence);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ }
+ nError1 = testFile.isEndOfFile(pEOF);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ CPPUNIT_ASSERT_MESSAGE("test for readLine function: read three lines of the file and check the file pointer moving.",
+ *pEOF);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for readLine function: read three lines of the file and check the file pointer moving.",
+ 0, strncmp(reinterpret_cast<char *>(aSequence.getArray()), &pBuffer_Char[26], 26));
+ }
+ CPPUNIT_TEST_SUITE(readLine);
+ CPPUNIT_TEST(readLine_001);
+ CPPUNIT_TEST(readLine_002);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline static RC copy(const OUString& ustrSourceFileURL, const OUString& ustrDestFileURL)
+
+ class copy : public CppUnit::TestFixture
+ {
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpdir/tmpname.
+ createTestDirectory(aTmpName3);
+ createTestFile(aTmpName4);
+
+ // write chars into the file.
+ File testFile(aTmpName4);
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ sal_uInt64 nCount_write = 0;
+ nError1 = testFile.write(pBuffer_Char, sizeof(pBuffer_Char), nCount_write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = testFile.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpdir/tmpname.
+ deleteTestFile(aTmpName4);
+ deleteTestDirectory(aTmpName3);
+ }
+
+ void copy_001()
+ {
+ File testFile(aTmpName6);
+
+ // copy $TEMP/tmpdir/tmpname to $TEMP/tmpname.
+ auto nError1 = File::copy(aTmpName4, aTmpName6);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ // check
+ nError1 = testFile.open(osl_File_OpenFlag_Create);
+ deleteTestFile(aTmpName6);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for copy function: copy file to upper directory",
+ osl::FileBase::E_EXIST, nError1);
+ }
+
+ void copy_002()
+ {
+ // copy $TEMP/tmpdir/tmpname to $TEMP/tmpdir.
+ auto nError1 = File::copy(aTmpName4, aTmpName3);
+
+ CPPUNIT_ASSERT_MESSAGE("test for copy function: use directory as destination",
+ (osl::FileBase::E_ISDIR == nError1) ||(osl::FileBase::E_ACCES == nError1));
+ }
+
+ void copy_003()
+ {
+#if 0
+ // copy $TEMP/tmpdir/tmpname to $ROOT/tmpname.
+ auto nError1 = File::copy(aTmpName4, aTmpName7);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for copy function: copy to an illegal place",
+ osl::FileBase::E_ACCES, nError1);
+#endif
+ }
+
+ void copy_004()
+ {
+ // copy $TEMP/tmpname to $TEMP/tmpdir/tmpname.
+ auto nError1 = File::copy(aTmpName6, aTmpName4);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for copy function: copy a not exist file",
+ osl::FileBase::E_NOENT, nError1);
+ }
+
+ void copy_005()
+ {
+ // copy $TEMP/tmpname to $TEMP/system.path using system path.
+ auto nError1 = File::copy(aTmpName6, aSysPath1);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for copy function: copy a file using system file path",
+ osl::FileBase::E_INVAL, nError1);
+ }
+
+ void copy_006()
+ {
+ createTestFile(aTmpName6);
+ File tmpFile(aTmpName6);
+ tmpFile.open(osl_File_OpenFlag_Write | osl_File_OpenFlag_Read);
+ tmpFile.setSize(200);
+ tmpFile.close();
+ // copy to new path
+ auto nError1 = File::copy(aTmpName6, aTmpName4);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ // check if is the new file
+ File newFile(aTmpName4);
+ newFile.open(osl_File_OpenFlag_Write | osl_File_OpenFlag_Read);
+ nError1 = newFile.setPos(osl_Pos_End, 0);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ sal_uInt64 nFilePointer;
+ nError1 = newFile.getPos(nFilePointer);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ newFile.close();
+ deleteTestFile(aTmpName6);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for copy function: the dest file exist",
+ static_cast<sal_uInt64>(200), nFilePointer);
+ }
+
+ CPPUNIT_TEST_SUITE(copy);
+ CPPUNIT_TEST(copy_001);
+ CPPUNIT_TEST(copy_002);
+ CPPUNIT_TEST(copy_003);
+ CPPUNIT_TEST(copy_004);
+ CPPUNIT_TEST(copy_005);
+ CPPUNIT_TEST(copy_006);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline static RC move(const OUString& ustrSourceFileURL, const OUString& ustrDestFileURL)
+
+ class move : public CppUnit::TestFixture
+ {
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpdir/tmpname.
+ createTestDirectory(aTmpName3);
+ createTestFile(aTmpName4);
+
+ // write chars into the file.
+ File testFile(aTmpName4);
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ sal_uInt64 nCount_write = 0;
+ nError1 = testFile.write(pBuffer_Char, sizeof(pBuffer_Char), nCount_write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = testFile.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpdir/tmpname.
+ deleteTestFile(aTmpName4);
+ deleteTestDirectory(aTmpName3);
+ }
+
+
+ void move_001()
+ {
+ // rename $TEMP/tmpdir/tmpname to $TEMP/canonical.name.
+ auto nError1 = File::move(aTmpName4, aCanURL1);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ // check
+ File testFile(aCanURL1);
+ auto nError2 = testFile.open(osl_File_OpenFlag_Create);
+ deleteTestFile(aCanURL1);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for move function: rename file to another directory",
+ osl::FileBase::E_EXIST, nError2);
+ }
+
+ void move_002()
+ {
+#ifdef _WIN32
+ // move $TEMP/tmpdir/tmpname to $TEMP/tmpdir.
+ auto nError1 = File::move(aTmpName4, aTmpName3);
+ // returned osl::FileBase::E_ACCES on WNT
+ CPPUNIT_ASSERT_MESSAGE("test for move function: use directory as destination",
+ (osl::FileBase::E_ACCES == nError1 || osl::FileBase::E_ISDIR == nError1) ||(osl::FileBase::E_EXIST == nError1));
+#endif
+ }
+
+ void move_003()
+ {
+#if 0
+ // move $TEMP/tmpdir/tmpname to $ROOT/tmpname.
+ auto nError1 = File::move(aTmpName4, aTmpName7);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for move function: move to an illegal place",
+ osl::FileBase::E_ACCES, nError1);
+#endif
+ }
+
+ void move_004()
+ {
+ // move $TEMP/tmpname to $TEMP/tmpdir/tmpname.
+ auto nError1 = File::move(aTmpName6, aTmpName4);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for move function: move a not exist file",
+ osl::FileBase::E_NOENT, nError1);
+ }
+
+ void move_005()
+ {
+ // move $TEMP/tmpname to $TEMP/system.path using system path.
+ auto nError1 = File::move(aTmpName6, aSysPath1);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for move function: move a file using system file",
+ osl::FileBase::E_INVAL, nError1);
+ }
+
+ void move_006()
+ {
+ // move directory $TEMP/tmpname to $TEMP/tmpdir/tmpname.
+ createTestDirectory(aTmpName6);
+ auto nError1 = File::move(aTmpName6, aTmpName4);
+ // move file $TEMP/tmpdir/tmpname to $TEMP/tmpname
+ auto nError2 = File::move(aTmpName4, aTmpName6);
+ deleteTestDirectory(aTmpName6);
+#if defined(_WIN32)
+ deleteTestDirectory(aTmpName4);// in Windows, it can be moved!!!!! this is only for not influence the following test.
+ deleteTestFile(aTmpName6);
+ nError1 = osl::FileBase::E_NOTDIR;
+ nError2 = osl::FileBase::E_ISDIR;
+#endif
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for move function: move a directory to an exist file with same name, did not pass in (W32)",
+ osl::FileBase::E_NOTDIR, nError1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for move function: move a directory to an exist file with same name, did not pass in (W32)",
+ osl::FileBase::E_ISDIR, nError2);
+ }
+
+ void move_007()
+ {
+ // create directory $TEMP/tmpname.
+ createTestDirectory(aTmpName6);
+ // move directory $TEMP/tmpdir to $TEMP/tmpname/tmpdir
+ auto nError1 = File::move(aTmpName3, aTmpName8);
+ // check
+ auto nError2 = Directory::create(aTmpName8);
+ File::move(aTmpName8, aTmpName3);
+ deleteTestDirectory(aTmpName6);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for move function: move a directory to an exist file with same name",
+ osl::FileBase::E_None, nError1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for move function: move a directory to an exist file with same name",
+ osl::FileBase::E_EXIST, nError2);
+ }
+
+ // bugid# 115420, after the bug fix, add the case
+ CPPUNIT_TEST_SUITE(move);
+ CPPUNIT_TEST(move_001);
+ CPPUNIT_TEST(move_002);
+ CPPUNIT_TEST(move_003);
+ CPPUNIT_TEST(move_004);
+ CPPUNIT_TEST(move_005);
+ CPPUNIT_TEST(move_006);
+ CPPUNIT_TEST(move_007);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline static RC remove(const OUString& ustrFileURL)
+
+ class remove : public CppUnit::TestFixture
+ {
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpdir/tmpname.
+ createTestDirectory(aTmpName3);
+ createTestFile(aTmpName4);
+
+ // write chars into the file.
+ File testFile(aTmpName4);
+
+ auto nError1 = testFile.open(osl_File_OpenFlag_Write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ sal_uInt64 nCount_write = 0;
+ nError1 = testFile.write(pBuffer_Char, sizeof(pBuffer_Char), nCount_write);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = testFile.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpdir/tmpname.
+ deleteTestFile(aTmpName4);
+ deleteTestDirectory(aTmpName3);
+ }
+
+
+ void remove_001()
+ {
+ // remove $TEMP/tmpdir/tmpname.
+ auto nError1 = File::remove(aTmpName4);
+ // check
+ File testFile(aTmpName4);
+ auto nError2 = testFile.open(osl_File_OpenFlag_Create);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for remove function: remove a file",
+ osl::FileBase::E_None, nError1);
+ CPPUNIT_ASSERT_MESSAGE("test for remove function: remove a file",
+ (osl::FileBase::E_EXIST != nError2));
+ }
+
+ void remove_002()
+ {
+ // remove $TEMP/tmpname.
+ auto nError1 = File::remove(aTmpName6);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for remove function: remove a file not exist",
+ osl::FileBase::E_NOENT, nError1);
+ }
+
+ void remove_003()
+ {
+ // remove $TEMP/system/path.
+ auto nError1 = File::remove(aSysPath2);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for remove function: removing a file not using full qualified URL",
+ osl::FileBase::E_INVAL, nError1);
+ }
+
+ void remove_004()
+ {
+ // remove $TEMP/tmpdir.
+ auto nError1 = File::remove(aTmpName3);
+
+ CPPUNIT_ASSERT_MESSAGE("test for remove function: remove a directory",
+ (osl::FileBase::E_ISDIR == nError1) || (osl::FileBase::E_ACCES == nError1));
+ }
+
+ CPPUNIT_TEST_SUITE(remove);
+ CPPUNIT_TEST(remove_001);
+ CPPUNIT_TEST(remove_002);
+ CPPUNIT_TEST(remove_003);
+ CPPUNIT_TEST(remove_004);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline static RC setAttributes(const OUString& ustrFileURL, sal_uInt64 uAttributes)
+
+ class setAttributes : public CppUnit::TestFixture
+ {
+ private:
+ DirectoryItem rItem;
+
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpdir/tmpname.
+ createTestFile(aTmpName6);
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpdir/tmpname.
+ deleteTestFile(aTmpName6);
+ }
+
+
+ void setAttributes_001()
+ {
+ // on windows, only can set 2 attributes: osl_File_Attribute_ReadOnly, osl_File_Attribute_Hidden
+#ifdef UNX
+ // set the file to readonly
+ auto nError2 = File::setAttributes(aTmpName6, osl_File_Attribute_ReadOnly | osl_File_Attribute_GrpRead | osl_File_Attribute_OwnRead | osl_File_Attribute_OthRead);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError2);
+ auto nError1 = DirectoryItem::get(aTmpName6, rItem);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ // get the file attributes
+ FileStatus rFileStatus(osl_FileStatus_Mask_Attributes);
+ nError1 = rItem.getFileStatus(rFileStatus);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ if (geteuid() == 0) // as root, access(W_OK) may be true despite mode
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for setAttributes function: set file attributes and get it to verify.",
+ static_cast<sal_uInt64>(osl_File_Attribute_GrpRead | osl_File_Attribute_OwnRead | osl_File_Attribute_OthRead),
+ rFileStatus.getAttributes());
+ }
+ else
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for setAttributes function: set file attributes and get it to verify.",
+ static_cast<sal_uInt64>(osl_File_Attribute_ReadOnly | osl_File_Attribute_GrpRead | osl_File_Attribute_OwnRead | osl_File_Attribute_OthRead),
+ rFileStatus.getAttributes());
+ }
+#else
+ // please see GetFileAttributes
+ auto nError2 = File::setAttributes(aTmpName6, osl_File_Attribute_ReadOnly);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError2);
+ auto nError1 = DirectoryItem::get(aTmpName6, rItem);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ // get the file attributes
+ FileStatus rFileStatus(osl_FileStatus_Mask_Attributes);
+ nError1 = rItem.getFileStatus(rFileStatus);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ // here the file has 2 Attributes: FILE_ATTRIBUTE_READONLY and FILE_ATTRIBUTE_NORMAL,
+ // but FILE_ATTRIBUTE_NORMAL is valid only if used alone, so this is maybe a bug
+ /*OString aString = OUStringToOString(aTmpName6, RTL_TEXTENCODING_ASCII_US);
+ DWORD dwFileAttributes = GetFileAttributes(aString.getStr());
+ if (dwFileAttributes & FILE_ATTRIBUTE_NORMAL)
+ printf("has normal attribute");
+ if (dwFileAttributes & FILE_ATTRIBUTE_READONLY)
+ printf("has readonly attribute");
+ */
+ CPPUNIT_ASSERT_MESSAGE("test for setAttributes function: set file attributes READONLY and get it to verify.",
+ (osl_File_Attribute_ReadOnly & rFileStatus.getAttributes()) != 0);
+#endif
+ }
+ void setAttributes_002()
+ {
+ // on UNX, can not set hidden attribute to file, rename file can set the attribute
+#ifdef _WIN32
+ // set the file to hidden
+ auto nError2 = File::setAttributes(aTmpName6, osl_File_Attribute_Hidden);
+
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError2);
+ auto nError1 = DirectoryItem::get(aTmpName6, rItem);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ // get the file attributes
+ FileStatus rFileStatus(osl_FileStatus_Mask_Attributes);
+ nError1 = rItem.getFileStatus(rFileStatus);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ CPPUNIT_ASSERT_MESSAGE("test for setAttributes function: set file attributes and get it to verify.",
+ (osl_File_Attribute_Hidden & rFileStatus.getAttributes()) != 0);
+#endif
+ }
+
+ CPPUNIT_TEST_SUITE(setAttributes);
+ CPPUNIT_TEST(setAttributes_001);
+ CPPUNIT_TEST(setAttributes_002);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline static RC setTime(
+ // const OUString& ustrFileURL,
+ // const TimeValue& rCreationTime,
+ // const TimeValue& rLastAccessTime,
+ // const TimeValue& rLastWriteTime)
+
+ class setTime : public CppUnit::TestFixture
+ {
+ private:
+ DirectoryItem rItem;
+
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpdir/tmpname.
+ createTestFile(aTmpName6);
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpdir/tmpname.
+ deleteTestFile(aTmpName6);
+ }
+
+
+ void setTime_001()
+ {
+ TimeValue *pTV_current = nullptr;
+ CPPUNIT_ASSERT((pTV_current = static_cast<TimeValue*>(malloc(sizeof(TimeValue)))) != nullptr);
+ TimeValue *pTV_creation = nullptr;
+ CPPUNIT_ASSERT((pTV_creation = static_cast<TimeValue*>(malloc(sizeof(TimeValue)))) != nullptr);
+ TimeValue *pTV_access = nullptr;
+ CPPUNIT_ASSERT((pTV_access = static_cast<TimeValue*>(malloc(sizeof(TimeValue)))) != nullptr);
+ TimeValue *pTV_modify = nullptr;
+ CPPUNIT_ASSERT((pTV_modify = static_cast<TimeValue*>(malloc(sizeof(TimeValue)))) != nullptr);
+
+ // get current time
+ bool bOk = osl_getSystemTime(pTV_current);
+ CPPUNIT_ASSERT(bOk);
+
+ // set the file time
+ auto nError2 = File::setTime(aTmpName6, *pTV_current, *pTV_current, *pTV_current);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(errorToStr(nError2).getStr(), osl::FileBase::E_None, nError2);
+
+ // get the file access time, creation time, modify time
+ auto nError1 = DirectoryItem::get(aTmpName6, rItem);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(errorToStr(nError1).getStr(), osl::FileBase::E_None, nError1);
+
+ FileStatus rFileStatus(osl_FileStatus_Mask_AccessTime);
+ nError1 = rItem.getFileStatus(rFileStatus);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(errorToStr(nError1).getStr(), osl::FileBase::E_None, nError1);
+ *pTV_access = rFileStatus.getAccessTime();
+
+ FileStatus rFileStatus1(osl_FileStatus_Mask_CreationTime);
+ nError1 = rItem.getFileStatus(rFileStatus1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(errorToStr(nError1).getStr(), osl::FileBase::E_None, nError1);
+ *pTV_creation = rFileStatus1.getCreationTime();
+
+ FileStatus rFileStatus2(osl_FileStatus_Mask_ModifyTime);
+ nError1 = rItem.getFileStatus(rFileStatus2);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(errorToStr(nError1).getStr(), osl::FileBase::E_None, nError1);
+ *pTV_modify = rFileStatus2.getModifyTime();
+
+ CPPUNIT_ASSERT_MESSAGE("test for setTime function: set access time then get it. time precision is still a problem for it cut off the nanosec.",
+ t_compareTime(pTV_access, pTV_current, delta));
+#if defined(_WIN32)
+ // Unfortunately there is no way to get the creation time of a file under Unix (it's a Windows only feature).
+ // That means the flag osl_FileStatus_Mask_CreationTime should be deprecated under Unix.
+ CPPUNIT_ASSERT_MESSAGE("test for setTime function: set creation time then get it. ",
+ t_compareTime(pTV_creation, pTV_current, delta));
+#endif
+ CPPUNIT_ASSERT_MESSAGE("test for setTime function: set modify time then get it. ",
+ t_compareTime(pTV_modify, pTV_current, delta));
+ free(pTV_current);
+ free(pTV_creation);
+ free(pTV_access);
+ free(pTV_modify);
+ }
+
+ CPPUNIT_TEST_SUITE(setTime);
+ CPPUNIT_TEST(setTime_001);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline static RC sync()
+
+ class sync : public CppUnit::TestFixture
+ {
+ private:
+ DirectoryItem rItem;
+
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpdir/tmpname.
+ createTestFile(aTmpName6);
+
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpdir/tmpname.
+ deleteTestFile(aTmpName6);
+ }
+
+ // test case: if The file is located on a read only file system.
+ void sync_001()
+ {
+ auto nError1 = DirectoryItem::get(aTmpName6, rItem);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ File tmp_file(aTmpName6);
+ osl::FileBase::RC err = tmp_file.open(osl_File_OpenFlag_Write);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("File open failed", osl::FileBase::E_None, err);
+
+ char buffer[50000];
+ sal_uInt64 written = 0;
+ nError1 = tmp_file.write(static_cast<void*>(buffer), sizeof(buffer), written);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("write failed!", osl::FileBase::E_None, nError1);
+
+ // set the file to readonly
+ auto nError2 = File::setAttributes(aTmpName6, osl_File_Attribute_ReadOnly | osl_File_Attribute_GrpRead | osl_File_Attribute_OwnRead | osl_File_Attribute_OthRead);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError2);
+
+ nError2 = tmp_file.sync();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("can not sync to readonly file!", osl::FileBase::E_None, nError2);
+
+ tmp_file.close();
+ }
+ // test case:no enough space, how to create such case???see test_cpy_wrt_file.cxx::test_osl_writeFile
+
+ CPPUNIT_TEST_SUITE(sync);
+ CPPUNIT_TEST(sync_001);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_File::ctors, "osl_File");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_File::open, "osl_File");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_File::close, "osl_File");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_File::setPos, "osl_File");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_File::getPos, "osl_File");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_File::isEndOfFile, "osl_File");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_File::setSize, "osl_File");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_File::read, "osl_File");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_File::write, "osl_File");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_File::readLine, "osl_File");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_File::copy, "osl_File");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_File::move, "osl_File");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_File::remove, "osl_File");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_File::setAttributes, "osl_File");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_File::setTime, "osl_File");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_File::sync, "osl_File");
+
+ CPPUNIT_REGISTRY_ADD_TO_DEFAULT("osl_File");
+}
+
+// Beginning of the test cases for DirectoryItem class
+
+namespace osl_DirectoryItem
+{
+ // testing the method
+ // DirectoryItem(): _pData(NULL)
+
+ class ctors : public CppUnit::TestFixture
+ {
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpname.
+ createTestFile(aTmpName6);
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpname.
+ deleteTestFile(aTmpName6);
+ }
+
+ void ctors_001()
+ {
+ File testFile(aTmpName6);
+ DirectoryItem rItem; // constructor
+
+ // get the DirectoryItem.
+ auto nError1 = DirectoryItem::get(aTmpName6, rItem);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for ctors function: initialize a new instance of DirectoryItem and get an item to check.",
+ osl::FileBase::E_None, nError1);
+ }
+
+ CPPUNIT_TEST_SUITE(ctors);
+ CPPUNIT_TEST(ctors_001);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // DirectoryItem(const DirectoryItem& rItem): _pData(rItem._pData)
+
+ class copy_assin_Ctors : public CppUnit::TestFixture
+ {
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpname.
+ createTestFile(aTmpName6);
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpname.
+ deleteTestFile(aTmpName6);
+ }
+
+
+ void copy_assin_Ctors_001()
+ {
+ DirectoryItem rItem; // constructor
+ // get the DirectoryItem.
+ auto nError1 = DirectoryItem::get(aTmpName6, rItem);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ DirectoryItem copyItem(rItem); // copy constructor
+ FileStatus rFileStatus(osl_FileStatus_Mask_FileName);
+ nError1 = copyItem.getFileStatus(rFileStatus);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ CPPUNIT_ASSERT_MESSAGE("test for copy_assin_Ctors function: use copy constructor to get an item and check filename.",
+ compareFileName(rFileStatus.getFileName(), aTmpName2));
+ }
+
+ void copy_assin_Ctors_002()
+ {
+ DirectoryItem rItem; // constructor
+ // get the DirectoryItem.
+ auto nError1 = DirectoryItem::get(aTmpName6, rItem);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ DirectoryItem copyItem;
+ copyItem = rItem; // assignment operator
+ FileStatus rFileStatus(osl_FileStatus_Mask_FileName);
+ nError1 = copyItem.getFileStatus(rFileStatus);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ CPPUNIT_ASSERT_MESSAGE("test for copy_assin_Ctors function: test assignment operator here since it is same as copy constructor in test way.",
+ compareFileName(rFileStatus.getFileName(), aTmpName2));
+ }
+
+ CPPUNIT_TEST_SUITE(copy_assin_Ctors);
+ CPPUNIT_TEST(copy_assin_Ctors_001);
+ CPPUNIT_TEST(copy_assin_Ctors_002);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline sal_Bool is()
+
+ class is : public CppUnit::TestFixture
+ {
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpname.
+ createTestFile(aTmpName6);
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpname.
+ deleteTestFile(aTmpName6);
+ }
+
+ void is_001()
+ {
+ DirectoryItem rItem; // constructor
+
+ CPPUNIT_ASSERT_MESSAGE("test for is function: use an uninitialized instance.",
+ !rItem.is());
+ }
+
+ void is_002()
+ {
+ DirectoryItem rItem; // constructor
+ // get the DirectoryItem.
+ auto nError1 = DirectoryItem::get(aTmpName6, rItem);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ CPPUNIT_ASSERT_MESSAGE("test for is function: use an uninitialized instance.",
+ rItem.is());
+ }
+
+ CPPUNIT_TEST_SUITE(is);
+ CPPUNIT_TEST(is_001);
+ CPPUNIT_TEST(is_002);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // static inline RC get(const OUString& ustrFileURL, DirectoryItem& rItem)
+
+ class get : public CppUnit::TestFixture
+ {
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpname.
+ createTestFile(aTmpName6);
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpname.
+ deleteTestFile(aTmpName6);
+ }
+
+
+ void get_001()
+ {
+ DirectoryItem rItem;
+ auto nError2 = DirectoryItem::get(aTmpName6, rItem);
+
+ // check the file name
+ FileStatus rFileStatus(osl_FileStatus_Mask_FileName);
+ auto nError1 = rItem.getFileStatus(rFileStatus);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for get function: use copy constructor to get an item and check filename.",
+ osl::FileBase::E_None, nError2);
+ CPPUNIT_ASSERT_MESSAGE("test for get function: use copy constructor to get an item and check filename.",
+ compareFileName(rFileStatus.getFileName(), aTmpName2));
+ }
+
+ void get_002()
+ {
+ DirectoryItem rItem;
+ auto nError1 = DirectoryItem::get(aSysPath1, rItem);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for get function: use a system name instead of a URL.",
+ osl::FileBase::E_INVAL, nError1);
+ }
+
+ void get_003()
+ {
+ DirectoryItem rItem;
+
+ auto nError1 = DirectoryItem::get(aTmpName3, rItem);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for get function: use a non existed file URL.",
+ osl::FileBase::E_NOENT, nError1);
+ }
+
+ CPPUNIT_TEST_SUITE(get);
+ CPPUNIT_TEST(get_001);
+ CPPUNIT_TEST(get_002);
+ CPPUNIT_TEST(get_003);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline RC getFileStatus(FileStatus& rStatus)
+
+ class getFileStatus : public CppUnit::TestFixture
+ {
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpdir/tmpname.
+ createTestDirectory(aTmpName3);
+ createTestFile(aTmpName4);
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpdir/tmpname.
+ deleteTestFile(aTmpName4);
+ deleteTestDirectory(aTmpName3);
+ }
+
+
+ void getFileStatus_001()
+ {
+ DirectoryItem rItem;
+ // get the DirectoryItem.
+ auto nError1 = DirectoryItem::get(aTmpName4, rItem);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ // check the file name
+ FileStatus rFileStatus(osl_FileStatus_Mask_FileName);
+ auto nError2 = rItem.getFileStatus(rFileStatus);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for getFileStatus function: get file status and check filename",
+ osl::FileBase::E_None, nError2);
+ CPPUNIT_ASSERT_MESSAGE("test for getFileStatus function: get file status and check filename",
+ compareFileName(rFileStatus.getFileName(), aTmpName2));
+ }
+
+ void getFileStatus_002()
+ {
+ DirectoryItem rItem; // constructor
+ // get the DirectoryItem.
+ auto nError1 = DirectoryItem::get(aTmpName6, rItem);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_NOENT, nError1);
+
+ // check the file name
+ FileStatus rFileStatus(osl_FileStatus_Mask_FileName);
+ auto nError2 = rItem.getFileStatus(rFileStatus);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for getFileStatus function: file not existed",
+ osl::FileBase::E_INVAL, nError2);
+ }
+
+ void getFileStatus_003()
+ {
+ DirectoryItem rItem; // constructor
+ // get the DirectoryItem.
+ auto nError1 = DirectoryItem::get(aTmpName3, rItem);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ // check the file name
+ FileStatus rFileStatus(osl_FileStatus_Mask_FileName);
+ auto nError2 = rItem.getFileStatus(rFileStatus);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for getFileStatus function: get directory information",
+ osl::FileBase::E_None, nError2);
+ CPPUNIT_ASSERT_MESSAGE("test for getFileStatus function: get directory information",
+ compareFileName(rFileStatus.getFileName(), aTmpName1));
+ }
+
+ CPPUNIT_TEST_SUITE(getFileStatus);
+ CPPUNIT_TEST(getFileStatus_001);
+ CPPUNIT_TEST(getFileStatus_002);
+ CPPUNIT_TEST(getFileStatus_003);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_DirectoryItem::ctors, "osl_DirectoryItem");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_DirectoryItem::copy_assin_Ctors, "osl_DirectoryItem");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_DirectoryItem::is, "osl_DirectoryItem");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_DirectoryItem::get, "osl_DirectoryItem");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_DirectoryItem::getFileStatus, "osl_DirectoryItem");
+
+ CPPUNIT_REGISTRY_ADD_TO_DEFAULT("osl_DirectoryItem");
+}
+
+// Beginning of the test cases for Directory class
+
+namespace osl_Directory
+{
+ // testing the method
+ // Directory(const OUString& strPath): _pData(0), _aPath(strPath)
+
+ class ctors : public CppUnit::TestFixture
+ {
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpdir/tmpname.
+ createTestDirectory(aTmpName3);
+ createTestFile(aTmpName4);
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpdir/tmpname.
+ deleteTestFile(aTmpName4);
+ deleteTestDirectory(aTmpName3);
+ // LLA: t_print("tearDown done.\n");
+ }
+
+
+ void ctors_001()
+ {
+ Directory testDirectory(aTmpName3); // constructor
+
+ // open a directory
+ auto nError1 = testDirectory.open();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ // close a directory
+ auto nError2 = testDirectory.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError2);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for ctors function: create an instance and check open and close",
+ osl::FileBase::E_None, nError1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for ctors function: create an instance and check open and close",
+ osl::FileBase::E_None, nError2);
+ }
+
+ void ctors_002()
+ {
+ Directory testDirectory(aTmpName9); // constructor
+
+ // open a directory
+ auto nError1 = testDirectory.open();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ // close a directory
+ auto nError2 = testDirectory.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError2);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for ctors function: relative URL, :-), it is also worked",
+ osl::FileBase::E_None, nError1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for ctors function: relative URL, :-), it is also worked",
+ osl::FileBase::E_None, nError2);
+ }
+
+ CPPUNIT_TEST_SUITE(ctors);
+ CPPUNIT_TEST(ctors_001);
+ CPPUNIT_TEST(ctors_002);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline RC open()
+
+ class open : public CppUnit::TestFixture
+ {
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpdir/tmpname.
+ createTestDirectory(aTmpName3);
+ createTestFile(aTmpName4);
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpdir/tmpname.
+ deleteTestFile(aTmpName4);
+ deleteTestDirectory(aTmpName3);
+ }
+
+ void open_001()
+ {
+ Directory testDirectory(aTmpName3);
+
+ // open a directory
+ auto nError1 = testDirectory.open();
+ // check if directory is opened.
+ bool bOk = testDirectory.isOpen();
+ // close a directory
+ auto nError2 = testDirectory.close();
+
+ CPPUNIT_ASSERT_MESSAGE("test for open function: open a directory and check for open",
+ bOk);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for open function: open a directory and check for open",
+ osl::FileBase::E_None, nError1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for open function: open a directory and check for open",
+ osl::FileBase::E_None, nError2);
+ }
+
+ void open_002()
+ {
+ Directory testDirectory(aTmpName6);
+
+ auto nError1 = testDirectory.open();
+ if (nError1 == osl::FileBase::E_None)
+ {
+ auto nError2 = testDirectory.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError2);
+ }
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for open function: open a file that is not existed",
+ osl::FileBase::E_NOENT, nError1);
+ }
+
+ void open_003()
+ {
+ Directory testDirectory(aUserDirectorySys);
+
+ auto nError1 = testDirectory.open();
+ if (nError1 == osl::FileBase::E_None)
+ {
+ auto nError2 = testDirectory.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError2);
+ }
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for open function: using system path",
+ osl::FileBase::E_INVAL, nError1);
+ }
+
+ void open_004()
+ {
+ Directory testDirectory(aTmpName4);
+
+ auto nError1 = testDirectory.open();
+ if (nError1 == osl::FileBase::E_None)
+ {
+ auto nError2 = testDirectory.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError2);
+ }
+
+ CPPUNIT_ASSERT_MESSAGE("test for open function: open a file instead of a directory",
+ (osl::FileBase::E_NOTDIR == nError1) || (osl::FileBase::E_ACCES == nError1));
+ }
+
+ CPPUNIT_TEST_SUITE(open);
+ CPPUNIT_TEST(open_001);
+ CPPUNIT_TEST(open_002);
+ CPPUNIT_TEST(open_003);
+ CPPUNIT_TEST(open_004);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline sal_Bool isOpen() { return _pData != NULL; };
+
+ class isOpen : public CppUnit::TestFixture
+ {
+ public:
+ void setUp() override
+ {
+ // create a tempfile in $TEMP/tmpdir/tmpname.
+ createTestDirectory(aTmpName3);
+ createTestFile(aTmpName4);
+ }
+
+ void tearDown() override
+ {
+ // remove the tempfile in $TEMP/tmpdir/tmpname.
+ deleteTestFile(aTmpName4);
+ deleteTestDirectory(aTmpName3);
+ }
+
+
+ void isOpen_001()
+ {
+ Directory testDirectory(aTmpName3); // constructor
+
+ // open a directory
+ auto nError1 = testDirectory.open();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ // check if directory is opened.
+ bool bOk = testDirectory.isOpen();
+ // close a directory
+ auto nError2 = testDirectory.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError2);
+ CPPUNIT_ASSERT_MESSAGE("test for isOpen function: open a directory and check for open",
+ bOk);
+ }
+
+ void isOpen_002()
+ {
+ Directory testDirectory(aTmpName3); // constructor
+
+ // check if directory is opened.
+ bool bOk = testDirectory.isOpen();
+
+ CPPUNIT_ASSERT_MESSAGE("test for isOpen function: do not open a directory and check for open",
+ !bOk);
+ }
+
+ CPPUNIT_TEST_SUITE(isOpen);
+ CPPUNIT_TEST(isOpen_001);
+ CPPUNIT_TEST(isOpen_002);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline RC close()
+
+ class close : public CppUnit::TestFixture
+ {
+ public:
+ void setUp() override
+ {
+ // create a tempdirectory : $TEMP/tmpdir.
+ createTestDirectory(aTmpName3);
+ }
+
+ void tearDown() override
+ {
+ // remove a tempdirectory : $TEMP/tmpdir.
+ deleteTestDirectory(aTmpName3);
+ }
+
+ void close_001()
+ {
+ Directory testDirectory(aTmpName3);
+
+ // open a directory
+ auto nError1 = testDirectory.open();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ // close a directory
+ auto nError2 = testDirectory.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError2);
+ // check if directory is opened.
+ bool bOk = testDirectory.isOpen();
+
+ CPPUNIT_ASSERT_MESSAGE("test for isOpen function: close a directory and check for open",
+ !bOk);
+ }
+
+ void close_002()
+ {
+ Directory testDirectory(aTmpName3);
+
+ // close a directory
+ auto nError1 = testDirectory.close();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for isOpen function: close a not opened directory",
+ osl::FileBase::E_BADF, nError1);
+ }
+
+ CPPUNIT_TEST_SUITE(close);
+ CPPUNIT_TEST(close_001);
+ CPPUNIT_TEST(close_002);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline RC reset()
+
+ class reset : public CppUnit::TestFixture
+ {
+ private:
+ DirectoryItem rItem;
+
+ public:
+ void setUp() override
+ {
+ // create a tempdirectory : $TEMP/tmpdir.
+ createTestDirectory(aTmpName3);
+ // create three files : $TEMP/tmpdir/tmpname, $TEMP/tmpdir/tmpdir, $TEMP/tmpdir/hiddenfile,
+ createTestFile(aTmpName3, aTmpName2);
+ createTestFile(aTmpName3, aTmpName1);
+ createTestFile(aTmpName3, aHidURL1);
+ }
+
+ void tearDown() override
+ {
+ // remove three files : $TEMP/tmpdir/tmpname, $TEMP/tmpdir/tmpdir, $TEMP/tmpdir/hiddenfile,
+ deleteTestFile(aTmpName3, aHidURL1);
+ deleteTestFile(aTmpName3, aTmpName1);
+ deleteTestFile(aTmpName3, aTmpName2);
+ // remove a tempdirectory : $TEMP/tmpdir.
+ deleteTestDirectory(aTmpName3);
+ }
+
+
+ void reset_001()
+ {
+ Directory testDirectory(aTmpName3); // constructor
+
+ // open a directory
+ auto nError1 = testDirectory.open();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ // get first Item
+ nError1 = testDirectory.getNextItem(rItem, 1);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ // check the file name of first Item
+ FileStatus rFileStatusFirst(osl_FileStatus_Mask_FileName);
+ nError1 = rItem.getFileStatus(rFileStatusFirst);
+
+ // get second Item
+ // mindy: nError1 = testDirectory.getNextItem(rItem, 0);
+ // mindy: CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ // reset enumeration
+ auto nError2 = testDirectory.reset();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError2);
+ // get reset Item, if reset does not work, getNextItem() should return the second Item (aTmpName1)
+ nError1 = testDirectory.getNextItem(rItem);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ // check the file name again
+ FileStatus rFileStatus(osl_FileStatus_Mask_FileName);
+ nError1 = rItem.getFileStatus(rFileStatus);
+ // close a directory
+ nError1 = testDirectory.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ bool bOK1,bOK2,bOK3;
+ bOK1 = compareFileName(rFileStatus.getFileName(), aTmpName2);
+ bOK2 = compareFileName(rFileStatus.getFileName(), aHidURL1);
+ bOK3 = compareFileName(rFileStatus.getFileName(), rFileStatusFirst.getFileName());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for reset function: get two directory item, reset it, then get again, check the filename",
+ osl::FileBase::E_None, nError2);
+ CPPUNIT_ASSERT_MESSAGE("test for reset function: get two directory item, reset it, then get again, check the filename",
+ (bOK1 || bOK2 || bOK3));
+ }
+
+ void reset_002()
+ {
+ Directory testDirectory(aTmpName6); // constructor
+
+ // close a directory
+ auto nError1 = testDirectory.reset();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for reset function: reset a non existed directory",
+ osl::FileBase::E_NOENT, nError1);
+ }
+
+ void reset_003()
+ {
+ Directory testDirectory(aTmpName4); // constructor
+
+ // close a directory
+ auto nError1 = testDirectory.reset();
+
+ CPPUNIT_ASSERT_MESSAGE("test for reset function: reset a file instead of a directory",
+ (osl::FileBase::E_NOTDIR == nError1) || (osl::FileBase::E_NOENT == nError1));
+ }
+
+ void reset_004()
+ {
+ Directory testDirectory(aUserDirectorySys); // constructor
+
+ // close a directory
+ auto nError1 = testDirectory.reset();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for reset function: use a system path",
+ osl::FileBase::E_INVAL, nError1);
+ }
+
+ CPPUNIT_TEST_SUITE(reset);
+ CPPUNIT_TEST(reset_001);
+ CPPUNIT_TEST(reset_002);
+ CPPUNIT_TEST(reset_003);
+ CPPUNIT_TEST(reset_004);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline RC getNextItem(DirectoryItem& rItem, sal_uInt32 nHint = 0)
+
+ class getNextItem : public CppUnit::TestFixture
+ {
+ private:
+ DirectoryItem rItem;
+
+ public:
+ void setUp() override
+ {
+ // create a tempdirectory : $TEMP/tmpdir.
+ createTestDirectory(aTmpName3);
+ // create three files : $TEMP/tmpdir/tmpname, $TEMP/tmpdir/tmpdir, $TEMP/tmpdir/hiddenfile,
+ createTestFile(aTmpName3, aTmpName2);
+ createTestFile(aTmpName3, aTmpName1);
+ createTestFile(aTmpName3, aHidURL1);
+
+ }
+
+ void tearDown() override
+ {
+ // remove three files : $TEMP/tmpdir/tmpname, $TEMP/tmpdir/tmpdir, $TEMP/tmpdir/hiddenfile,
+ deleteTestFile(aTmpName3, aHidURL1);
+ deleteTestFile(aTmpName3, aTmpName1);
+ deleteTestFile(aTmpName3, aTmpName2);
+ // remove a tempdirectory : $TEMP/tmpdir.
+ deleteTestDirectory(aTmpName3);
+ }
+
+
+ void getNextItem_001()
+ {
+ Directory testDirectory(aTmpName3); // constructor
+
+ // open a directory
+ auto nError1 = testDirectory.open();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ // check the file name
+ bool bOk1 = false;
+ bool bOk2 = false;
+ bool bOk3 = false;
+ FileStatus rFileStatus(osl_FileStatus_Mask_FileName);
+
+ for (int nCount = 0; nCount < 3; nCount++)
+ {
+ // get three Items
+ nError1 = testDirectory.getNextItem(rItem, 2);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ nError1 = rItem.getFileStatus(rFileStatus);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ // a special order is not guaranteed. So any file may occur on any time.
+ // But every file name should occur only once.
+ if (!bOk1 && compareFileName(rFileStatus.getFileName(), aTmpName1))
+ {
+ bOk1 = true;
+ }
+
+ if (!bOk2 && compareFileName(rFileStatus.getFileName(), aTmpName2))
+ {
+ bOk2 = true;
+ }
+
+ if (!bOk3 && compareFileName(rFileStatus.getFileName(), aHidURL1))
+ {
+ bOk3 = true;
+ }
+ }
+
+ // close a directory
+ nError1 = testDirectory.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ CPPUNIT_ASSERT_MESSAGE("test for getNextItem function: retrieve three items and check their names.",
+ bOk1);
+ CPPUNIT_ASSERT_MESSAGE("test for getNextItem function: retrieve three items and check their names.",
+ bOk2);
+ CPPUNIT_ASSERT_MESSAGE("test for getNextItem function: retrieve three items and check their names.",
+ bOk3);
+ }
+
+ void getNextItem_002()
+ {
+ Directory testDirectory(aTmpName3); // constructor
+ auto nError1 = testDirectory.getNextItem(rItem);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for getNextItem function: retrieve an item in a directory which is not opened, also test for nHint's default value.",
+ osl::FileBase::E_INVAL, nError1);
+ }
+
+ void getNextItem_003()
+ {
+ Directory testDirectory(aTmpName3); // constructor
+
+ // open a directory
+ auto nError1 = testDirectory.open();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ osl::FileBase::RC nError2 = osl::FileBase::E_None;
+ for (int nCount = 0; nCount < 4; nCount++)
+ {
+ nError2 = testDirectory.getNextItem(rItem, 3);
+ }
+
+ // close a directory
+ nError1 = testDirectory.close();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for getNextItem function: retrieve 4 times in a directory which contain only 3 files.",
+ osl::FileBase::E_NOENT, nError2);
+ }
+
+ void getNextItem_004()
+ {
+ // create a link file(can not on Windows), then check if getNextItem can get it.
+#ifdef UNX
+ bool bLnkOK = false;
+ bool bFoundOK = false;
+
+ OUString aUStr_LnkFileSys(aTempDirectorySys), aUStr_SrcFileSys(aTempDirectorySys);
+ aUStr_LnkFileSys += aSlashURL + "/tmpdir/link.file";
+ aUStr_SrcFileSys += aSlashURL + "/tmpdir/tmpname";
+
+ OString strLinkFileName, strSrcFileName;
+ strLinkFileName = OUStringToOString(aUStr_LnkFileSys, RTL_TEXTENCODING_ASCII_US);
+ strSrcFileName = OUStringToOString(aUStr_SrcFileSys, RTL_TEXTENCODING_ASCII_US);
+
+ // create a link file and link it to file "/tmp/PID/tmpdir/tmpname"
+ sal_Int32 fd = symlink(strSrcFileName.getStr(), strLinkFileName.getStr());
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), fd);
+ Directory testDirectory(aTmpName3);
+
+ // open a directory
+ auto nError1 = testDirectory.open();
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ OUString aFileName ("link.file");
+
+ while (true) {
+ nError1 = testDirectory.getNextItem(rItem, 4);
+ if (nError1 == osl::FileBase::E_None) {
+ FileStatus rFileStatus(osl_FileStatus_Mask_FileName | osl_FileStatus_Mask_Type);
+ rItem.getFileStatus(rFileStatus);
+ if (compareFileName(rFileStatus.getFileName(), aFileName))
+ {
+ bFoundOK = true;
+ if (rFileStatus.getFileType() == FileStatus::Link)
+ {
+ bLnkOK = true;
+ break;
+ }
+ }
+ }
+ else
+ break;
+ }
+ fd = std::remove(strLinkFileName.getStr());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("remove link file failed", static_cast<sal_Int32>(0), fd);
+ CPPUNIT_ASSERT_MESSAGE("test for getNextItem function: check if can retrieve the link file name",
+ bFoundOK);
+ CPPUNIT_ASSERT_MESSAGE("test for getNextItem function: check if link file has file type link",
+ bLnkOK);
+#endif
+ }
+
+ CPPUNIT_TEST_SUITE(getNextItem);
+ CPPUNIT_TEST(getNextItem_001);
+ CPPUNIT_TEST(getNextItem_002);
+ CPPUNIT_TEST(getNextItem_003);
+ CPPUNIT_TEST(getNextItem_004);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline static RC getVolumeInfo(const OUString& ustrDirectoryURL, VolumeInfo& rInfo)
+
+ class getVolumeInfo : public CppUnit::TestFixture
+ {
+ public:
+ void checkValidMask(osl::VolumeInfo const& _aVolumeInfo, sal_Int32 _nMask)
+ {
+ if (_nMask == osl_VolumeInfo_Mask_FileSystemName)
+ {
+ // get file system name
+ OUString aFileSysName = _aVolumeInfo.getFileSystemName();
+
+ bool bRes2 = compareFileName(aFileSysName, aNullURL);
+ CPPUNIT_ASSERT_MESSAGE("test for getVolumeInfo function: getVolumeInfo of root directory.",
+ !bRes2);
+ }
+
+ if (_nMask == osl_VolumeInfo_Mask_Attributes)
+ {
+ bool b1 = _aVolumeInfo.getRemoteFlag();
+ bool b2 = _aVolumeInfo.getRemoveableFlag();
+ bool b3 = _aVolumeInfo.getCompactDiscFlag();
+ bool b4 = _aVolumeInfo.getFloppyDiskFlag();
+ bool b5 = _aVolumeInfo.getFixedDiskFlag();
+ bool b6 = _aVolumeInfo.getRAMDiskFlag();
+
+ OString sAttr;
+ if (b1) sAttr = "Remote";
+ if (b2) sAttr += " Removeable";
+ if (b3) sAttr += " CDROM";
+ if (b4) sAttr += " Floppy";
+ if (b5) sAttr += " FixedDisk";
+ if (b6) sAttr += " RAMDisk";
+
+ printf("Attributes: %s\n", sAttr.getStr());
+ }
+ if (_nMask == osl_VolumeInfo_Mask_TotalSpace)
+ {
+ // within Linux, df / * 1024 bytes is the result
+ sal_uInt64 nSize = _aVolumeInfo.getTotalSpace();
+ printf("Total space: %" SAL_PRIuUINT64 "\n", nSize);
+ }
+ if (_nMask == osl_VolumeInfo_Mask_UsedSpace)
+ {
+ sal_uInt64 nSize = _aVolumeInfo.getUsedSpace();
+ printf(" Used space: %" SAL_PRIuUINT64 "\n", nSize);
+ }
+ if (_nMask == osl_VolumeInfo_Mask_FreeSpace)
+ {
+ sal_uInt64 nSize = _aVolumeInfo.getFreeSpace();
+ printf(" Free space: %" SAL_PRIuUINT64 "\n", nSize);
+ }
+ if (_nMask == osl_VolumeInfo_Mask_MaxNameLength)
+ {
+ sal_uInt32 nLength = _aVolumeInfo.getMaxNameLength();
+ printf("max name length: %" SAL_PRIuUINT32 "\n", nLength);
+ }
+ if (_nMask == osl_VolumeInfo_Mask_MaxPathLength)
+ {
+ sal_uInt32 nLength = _aVolumeInfo.getMaxPathLength();
+ printf("max path length: %" SAL_PRIuUINT32 "\n", nLength);
+ }
+ if (_nMask == osl_VolumeInfo_Mask_FileSystemCaseHandling)
+ {
+ bool bIsCase = _aVolumeInfo.isCaseSensitiveFileSystem();
+ printf("filesystem case sensitive: %s\n", bIsCase ? "yes" : "no");
+ }
+ }
+
+ void checkVolumeInfo(sal_Int32 _nMask)
+ {
+ VolumeInfo aVolumeInfo(_nMask);
+ // call getVolumeInfo here
+ auto nError1 = Directory::getVolumeInfo(aVolURL1, aVolumeInfo);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "test for getVolumeInfo function: getVolumeInfo of root directory.",
+ osl::FileBase::E_None, nError1);
+ // LLA: IMHO it's not a bug, if VolumeInfo is not valid, it's a feature
+ // LLA: CPPUNIT_ASSERT_MESSAGE("mask is not valid", sal_True == aVolumeInfo.isValid(_nMask));
+ if (aVolumeInfo.isValid(_nMask))
+ checkValidMask(aVolumeInfo, _nMask);
+ }
+
+ void getVolumeInfo_001_1()
+ {
+ sal_Int32 mask = osl_VolumeInfo_Mask_FileSystemName;
+ checkVolumeInfo(mask);
+ }
+
+ void getVolumeInfo_001_2()
+ {
+ sal_Int32 mask = osl_VolumeInfo_Mask_Attributes;
+ checkVolumeInfo(mask);
+ }
+
+ void getVolumeInfo_001_3()
+ {
+ sal_Int32 mask = osl_VolumeInfo_Mask_TotalSpace;
+ checkVolumeInfo(mask);
+ }
+
+ void getVolumeInfo_001_4()
+ {
+ sal_Int32 mask = osl_VolumeInfo_Mask_UsedSpace;
+ checkVolumeInfo(mask);
+ }
+
+ void getVolumeInfo_001_5()
+ {
+ sal_Int32 mask = osl_VolumeInfo_Mask_FreeSpace;
+ checkVolumeInfo(mask);
+ }
+
+ void getVolumeInfo_001_6()
+ {
+ sal_Int32 mask = osl_VolumeInfo_Mask_MaxNameLength;
+ checkVolumeInfo(mask);
+ }
+
+ void getVolumeInfo_001_7()
+ {
+ sal_Int32 mask = osl_VolumeInfo_Mask_MaxPathLength;
+ checkVolumeInfo(mask);
+ }
+
+ void getVolumeInfo_001_8()
+ {
+ sal_Int32 mask = osl_VolumeInfo_Mask_FileSystemCaseHandling;
+ checkVolumeInfo(mask);
+ }
+
+ void getVolumeInfo_002()
+ {
+ sal_Int32 mask = osl_VolumeInfo_Mask_FileSystemName;
+ VolumeInfo aVolumeInfo(mask);
+ // call getVolumeInfo here
+
+ OUString aRootSysURL;
+ auto nError1 = osl::File::getFileURLFromSystemPath(aRootSys, aRootSysURL);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("can't convert root path to file url", osl::FileBase::E_None, nError1);
+
+ nError1 = Directory::getVolumeInfo(aRootSys, aVolumeInfo);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for getVolumeInfo function: use system path as parameter.",
+ osl::FileBase::E_INVAL, nError1);
+ }
+
+ void getVolumeInfo_003()
+ {
+// LLA: in Windows, it reply no error, it did not pass in (W32).
+#if defined(UNX) && !defined(IOS)
+ sal_Int32 mask = osl_VolumeInfo_Mask_FileSystemName;
+ VolumeInfo aVolumeInfo(mask);
+ // call getVolumeInfo here
+ auto nError1 = Directory::getVolumeInfo(aTmpName3, aVolumeInfo);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for getVolumeInfo function: non-existence test. ",
+ osl::FileBase::E_NOENT, nError1);
+#endif
+ }
+
+ CPPUNIT_TEST_SUITE(getVolumeInfo);
+ CPPUNIT_TEST(getVolumeInfo_001_1);
+ CPPUNIT_TEST(getVolumeInfo_001_2);
+ CPPUNIT_TEST(getVolumeInfo_001_3);
+ CPPUNIT_TEST(getVolumeInfo_001_4);
+ CPPUNIT_TEST(getVolumeInfo_001_5);
+ CPPUNIT_TEST(getVolumeInfo_001_6);
+ CPPUNIT_TEST(getVolumeInfo_001_7);
+ CPPUNIT_TEST(getVolumeInfo_001_8);
+ CPPUNIT_TEST(getVolumeInfo_002);
+ CPPUNIT_TEST(getVolumeInfo_003);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline static RC create(const OUString& ustrDirectoryURL)
+
+ class create : public CppUnit::TestFixture
+ {
+ public:
+ void create_001()
+ {
+ // create directory in $TEMP/tmpdir
+ auto nError1 = Directory::create(aTmpName3);
+ // check for existence
+ auto nError2 = Directory::create(aTmpName3);
+ // remove it
+ deleteTestDirectory(aTmpName3);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for create function: create a directory and check its existence.",
+ osl::FileBase::E_None, nError1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for create function: create a directory and check its existence.",
+ osl::FileBase::E_EXIST, nError2);
+ }
+
+ void create_002()
+ {
+#if !defined(_WIN32) && !defined(MACOSX) && defined(SAL_UNX)
+ if (geteuid() == 0) // don't test if building as root
+ return;
+
+ OUString aTmpDir;
+ auto nError1 = osl::FileBase::createTempFile(nullptr, nullptr, &aTmpDir);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("temp File creation failed", osl::FileBase::E_None, nError1);
+
+ nError1 = File::remove(aTmpDir);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("temp File removal failed", osl::FileBase::E_None, nError1);
+
+ nError1 = Directory::create(aTmpDir);
+ OString sError = "test for create function: create a directory '" +
+ OUStringToOString(aTmpDir, RTL_TEXTENCODING_ASCII_US) +
+ "' and check its existence.";
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sError.getStr(), osl::FileBase::E_None, nError1);
+ osl_setFileAttributes(aTmpDir.pData, 0); // no access allowed now
+
+ // Shouldn't be possible now to create a dir underneath it
+ OUString aTmpSubLevel = aTmpDir + "/notallowedhere";
+ nError1 = Directory::create(aTmpSubLevel);
+
+ // allow removal
+ osl_setFileAttributes(aTmpDir.pData,
+ osl_File_Attribute_OwnRead |
+ osl_File_Attribute_OwnWrite |
+ osl_File_Attribute_OwnExe);
+ deleteTestDirectory(aTmpDir);
+ sError = "test for create function: create a directory under '" +
+ OUStringToOString(aTmpDir, RTL_TEXTENCODING_ASCII_US) +
+ "' for access test.";
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sError.getStr(), osl::FileBase::E_ACCES, nError1);
+#endif
+ }
+
+ void create_003()
+ {
+ // create directory in /tmpname
+ auto nError1 = Directory::create(aSysPath1);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for create function: create a directory using system path.",
+ osl::FileBase::E_INVAL, nError1);
+ }
+
+ CPPUNIT_TEST_SUITE(create);
+ CPPUNIT_TEST(create_001);
+ CPPUNIT_TEST(create_002);
+ CPPUNIT_TEST(create_003);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // testing the method
+ // inline static RC remove(const OUString& ustrDirectoryURL)
+
+ class remove : public CppUnit::TestFixture
+ {
+ public:
+ void remove_001()
+ {
+ // create directory in $TEMP/tmpdir
+ auto nError1 = Directory::create(aTmpName3);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ // remove it
+ nError1 = Directory::remove(aTmpName3);
+ // check for existence
+ Directory rDirectory(aTmpName3);
+ auto nError2 = rDirectory.open();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for remove function: remove a directory and check its existence.",
+ osl::FileBase::E_None, nError1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for remove function: remove a directory and check its existence.",
+ osl::FileBase::E_NOENT, nError2);
+ }
+
+ void remove_002()
+ {
+ // create directory in $TEMP/tmpdir
+ auto nError1 = Directory::create(aTmpName3);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1);
+ // try to remove it by system path
+ nError1 = Directory::remove(aSysPath3);
+ // check for existence
+ Directory rDirectory(aTmpName3);
+ auto nError2 = rDirectory.open();
+
+ if (nError2 != osl::FileBase::E_NOENT)
+ Directory::remove(aTmpName3);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for remove function: remove a directory by its system path, and check its existence.",
+ osl::FileBase::E_INVAL, nError1);
+ }
+
+ void remove_003()
+ {
+ // try to remove a non-existed directory
+ auto nError1 = Directory::remove(aTmpName6);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("test for remove function: try to remove a non-existed directory.",
+ osl::FileBase::E_NOENT, nError1);
+ }
+
+ void remove_004()
+ {
+ createTestFile(aTmpName6);
+ bool bExist = ifFileExist(aTmpName6);
+ // try to remove file.
+ auto nError1 = Directory::remove(aTmpName6);
+ deleteTestFile(aTmpName6);
+
+ CPPUNIT_ASSERT_MESSAGE("test for remove function: try to remove a file but not directory.",
+ bExist);
+ CPPUNIT_ASSERT_MESSAGE("test for remove function: try to remove a file but not directory.",
+ (osl::FileBase::E_NOTDIR == nError1) || (osl::FileBase::E_NOENT == nError1));
+ }
+
+ void remove_005()
+ {
+ createTestDirectory(aTmpName3);
+ createTestFile(aTmpName4);
+ auto nError1 = Directory::remove(aTmpName3);
+ deleteTestFile(aTmpName4);
+ deleteTestDirectory(aTmpName3);
+ OString sError = "test for remove function: try to remove a directory that is not empty." +
+ errorToStr(nError1);
+#if defined(__sun)
+ // on UNX, the implementation uses rmdir(), which EEXIST is thrown on Solaris when the directory is not empty, refer to: 'man -s 2 rmdir', while on linux, ENOTEMPTY is thrown.
+ // EEXIST The directory contains entries other than those for "." and "..".
+ printf("#Solaris test\n");
+ CPPUNIT_ASSERT_MESSAGE(sError.getStr(), (osl::FileBase::E_EXIST == nError1));
+#else
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sError.getStr(), osl::FileBase::E_NOTEMPTY, nError1);
+#endif
+ }
+
+ CPPUNIT_TEST_SUITE(remove);
+ CPPUNIT_TEST(remove_001);
+ CPPUNIT_TEST(remove_002);
+ CPPUNIT_TEST(remove_003);
+ CPPUNIT_TEST(remove_004);
+ CPPUNIT_TEST(remove_005);
+ CPPUNIT_TEST_SUITE_END();
+ };
+
+ // TEST Directory::createPath
+
+ #ifdef _WIN32
+ # define PATH_BUFFER_SIZE MAX_PATH
+ #else
+ # define PATH_BUFFER_SIZE PATH_MAX
+ #endif
+
+#define TEST_PATH_POSTFIX "hello/world"
+
+ static OUString const & get_test_path()
+ {
+ static OUString test_path = []()
+ {
+ OUString tmp;
+ osl::FileBase::RC rc = osl::FileBase::getTempDirURL(tmp);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE
+ (
+ "Getting the location of TMP dir failed",
+ osl::FileBase::E_None, rc
+ );
+
+ OUString system_path;
+ rc = osl::FileBase::getSystemPathFromFileURL(tmp, system_path);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE
+ (
+ "Cannot convert the TMP dir to system path",
+ osl::FileBase::E_None, rc
+ );
+
+ OString tmp_x(OUStringToOString(system_path, RTL_TEXTENCODING_UTF8));
+ if (tmp_x.lastIndexOf('/') != (tmp_x.getLength() - 1))
+ tmp_x += "/";
+
+#if !defined(_WIN32) && !defined(ANDROID) && !defined(AIX)
+ // FIXME would be nice to create unique dir even on Windows
+ tmp_x += "XXXXXX";
+ char *out = mkdtemp(const_cast<char*>(tmp_x.getStr()));
+
+ CPPUNIT_ASSERT_MESSAGE
+ (
+ "mkdtemp call failed",
+ out != nullptr
+ );
+
+ tmp_x += "/";
+#endif
+ tmp_x += TEST_PATH_POSTFIX;
+
+ OUString tmpTestPath;
+ rc = osl::FileBase::getFileURLFromSystemPath(OStringToOUString(tmp_x, RTL_TEXTENCODING_UTF8), tmpTestPath);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE
+ (
+ "Cannot convert the system path back to a URL",
+ osl::FileBase::E_None, rc
+ );
+ return tmpTestPath;
+ }();
+ return test_path;
+ }
+
+ static void rm_test_path(const OUString& path)
+ {
+ sal_Unicode buffer[PATH_BUFFER_SIZE];
+ memcpy(buffer, path.getStr(), (path.getLength() + 1) * sizeof(sal_Unicode));
+
+ sal_Int32 i = rtl_ustr_lastIndexOfChar(buffer, '/');
+ if (i == path.getLength())
+ buffer[i] = 0;
+
+ Directory::remove(OUString(buffer));
+
+ i = rtl_ustr_lastIndexOfChar(buffer, '/');
+ assert(i != -1);
+ if (i != -1)
+ {
+ buffer[i] = 0;
+ Directory::remove(OUString(buffer));
+ }
+ }
+
+ namespace {
+
+ class DirCreatedObserver : public DirectoryCreationObserver
+ {
+ public:
+ DirCreatedObserver() : i(0) {}
+ virtual void DirectoryCreated(const OUString&) override { i++; };
+
+ int number_of_dirs_created() const { return i; }
+
+ private:
+ int i;
+ };
+
+ }
+
+ class createPath : public CppUnit::TestFixture
+ {
+ public:
+ createPath()
+ {}
+
+ void with_relative_path()
+ {
+ osl::FileBase::RC rc = Directory::createPath(TEST_PATH_POSTFIX);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE
+ (
+ "osl_createDirectoryPath contract broken",
+ osl::FileBase::E_INVAL, rc
+ );
+ }
+
+ void without_callback()
+ {
+ OUString tp_url = get_test_path();
+
+ rm_test_path(tp_url);
+
+ osl::FileBase::RC rc = Directory::createPath(tp_url);
+
+ rm_test_path(tp_url);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE
+ (
+ "osl_createDirectoryPath failed",
+ osl::FileBase::E_None, rc
+ );
+ }
+
+ void with_callback()
+ {
+ OUString tp_url = get_test_path();
+
+ rm_test_path(tp_url);
+
+ DirCreatedObserver* observer = new DirCreatedObserver;
+ osl::FileBase::RC rc = Directory::createPath(tp_url, observer);
+ int nDirs = observer->number_of_dirs_created();
+ delete observer;
+
+ rm_test_path(tp_url);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE
+ (
+ "osl_createDirectoryPath failed",
+ osl::FileBase::E_None, rc
+ );
+ CPPUNIT_ASSERT_MESSAGE
+ (
+ "osl_createDirectoryPath failed",
+ nDirs > 0
+ );
+
+ }
+
+#ifdef _WIN32
+
+ const char* get_unused_drive_letter()
+ {
+ static const char m_aBuff[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ DWORD ld = GetLogicalDrives();
+ DWORD i = 4;
+ DWORD j = 2;
+
+ while ((ld & i) && (i > 1))
+ { i = i << 1; j++; }
+
+ if (i > 2)
+ return m_aBuff + j;
+
+ return nullptr;
+ }
+
+ void at_invalid_logical_drive()
+ {
+ const char* drv = get_unused_drive_letter();
+ char buff[PATH_BUFFER_SIZE];
+ memset(buff, 0, sizeof(buff));
+
+ strncpy(buff, drv, 1);
+ strcat(buff, ":\\");
+ strcat(buff, TEST_PATH_POSTFIX);
+
+ OUString path = OUString::createFromAscii(buff);
+ OUString tp_url;
+ osl::FileBase::getFileURLFromSystemPath(path, tp_url);
+
+ osl::FileBase::RC rc = Directory::createPath(tp_url);
+
+ CPPUNIT_ASSERT_MESSAGE
+ (
+ "osl_createDirectoryPath doesn't fail on unused logical drive letters",
+ rc != osl::FileBase::E_None
+ );
+ }
+#endif /* _WIN32 */
+
+ CPPUNIT_TEST_SUITE(createPath);
+ CPPUNIT_TEST(with_relative_path);
+ CPPUNIT_TEST(without_callback);
+ CPPUNIT_TEST(with_callback);
+#ifdef _WIN32
+ CPPUNIT_TEST(at_invalid_logical_drive);
+#endif
+ CPPUNIT_TEST_SUITE_END();
+
+ };
+
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_Directory::ctors);
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_Directory::open);
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_Directory::isOpen);
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_Directory::close);
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_Directory::reset);
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_Directory::getNextItem);
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_Directory::getVolumeInfo);
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_Directory::create);
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_Directory::remove);
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_Directory::createPath);
+}
+
+#if 0
+#if defined UNX
+/** get Current PID.
+*/
+OUString getCurrentPID()
+{
+ //~ Get current PID and turn it into OUString;
+ int nPID = 0;
+#ifdef _WIN32
+ nPID = GetCurrentProcessId();
+#else
+ nPID = getpid();
+#endif
+ return OUString::number(nPID);
+}
+#endif
+#endif
+
+namespace {
+
+//~ do some clean up work after all test completed.
+class GlobalObject
+{
+public:
+ ~GlobalObject()
+ {
+ try
+ {
+ //~ special clean up task in Windows and Unix separately;
+#if (defined UNX)
+ //~ some clean up task for UNIX OS
+ ;
+#else
+ //~ some clean up task for Windows OS
+ //~ check if some files are in the way, remove them if necessary.
+ if (ifFileExist(aTmpName6))
+ deleteTestFile(aTmpName6);
+ if (ifFileExist(aTmpName4))
+ deleteTestFile(aTmpName4);
+ if (checkDirectory(aTmpName4, oslCheckMode::Exist))
+ deleteTestDirectory(aTmpName4);
+ if (ifFileExist(aTmpName3))
+ deleteTestFile(aTmpName3);
+ if (checkDirectory(aTmpName3, oslCheckMode::Exist))
+ deleteTestDirectory(aTmpName3);
+
+ OUString aUStr(aUserDirectoryURL);
+ concatURL(aUStr, aHidURL1);
+ if (ifFileExist(aUStr))
+ deleteTestFile(aUStr);
+
+ OUString aUStr1(aRootURL);
+ concatURL(aUStr1, aTmpName2);
+ if (ifFileExist(aUStr1))
+ deleteTestFile(aUStr1);
+#endif
+ }
+ catch (const CppUnit::Exception &e)
+ {
+ printf("Exception caught in GlobalObject dtor(). Exception message: '%s'. Source line: %d\n", e.what(), e.sourceLine().lineNumber());
+ }
+ catch (...)
+ {
+ printf("Exception caught (...) in GlobalObject dtor()\n");
+ }
+ }
+};
+
+}
+
+static GlobalObject theGlobalObject;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/osl/file/osl_File_Const.h b/sal/qa/osl/file/osl_File_Const.h
new file mode 100644
index 000000000..beee8d6d6
--- /dev/null
+++ b/sal/qa/osl/file/osl_File_Const.h
@@ -0,0 +1,206 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SAL_QA_OSL_FILE_OSL_FILE_CONST_H
+#define INCLUDED_SAL_QA_OSL_FILE_OSL_FILE_CONST_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sal/types.h>
+
+#include <rtl/ustring.hxx>
+
+#include <cppunit/extensions/HelperMacros.h>
+
+static OUString getTempDirectoryURL_()
+{
+ OUString aDir;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("couldn't get system temp URL",
+ osl::FileBase::E_None, osl::FileBase::getTempDirURL(aDir));
+ // This resolves symlinks in the temp path if any
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None,
+ osl::FileBase::getAbsoluteFileURL(aDir, aDir, aDir));
+ return aDir;
+}
+
+static OUString getTempDirectorySys_()
+{
+ OUString aDir;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("couldn't get system temp directory",
+ osl::FileBase::E_None, osl::FileBase::getSystemPathFromFileURL(getTempDirectoryURL_(), aDir));
+ return aDir;
+}
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+// common used string resource
+// these common used string will be used as assist resource in test
+// they are mostly OS independent, some of the resource can be reused
+// so, a common test data repository will be better since it can be
+// shared among all test code
+
+const char pBuffer_Char[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+const char pBuffer_Number[] = "1234567890";
+const char pBuffer_Blank[] = "";
+
+// OS dependent/independent definitions/includes
+// we use FILE_PREFIX for URL prefix,
+// TEST_PLATFORM for test platform initial,
+// TEST_PLATFORM_ROOT for root dir in comrresponding platform,
+// TEST_PLATFORM_TEMP for temp dir in comrresponding platform,
+// PATH_LIST_DELIMITER for separator of path list in comrresponding platform,
+// PATH_SEPARATOR for separator in URL or system path in comrresponding platform,
+// PATH_MAX/MAX_PATH for max path length in comrresponding platform,
+
+// OS independent const definition
+
+# define FILE_PREFIX "file:///"
+# define TEST_FILE_SIZE 1024
+
+// OS dependent declaration and includes
+
+#if ( defined UNX ) //Unix
+# include <unistd.h>
+# include <limits.h>
+# include <math.h>
+# include <errno.h>
+# include <fcntl.h>
+# include <sys/stat.h>
+# if !defined(MACOSX) && !defined(IOS) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined (DRAGONFLY) && !defined(HAIKU)
+# include <sys/statfs.h>
+# else
+# include <sys/param.h>
+# ifndef HAIKU
+# include <sys/mount.h>
+# endif
+# endif
+# if !defined(ANDROID)
+# include <sys/statvfs.h>
+# endif
+# include <sys/types.h>
+# define TEST_PLATFORM_ROOT "/"
+# define PATH_LIST_DELIMITER ":"
+# define PATH_SEPARATOR "/"
+#endif
+
+#if defined(_WIN32) // Windows
+# include <io.h>
+# define PATH_MAX MAX_PATH
+# define TEST_PLATFORM_ROOT "c:/"
+# define PATH_LIST_DELIMITER ";"
+# define PATH_SEPARATOR "/"
+#endif
+
+// OS independent file definition
+
+OUString aNullURL( "" );
+OUString aSlashURL( PATH_SEPARATOR );
+OUString aPreURL( FILE_PREFIX );
+OUString aRootURL( FILE_PREFIX TEST_PLATFORM_ROOT );
+
+OUString aTempDirectorySys(getTempDirectorySys_());
+OUString aTempDirectoryURL(getTempDirectoryURL_());
+OUString aUserDirectorySys( aTempDirectorySys + "" );
+OUString aUserDirectoryURL( aTempDirectoryURL + "" );
+
+// common used URL:temp, canonical, root, relative, link,etc
+
+OUString aCanURL1( aTempDirectoryURL + "/canonical.name" );
+OUString aCanURL2(
+ RTL_CONSTASCII_USTRINGPARAM("ca@#;+.,$///78no\0ni..name"));
+OUString aCanURL3( "ca@#;+.,$//tmp/678nonical//name" );
+OUString aCanURL4( "canonical.name" );
+OUString aTmpName1( "tmpdir" );
+OUString aTmpName2( "tmpname" );
+OUString aTmpName3( aTempDirectoryURL + "/tmpdir" );
+OUString aTmpName4( aTempDirectoryURL + "/tmpdir/tmpname" );
+OUString aTmpName5( aTempDirectoryURL + "/tmpdir/../tmpdir/./tmpname" );
+OUString aTmpName6( aTempDirectoryURL + "/tmpname" );
+OUString aTmpName7( aTempDirectoryURL + "/noaccess" );
+OUString aTmpName8( aTempDirectoryURL + "/tmpname/tmpdir" );
+OUString aTmpName9( aTempDirectoryURL + "/tmpdir/../tmpdir/./" );
+OUString aTmpName10(aTempDirectoryURL + u"/\xE6\x9C\xAA\xE5\x91\xBD\xE5\x90\x8Dzhgb18030");
+
+OUString aRelURL1( "relative/file1" );
+OUString aRelURL2( "relative/./file2" );
+OUString aRelURL3( "relative/../file3" );
+OUString aRelURL4( "././relative/../file4" );
+OUString aRelURL5( aTempDirectoryURL + "/./../" );
+OUString aLnkURL1( aTempDirectoryURL + "/link.file" );
+OUString aHidURL1( ".hiddenfile" );
+
+// common used System Path:temp, root,etc
+
+OUString aRootSys( TEST_PLATFORM_ROOT );
+OUString aSysPath1( aTempDirectorySys + "/system.path" );
+OUString aSysPath2( aTempDirectorySys + "/system/path" );
+OUString aSysPath3( aTempDirectorySys + "/tmpdir" );
+OUString aSysPath4( aTempDirectorySys + "/tmpname" );
+OUString aSysPath5( aTempDirectorySys + u"/\xE6\x9C\xAA\xE5\x91\xBD\xE5\x90\x8Dzhgb18030" );
+OUString aSysPathLnk( aTempDirectorySys + "/link.file" );
+OUString aFifoSys( aTempDirectorySys + "/tmpdir/fifo" );
+
+// FileType URL, we pick some canonical file in corresponding system for test:
+// socket, link, etc.
+// Note that this may be changed in the different platform, so be careful to use.
+
+#if ( defined UNX ) // Unix
+OUString aTypeURL1( FILE_PREFIX "dev/ccv"); //socket Solaris/Linux
+OUString aTypeURL2( FILE_PREFIX "devices/pseudo/tcp@0:tcp"); //special Solaris/Linux
+OUString aTypeURL3( FILE_PREFIX "lib" ); //link Solaris
+#else // Windows
+OUString aTypeURL1( FILE_PREFIX "" );
+OUString aTypeURL2( FILE_PREFIX "" );
+OUString aTypeURL3( FILE_PREFIX "" );
+#endif
+
+// Volume device URL, we pick some canonical volume device for test:
+// UNIX file system, Floppy Disk, Proc file system, Temp file system, Compact Disk.
+
+#if ( defined UNX ) // Unix
+OUString aVolURL1( FILE_PREFIX ""); //ufs Solaris/Linux
+#ifdef __sun
+OUString aVolURL2( FILE_PREFIX "dev/fd" ); //fd Solaris
+#else
+OUString aVolURL2( FILE_PREFIX "dev/floppy/0u1440" ); //fd0 Linux
+#endif
+OUString aVolURL3( FILE_PREFIX "proc" ); //proc Solaris/Linux
+OUString aVolURL4( FILE_PREFIX "staroffice" ); //nfs Solaris/Linux
+OUString aVolURL5( FILE_PREFIX "tmp" ); //tmpfs Solaris
+OUString aVolURL6( FILE_PREFIX "cdrom" ); //cd Solaris
+#else // Windows
+OUString aVolURL1( FILE_PREFIX "c:/" );
+OUString aVolURL2( FILE_PREFIX "a:/" );
+OUString aVolURL3( FILE_PREFIX "" );
+OUString aVolURL4( FILE_PREFIX "" );
+OUString aVolURL5( FILE_PREFIX "c:/temp" );
+OUString aVolURL6( FILE_PREFIX "e:/" );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // INCLUDED_SAL_QA_OSL_FILE_OSL_FILE_CONST_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/osl/file/osl_old_test_file.cxx b/sal/qa/osl/file/osl_old_test_file.cxx
new file mode 100644
index 000000000..7b0ef6e6d
--- /dev/null
+++ b/sal/qa/osl/file/osl_old_test_file.cxx
@@ -0,0 +1,115 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <osl/file.h>
+#include <rtl/ustring.hxx>
+
+#ifdef SAL_UNX
+#define TEST_VOLUME ""
+#elif defined _WIN32
+#define TEST_VOLUME "Z:/"
+#endif
+
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <utility>
+
+namespace osl_test_file
+{
+
+class oldtestfile : public CppUnit::TestFixture
+{
+public:
+ void test_file_001();
+ void test_file_002();
+ void test_file_004();
+
+ CPPUNIT_TEST_SUITE( oldtestfile );
+ CPPUNIT_TEST( test_file_001 );
+ CPPUNIT_TEST( test_file_002 );
+ CPPUNIT_TEST( test_file_004 );
+ CPPUNIT_TEST_SUITE_END( );
+};
+
+const std::pair<OUString, OUString> aSource1[] = {
+ { u"a", u"file:///" TEST_VOLUME "bla/a" },
+ ///TODO: check if last slash must be omitted in resolved path.
+// { u"a/", u"file:///" TEST_VOLUME "bla/a" },
+ { u"../a", u"file:///" TEST_VOLUME "a" },
+ { u"a/..", u"file:///" TEST_VOLUME "bla/" },
+ { u"a/../b", u"file:///" TEST_VOLUME "bla/b" },
+ { u"..", u"file:///" TEST_VOLUME "" },
+ { u"a/b/c/d", u"file:///" TEST_VOLUME "bla/a/b/c/d" },
+ { u"a/./c", u"file:///" TEST_VOLUME "bla/a/c" },
+ { u"a/././c", u"file:///" TEST_VOLUME "bla/a/c" },
+ { u"file:///" TEST_VOLUME "bla1/blub", u"file:///" TEST_VOLUME "bla1/blub" },
+};
+
+const std::pair<OUString, OUString> aSource2[] = {
+ { u"a", u"file:///" TEST_VOLUME "bla/blubs/schnubbel/a" },
+ ///TODO: check if last slash must be omitted in resolved path.
+// { u"a/", u"file:///" TEST_VOLUME "bla/blubs/schnubbel/a" },
+ { u"../a", u"file:///" TEST_VOLUME "bla/blubs/a" },
+ { u"../../a", u"file:///" TEST_VOLUME "bla/a" },
+ { u"../../../a", u"file:///" TEST_VOLUME "a" },
+ { u"../../../a/b/c/d", u"file:///" TEST_VOLUME "a/b/c/d" },
+};
+
+void oldtestfile::test_file_001()
+{
+ OUString base1( "file:///" TEST_VOLUME "bla" );
+ for (const auto& [rel, expected] : aSource1)
+ {
+ OUString target;
+ oslFileError e = osl_getAbsoluteFileURL( base1.pData, rel.pData , &target.pData );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("failure #1", osl_File_E_None, e );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("failure #1.1", expected, target);
+ }
+}
+
+void oldtestfile::test_file_002()
+{
+ OUString base2( "file:///" TEST_VOLUME "bla/blubs/schnubbel" );
+ for (const auto& [rel, expected] : aSource2)
+ {
+ OUString target;
+ oslFileError e = osl_getAbsoluteFileURL( base2.pData, rel.pData , &target.pData );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("failure #2", osl_File_E_None, e );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("failure #2.1", expected, target);
+ }
+}
+
+void oldtestfile::test_file_004()
+{
+ OUString base4( "file:///" TEST_VOLUME "bla/" );
+ for (const auto& [rel, expected] : aSource1)
+ {
+ OUString target;
+ oslFileError e = osl_getAbsoluteFileURL( base4.pData, rel.pData , &target.pData );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("failure #10", osl_File_E_None, e );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("failure #10.1", expected, target);
+ }
+}
+
+} // namespace osl_test_file
+
+CPPUNIT_TEST_SUITE_REGISTRATION( osl_test_file::oldtestfile);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/osl/file/test_cpy_wrt_file.cxx b/sal/qa/osl/file/test_cpy_wrt_file.cxx
new file mode 100644
index 000000000..6843d10b3
--- /dev/null
+++ b/sal/qa/osl/file/test_cpy_wrt_file.cxx
@@ -0,0 +1,76 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/types.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+#include <osl/file.hxx>
+#include <osl/thread.h>
+#include <rtl/ustring.hxx>
+
+using namespace osl;
+
+class test_osl_writeFile : public CppUnit::TestFixture
+{
+public:
+ void wrt_file()
+ {
+ FileBase::RC err;
+
+ //create a tempfile
+ OUString aTmpFile;
+ err = FileBase::createTempFile(nullptr, nullptr, &aTmpFile);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("temp File creation failed", osl::FileBase::E_None, err);
+
+ //now attempt to open with Create flag an existing file, should get E_EXIST
+ File tmp_file(aTmpFile);
+ err = tmp_file.open(osl_File_OpenFlag_Write | osl_File_OpenFlag_Create);
+
+ OString sErrorMsg = "Expected that '" +
+ OUStringToOString(aTmpFile, RTL_TEXTENCODING_ASCII_US) +
+ "' would exist!";
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sErrorMsg.getStr(), FileBase::E_EXIST, err);
+
+ char buffer[1];
+ sal_uInt64 written = 0;
+ err = tmp_file.write(static_cast<void*>(buffer), sizeof(buffer), written);
+ CPPUNIT_ASSERT_MESSAGE("write on unconnected file should fail",
+ err != osl::FileBase::E_None);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("write on unconnected file should fail",
+ sal_uInt64(0), written);
+
+ err = tmp_file.sync();
+ CPPUNIT_ASSERT_MESSAGE("sync on unconnected file should fail", err != FileBase::E_None);
+ err = tmp_file.close();
+ CPPUNIT_ASSERT_MESSAGE("close on unconnected file should fail", err != FileBase::E_None);
+
+ err = ::osl::File::remove(aTmpFile);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("temp file should have existed", FileBase::E_None, err);
+ }
+
+ CPPUNIT_TEST_SUITE(test_osl_writeFile);
+ CPPUNIT_TEST(wrt_file);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+// register test suites
+CPPUNIT_TEST_SUITE_REGISTRATION(test_osl_writeFile);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/osl/getsystempathfromfileurl/test-getsystempathfromfileurl.cxx b/sal/qa/osl/getsystempathfromfileurl/test-getsystempathfromfileurl.cxx
new file mode 100644
index 000000000..4fd5d6b16
--- /dev/null
+++ b/sal/qa/osl/getsystempathfromfileurl/test-getsystempathfromfileurl.cxx
@@ -0,0 +1,243 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <osl/file.hxx>
+
+#if defined(_WIN32)
+#define MY_PATH_IN "/c:/foo/bar"
+#define MY_PATH_OUT "c:\\foo\\bar"
+#define MY_PATH_OUT_CONT MY_PATH_OUT "\\"
+#define MY_PATH_OUT_REL "foo\\bar"
+#else
+#define MY_PATH_IN "/foo/bar"
+#define MY_PATH_OUT MY_PATH_IN
+#define MY_PATH_OUT_CONT MY_PATH_OUT "/"
+#define MY_PATH_OUT_REL "foo/bar"
+#endif
+
+namespace {
+
+class Test: public CppUnit::TestFixture {
+private:
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(testBadScheme);
+ CPPUNIT_TEST(testNoScheme);
+ CPPUNIT_TEST(testBadAuthority);
+ CPPUNIT_TEST(testLocalhost1Authority);
+ CPPUNIT_TEST(testLocalhost2Authority);
+ CPPUNIT_TEST(testLocalhost3Authority);
+ CPPUNIT_TEST(testNoAuthority);
+ CPPUNIT_TEST(testEmptyPath);
+ CPPUNIT_TEST(testHomeAbbreviation);
+ CPPUNIT_TEST(testOtherHomeAbbreviation);
+ CPPUNIT_TEST(testRelative);
+ CPPUNIT_TEST(testEscape);
+ CPPUNIT_TEST(testBadEscape2f);
+ CPPUNIT_TEST(testBadEscape2F);
+ CPPUNIT_TEST(testBad0);
+ CPPUNIT_TEST(testBadEscape0);
+ CPPUNIT_TEST(testBadQuery);
+ CPPUNIT_TEST(testBadFragment);
+ CPPUNIT_TEST_SUITE_END();
+
+ void testBadScheme();
+ void testNoScheme();
+ void testBadAuthority();
+ void testLocalhost1Authority();
+ void testLocalhost2Authority();
+ void testLocalhost3Authority();
+ void testNoAuthority();
+ void testEmptyPath();
+ void testHomeAbbreviation();
+ void testOtherHomeAbbreviation();
+ void testRelative();
+ void testEscape();
+ void testBadEscape2f();
+ void testBadEscape2F();
+ void testBad0();
+ void testBadEscape0();
+ void testBadQuery();
+ void testBadFragment();
+};
+
+void Test::testBadScheme() {
+ OUString p;
+ auto e = osl::FileBase::getSystemPathFromFileURL("foo:bar", p);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_INVAL, e);
+ CPPUNIT_ASSERT_EQUAL(OUString(), p);
+}
+
+void Test::testNoScheme() {
+#if !defined(_WIN32) //TODO
+ OUString p;
+ auto e = osl::FileBase::getSystemPathFromFileURL("//" MY_PATH_IN, p);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e);
+ CPPUNIT_ASSERT_EQUAL(OUString(MY_PATH_OUT), p);
+#endif
+}
+
+void Test::testBadAuthority() {
+#if defined UNX
+ OUString p;
+ auto e = osl::FileBase::getSystemPathFromFileURL(
+ "file://baz" MY_PATH_IN, p);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_INVAL, e);
+ CPPUNIT_ASSERT_EQUAL(OUString(), p);
+#endif
+}
+
+void Test::testLocalhost1Authority() {
+ OUString p;
+ auto e = osl::FileBase::getSystemPathFromFileURL(
+ "file://localhost" MY_PATH_IN, p);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e);
+ CPPUNIT_ASSERT_EQUAL(OUString(MY_PATH_OUT), p);
+}
+
+void Test::testLocalhost2Authority() {
+ OUString p;
+ auto e = osl::FileBase::getSystemPathFromFileURL(
+ "file://LOCALHOST" MY_PATH_IN, p);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e);
+ CPPUNIT_ASSERT_EQUAL(OUString(MY_PATH_OUT), p);
+}
+
+void Test::testLocalhost3Authority() {
+ OUString p;
+ auto e = osl::FileBase::getSystemPathFromFileURL(
+ "file://127.0.0.1" MY_PATH_IN, p);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e);
+ CPPUNIT_ASSERT_EQUAL(OUString(MY_PATH_OUT), p);
+}
+
+void Test::testNoAuthority() {
+ OUString p;
+ auto e = osl::FileBase::getSystemPathFromFileURL("file:" MY_PATH_IN, p);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e);
+ CPPUNIT_ASSERT_EQUAL(OUString(MY_PATH_OUT), p);
+}
+
+void Test::testEmptyPath() {
+#if defined UNX
+ OUString p;
+ auto e = osl::FileBase::getSystemPathFromFileURL("file://", p);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e);
+ CPPUNIT_ASSERT_EQUAL(OUString("/"), p);
+#endif
+}
+
+void Test::testHomeAbbreviation() {
+#if defined UNX
+ OUString p;
+ auto e = osl::FileBase::getSystemPathFromFileURL("file:///~", p);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e);
+ // could theoretically fail due to osl::Security::getHomeDir problem
+ e = osl::FileBase::getSystemPathFromFileURL("file:///~/foo%2525/bar", p);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e);
+ // could theoretically fail due to osl::Security::getHomeDir problem
+ CPPUNIT_ASSERT(p.endsWith("/foo%25/bar"));
+#endif
+}
+
+void Test::testOtherHomeAbbreviation() {
+#if defined UNX
+ OUString p;
+ auto e = osl::FileBase::getSystemPathFromFileURL(
+ "file:///~baz" MY_PATH_IN, p);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_INVAL, e); // not supported for now
+ CPPUNIT_ASSERT_EQUAL(OUString(), p);
+#endif
+}
+
+void Test::testRelative() {
+ OUString p;
+ auto e = osl::FileBase::getSystemPathFromFileURL("foo/bar", p);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e);
+ CPPUNIT_ASSERT(p.endsWith(MY_PATH_OUT_REL));
+}
+
+void Test::testEscape() {
+ OUString p;
+ auto e = osl::FileBase::getSystemPathFromFileURL(
+ "file://" MY_PATH_IN "/b%61z", p);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, e);
+ CPPUNIT_ASSERT_EQUAL(OUString(MY_PATH_OUT_CONT "baz"), p);
+}
+
+void Test::testBadEscape2f() {
+ OUString p;
+ auto e = osl::FileBase::getSystemPathFromFileURL(
+ "file://" MY_PATH_IN "/b%2fz", p);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_INVAL, e);
+ CPPUNIT_ASSERT_EQUAL(OUString(), p);
+}
+
+void Test::testBadEscape2F() {
+ OUString p;
+ auto e = osl::FileBase::getSystemPathFromFileURL(
+ "file://" MY_PATH_IN "/b%2Fz", p);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_INVAL, e);
+ CPPUNIT_ASSERT_EQUAL(OUString(), p);
+}
+
+void Test::testBad0() {
+ OUString p;
+ auto e = osl::FileBase::getSystemPathFromFileURL(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("file://" MY_PATH_IN "/b\x00z")),
+ p);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_INVAL, e);
+ CPPUNIT_ASSERT_EQUAL(OUString(), p);
+}
+
+void Test::testBadEscape0() {
+ OUString p;
+ auto e = osl::FileBase::getSystemPathFromFileURL(
+ "file://" MY_PATH_IN "/b%00z", p);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_INVAL, e);
+ CPPUNIT_ASSERT_EQUAL(OUString(), p);
+}
+
+void Test::testBadQuery() {
+ OUString p;
+ auto e = osl::FileBase::getSystemPathFromFileURL(
+ "file://" MY_PATH_IN "?baz", p);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_INVAL, e);
+ CPPUNIT_ASSERT_EQUAL(OUString(), p);
+}
+
+void Test::testBadFragment() {
+ OUString p;
+ auto e = osl::FileBase::getSystemPathFromFileURL(
+ "file://" MY_PATH_IN "#baz", p);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_INVAL, e);
+ CPPUNIT_ASSERT_EQUAL(OUString(), p);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/osl/module/osl_Module.cxx b/sal/qa/osl/module/osl_Module.cxx
new file mode 100644
index 000000000..f440a7151
--- /dev/null
+++ b/sal/qa/osl/module/osl_Module.cxx
@@ -0,0 +1,376 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+// include files
+
+#include "osl_Module_Const.h"
+
+using namespace osl;
+
+/** get dll file URL.
+*/
+static OUString getDllURL()
+{
+#if defined(_WIN32) // lib in Unix and lib in Windows are not same in file name.
+ OUString libPath( "test_Module_DLL.dll" );
+#else
+ OUString libPath( "libtest_Module_DLL.so" );
+#endif
+
+ OUString dirPath, dllPath;
+ osl::Module::getUrlFromAddress(
+ reinterpret_cast<oslGenericFunction>(&getDllURL), dirPath);
+ dirPath = dirPath.copy( 0, dirPath.lastIndexOf('/') + 1);
+ osl::FileBase::getAbsoluteFileURL( dirPath, libPath, dllPath );
+
+ return dllPath;
+}
+
+namespace osl_Module
+{
+ namespace {
+
+ /** class and member function that is available for module test :
+ */
+
+ class testClass
+ {
+ public:
+ static void myFunc()
+ {
+ printf("#Sun Microsystem\n");
+ };
+ };
+
+ }
+
+ /** testing the methods:
+ Module();
+ Module( const OUString& strModuleName, sal_Int32 nRtldMode = SAL_LOADMODULE_DEFAULT);
+ */
+ class ctors : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ void ctors_none( )
+ {
+ ::osl::Module aMod;
+ bRes = aMod.is();
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test constructor without parameter.",
+ !bRes );
+ }
+
+ void ctors_name_mode( )
+ {
+ OUString aFileURL;
+ bRes = osl::Module::getUrlFromAddress(
+ reinterpret_cast<oslGenericFunction>(
+ &osl_Module::testClass::myFunc),
+ aFileURL);
+
+ if ( !bRes )
+ {
+ CPPUNIT_ASSERT_MESSAGE("Cannot locate current module.", false );
+ }
+
+ ::osl::Module aMod( aFileURL );
+ bRes = aMod.is( );
+ aMod.unload( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test constructor with load action.",
+ bRes );
+ }
+
+ CPPUNIT_TEST_SUITE( ctors );
+ CPPUNIT_TEST( ctors_none );
+ CPPUNIT_TEST( ctors_name_mode );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class ctors
+
+ /** testing the methods:
+ static sal_Bool getUrlFromAddress(void * addr, OUString & libraryUrl)
+ */
+ class getUrlFromAddress : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ void getUrlFromAddress_001( )
+ {
+ OUString aFileURL;
+ bRes = osl::Module::getUrlFromAddress(
+ reinterpret_cast<oslGenericFunction>(
+ &osl_Module::testClass::myFunc),
+ aFileURL);
+ if ( !bRes )
+ {
+ CPPUNIT_ASSERT_MESSAGE("Cannot locate current module.", false );
+ }
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test get Module URL from address.",
+ bRes );
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test get Module URL from address.",
+ 0 < aFileURL.lastIndexOf('/') );
+ }
+
+ void getUrlFromAddress_002( )
+ {
+#if !defined( MACOSX )
+ // TODO: Find out why this fails on macOS
+ ::osl::Module aMod( getDllURL( ) );
+ FuncPtr pFunc = reinterpret_cast<FuncPtr>(aMod.getSymbol( "firstfunc" ));
+
+ OUString aFileURL;
+ bRes = osl::Module::getUrlFromAddress(
+ reinterpret_cast<oslGenericFunction>(pFunc), aFileURL);
+ if ( !bRes )
+ {
+ CPPUNIT_ASSERT_MESSAGE("Cannot locate current module.", false );
+ }
+ aMod.unload( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: load an external library, get its function address and get its URL.",
+ bRes );
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: load an external library, get its function address and get its URL.",
+ 0 < aFileURL.lastIndexOf('/') );
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: load an external library, get its function address and get its URL.",
+ aFileURL.equalsIgnoreAsciiCase( getDllURL( ) ) );
+#endif
+ }
+
+ /* tester comments: another case is getFunctionSymbol_001*/
+
+ CPPUNIT_TEST_SUITE( getUrlFromAddress );
+ CPPUNIT_TEST( getUrlFromAddress_001 );
+ CPPUNIT_TEST( getUrlFromAddress_002 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class getUrlFromAddress
+
+ /** testing the method:
+ sal_Bool SAL_CALL load( const OUString& strModuleName,
+ sal_Int32 nRtldMode = SAL_LOADMODULE_DEFAULT)
+ */
+ class load : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ void load_001( )
+ {
+ ::osl::Module aMod( getDllURL( ) );
+ ::osl::Module aMod1;
+
+ aMod1.load( getDllURL( ) );
+ bRes = oslModule(aMod) == oslModule(aMod1);
+ aMod.unload( );
+ aMod1.unload( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: load function should do the same thing as constructor with library name.",
+ bRes );
+ }
+
+ CPPUNIT_TEST_SUITE( load );
+ CPPUNIT_TEST( load_001 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class load
+
+ /** testing the method:
+ void SAL_CALL unload()
+ */
+ class unload : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ void unload_001( )
+ {
+ ::osl::Module aMod( getDllURL( ) );
+
+ aMod.unload( );
+ bRes = oslModule(aMod) ==nullptr;
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: unload function should do the same thing as destructor.",
+ bRes );
+ }
+
+ CPPUNIT_TEST_SUITE( unload );
+ CPPUNIT_TEST( unload_001 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class unload
+
+ /** testing the methods:
+ sal_Bool SAL_CALL is() const
+ */
+ class is : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ void is_001( )
+ {
+ OUString aFileURL;
+ bRes = osl::Module::getUrlFromAddress(
+ reinterpret_cast<oslGenericFunction>(
+ osl_Module::testClass::myFunc),
+ aFileURL);
+ if ( !bRes )
+ {
+ CPPUNIT_ASSERT_MESSAGE("Cannot locate current module - using executable instead", false );
+ }
+
+ ::osl::Module aMod;
+ bRes = aMod.is( );
+ aMod.load( aFileURL );
+ bRes1 = aMod.is( );
+ aMod.unload( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test if a module is a loaded module.",
+ !bRes );
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test if a module is a loaded module.",
+ bRes1 );
+ }
+ CPPUNIT_TEST_SUITE( is );
+ CPPUNIT_TEST( is_001 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class is
+
+ /** testing the methods:
+ void* SAL_CALL getSymbol( const OUString& strSymbolName)
+ */
+ class getSymbol : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes;
+
+ void getSymbol_001( )
+ {
+#if !defined( MACOSX )
+ // TODO: Find out why this fails on macOS
+ ::osl::Module aMod( getDllURL( ) );
+ FuncPtr pFunc = reinterpret_cast<FuncPtr>(aMod.getSymbol( "firstfunc" ));
+ bRes = false;
+ if ( pFunc )
+ bRes = pFunc( bRes );
+ aMod.unload();
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: load a dll and call one function in it.",
+ bRes );
+#endif
+ }
+
+ CPPUNIT_TEST_SUITE( getSymbol );
+ CPPUNIT_TEST( getSymbol_001 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class getSymbol
+
+ /** testing the methods:
+ operator oslModule() const
+ */
+ class optr_oslModule : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ void optr_oslModule_001( )
+ {
+#if !defined( MACOSX )
+ // TODO: Find out why this fails on macOS
+ ::osl::Module aMod;
+ bRes = ( static_cast<oslModule>(aMod) == nullptr );
+
+ aMod.load( getDllURL( ) );
+ bRes1 = static_cast<oslModule>(aMod) != nullptr;
+
+ aMod.unload( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: the m_Module of a Module instance will be NULL when is not loaded, it will not be NULL after loaded.",
+ bRes );
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: the m_Module of a Module instance will be NULL when is not loaded, it will not be NULL after loaded.",
+ bRes1 );
+#endif
+ }
+
+ void optr_oslModule_002( )
+ {
+#if !defined( MACOSX )
+ // TODO: Find out why this fails on macOS
+ ::osl::Module aMod( getDllURL( ) );
+ OUString funcName( "firstfunc" );
+
+ FuncPtr pFunc = reinterpret_cast<FuncPtr>(osl_getSymbol( static_cast<oslModule>(aMod), funcName.pData ));
+ bRes = false;
+ if ( pFunc )
+ bRes = pFunc( bRes );
+
+ aMod.unload();
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: use m_Module to call osl_getSymbol() function.",
+ bRes );
+#endif
+ }
+
+ CPPUNIT_TEST_SUITE( optr_oslModule );
+ CPPUNIT_TEST( optr_oslModule_001 );
+ CPPUNIT_TEST( optr_oslModule_002 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class optr_oslModule
+
+ /** testing the methods:
+ oslGenericFunction SAL_CALL getFunctionSymbol( const OUString& ustrFunctionSymbolName )
+ */
+ class getFunctionSymbol : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ void getFunctionSymbol_001( )
+ {
+#if !defined( MACOSX )
+ // TODO: Find out why this fails on macOS
+ ::osl::Module aMod( getDllURL( ) );
+ oslGenericFunction oslFunc = aMod.getFunctionSymbol( "firstfunc" );
+ OUString aLibraryURL;
+ bRes = ::osl::Module::getUrlFromAddress( oslFunc, aLibraryURL);
+ aMod.unload();
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: load a dll and get its function addr and get its URL.",
+ bRes );
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: load a dll and get its function addr and get its URL.",
+ aLibraryURL.equalsIgnoreAsciiCase( getDllURL() ) );
+#endif
+ }
+
+ CPPUNIT_TEST_SUITE( getFunctionSymbol );
+ CPPUNIT_TEST( getFunctionSymbol_001 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class getFunctionSymbol
+
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Module::ctors);
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Module::getUrlFromAddress);
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Module::load);
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Module::unload);
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Module::is);
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Module::getSymbol);
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Module::optr_oslModule);
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Module::getFunctionSymbol);
+
+} // namespace osl_Module
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/osl/module/osl_Module_Const.h b/sal/qa/osl/module/osl_Module_Const.h
new file mode 100644
index 000000000..3434d439f
--- /dev/null
+++ b/sal/qa/osl/module/osl_Module_Const.h
@@ -0,0 +1,46 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SAL_QA_OSL_MODULE_OSL_MODULE_CONST_H
+#define INCLUDED_SAL_QA_OSL_MODULE_OSL_MODULE_CONST_H
+
+#include <sal/types.h>
+#include <rtl/ustring.hxx>
+#include <osl/module.hxx>
+#include <osl/file.hxx>
+
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#if defined(UNX) // Unix
+# include <unistd.h>
+#elif defined(_WIN32) // Windows
+# include <io.h>
+#endif
+
+# define FILE_PREFIX "file:///"
+
+// function pointer type.
+
+typedef sal_Bool (* FuncPtr )( sal_Bool );
+
+#endif // INCLUDED_SAL_QA_OSL_MODULE_OSL_MODULE_CONST_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/osl/module/osl_Module_DLL.cxx b/sal/qa/osl/module/osl_Module_DLL.cxx
new file mode 100644
index 000000000..59f30b137
--- /dev/null
+++ b/sal/qa/osl/module/osl_Module_DLL.cxx
@@ -0,0 +1,32 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "osl_Module_Const.h"
+
+#include <stdio.h>
+#include <sal/types.h>
+
+// This module contains no tests. It is loaded as a dynamic library by
+// osl_Module.
+// But we instantiate a test plugin to fake the build process.
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+extern "C" SAL_DLLPUBLIC_EXPORT sal_Bool firstfunc(sal_Bool) { return true; }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/osl/mutex/osl_Mutex.cxx b/sal/qa/osl/mutex/osl_Mutex.cxx
new file mode 100644
index 000000000..3424bca07
--- /dev/null
+++ b/sal/qa/osl/mutex/osl_Mutex.cxx
@@ -0,0 +1,905 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+// include files
+
+#include <sal/types.h>
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+#include "osl_Mutex_Const.h"
+
+using namespace osl;
+
+/** pause nSec seconds helper function.
+*/
+namespace ThreadHelper
+{
+ static void thread_sleep_tenth_sec(sal_uInt32 _nTenthSec)
+ {
+ osl::Thread::wait(std::chrono::milliseconds(_nTenthSec * 100));
+ }
+ static void thread_sleep( sal_uInt32 _nSec )
+ {
+ /// print statement in thread process must use fflush() to force display.
+ // t_print("# wait %d seconds. ", _nSec );
+ fflush(stdout);
+
+ thread_sleep_tenth_sec( _nSec * 10 );
+ // printf("# done\n" );
+ }
+}
+
+// Beginning of the test cases for osl_Mutex class
+
+namespace {
+
+/** mutually exclusive data
+*/
+struct resource {
+ sal_Int32 data1;
+ sal_Int32 data2;
+ Mutex lock;
+};
+
+/** IncreaseThread provide data.
+*/
+class IncreaseThread : public Thread
+{
+public:
+ explicit IncreaseThread( struct resource *pData ): pResource( pData ) { }
+
+ virtual ~IncreaseThread( ) override
+ {
+ CPPUNIT_ASSERT_MESSAGE( "#IncreaseThread does not shutdown properly.\n", !isRunning( ) );
+ }
+protected:
+ struct resource *pResource;
+
+ void SAL_CALL run( ) override
+ {
+ pResource->lock.acquire( );
+ for( sal_Int8 i = 0; i < 3; i++ )
+ {
+ pResource->data1++;
+ yield( ); //yield() give CPU time to other thread, other thread if not block, they will change the data;
+ }
+ if ( pResource->data2 == 0 )
+ pResource->data2 = ( pResource->data1 > 0 ? pResource->data1 : 0 - pResource->data1 );
+ pResource->lock.release();
+ }
+};
+
+/** DecreaseThread consume data.
+*/
+class DecreaseThread : public Thread
+{
+public:
+ explicit DecreaseThread( struct resource *pData ): pResource( pData ) { }
+
+ virtual ~DecreaseThread( ) override
+ {
+ CPPUNIT_ASSERT_MESSAGE( "#DecreaseThread does not shutdown properly.\n", !isRunning( ) );
+ }
+protected:
+ struct resource *pResource;
+
+ void SAL_CALL run( ) override
+ {
+ pResource->lock.acquire( );
+ for( sal_Int8 i = 0; i < 3; i++ )
+ {
+ pResource->data1--;
+ yield( ); //yield() give CPU time to other thread, other thread if not block, they will change the data;
+ }
+ if ( pResource->data2 == 0 )
+ pResource->data2 = ( pResource->data1 > 0 ? pResource->data1 : 0 - pResource->data1 );
+ pResource->lock.release();
+ }
+};
+
+/** chain structure used in Threads as critical resource
+*/
+struct chain {
+ sal_Int32 buffer[ BUFFER_SIZE ];
+ Mutex lock;
+ sal_Int8 pos;
+};
+
+/** PutThread write to the chain structure in a mutex manner.
+*/
+class PutThread : public Thread
+{
+public:
+ //get the struct pointer to write data to buffer
+ explicit PutThread( struct chain* pData ): pChain( pData ) { }
+
+ virtual ~PutThread( ) override
+ {
+ CPPUNIT_ASSERT_MESSAGE( "#PutThread does not shutdown properly.\n", !isRunning( ) );
+ }
+protected:
+ struct chain* pChain;
+
+ void SAL_CALL run( ) override
+ {
+ //block here if the mutex has been acquired
+ pChain->lock.acquire( );
+
+ //current position in buffer to write
+ sal_Int8 nPos = pChain->pos;
+ oslThreadIdentifier oId = getIdentifier( );
+ //write data
+ sal_Int8 i;
+ for ( i = 0; i < 5; i++ )
+ {
+ pChain->buffer[ nPos + i ] = oId;
+ yield( );
+ }
+ //revise the position
+ pChain->pos = nPos + i;
+
+ //finish writing, release the mutex
+ pChain->lock.release();
+ }
+};
+
+/** thread for testing Mutex acquire.
+ */
+class HoldThread : public Thread
+{
+public:
+ //get the Mutex pointer to operate
+ explicit HoldThread( Mutex* pMutex ): pMyMutex( pMutex ) { }
+
+ virtual ~HoldThread( ) override
+ {
+ CPPUNIT_ASSERT_MESSAGE( "#HoldThread does not shutdown properly.\n", !isRunning( ) );
+ }
+protected:
+ Mutex* pMyMutex;
+
+ void SAL_CALL run() override
+ {
+ // block here if the mutex has been acquired
+ pMyMutex->acquire( );
+ printf("# Mutex acquired. \n" );
+ pMyMutex->release( );
+ }
+};
+
+class WaitThread : public Thread
+{
+public:
+ //get the Mutex pointer to operate
+ explicit WaitThread( Mutex* pMutex ): pMyMutex( pMutex ) { }
+
+ virtual ~WaitThread( ) override
+ {
+ CPPUNIT_ASSERT_MESSAGE( "#WaitThread does not shutdown properly.\n", !isRunning( ) );
+ }
+protected:
+ Mutex* pMyMutex;
+
+ void SAL_CALL run( ) override
+ {
+ // block here if the mutex has been acquired
+ pMyMutex->acquire( );
+ ThreadHelper::thread_sleep_tenth_sec( 2 );
+ pMyMutex->release( );
+ }
+};
+
+/** thread for testing getGlobalMutex.
+ */
+class GlobalMutexThread : public Thread
+{
+public:
+ //get the Mutex pointer to operate
+ GlobalMutexThread( ){ }
+
+ virtual ~GlobalMutexThread( ) override
+ {
+ CPPUNIT_ASSERT_MESSAGE( "#GlobalMutexThread does not shutdown properly.\n", !isRunning( ) );
+ }
+protected:
+ void SAL_CALL run( ) override
+ {
+ // block here if the mutex has been acquired
+ Mutex* pGlobalMutex;
+ pGlobalMutex = Mutex::getGlobalMutex( );
+ pGlobalMutex->acquire( );
+ printf("# Global Mutex acquired. \n" );
+ pGlobalMutex->release( );
+ }
+};
+
+}
+
+namespace osl_Mutex
+{
+
+ /** Test of the osl::Mutex::constructor
+ */
+ class ctor : public CppUnit::TestFixture
+ {
+ public:
+ // initialise your test code values here.
+ struct chain m_Data;
+ struct resource m_Res;
+
+ void setUp( ) override
+ {
+ for ( sal_Int8 i=0; i < BUFFER_SIZE; i++ )
+ m_Data.buffer[i] = 0;
+ m_Data.pos = 0;
+
+ m_Res.data1 = 0;
+ m_Res.data2 = 0;
+ }
+
+ /** Create two threads to write data to the same buffer, use Mutex to assure
+ during one thread write data five times, the other thread should not begin writing.
+ the two threads wrote two different data: their thread ID, so we can check the data
+ in buffer to know the order of the two threads writing
+ */
+ void ctor_001()
+ {
+ PutThread myThread1( &m_Data );
+ PutThread myThread2( &m_Data );
+
+ myThread1.create( );
+ myThread2.create( );
+
+ //wait until the two threads terminate
+ myThread1.join( );
+ myThread2.join( );
+
+ bool bRes = false;
+
+ // every 5 data should the same
+ // LLA: this is not a good check, it's too fix
+ if (m_Data.buffer[0] == m_Data.buffer[1] &&
+ m_Data.buffer[1] == m_Data.buffer[2] &&
+ m_Data.buffer[2] == m_Data.buffer[3] &&
+ m_Data.buffer[3] == m_Data.buffer[4] &&
+ m_Data.buffer[5] == m_Data.buffer[6] &&
+ m_Data.buffer[6] == m_Data.buffer[7] &&
+ m_Data.buffer[7] == m_Data.buffer[8] &&
+ m_Data.buffer[8] == m_Data.buffer[9])
+ bRes = true;
+
+ /*for (sal_Int8 i=0; i<BUFFER_SIZE; i++)
+ printf("#data in buffer is %d\n", m_Data.buffer[i]);
+ */
+
+ CPPUNIT_ASSERT_MESSAGE("Mutex ctor", bRes);
+
+ }
+
+ /** Create two threads to write data to operate on the same number , use Mutex to assure,
+ one thread increase data 3 times, the other thread decrease 3 times, store the operate
+ result when the first thread complete, if it is interrupt by the other thread, the stored
+ number will not be 3.
+ */
+ void ctor_002()
+ {
+ IncreaseThread myThread1( &m_Res );
+ DecreaseThread myThread2( &m_Res );
+
+ myThread1.create( );
+ myThread2.create( );
+
+ //wait until the two threads terminate
+ myThread1.join( );
+ myThread2.join( );
+
+ bool bRes = false;
+
+ // every 5 data should the same
+ if ( ( m_Res.data1 == 0 ) && ( m_Res.data2 == 3 ) )
+ bRes = true;
+
+ CPPUNIT_ASSERT_MESSAGE( "test Mutex ctor function: increase and decrease a number 3 times without interrupt.", bRes );
+ }
+
+ CPPUNIT_TEST_SUITE( ctor );
+ CPPUNIT_TEST( ctor_001 );
+ CPPUNIT_TEST( ctor_002 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class ctor
+
+ /** Test of the osl::Mutex::acquire method
+ */
+ class acquire : public CppUnit::TestFixture
+ {
+ public:
+ // acquire mutex in main thread, and then call acquire again in myThread,
+ // the child thread should block, wait 2 secs, it still block.
+ // Then release mutex in main thread, the child thread could return from acquire,
+ // and go to exec next statement, so could terminate quickly.
+ void acquire_001( )
+ {
+ Mutex aMutex;
+ //acquire here
+ bool bRes = aMutex.acquire( );
+ // pass the pointer of mutex to child thread
+ HoldThread myThread( &aMutex );
+ myThread.create( );
+
+ ThreadHelper::thread_sleep_tenth_sec( 2 );
+ // if acquire in myThread does not work, 2 secs is long enough,
+ // myThread should terminate now, and bRes1 should be sal_False
+ bool bRes1 = myThread.isRunning( );
+
+ aMutex.release( );
+ ThreadHelper::thread_sleep_tenth_sec( 1 );
+ // after release mutex, myThread stops blocking and will terminate immediately
+ bool bRes2 = myThread.isRunning( );
+ myThread.join( );
+
+ CPPUNIT_ASSERT_MESSAGE( "Mutex acquire", bRes );
+ CPPUNIT_ASSERT_MESSAGE( "Mutex acquire", bRes1 );
+ CPPUNIT_ASSERT_MESSAGE( "Mutex acquire", !bRes2 );
+ }
+
+ //in the same thread, acquire twice should success
+ void acquire_002()
+ {
+ Mutex aMutex;
+ //acquire here
+ bool bRes = aMutex.acquire();
+ bool bRes1 = aMutex.acquire();
+
+ bool bRes2 = aMutex.tryToAcquire();
+
+ aMutex.release();
+
+ CPPUNIT_ASSERT_MESSAGE("Mutex acquire", bRes);
+ CPPUNIT_ASSERT_MESSAGE("Mutex acquire", bRes1);
+ CPPUNIT_ASSERT_MESSAGE("Mutex acquire", bRes2);
+
+ }
+
+ CPPUNIT_TEST_SUITE( acquire );
+ CPPUNIT_TEST( acquire_001 );
+ CPPUNIT_TEST( acquire_002 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class acquire
+
+ /** Test of the osl::Mutex::tryToAcquire method
+ */
+ class tryToAcquire : public CppUnit::TestFixture
+ {
+ public:
+ // First let child thread acquire the mutex, and wait 2 secs, during the 2 secs,
+ // in main thread, tryToAcquire mutex should return False
+ // then after the child thread terminated, tryToAcquire should return True
+ void tryToAcquire_001()
+ {
+ Mutex aMutex;
+ WaitThread myThread(&aMutex);
+ myThread.create();
+
+ // ensure the child thread acquire the mutex
+ ThreadHelper::thread_sleep_tenth_sec(1);
+
+ bool bRes1 = aMutex.tryToAcquire();
+
+ if (bRes1)
+ aMutex.release();
+ // wait the child thread terminate
+ myThread.join();
+
+ bool bRes2 = aMutex.tryToAcquire();
+
+ if (bRes2)
+ aMutex.release();
+
+ CPPUNIT_ASSERT_MESSAGE("Try to acquire Mutex", !bRes1);
+ CPPUNIT_ASSERT_MESSAGE("Try to acquire Mutex", bRes2);
+ }
+
+ CPPUNIT_TEST_SUITE(tryToAcquire);
+ CPPUNIT_TEST(tryToAcquire_001);
+ CPPUNIT_TEST_SUITE_END();
+ }; // class tryToAcquire
+
+ /** Test of the osl::Mutex::release method
+ */
+ class release : public CppUnit::TestFixture
+ {
+ public:
+ /** acquire/release are not used in pairs: after child thread acquired mutex,
+ the main thread release it, then any thread could acquire it.
+ */
+ void release_001()
+ {
+ Mutex aMutex;
+ WaitThread myThread( &aMutex );
+ myThread.create( );
+
+ // ensure the child thread acquire the mutex
+ ThreadHelper::thread_sleep_tenth_sec( 1 );
+
+ bool bRunning = myThread.isRunning( );
+ bool bRes1 = aMutex.tryToAcquire( );
+ // wait the child thread terminate
+ myThread.join( );
+
+ bool bRes2 = aMutex.tryToAcquire( );
+
+ if ( bRes2 )
+ aMutex.release( );
+
+ CPPUNIT_ASSERT_MESSAGE( "release Mutex: try to acquire before and after the mutex has been released",
+ !bRes1 );
+ CPPUNIT_ASSERT_MESSAGE( "release Mutex: try to acquire before and after the mutex has been released",
+ bRes2 );
+ CPPUNIT_ASSERT_MESSAGE( "release Mutex: try to acquire before and after the mutex has been released",
+ bRunning );
+
+ }
+
+ // how about release twice?
+ void release_002()
+ {
+ }
+
+ CPPUNIT_TEST_SUITE( release );
+ CPPUNIT_TEST( release_001 );
+ CPPUNIT_TEST( release_002 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class release
+
+ /** Test of the osl::Mutex::getGlobalMutex method
+ */
+ class getGlobalMutex : public CppUnit::TestFixture
+ {
+ public:
+ // initialise your test code values here.
+ void getGlobalMutex_001()
+ {
+ Mutex* pGlobalMutex;
+ pGlobalMutex = Mutex::getGlobalMutex();
+ pGlobalMutex->acquire();
+
+ GlobalMutexThread myThread;
+ myThread.create();
+
+ ThreadHelper::thread_sleep_tenth_sec(1);
+ bool bRes1 = myThread.isRunning();
+
+ pGlobalMutex->release();
+ ThreadHelper::thread_sleep_tenth_sec(1);
+ // after release mutex, myThread stops blocking and will terminate immediately
+ bool bRes2 = myThread.isRunning();
+
+ CPPUNIT_ASSERT_MESSAGE("Global Mutex works", bRes1);
+ CPPUNIT_ASSERT_MESSAGE("Global Mutex works", !bRes2);
+ }
+
+ void getGlobalMutex_002( )
+ {
+ bool bRes;
+
+ Mutex *pGlobalMutex;
+ pGlobalMutex = Mutex::getGlobalMutex( );
+ pGlobalMutex->acquire( );
+ {
+ Mutex *pGlobalMutex1;
+ pGlobalMutex1 = Mutex::getGlobalMutex( );
+ bRes = pGlobalMutex1->release( );
+ }
+
+ CPPUNIT_ASSERT_MESSAGE( "Global Mutex works: if the code between {} get the different mutex as the former one, it will return false when release.",
+ bRes );
+ }
+
+ CPPUNIT_TEST_SUITE(getGlobalMutex);
+ CPPUNIT_TEST(getGlobalMutex_001);
+ CPPUNIT_TEST(getGlobalMutex_002);
+ CPPUNIT_TEST_SUITE_END();
+ }; // class getGlobalMutex
+
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Mutex::ctor, "osl_Mutex");
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Mutex::acquire, "osl_Mutex");
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Mutex::tryToAcquire, "osl_Mutex");
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Mutex::release, "osl_Mutex");
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Mutex::getGlobalMutex, "osl_Mutex");
+} // namespace osl_Mutex
+
+// Beginning of the test cases for osl_Guard class
+
+namespace {
+
+class GuardThread : public Thread
+{
+public:
+ //get the Mutex pointer to operate
+ explicit GuardThread( Mutex* pMutex ): pMyMutex( pMutex ) { }
+
+ virtual ~GuardThread( ) override
+ {
+ CPPUNIT_ASSERT_MESSAGE( "#GuardThread does not shutdown properly.\n", !isRunning( ) );
+ }
+protected:
+ Mutex* pMyMutex;
+
+ void SAL_CALL run( ) override
+ {
+ // block here if the mutex has been acquired
+ MutexGuard aGuard( pMyMutex );
+ ThreadHelper::thread_sleep_tenth_sec( 2 );
+ }
+};
+
+}
+
+namespace osl_Guard
+{
+ class ctor : public CppUnit::TestFixture
+ {
+ public:
+ // insert your test code here.
+ void ctor_001()
+ {
+ Mutex aMutex;
+ GuardThread myThread(&aMutex);
+ myThread.create();
+
+ ThreadHelper::thread_sleep_tenth_sec(1);
+ bool bRes = aMutex.tryToAcquire();
+ // after 1 second, the mutex has been guarded, and the child thread should be running
+ bool bRes1 = myThread.isRunning();
+
+ myThread.join();
+ bool bRes2 = aMutex.tryToAcquire();
+
+ CPPUNIT_ASSERT_MESSAGE("GuardThread constructor",
+ !bRes);
+ CPPUNIT_ASSERT_MESSAGE("GuardThread constructor",
+ bRes1);
+ CPPUNIT_ASSERT_MESSAGE("GuardThread constructor",
+ bRes2);
+ }
+
+ void ctor_002( )
+ {
+ Mutex aMutex;
+
+ /// use reference constructor here
+ MutexGuard myGuard( aMutex );
+
+ /// the GuardThread will block here when it is initialised.
+ GuardThread myThread( &aMutex );
+ myThread.create( );
+
+ /// is it still blocking?
+ ThreadHelper::thread_sleep_tenth_sec( 2 );
+ bool bRes = myThread.isRunning( );
+
+ /// oh, release him.
+ aMutex.release( );
+ myThread.join( );
+
+ CPPUNIT_ASSERT_MESSAGE("GuardThread constructor: reference initialization, acquire the mutex before running the thread, then check if it is blocking.",
+ bRes);
+ }
+
+ CPPUNIT_TEST_SUITE(ctor);
+ CPPUNIT_TEST(ctor_001);
+ CPPUNIT_TEST(ctor_002);
+ CPPUNIT_TEST_SUITE_END();
+ }; // class ctor
+
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Guard::ctor, "osl_Guard");
+} // namespace osl_Guard
+
+// Beginning of the test cases for osl_ClearableGuard class
+
+namespace {
+
+/** Thread for test ClearableGuard
+ */
+class ClearGuardThread : public Thread
+{
+public:
+ //get the Mutex pointer to operate
+ explicit ClearGuardThread( Mutex* pMutex ): pMyMutex( pMutex ) {}
+
+ virtual ~ClearGuardThread( ) override
+ {
+ CPPUNIT_ASSERT_MESSAGE( "#ClearGuardThread does not shutdown properly.\n", !isRunning( ) );
+ }
+protected:
+ Mutex* pMyMutex;
+
+ void SAL_CALL run( ) override
+ {
+ // acquire the mutex
+ // printf("# ClearGuardThread" );
+ ClearableMutexGuard aGuard( pMyMutex );
+ ThreadHelper::thread_sleep( 5 );
+
+ // release the mutex
+ aGuard.clear( );
+ ThreadHelper::thread_sleep( 2 );
+ }
+};
+
+}
+
+namespace osl_ClearableGuard
+{
+
+ class ctor : public CppUnit::TestFixture
+ {
+ public:
+ void ctor_001()
+ {
+ Mutex aMutex;
+
+ /// now, the aMutex has been guarded.
+ ClearableMutexGuard myMutexGuard( &aMutex );
+
+ /// it will return sal_False if the aMutex has not been Guarded.
+ bool bRes = aMutex.release( );
+
+ CPPUNIT_ASSERT_MESSAGE("ClearableMutexGuard constructor, test the acquire operation when initialized.",
+ bRes);
+ }
+
+ void ctor_002( )
+ {
+ Mutex aMutex;
+
+ /// now, the aMutex has been guarded, this time, we use reference constructor.
+ ClearableMutexGuard myMutexGuard( aMutex );
+
+ /// it will return sal_False if the aMutex has not been Guarded.
+ bool bRes = aMutex.release( );
+
+ CPPUNIT_ASSERT_MESSAGE("ClearableMutexGuard constructor, test the acquire operation when initialized, we use reference constructor this time.",
+ bRes);
+ }
+
+ CPPUNIT_TEST_SUITE(ctor);
+ CPPUNIT_TEST(ctor_001);
+ CPPUNIT_TEST(ctor_002);
+ CPPUNIT_TEST_SUITE_END();
+ }; // class ctor
+
+ class clear : public CppUnit::TestFixture
+ {
+ public:
+ void clear_001()
+ {
+ Mutex aMutex;
+ ClearGuardThread myThread(&aMutex);
+ myThread.create();
+
+ TimeValue aTimeVal_befor;
+ osl_getSystemTime( &aTimeVal_befor );
+ // wait 1 second to assure the child thread has begun
+ ThreadHelper::thread_sleep(1);
+
+ while (true)
+ {
+ if (aMutex.tryToAcquire())
+ {
+ break;
+ }
+ ThreadHelper::thread_sleep(1);
+ }
+ TimeValue aTimeVal_after;
+ osl_getSystemTime( &aTimeVal_after );
+ sal_Int32 nSec = aTimeVal_after.Seconds - aTimeVal_befor.Seconds;
+ printf("nSec is %" SAL_PRIdINT32 "\n", nSec);
+
+ myThread.join();
+
+ CPPUNIT_ASSERT_MESSAGE("ClearableGuard method: clear",
+ nSec < 7);
+ CPPUNIT_ASSERT_MESSAGE("ClearableGuard method: clear",
+ nSec > 1);
+ }
+
+ void clear_002( )
+ {
+ Mutex aMutex;
+
+ /// now, the aMutex has been guarded.
+ ClearableMutexGuard myMutexGuard( &aMutex );
+
+ /// launch the HoldThread, it will be blocked here.
+ HoldThread myThread( &aMutex );
+ myThread.create( );
+
+ /// is it blocking?
+ ThreadHelper::thread_sleep_tenth_sec( 4 );
+ bool bRes = myThread.isRunning( );
+
+ /// use clear to release.
+ myMutexGuard.clear( );
+ myThread.join( );
+ bool bRes1 = myThread.isRunning( );
+
+ CPPUNIT_ASSERT_MESSAGE( "ClearableGuard method: clear, control the HoldThread's running status!",
+ bRes );
+ CPPUNIT_ASSERT_MESSAGE( "ClearableGuard method: clear, control the HoldThread's running status!",
+ !bRes1 );
+ }
+
+ CPPUNIT_TEST_SUITE( clear );
+ CPPUNIT_TEST( clear_001 );
+ CPPUNIT_TEST( clear_002 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class clear
+
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( osl_ClearableGuard::ctor, "osl_ClearableGuard" );
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( osl_ClearableGuard::clear, "osl_ClearableGuard" );
+} // namespace osl_ClearableGuard
+
+// Beginning of the test cases for osl_ResettableGuard class
+
+namespace {
+
+/** Thread for test ResettableGuard
+ */
+class ResetGuardThread : public Thread
+{
+public:
+ //get the Mutex pointer to operate
+ explicit ResetGuardThread( Mutex* pMutex ): pMyMutex( pMutex ) {}
+
+ virtual ~ResetGuardThread( ) override
+ {
+ CPPUNIT_ASSERT_MESSAGE( "#ResetGuardThread does not shutdown properly.\n", !isRunning( ) );
+ }
+protected:
+ Mutex* pMyMutex;
+
+ void SAL_CALL run( ) override
+ {
+ // acquire the mutex
+ printf("# ResettableGuard\n" );
+ ResettableMutexGuard aGuard( pMyMutex );
+ // release the mutex
+ aGuard.clear( );
+ ThreadHelper::thread_sleep_tenth_sec( 2 );
+ }
+};
+
+}
+
+namespace osl_ResettableGuard
+{
+ class ctor : public CppUnit::TestFixture
+ {
+ public:
+ void ctor_001()
+ {
+ Mutex aMutex;
+
+ /// now, the aMutex has been guarded.
+ ResettableMutexGuard myMutexGuard( &aMutex );
+
+ /// it will return sal_False if the aMutex has not been Guarded.
+ bool bRes = aMutex.release( );
+
+ CPPUNIT_ASSERT_MESSAGE("ResettableMutexGuard constructor, test the acquire operation when initialized.",
+ bRes);
+
+ aMutex.acquire();
+ }
+
+ void ctor_002( )
+ {
+ Mutex aMutex;
+
+ /// now, the aMutex has been guarded, this time, we use reference constructor.
+ ResettableMutexGuard myMutexGuard( aMutex );
+
+ /// it will return sal_False if the aMutex has not been Guarded.
+ bool bRes = aMutex.release( );
+
+ CPPUNIT_ASSERT_MESSAGE( "ResettableMutexGuard constructor, test the acquire operation when initialized, we use reference constructor this time.",
+ bRes);
+
+ aMutex.acquire();
+ }
+
+ CPPUNIT_TEST_SUITE(ctor);
+ CPPUNIT_TEST(ctor_001);
+ CPPUNIT_TEST(ctor_002);
+ CPPUNIT_TEST_SUITE_END();
+ }; // class ctor
+
+ class reset : public CppUnit::TestFixture
+ {
+ public:
+ void reset_001( )
+ {
+ Mutex aMutex;
+ ResetGuardThread myThread( &aMutex );
+ ResettableMutexGuard myMutexGuard( aMutex );
+ myThread.create( );
+
+ /// is it running? and clear done?
+ bool bRes = myThread.isRunning( );
+ myMutexGuard.clear( );
+ ThreadHelper::thread_sleep_tenth_sec( 1 );
+
+ /// if reset is not success, the release will return sal_False
+ myMutexGuard.reset( );
+ bool bRes1 = aMutex.release( );
+ myThread.join( );
+
+ CPPUNIT_ASSERT_MESSAGE( "ResettableMutexGuard method: reset",
+ bRes );
+ CPPUNIT_ASSERT_MESSAGE( "ResettableMutexGuard method: reset",
+ bRes1 );
+
+ aMutex.acquire();
+ }
+
+#ifdef LINUX
+ void reset_002( )
+ {
+ Mutex aMutex;
+ ResettableMutexGuard myMutexGuard( &aMutex );
+
+ /// shouldn't release after clear;
+ myMutexGuard.clear( );
+ aMutex.acquire();
+ bool bRes = aMutex.release( );
+
+ /// can release after reset.
+ myMutexGuard.reset( );
+ bool bRes1 = aMutex.release( );
+
+ CPPUNIT_ASSERT_MESSAGE( "ResettableMutexGuard method: reset, release after clear and reset, on Solaris, the mutex can be release without acquire, so it can not passed on (SOLARIS), but not the reason for reset_002",
+ bRes );
+ CPPUNIT_ASSERT_MESSAGE( "ResettableMutexGuard method: reset, release after clear and reset, on Solaris, the mutex can be release without acquire, so it can not passed on (SOLARIS), but not the reason for reset_002",
+ bRes1 );
+
+ aMutex.acquire();
+ }
+#endif
+
+ CPPUNIT_TEST_SUITE(reset);
+ CPPUNIT_TEST(reset_001);
+#ifdef LINUX
+ CPPUNIT_TEST(reset_002);
+#endif
+ CPPUNIT_TEST_SUITE_END();
+ }; // class reset
+
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_ResettableGuard::ctor);
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_ResettableGuard::reset);
+} // namespace osl_ResettableGuard
+
+// The following sets variables for GNU EMACS
+// Local Variables:
+// tab-width:4
+// End:
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/osl/mutex/osl_Mutex_Const.h b/sal/qa/osl/mutex/osl_Mutex_Const.h
new file mode 100644
index 000000000..a5ac53ed4
--- /dev/null
+++ b/sal/qa/osl/mutex/osl_Mutex_Const.h
@@ -0,0 +1,37 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SAL_QA_OSL_MUTEX_OSL_MUTEX_CONST_H
+#define INCLUDED_SAL_QA_OSL_MUTEX_OSL_MUTEX_CONST_H
+
+#include <sal/types.h>
+#include <rtl/ustring.hxx>
+#include <osl/thread.hxx>
+#include <osl/mutex.hxx>
+#include <osl/time.h>
+
+#ifdef UNX
+#include <unistd.h>
+#endif
+
+#define BUFFER_SIZE 16
+
+#endif // INCLUDED_SAL_QA_OSL_MUTEX_OSL_MUTEX_CONST_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/osl/pipe/osl_Pipe.cxx b/sal/qa/osl/pipe/osl_Pipe.cxx
new file mode 100644
index 000000000..eef77e998
--- /dev/null
+++ b/sal/qa/osl/pipe/osl_Pipe.cxx
@@ -0,0 +1,894 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+// include files
+
+#include <sal/types.h>
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+#include <rtl/ustring.hxx>
+
+#include <osl/test/uniquepipename.hxx>
+#include <osl/thread.hxx>
+
+#include <osl/pipe.hxx>
+#include <osl/time.h>
+
+#ifdef UNX
+#include <unistd.h>
+#endif
+#include <string.h>
+
+using namespace osl;
+
+/** print last error of pipe system.
+ */
+static void printPipeError( ::osl::Pipe const & aPipe )
+{
+ oslPipeError nError = aPipe.getError( );
+ printf("#printPipeError# " );
+ switch ( nError ) {
+ case osl_Pipe_E_None:
+ printf("Success!\n" );
+ break;
+ case osl_Pipe_E_NotFound:
+ printf("The returned error is: Not found!\n" );
+ break;
+ case osl_Pipe_E_AlreadyExists:
+ printf("The returned error is: Already exist!\n" );
+ break;
+ case osl_Pipe_E_NoProtocol:
+ printf("The returned error is: No protocol!\n" );
+ break;
+ case osl_Pipe_E_NetworkReset:
+ printf("The returned error is: Network reset!\n" );
+ break;
+ case osl_Pipe_E_ConnectionAbort:
+ printf("The returned error is: Connection aborted!\n" );
+ break;
+ case osl_Pipe_E_ConnectionReset:
+ printf("The returned error is: Connection reset!\n" );
+ break;
+ case osl_Pipe_E_NoBufferSpace:
+ printf("The returned error is: No buffer space!\n" );
+ break;
+ case osl_Pipe_E_TimedOut:
+ printf("The returned error is: Timeout!\n" );
+ break;
+ case osl_Pipe_E_ConnectionRefused:
+ printf("The returned error is: Connection refused!\n" );
+ break;
+ case osl_Pipe_E_invalidError:
+ printf("The returned error is: Invalid error!\n" );
+ break;
+ default:
+ printf("The returned error is: Number %d, Unknown Error\n", nError );
+ break;
+ }
+}
+
+// pipe name and transfer contents
+
+constexpr OUStringLiteral aTestPipeName(u"testpipe2");
+constexpr OUStringLiteral aTestPipe1(u"testpipe1");
+
+constexpr OStringLiteral m_pTestString1("Sun Microsystems");
+constexpr OStringLiteral m_pTestString2("test pipe PASS/OK");
+
+// test code start here
+
+namespace osl_Pipe
+{
+
+// most return value -1 denote a fail of operation.
+
+#define OSL_PIPE_FAIL -1
+
+ /** testing the methods:
+ inline Pipe();
+ inline Pipe(const OUString& strName, oslPipeOptions Options);
+ inline Pipe(const OUString& strName, oslPipeOptions Options,const Security & rSecurity);
+ inline Pipe(const Pipe& pipe);
+ inline Pipe(oslPipe pipe, __sal_NoAcquire noacquire );
+ inline Pipe(oslPipe Pipe);
+ */
+ class ctors : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1, bRes2;
+
+ void ctors_none( )
+ {
+ ::osl::Pipe aPipe;
+ bRes = aPipe.is( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test constructor with no parameter, yet no case to test.",
+ !bRes );
+ }
+
+ void ctors_name_option( )
+ {
+ /// create a named pipe.
+ ::osl::Pipe aPipe( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE );
+ ::osl::Pipe aAssignPipe( test::uniquePipeName(aTestPipeName), osl_Pipe_OPEN );
+
+ bRes = aPipe.is( ) && aAssignPipe.is( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test constructor with name and option.",
+ bRes );
+ }
+
+ void ctors_name_option_security( )
+ {
+ /// create a security pipe.
+ const ::osl::Security rSecurity;
+ ::osl::Pipe aSecurityPipe( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE, rSecurity );
+
+ bRes = aSecurityPipe.is( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test constructor with name, option and security, the test of security is not implemented yet.",
+ bRes );
+ }
+
+ void ctors_copy( )
+ {
+ /// create a pipe.
+ ::osl::Pipe aPipe( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE );
+ /// create a pipe using copy constructor.
+ ::osl::Pipe aCopyPipe( aPipe );
+
+ bRes = aCopyPipe.is( ) && aCopyPipe == aPipe;
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test copy constructor.",
+ bRes );
+ }
+
+ /* Note: DO NOT DO THIS - I have very deliberately caused send to FAIL, *on purpose* as this is the
+ only sane way to test noacquire. This is a terrible misuse of no-acquire, but in this case is
+ needed only so we can test to make sure no-acquire is working!
+ */
+ void ctors_no_acquire( )
+ {
+ /// create a pipe.
+ OUString aPipeName(test::uniquePipeName(aTestPipeName));
+ oslPipe handle(osl_createPipe(aPipeName.pData, osl_Pipe_CREATE, nullptr));
+ /// constructs a pipe reference without acquiring the handle.
+ std::unique_ptr<osl::Pipe> xNoAcquirePipe(new osl::Pipe(handle, SAL_NO_ACQUIRE));
+
+ StreamPipe aStreamPipe(handle);
+ xNoAcquirePipe.reset();
+ int nRet = aStreamPipe.send("a", 1);
+
+ if (nRet >= 0)
+ bRes = false;
+ else
+ bRes = true;
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test constructor with no acquire of handle, deleted nonacquired pipe but could still send on original pipe!.",
+ bRes );
+ }
+
+ void ctors_acquire( )
+ {
+ /// create a base pipe.
+ ::osl::Pipe aPipe( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE );
+ /// constructs two pipes, the second acquires the first pipe's handle.
+ ::osl::Pipe aAcquirePipe( aPipe.getHandle( ) );
+ ::osl::Pipe aAcquirePipe1( nullptr );
+
+ bRes = aAcquirePipe.is();
+ bRes1 = aAcquirePipe1.is();
+ bRes2 = aPipe == aAcquirePipe;
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test constructor with acquire of handle, original pipe does not exist.",
+ bRes );
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test constructor with acquire of handle, copied pipe does not exist",
+ !bRes1 );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test pipes should have same handle", bRes2);
+ }
+
+ CPPUNIT_TEST_SUITE( ctors );
+ CPPUNIT_TEST( ctors_none );
+ CPPUNIT_TEST( ctors_name_option );
+ CPPUNIT_TEST( ctors_name_option_security );
+ CPPUNIT_TEST( ctors_copy );
+ CPPUNIT_TEST( ctors_no_acquire );
+ CPPUNIT_TEST( ctors_acquire );
+ CPPUNIT_TEST_SUITE_END( );
+ };
+
+ /** testing the method:
+ inline sal_Bool SAL_CALL is() const;
+ */
+ class is : public CppUnit::TestFixture
+ {
+ public:
+ void is_001( )
+ {
+ ::osl::Pipe aPipe;
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test is(), check if the pipe is a valid one.", !aPipe.is( ) );
+ }
+
+ void is_002( )
+ {
+ ::osl::Pipe aPipe( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test is(), a normal pipe creation.", aPipe.is( ) );
+ }
+
+ void is_003( )
+ {
+ ::osl::Pipe aPipe( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE );
+ aPipe.clear( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test is(), an invalid case.", !aPipe.is( ) );
+ }
+
+ void is_004( )
+ {
+ ::osl::Pipe aPipe( nullptr );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test is(), an invalid constructor.", !aPipe.is( ) );
+ }
+
+ CPPUNIT_TEST_SUITE( is );
+ CPPUNIT_TEST( is_001 );
+ CPPUNIT_TEST( is_002 );
+ CPPUNIT_TEST( is_003 );
+ CPPUNIT_TEST( is_004 );
+ CPPUNIT_TEST_SUITE_END( );
+ };
+
+ /** testing the methods:
+ inline sal_Bool create( const OUString & strName,
+ oslPipeOptions Options, const Security &rSec );
+ nline sal_Bool create( const OUString & strName,
+ oslPipeOptions Options = osl_Pipe_OPEN );
+ */
+ class create : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ /** tester comment:
+
+ security create only be tested creation, security section is
+ untested yet.
+ */
+
+ void create_named_security_001( )
+ {
+ const Security rSec;
+ ::osl::Pipe aPipe;
+ bRes = aPipe.create( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE, rSec );
+ bRes1 = aPipe.create( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE, rSec );
+ aPipe.clear( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test creation.",
+ bRes);
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test creation.",
+ !bRes1);
+ }
+
+ void create_named_security_002( )
+ {
+ const Security rSec;
+ ::osl::Pipe aPipe, aPipe1;
+ bRes = aPipe.create( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE, rSec );
+ bRes1 = aPipe1.create( test::uniquePipeName(aTestPipeName), osl_Pipe_OPEN, rSec );
+ aPipe.clear( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test creation and open.",
+ bRes);
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test creation and open.",
+ bRes1);
+ }
+
+ void create_named_001( )
+ {
+ ::osl::Pipe aPipe;
+ bRes = aPipe.create( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE );
+ bRes1 = aPipe.create( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE );
+ aPipe.clear( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test creation.",
+ bRes);
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test creation.",
+ !bRes1);
+ }
+
+ void create_named_002( )
+ {
+ ::osl::Pipe aPipe, aPipe1;
+ bRes = aPipe.create( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE );
+ bRes1 = aPipe1.create( test::uniquePipeName(aTestPipeName) );
+ aPipe.clear( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test creation and open.",
+ bRes);
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test creation and open.",
+ bRes1);
+ }
+
+ void create_named_003( )
+ {
+ ::osl::Pipe aPipe;
+ bRes = aPipe.create( test::uniquePipeName(aTestPipeName) );
+ aPipe.clear( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test default option is open.",
+ !bRes );
+ }
+
+ CPPUNIT_TEST_SUITE( create );
+ CPPUNIT_TEST( create_named_security_001 );
+ CPPUNIT_TEST( create_named_security_002 );
+ CPPUNIT_TEST( create_named_001 );
+ CPPUNIT_TEST( create_named_002 );
+ CPPUNIT_TEST( create_named_003 );
+ CPPUNIT_TEST_SUITE_END( );
+ };
+
+ /** testing the method:
+ inline void SAL_CALL clear();
+ */
+ class clear : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ void clear_001( )
+ {
+ ::osl::Pipe aPipe;
+ aPipe.create( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE );
+ aPipe.clear( );
+ bRes = aPipe.is( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test clear.",
+ !bRes );
+ }
+
+ CPPUNIT_TEST_SUITE( clear );
+ CPPUNIT_TEST( clear_001 );
+ CPPUNIT_TEST_SUITE_END( );
+ };
+
+ /** testing the methods:
+ inline Pipe& SAL_CALL operator= (const Pipe& pipe);
+ inline Pipe& SAL_CALL operator= (const oslPipe pipe );
+ */
+ class assign : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ void assign_ref( )
+ {
+ ::osl::Pipe aPipe, aPipe1;
+ aPipe.create( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE );
+ aPipe1 = aPipe;
+ bRes = aPipe1.is( );
+ bRes1 = aPipe == aPipe1;
+ aPipe.close( );
+ aPipe1.close( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test assign with reference.",
+ bRes );
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test assign with reference.",
+ bRes1 );
+ }
+
+ void assign_handle( )
+ {
+ ::osl::Pipe aPipe, aPipe1;
+ aPipe.create( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE );
+ aPipe1 = aPipe.getHandle( );
+ bRes = aPipe1.is( );
+ bRes1 = aPipe == aPipe1;
+ aPipe.close( );
+ aPipe1.close( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test assign with handle.",
+ bRes );
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test assign with handle.",
+ bRes1 );
+ }
+
+ CPPUNIT_TEST_SUITE( assign );
+ CPPUNIT_TEST( assign_ref );
+ CPPUNIT_TEST( assign_handle );
+ CPPUNIT_TEST_SUITE_END( );
+ };
+
+ /** testing the method:
+ inline sal_Bool SAL_CALL isValid() const;
+ isValid( ) has not been implemented under the following platforms, please refer to osl/pipe.hxx
+ */
+
+ /** testing the method:
+ inline sal_Bool SAL_CALL operator==( const Pipe& rPipe ) const;
+ */
+ class isEqual : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ void isEqual_001( )
+ {
+ ::osl::Pipe aPipe;
+ aPipe.create( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE );
+ bRes = aPipe == aPipe; // NOLINT(misc-redundant-expression)
+ aPipe.close( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test isEqual(), compare itself.",
+ bRes );
+ }
+
+ void isEqual_002( )
+ {
+ ::osl::Pipe aPipe, aPipe1, aPipe2;
+ aPipe.create( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE );
+
+ aPipe1 = aPipe;
+ aPipe2.create( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE );
+
+ bRes = aPipe == aPipe1;
+ bRes1 = aPipe == aPipe2;
+ aPipe.close( );
+ aPipe1.close( );
+ aPipe2.close( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test isEqual(),create one copy instance, and compare.",
+ bRes );
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test isEqual(),create one copy instance, and compare.",
+ !bRes1 );
+ }
+
+ CPPUNIT_TEST_SUITE( isEqual );
+ CPPUNIT_TEST( isEqual_001 );
+ CPPUNIT_TEST( isEqual_002 );
+ CPPUNIT_TEST_SUITE_END( );
+ };
+
+ /** testing the method:
+ inline void SAL_CALL close();
+ */
+ class close : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ void close_001( )
+ {
+ ::osl::Pipe aPipe( test::uniquePipeName(aTestPipe1), osl_Pipe_CREATE );
+ aPipe.close( );
+ bRes = aPipe.is( );
+
+ aPipe.clear( );
+ bRes1 = aPipe.is( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: difference between close and clear.",
+ bRes);
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: difference between close and clear.",
+ !bRes1);
+ }
+
+ void close_002( )
+ {
+ ::osl::StreamPipe aPipe( test::uniquePipeName(aTestPipe1), osl_Pipe_CREATE );
+ aPipe.close( );
+ int nRet = aPipe.send( m_pTestString1.getStr(), 3 );
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "#test comment#: use after close.",
+ OSL_PIPE_FAIL, nRet );
+ }
+
+ CPPUNIT_TEST_SUITE( close );
+ CPPUNIT_TEST( close_001 );
+ CPPUNIT_TEST( close_002 );
+ CPPUNIT_TEST_SUITE_END( );
+ };
+
+ /** testing the method:
+ inline oslPipeError SAL_CALL accept(StreamPipe& Connection);
+ please refer to StreamPipe::recv
+ */
+
+ /** testing the method:
+ inline oslPipeError SAL_CALL getError() const;
+ */
+ class getError : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ void getError_001( )
+ {
+ ::osl::Pipe aPipe( test::uniquePipeName(aTestPipeName), osl_Pipe_OPEN );
+ oslPipeError nError = aPipe.getError( );
+ printPipeError( aPipe );
+ aPipe.clear( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: open a non-exist pipe.",
+ nError != osl_Pipe_E_None );
+ }
+
+ void getError_002( )
+ {
+ ::osl::Pipe aPipe( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE );
+ ::osl::Pipe aPipe1( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE );
+ oslPipeError nError = aPipe.getError( );
+ printPipeError( aPipe );
+ aPipe.clear( );
+ aPipe1.clear( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: create an already exist pipe.",
+ nError != osl_Pipe_E_None );
+ }
+
+ CPPUNIT_TEST_SUITE( getError );
+ CPPUNIT_TEST( getError_001 );
+ CPPUNIT_TEST( getError_002 );
+ CPPUNIT_TEST_SUITE_END( );
+ };
+
+ /** testing the method:
+ inline oslPipe SAL_CALL getHandle() const;
+ */
+ class getHandle : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ void getHandle_equalityOperatorAgainstSelf( )
+ {
+ ::osl::Pipe aPipe( test::uniquePipeName(aTestPipeName), osl_Pipe_OPEN );
+ bRes = aPipe == aPipe.getHandle( );
+ aPipe.clear( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: one pipe should equal to its handle.",
+ bRes );
+ }
+
+ void getHandle_equalityOperatorAgainstDerivedPipe( )
+ {
+ ::osl::Pipe aPipe( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE );
+ ::osl::Pipe aPipe1( aPipe.getHandle( ) );
+ bRes = aPipe == aPipe1;
+ aPipe.clear( );
+ aPipe1.clear( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: one pipe derived from another pipe's handle.",
+ bRes );
+ }
+
+ CPPUNIT_TEST_SUITE( getHandle );
+ CPPUNIT_TEST( getHandle_equalityOperatorAgainstSelf );
+ CPPUNIT_TEST( getHandle_equalityOperatorAgainstDerivedPipe );
+ CPPUNIT_TEST_SUITE_END( );
+ };
+
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_Pipe::ctors);
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_Pipe::is);
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_Pipe::create);
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_Pipe::clear);
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_Pipe::assign);
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_Pipe::isEqual);
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_Pipe::close);
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_Pipe::getError);
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_Pipe::getHandle);
+
+} // namespace osl_Pipe
+
+namespace osl_StreamPipe
+{
+
+ /** testing the methods:
+ inline StreamPipe();
+ inline StreamPipe(oslPipe Pipe);
+ inline StreamPipe(const StreamPipe& Pipe);
+ inline StreamPipe(const OUString& strName, oslPipeOptions Options = osl_Pipe_OPEN);
+ inline StreamPipe(const OUString& strName, oslPipeOptions Options, const Security &rSec );
+ inline StreamPipe( oslPipe pipe, __sal_NoAcquire noacquire );
+ */
+ class ctors : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ void ctors_none( )
+ {
+ // create a pipe.
+ ::osl::StreamPipe aStreamPipe( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE );
+ // create an unattached pipe.
+ ::osl::StreamPipe aStreamPipe1;
+ bRes = aStreamPipe1.is( );
+
+ // assign it and check.
+ aStreamPipe1 = aStreamPipe;
+ bRes1 = aStreamPipe1.is( );
+ aStreamPipe.clear( );
+ aStreamPipe1.clear( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test constructor with no parameter, before and after assign.",
+ !bRes );
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test constructor with no parameter, before and after assign.",
+ bRes1 );
+ }
+
+ void ctors_handle( )
+ {
+ // create a pipe.
+ ::osl::StreamPipe aStreamPipe( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE );
+ // create a pipe with last handle.
+ ::osl::StreamPipe aStreamPipe1( aStreamPipe.getHandle( ) );
+ bRes = aStreamPipe1.is( ) && aStreamPipe == aStreamPipe1;
+ aStreamPipe.clear( );
+ aStreamPipe1.clear( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test constructor with other's handle.",
+ bRes );
+ }
+
+ void ctors_copy( )
+ {
+ // create a pipe.
+ ::osl::StreamPipe aStreamPipe( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE );
+ // create an unattached pipe.
+ ::osl::StreamPipe aStreamPipe1( aStreamPipe );
+ bRes = aStreamPipe1.is( ) && aStreamPipe == aStreamPipe1;
+ aStreamPipe.clear( );
+ aStreamPipe1.clear( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test copy constructor.",
+ bRes );
+ }
+
+ void ctors_name_option( )
+ {
+ // create a pipe.
+ ::osl::StreamPipe aStreamPipe( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE );
+ // create an unattached pipe.
+ ::osl::StreamPipe aStreamPipe1( test::uniquePipeName(aTestPipeName), osl_Pipe_OPEN );
+ bRes = aStreamPipe1.is( ) && aStreamPipe.is( );
+ aStreamPipe.clear( );
+ aStreamPipe1.clear( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test constructor with name and option.",
+ bRes );
+ }
+
+ void ctors_name_option_security( )
+ {
+ /// create a security pipe.
+ const ::osl::Security rSecurity;
+ ::osl::StreamPipe aSecurityPipe( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE, rSecurity );
+
+ bRes = aSecurityPipe.is( );
+ aSecurityPipe.clear( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test constructor with name, option and security, the test of security is not implemented yet.",
+ bRes );
+ }
+
+ /** tester comment:
+
+ When test the following constructor, don't know how to test the
+ acquire and no acquire action. possible plans:
+ 1.release one handle and check the other( did not success since the
+ other still exist and valid. )
+ 2. release one handle twice to see getLastError( )(the getLastError
+ always returns invalidError(LINUX)).
+ */
+
+ void ctors_no_acquire( )
+ {
+ // create a pipe.
+ ::osl::StreamPipe aPipe( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE );
+ osl_acquirePipe(aPipe.getHandle());
+ // constructs a pipe reference without acquiring the handle.
+ ::osl::StreamPipe aNoAcquirePipe( aPipe.getHandle( ), SAL_NO_ACQUIRE );
+
+ bRes = aNoAcquirePipe.is( );
+ aPipe.clear( );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: test constructor with no acquire of handle, only validation test, do not know how to test no acquire.",
+ bRes );
+ }
+
+ CPPUNIT_TEST_SUITE( ctors );
+ CPPUNIT_TEST( ctors_none );
+ CPPUNIT_TEST( ctors_handle );
+ CPPUNIT_TEST( ctors_copy );
+ CPPUNIT_TEST( ctors_name_option );
+ CPPUNIT_TEST( ctors_name_option_security );
+ CPPUNIT_TEST( ctors_no_acquire );
+ CPPUNIT_TEST_SUITE_END( );
+ };
+
+ /** testing the methods:
+ inline StreamPipe & SAL_CALL operator=(oslPipe Pipe);
+ inline StreamPipe& SAL_CALL operator=(const Pipe& pipe);
+ mindy: not implemented in osl/pipe.hxx, so remove the cases
+ */
+
+ /** wait _nSec seconds.
+ */
+ static void thread_sleep( sal_uInt32 _nSec )
+ {
+ /// print statement in thread process must use fflush() to force display.
+ fflush(stdout);
+
+ osl::Thread::wait(std::chrono::seconds(_nSec));
+ }
+ // test read/write & send/recv data to pipe
+
+ namespace {
+
+ class Pipe_DataSink_Thread : public Thread
+ {
+ public:
+ char buf[256];
+ Pipe_DataSink_Thread( ) { }
+
+ protected:
+ void SAL_CALL run( ) override
+ {
+ printf("open pipe\n");
+ ::osl::StreamPipe aSenderPipe( test::uniquePipeName(aTestPipeName), osl_Pipe_OPEN ); // test::uniquePipeName(aTestPipeName) is a string = "TestPipe"
+ if ( !aSenderPipe.is() )
+ {
+ printf("pipe open failed! \n");
+ }
+ else
+ {
+ printf("read\n");
+ sal_Int32 nChars = aSenderPipe.read( buf, m_pTestString1.getLength() + 1 );
+ if ( nChars < 0 )
+ {
+ printf("read failed! \n");
+ return;
+ }
+ buf[sizeof(buf)-1] = '\0';
+ printf("buffer is %s \n", buf);
+ printf("send\n");
+ nChars = aSenderPipe.send( m_pTestString2.getStr(), m_pTestString2.getLength() + 1 );
+ if ( nChars < 0 )
+ {
+ printf("client send failed! \n");
+ return;
+ }
+ }
+ }
+
+ };
+
+ class Pipe_DataSource_Thread : public Thread
+ {
+ public:
+ char buf[256];
+ ::osl::Pipe aListenPipe;
+ ::osl::StreamPipe aConnectionPipe;
+ Pipe_DataSource_Thread( )
+ {
+ printf("create pipe\n");
+ aListenPipe.create( test::uniquePipeName(aTestPipeName), osl_Pipe_CREATE );
+ }
+ virtual ~Pipe_DataSource_Thread( ) override
+ {
+ aListenPipe.close();
+ }
+ protected:
+ void SAL_CALL run( ) override
+ {
+ //create pipe.
+ printf("listen\n");
+ if ( !aListenPipe.is() )
+ {
+ printf("pipe create failed! \n");
+ }
+ else
+ {
+ //start server and wait for connection.
+ printf("accept\n");
+ if ( aListenPipe.accept( aConnectionPipe ) != osl_Pipe_E_None )
+ {
+ printf("pipe accept failed!");
+ return;
+ }
+ printf("write\n");
+ // write to pipe
+ sal_Int32 nChars = aConnectionPipe.write( m_pTestString1.getStr(), m_pTestString1.getLength() + 1 );
+ if ( nChars < 0)
+ {
+ printf("server write failed! \n");
+ return;
+ }
+ printf("recv\n");
+ nChars = aConnectionPipe.recv( buf, 256 );
+
+ if ( nChars < 0)
+ {
+ printf("server receive failed! \n");
+ return;
+ }
+ buf[sizeof(buf)-1] = '\0';
+ printf("received message is: %s\n", buf );
+ }
+ }
+ };
+
+ }
+
+ /** testing the method: read/write/send/recv and Pipe::accept
+ */
+ class recv : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ void recv_001( )
+ {
+ //launch threads.
+ Pipe_DataSource_Thread myDataSourceThread;
+ Pipe_DataSink_Thread myDataSinkThread;
+ myDataSourceThread.create( );
+ thread_sleep( 1 );
+ myDataSinkThread.create( );
+
+ //wait until the thread terminate
+ myDataSinkThread.join( );
+ myDataSourceThread.join( );
+
+ int nCompare1 = strcmp( myDataSinkThread.buf, m_pTestString1.getStr() );
+ int nCompare2 = strcmp( myDataSourceThread.buf, m_pTestString2.getStr() );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "test send/recv/write/read.", 0, nCompare1 );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "test send/recv/write/read.", 0, nCompare2 );
+ }
+ //close pipe when accept
+ void recv_002()
+ {
+ thread_sleep( 1 );
+
+ Pipe_DataSource_Thread myDataSourceThread;
+ Pipe_DataSink_Thread myDataSinkThread;
+ myDataSourceThread.create( );
+ thread_sleep( 1 );
+ myDataSourceThread.aListenPipe.close();
+ myDataSourceThread.join( );
+ //no condition judgment here, if the case could finish executing within 1 or 2 seconds, it passes.
+ }
+
+ CPPUNIT_TEST_SUITE( recv );
+ CPPUNIT_TEST( recv_001 );
+ CPPUNIT_TEST( recv_002 );
+ CPPUNIT_TEST_SUITE_END( );
+ };
+
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_StreamPipe::ctors);
+//CPPUNIT_TEST_SUITE_REGISTRATION(osl_StreamPipe::assign);
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_StreamPipe::recv);
+
+} // namespace osl_StreamPipe
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/osl/process/batch.bat b/sal/qa/osl/process/batch.bat
new file mode 100755
index 000000000..e27f7191b
--- /dev/null
+++ b/sal/qa/osl/process/batch.bat
@@ -0,0 +1,19 @@
+rem
+rem This file is part of the LibreOffice project.
+rem
+rem This Source Code Form is subject to the terms of the Mozilla Public
+rem License, v. 2.0. If a copy of the MPL was not distributed with this
+rem file, You can obtain one at http://mozilla.org/MPL/2.0/.
+rem
+rem This file incorporates work covered by the following license notice:
+rem
+rem Licensed to the Apache Software Foundation (ASF) under one or more
+rem contributor license agreements. See the NOTICE file distributed
+rem with this work for additional information regarding copyright
+rem ownership. The ASF licenses this file to you under the Apache
+rem License, Version 2.0 (the "License"); you may not use this file
+rem except in compliance with the License. You may obtain a copy of
+rem the License at http://www.apache.org/licenses/LICENSE-2.0 .
+rem
+@echo off
+echo "Hello world" \ No newline at end of file
diff --git a/sal/qa/osl/process/batch.sh b/sal/qa/osl/process/batch.sh
new file mode 100755
index 000000000..fd3828c6a
--- /dev/null
+++ b/sal/qa/osl/process/batch.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+echo "Hello world" \ No newline at end of file
diff --git a/sal/qa/osl/process/osl_Thread.cxx b/sal/qa/osl/process/osl_Thread.cxx
new file mode 100644
index 000000000..3f62c6ea3
--- /dev/null
+++ b/sal/qa/osl/process/osl_Thread.cxx
@@ -0,0 +1,2005 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <algorithm>
+#ifdef _WIN32
+#if !defined WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#else
+#include <unistd.h>
+#include <time.h>
+#endif
+
+// include files
+
+#include <sal/types.h>
+#include <rtl/string.hxx>
+#include <rtl/strbuf.hxx>
+#include <osl/thread.hxx>
+#include <osl/mutex.hxx>
+#include <osl/time.h>
+
+#include <string.h>
+#include <memory>
+
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#define t_print printf
+
+using namespace osl;
+
+namespace {
+
+// Small stopwatch
+class StopWatch {
+ TimeValue t1,t2; // Start and stoptime
+
+protected:
+ sal_Int32 m_nNanoSec;
+ sal_Int32 m_nSeconds;
+
+ bool m_bIsValid; // TRUE, when started and stopped
+ bool m_bIsRunning; // TRUE, when started
+
+public:
+ StopWatch();
+
+ void start(); // Starts time
+ void stop(); // Stops time
+
+ double getSeconds() const;
+ double getTenthSec() const;
+};
+
+}
+
+// ================================= Stop Watch =================================
+
+// A small stopwatch for internal use
+// (c) Lars Langhans 29.12.1996 22:10
+
+StopWatch::StopWatch()
+ : m_nNanoSec(0)
+ , m_nSeconds(0)
+ , m_bIsValid(false)
+ , m_bIsRunning(false)
+{
+ t1.Seconds = 0;
+ t1.Nanosec = 0;
+ t2.Seconds = 0;
+ t2.Nanosec = 0;
+}
+
+void StopWatch::start()
+{
+// pre: %
+// post: Start Timer
+
+ m_bIsValid = false;
+ m_bIsRunning = true;
+ osl_getSystemTime( &t1 );
+ t_print("# %u %u nsecs\n", static_cast<unsigned>(t1.Seconds), static_cast<unsigned>(t1.Nanosec));
+ // gettimeofday(&t1, 0);
+}
+
+void StopWatch::stop()
+{
+// pre: Timer should be started
+// post: Timer will stopped
+
+ osl_getSystemTime( &t2 );
+ t_print("# %u %u nsecs\n", static_cast<unsigned>(t2.Seconds), static_cast<unsigned>(t2.Nanosec));
+
+ if (m_bIsRunning)
+ { // check if started.
+ m_nSeconds = static_cast<sal_Int32>(t2.Seconds) - static_cast<sal_Int32>(t1.Seconds);
+ if ( t2.Nanosec > t1.Nanosec )
+ m_nNanoSec = static_cast<sal_Int32>(t2.Nanosec) - static_cast<sal_Int32>(t1.Nanosec);
+ else
+ {
+ m_nNanoSec = 1000000000 + static_cast<sal_Int32>(t2.Nanosec) - static_cast<sal_Int32>(t1.Nanosec);
+ m_nSeconds -= 1;
+ }
+ t_print("# %u %u nsecs\n", static_cast<unsigned>(m_nSeconds), static_cast<unsigned>(m_nNanoSec) );
+ m_bIsValid = true;
+ m_bIsRunning = false;
+ }
+}
+
+double StopWatch::getSeconds() const
+{
+// pre: valid = TRUE
+// BACK: time in seconds
+
+ double nValue = 0.0;
+ if (m_bIsValid)
+ {
+ nValue = double(m_nNanoSec) / 1000000000.0 + m_nSeconds; // milli micro nano
+ }
+ return nValue;
+}
+
+double StopWatch::getTenthSec() const
+{
+ double nValue = 0.0;
+ if (m_bIsValid)
+ {
+ nValue = double(m_nNanoSec) / 100000000.0 + m_nSeconds * 10;
+ }
+ return nValue ;
+}
+
+namespace {
+
+template <class T>
+class ThreadSafeValue
+{
+ T m_nFlag;
+ Mutex m_aMutex;
+public:
+ explicit ThreadSafeValue(T n = 0): m_nFlag(n) {}
+ T getValue()
+ {
+ //block if already acquired by another thread.
+ osl::MutexGuard g(m_aMutex);
+ return m_nFlag;
+ }
+ void incValue()
+ {
+ //only one thread operate on the flag.
+ osl::MutexGuard g(m_aMutex);
+ m_nFlag++;
+ }
+ void acquire() {m_aMutex.acquire();}
+ void release() {m_aMutex.release();}
+};
+
+}
+
+namespace ThreadHelper
+{
+ static void thread_sleep_tenth_sec(sal_Int32 _nTenthSec)
+ {
+ osl::Thread::wait(std::chrono::milliseconds(_nTenthSec * 100));
+ }
+
+ static void outputPriority(oslThreadPriority const& _aPriority)
+ {
+ // LLA: output the priority
+ if (_aPriority == osl_Thread_PriorityHighest)
+ {
+ t_print("Prio is High\n");
+ }
+ else if (_aPriority == osl_Thread_PriorityAboveNormal)
+ {
+ t_print("Prio is above normal\n");
+ }
+ else if (_aPriority == osl_Thread_PriorityNormal)
+ {
+ t_print("Prio is normal\n");
+ }
+ else if (_aPriority == osl_Thread_PriorityBelowNormal)
+ {
+ t_print("Prio is below normal\n");
+ }
+ else if (_aPriority == osl_Thread_PriorityLowest)
+ {
+ t_print("Prio is lowest\n");
+ }
+ else
+ {
+ t_print("Prio is unknown\n");
+ }
+ }
+}
+
+namespace {
+
+/** Simple thread for testing Thread-create.
+
+ Just add 1 of value 0, and after running, result is 1.
+ */
+class myThread : public Thread
+{
+ ThreadSafeValue<sal_Int32> m_aFlag;
+public:
+ sal_Int32 getValue() { return m_aFlag.getValue(); }
+protected:
+ /** guarded value which initialized 0
+
+ @see ThreadSafeValue
+ */
+ void SAL_CALL run() override
+ {
+ while(schedule())
+ {
+ m_aFlag.incValue();
+ ThreadHelper::thread_sleep_tenth_sec(1);
+ }
+ }
+
+public:
+
+ virtual void SAL_CALL suspend() override
+ {
+ m_aFlag.acquire();
+ ::osl::Thread::suspend();
+ m_aFlag.release();
+ }
+
+ virtual ~myThread() override
+ {
+ if (isRunning())
+ {
+ t_print("error: not terminated.\n");
+ }
+ }
+
+};
+
+/** Thread which has a flag add 1 every second until 20
+ */
+class OCountThread : public Thread
+{
+ ThreadSafeValue<sal_Int32> m_aFlag;
+public:
+ OCountThread() : m_nWaitSec(0)
+ {
+ t_print("new OCountThread thread %u!\n", static_cast<unsigned>(getIdentifier()));
+ }
+ sal_Int32 getValue() { return m_aFlag.getValue(); }
+
+ void setWait(sal_Int32 nSec)
+ {
+ m_nWaitSec = nSec;
+ //m_bWait = sal_True;
+ }
+
+ virtual void SAL_CALL suspend() override
+ {
+ m_aFlag.acquire();
+ ::osl::Thread::suspend();
+ m_aFlag.release();
+ }
+
+protected:
+ //sal_Bool m_bWait;
+ sal_Int32 m_nWaitSec;
+
+ void SAL_CALL run() override
+ {
+ /// if the thread should terminate, schedule return false
+ while (m_aFlag.getValue() < 20 && schedule())
+ {
+ m_aFlag.incValue();
+ ThreadHelper::thread_sleep_tenth_sec(1);
+
+ if (m_nWaitSec != 0)
+ {
+ TimeValue nTV;
+ nTV.Seconds = m_nWaitSec / 10 ;
+ nTV.Nanosec = ( m_nWaitSec%10 ) * 100000000 ;
+ wait( nTV );
+ m_nWaitSec = 0;
+ }
+ }
+ }
+ void SAL_CALL onTerminated() override
+ {
+ t_print("normally terminate this thread %u!\n", static_cast<unsigned>(getIdentifier()));
+ }
+public:
+
+ virtual ~OCountThread() override
+ {
+ if (isRunning())
+ {
+ t_print("error: not terminated.\n");
+ }
+ }
+
+};
+
+/** no call schedule in the run method
+*/
+class ONoScheduleThread : public Thread
+{
+ ThreadSafeValue<sal_Int32> m_aFlag;
+public:
+ sal_Int32 getValue() { return m_aFlag.getValue(); }
+
+ virtual void SAL_CALL suspend() override
+ {
+ m_aFlag.acquire();
+ ::osl::Thread::suspend();
+ m_aFlag.release();
+ }
+protected:
+ void SAL_CALL run() override
+ {
+ while (m_aFlag.getValue() < 10)
+ {
+ m_aFlag.incValue();
+ ThreadHelper::thread_sleep_tenth_sec(1);
+ }
+ }
+ void SAL_CALL onTerminated() override
+ {
+ t_print("normally terminate this thread %u!\n", static_cast<unsigned>(getIdentifier()));
+ }
+public:
+ ONoScheduleThread()
+ {
+ t_print("new thread id %u!\n", static_cast<unsigned>(getIdentifier()));
+ }
+ virtual ~ONoScheduleThread() override
+ {
+ if (isRunning())
+ {
+ t_print("error: not terminated.\n");
+ }
+ }
+
+};
+
+
+class OAddThread : public Thread
+{
+ ThreadSafeValue<sal_Int32> m_aFlag;
+public:
+ //oslThreadIdentifier m_id, m_CurId;
+ OAddThread(){}
+ sal_Int32 getValue() { return m_aFlag.getValue(); }
+
+ virtual void SAL_CALL suspend() override
+ {
+ m_aFlag.acquire();
+ ::osl::Thread::suspend();
+ m_aFlag.release();
+ }
+protected:
+ void SAL_CALL run() override
+ {
+ //if the thread should terminate, schedule return false
+ while (schedule())
+ {
+ m_aFlag.incValue();
+ }
+ }
+ void SAL_CALL onTerminated() override
+ {
+ // t_print("normally terminate this thread %d!\n", getIdentifier());
+ }
+public:
+
+ virtual ~OAddThread() override
+ {
+ if (isRunning())
+ {
+ // t_print("error: not terminated.\n");
+ }
+ }
+
+};
+
+}
+
+namespace osl_Thread
+{
+
+ static void resumeAndWaitThread(Thread* _pThread)
+ {
+ // This function starts a thread, wait a second and suspends the thread
+ // Due to the fact, that a suspend and never run thread never really exists.
+
+ // Note: on UNX, after createSuspended, and then terminate the thread, it performs well;
+ // while on Windows, after createSuspended, the thread can not terminate, wait endlessly,
+ // so here call resume at first, then call terminate.
+#ifdef _WIN32
+ t_print("resumeAndWaitThread\n");
+ _pThread->resume();
+ ThreadHelper::thread_sleep_tenth_sec(1);
+#else
+ _pThread->resume();
+#endif
+ }
+
+ // kill a running thread and join it, if it has terminated, do nothing
+ static void termAndJoinThread(Thread* _pThread)
+ {
+ _pThread->terminate();
+
+// LLA: Windows feature???, a suspended thread can not terminated, so we have to weak it up
+#ifdef _WIN32
+ _pThread->resume();
+ ThreadHelper::thread_sleep_tenth_sec(1);
+#endif
+ t_print("#wait for join.\n");
+ _pThread->join();
+ }
+/** Test of the osl::Thread::create method
+ */
+
+ class create : public CppUnit::TestFixture
+ {
+ public:
+ /** Simple create a thread.
+
+ Create a simple thread, it just does add 1 to value(which initialized 0),
+ if the thread run, the value should be 1.
+ */
+ void create_001()
+ {
+ myThread* newthread = new myThread;
+ bool bRes = newthread->create();
+ CPPUNIT_ASSERT_MESSAGE("Can not creates a new thread!\n", bRes);
+
+ ThreadHelper::thread_sleep_tenth_sec(1); // wait short
+ bool isRunning = newthread->isRunning(); // check if thread is running
+ /// wait for the new thread to assure it has run
+ ThreadHelper::thread_sleep_tenth_sec(3);
+ sal_Int32 nValue = newthread->getValue();
+ /// to assure the new thread has terminated
+ termAndJoinThread(newthread);
+ delete newthread;
+
+ t_print(" nValue = %d\n", static_cast<int>(nValue));
+ t_print("isRunning = %s\n", isRunning ? "true" : "false");
+
+ CPPUNIT_ASSERT_MESSAGE(
+ "Creates a new thread",
+ nValue >= 1
+ );
+ CPPUNIT_ASSERT_MESSAGE(
+ "Creates a new thread",
+ isRunning
+ );
+
+ }
+
+ /** only one running thread per instance, return false if create secondly
+ */
+ void create_002()
+ {
+ myThread* newthread = new myThread;
+ bool res1 = newthread->create();
+ bool res2 = newthread->create();
+ t_print("In non pro, an assertion should occurred. This behaviour is right.\n");
+ termAndJoinThread(newthread);
+ delete newthread;
+
+ CPPUNIT_ASSERT_MESSAGE(
+ "Creates a new thread: can not create two threads per instance",
+ res1
+ );
+ CPPUNIT_ASSERT_MESSAGE(
+ "Creates a new thread: can not create two threads per instance",
+ !res2
+ );
+
+ }
+
+ CPPUNIT_TEST_SUITE(create);
+ CPPUNIT_TEST(create_001);
+ CPPUNIT_TEST(create_002);
+ CPPUNIT_TEST_SUITE_END();
+ }; // class create
+
+ /** Test of the osl::Thread::createSuspended method
+ */
+ class createSuspended : public CppUnit::TestFixture
+ {
+ public:
+ /** Create a suspended thread, use the same class as create_001
+
+ after create, wait enough time, check the value, if it's still the initial value, pass
+ */
+ void createSuspended_001()
+ {
+ myThread* newthread = new myThread;
+ bool bRes = newthread->createSuspended();
+ CPPUNIT_ASSERT_MESSAGE("Can not creates a new thread!", bRes);
+
+ ThreadHelper::thread_sleep_tenth_sec(1);
+ bool isRunning = newthread->isRunning();
+ ThreadHelper::thread_sleep_tenth_sec(3);
+ sal_Int32 nValue = newthread->getValue();
+
+ resumeAndWaitThread(newthread);
+
+ termAndJoinThread(newthread);
+ delete newthread;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "Creates a new suspended thread",
+ sal_Int32(0), nValue
+ );
+ CPPUNIT_ASSERT_MESSAGE(
+ "Creates a new suspended thread",
+ isRunning
+ );
+ }
+
+ void createSuspended_002()
+ {
+ myThread* newthread = new myThread;
+ bool res1 = newthread->createSuspended();
+ bool res2 = newthread->createSuspended();
+
+ resumeAndWaitThread(newthread);
+
+ termAndJoinThread(newthread);
+
+ delete newthread;
+
+ CPPUNIT_ASSERT_MESSAGE(
+ "Creates a new thread: can not create two threads per instance",
+ res1
+ );
+ CPPUNIT_ASSERT_MESSAGE(
+ "Creates a new thread: can not create two threads per instance",
+ !res2
+ );
+ }
+
+ CPPUNIT_TEST_SUITE(createSuspended);
+ CPPUNIT_TEST(createSuspended_001);
+ // LLA: Deadlocked!!!
+ CPPUNIT_TEST(createSuspended_002);
+ CPPUNIT_TEST_SUITE_END();
+ }; // class createSuspended
+
+ /** when the count value equal to or more than 3, suspend the thread.
+ */
+ static void suspendCountThread(OCountThread* _pCountThread)
+ {
+ sal_Int32 nValue = 0;
+ while (true)
+ {
+ nValue = _pCountThread->getValue();
+ if (nValue >= 3)
+ {
+ _pCountThread->suspend();
+ break;
+ }
+ }
+ }
+
+ /** Test of the osl::Thread::suspend method
+ */
+ class suspend : public CppUnit::TestFixture
+ {
+ public:
+ /** Use a thread which has a flag added 1 every second
+
+ ALGORITHM:
+ create the thread, after running special time, record value of flag, then suspend it,
+ wait a long time, check the flag, if it remains unchanged during suspending
+ */
+ void suspend_001()
+ {
+ OCountThread* aCountThread = new OCountThread();
+ bool bRes = aCountThread->create();
+ CPPUNIT_ASSERT_MESSAGE ( "Can't start thread!", bRes );
+ // the thread run for some seconds, but not terminate
+ suspendCountThread( aCountThread );
+
+ // the value just after calling suspend
+ sal_Int32 nValue = aCountThread->getValue(); // (2)
+
+ ThreadHelper::thread_sleep_tenth_sec(3);
+
+ // the value after waiting 3 seconds
+ sal_Int32 nLaterValue = aCountThread->getValue(); // (3)
+
+ resumeAndWaitThread(aCountThread);
+ termAndJoinThread(aCountThread);
+ delete aCountThread;
+
+ CPPUNIT_ASSERT_MESSAGE(
+ "Suspend the thread",
+ bRes
+ );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "Suspend the thread",
+ nValue, nLaterValue
+ );
+
+ }
+
+ CPPUNIT_TEST_SUITE(suspend);
+ CPPUNIT_TEST(suspend_001);
+ // LLA: Deadlocked!!!
+ // CPPUNIT_TEST(createSuspended_002);
+ CPPUNIT_TEST_SUITE_END();
+ }; // class suspend
+
+ /** Test of the osl::Thread::resume method
+ */
+ class resume : public CppUnit::TestFixture
+ {
+ public:
+ /** check if the thread run samely as usual after suspend and resume
+
+ ALGORITHM:
+ compare the values before and after suspend, they should be same,
+ then compare values before and after resume, the difference should be same as the sleep seconds number
+ */
+ void resume_001()
+ {
+ OCountThread* pCountThread = new OCountThread();
+ bool bRes = pCountThread->create();
+ CPPUNIT_ASSERT_MESSAGE ( "Can't start thread!", bRes );
+
+ suspendCountThread(pCountThread);
+
+ sal_Int32 nSuspendValue = pCountThread->getValue(); // (2)
+ // suspend for 3 seconds
+ ThreadHelper::thread_sleep_tenth_sec(3);
+ pCountThread->resume();
+
+ ThreadHelper::thread_sleep_tenth_sec(3);
+ sal_Int32 nResumeValue = pCountThread->getValue();
+
+ ThreadHelper::thread_sleep_tenth_sec(3);
+ sal_Int32 nLaterValue = pCountThread->getValue();
+
+ termAndJoinThread(pCountThread);
+ delete pCountThread;
+
+ t_print("SuspendValue: %d\n", static_cast<int>(nSuspendValue));
+ t_print("ResumeValue: %d\n", static_cast<int>(nResumeValue));
+ t_print("LaterValue: %d\n", static_cast<int>(nLaterValue));
+
+ /* LLA: this assumption is no longer relevant: nResumeValue == nSuspendValue && */
+ CPPUNIT_ASSERT_MESSAGE(
+ "Suspend then resume the thread",
+ nLaterValue >= 9
+ );
+ CPPUNIT_ASSERT_MESSAGE(
+ "Suspend then resume the thread",
+ nResumeValue > nSuspendValue
+ );
+ CPPUNIT_ASSERT_MESSAGE(
+ "Suspend then resume the thread",
+ nLaterValue > nResumeValue
+ );
+
+ }
+
+ /** Create a suspended thread then resume, check if the thread has run
+ */
+ void resume_002()
+ {
+ myThread* newthread = new myThread;
+ bool bRes = newthread->createSuspended();
+ CPPUNIT_ASSERT_MESSAGE ( "Can't create thread!", bRes );
+
+ newthread->resume();
+ ThreadHelper::thread_sleep_tenth_sec(2);
+ sal_Int32 nValue = newthread->getValue();
+
+ termAndJoinThread(newthread);
+ delete newthread;
+
+ t_print(" nValue = %d\n", static_cast<int>(nValue));
+
+ CPPUNIT_ASSERT_MESSAGE(
+ "Creates a suspended thread, then resume",
+ nValue >= 1
+ );
+ }
+
+ CPPUNIT_TEST_SUITE(resume);
+ CPPUNIT_TEST(resume_001);
+ CPPUNIT_TEST(resume_002);
+ CPPUNIT_TEST_SUITE_END();
+ }; // class resume
+
+ /** Test of the osl::Thread::terminate method
+ */
+ class terminate : public CppUnit::TestFixture
+ {
+ public:
+ /** Check after call terminate if the running thread running go on executing
+
+ ALGORITHM:
+ before and after call terminate, the values should be the same
+ */
+ void terminate_001()
+ {
+ OCountThread* aCountThread = new OCountThread();
+ bool bRes = aCountThread->create();
+ CPPUNIT_ASSERT_MESSAGE ( "Can't start thread!", bRes );
+
+ ThreadHelper::thread_sleep_tenth_sec(2);
+ sal_Int32 nValue = aCountThread->getValue();
+ aCountThread->terminate();
+ ThreadHelper::thread_sleep_tenth_sec(2);
+ sal_Int32 nLaterValue = aCountThread->getValue();
+
+ // isRunning should be false after terminate
+ bool isRunning = aCountThread->isRunning();
+ aCountThread->join();
+ delete aCountThread;
+
+ t_print(" nValue = %d\n", static_cast<int>(nValue));
+ t_print("nLaterValue = %d\n", static_cast<int>(nLaterValue));
+
+ CPPUNIT_ASSERT_MESSAGE(
+ "Terminate the thread",
+ !isRunning
+ );
+ CPPUNIT_ASSERT_MESSAGE(
+ "Terminate the thread",
+ nLaterValue >= nValue
+ );
+ }
+ /** Check if a suspended thread will terminate after call terminate, different on w32 and on UNX
+ */
+ void terminate_002()
+ {
+ OCountThread* aCountThread = new OCountThread();
+ bool bRes = aCountThread->create();
+ CPPUNIT_ASSERT_MESSAGE ( "Can't start thread!", bRes );
+
+ ThreadHelper::thread_sleep_tenth_sec(1);
+ suspendCountThread(aCountThread);
+ sal_Int32 nValue = aCountThread->getValue();
+
+ // seems a suspended thread can not be terminated on W32, while on Solaris can
+ resumeAndWaitThread(aCountThread);
+
+ ThreadHelper::thread_sleep_tenth_sec(2);
+
+ termAndJoinThread(aCountThread);
+ sal_Int32 nLaterValue = aCountThread->getValue();
+ delete aCountThread;
+
+ t_print(" nValue = %d\n", static_cast<int>(nValue));
+ t_print("nLaterValue = %d\n", static_cast<int>(nLaterValue));
+
+ CPPUNIT_ASSERT_MESSAGE(
+ "Suspend then resume the thread",
+ nLaterValue > nValue );
+ }
+
+ CPPUNIT_TEST_SUITE(terminate);
+ CPPUNIT_TEST(terminate_001);
+ CPPUNIT_TEST(terminate_002);
+ CPPUNIT_TEST_SUITE_END();
+ }; // class terminate
+
+ /** Test of the osl::Thread::join method
+ */
+ class join : public CppUnit::TestFixture
+ {
+ public:
+ /** Check after call terminate if the thread running function will not go on executing
+
+ the next statement after join will not exec before the thread terminates
+ ALGORITHM:
+ recode system time at the beginning of the thread run, call join, then record system time again,
+ the difference of the two times should be equal or more than 20 seconds, the CountThread normally terminates
+ */
+ void join_001()
+ {
+ OCountThread *aCountThread = new OCountThread();
+ bool bRes = aCountThread->create();
+ CPPUNIT_ASSERT_MESSAGE ( "Can't start thread!", bRes );
+
+ StopWatch aStopWatch;
+ aStopWatch.start();
+ // TimeValue aTimeVal_befor;
+ // osl_getSystemTime( &aTimeVal_befor );
+ //t_print("#join:the system time is %d,%d\n", pTimeVal_befor->Seconds,pTimeVal_befor->Nanosec);
+
+ aCountThread->join();
+
+ //the below line will be executed after aCountThread terminate
+ // TimeValue aTimeVal_after;
+ // osl_getSystemTime( &aTimeVal_after );
+ aStopWatch.stop();
+ // sal_uInt32 nSec = aTimeVal_after.Seconds - aTimeVal_befor.Seconds;
+ double nSec = aStopWatch.getSeconds();
+ t_print("join_001 nSec=%f\n", nSec);
+ delete aCountThread;
+
+ CPPUNIT_ASSERT_MESSAGE(
+ "Join the thread: after the thread terminate",
+ nSec >= 2
+ );
+
+ }
+ /** after terminated by another thread, join exited immediately
+
+ ALGORITHM:
+ terminate the thread when value>=3, call join, check the beginning time and time after join,
+ the difference should be 3 seconds, join costs little time
+ */
+ void join_002()
+ {
+ OCountThread *aCountThread = new OCountThread();
+ bool bRes = aCountThread->create();
+ CPPUNIT_ASSERT_MESSAGE ( "Can't start thread!", bRes );
+
+ //record the time when the running begin
+ // TimeValue aTimeVal_befor;
+ // osl_getSystemTime( &aTimeVal_befor );
+ StopWatch aStopWatch;
+ aStopWatch.start();
+
+ ThreadHelper::thread_sleep_tenth_sec(10);
+ termAndJoinThread(aCountThread);
+
+ //the below line will be executed after aCountThread terminate
+ // TimeValue aTimeVal_after;
+ // osl_getSystemTime( &aTimeVal_after );
+ // sal_uInt32 nSec = aTimeVal_after.Seconds - aTimeVal_befor.Seconds;
+ aStopWatch.stop();
+ double nSec = aStopWatch.getSeconds();
+ t_print("join_002 nSec=%f\n", nSec);
+
+ delete aCountThread;
+ CPPUNIT_ASSERT_MESSAGE(
+ "Join the thread: after thread terminate by another thread",
+ nSec >= 1
+ );
+ }
+
+ CPPUNIT_TEST_SUITE(join);
+ CPPUNIT_TEST(join_001);
+ CPPUNIT_TEST(join_002);
+ CPPUNIT_TEST_SUITE_END();
+ }; // class join
+
+ /** Test of the osl::Thread::isRunning method
+ */
+ class isRunning : public CppUnit::TestFixture
+ {
+ public:
+ void isRunning_001()
+ {
+ OCountThread *aCountThread = new OCountThread();
+ bool bRes = aCountThread->create();
+ CPPUNIT_ASSERT_MESSAGE ( "Can't start thread!", bRes );
+
+ bool bRun = aCountThread->isRunning();
+
+ ThreadHelper::thread_sleep_tenth_sec(2);
+ termAndJoinThread(aCountThread);
+ bool bTer = aCountThread->isRunning();
+ delete aCountThread;
+
+ CPPUNIT_ASSERT_MESSAGE(
+ "Test isRunning",
+ bRun
+ );
+ CPPUNIT_ASSERT_MESSAGE(
+ "Test isRunning",
+ !bTer
+ );
+ }
+ /** check the value of isRunning when suspending and after resume
+ */
+ void isRunning_002()
+ {
+ OCountThread *aCountThread = new OCountThread();
+ bool bRes = aCountThread->create();
+ CPPUNIT_ASSERT_MESSAGE ( "Can't start thread!", bRes );
+
+ // sal_Bool bRunning = aCountThread->isRunning();
+ // sal_Int32 nValue = 0;
+ suspendCountThread(aCountThread);
+
+ bool bRunning_sup = aCountThread->isRunning();
+ ThreadHelper::thread_sleep_tenth_sec(2);
+ aCountThread->resume();
+ ThreadHelper::thread_sleep_tenth_sec(2);
+ bool bRunning_res = aCountThread->isRunning();
+ termAndJoinThread(aCountThread);
+ bool bRunning_ter = aCountThread->isRunning();
+ delete aCountThread;
+
+ CPPUNIT_ASSERT_MESSAGE(
+ "Test isRunning",
+ bRes );
+ CPPUNIT_ASSERT_MESSAGE(
+ "Test isRunning",
+ bRunning_sup );
+ CPPUNIT_ASSERT_MESSAGE(
+ "Test isRunning",
+ bRunning_res );
+ CPPUNIT_ASSERT_MESSAGE(
+ "Test isRunning",
+ !bRunning_ter );
+
+ }
+
+ CPPUNIT_TEST_SUITE(isRunning);
+ CPPUNIT_TEST(isRunning_001);
+ CPPUNIT_TEST(isRunning_002);
+ CPPUNIT_TEST_SUITE_END();
+ }; // class isRunning
+
+ /// check osl::Thread::setPriority
+ class setPriority : public CppUnit::TestFixture
+ {
+ public:
+ // insert your test code here.
+ OString getPrioName(oslThreadPriority _aPriority)
+ {
+ OString sPrioStr;
+ switch (_aPriority)
+ {
+ case osl_Thread_PriorityHighest:
+ sPrioStr = "Highest";
+ break;
+
+ case osl_Thread_PriorityAboveNormal:
+ sPrioStr = "AboveNormal";
+ break;
+
+ case osl_Thread_PriorityNormal:
+ sPrioStr = "Normal";
+ break;
+
+ case osl_Thread_PriorityBelowNormal:
+ sPrioStr = "BelowNormal";
+ break;
+
+ case osl_Thread_PriorityLowest:
+ sPrioStr = "Lowest";
+ break;
+ default:
+ sPrioStr = "unknown";
+ }
+ return sPrioStr;
+ }
+
+ /** check 2 threads.
+
+ ALGORITHM:
+ Here the function should show, that 2 different threads,
+ which only increase a value, should run at the same time with same prio.
+ The test fails, if the difference between the two values is more than 5%
+ but IMHO this isn't a failure, it's only a feature of the OS.
+ */
+
+ void check2Threads(oslThreadPriority _aPriority)
+ {
+ // initial 5 threads with different priorities
+ OAddThread* pThread = new OAddThread();
+ OAddThread* p2Thread = new OAddThread();
+
+ //Create them and start running at the same time
+ pThread->create();
+ pThread->setPriority(_aPriority);
+ p2Thread->create();
+ p2Thread->setPriority(_aPriority);
+
+ ThreadHelper::thread_sleep_tenth_sec(5);
+
+ pThread->terminate();
+ p2Thread->terminate();
+
+ sal_Int32 nValueNormal = pThread->getValue();
+
+ sal_Int32 nValueNormal2 = p2Thread->getValue();
+
+ OString sPrio = getPrioName(_aPriority);
+ t_print("After 10 tenth seconds\n");
+
+ t_print("nValue in %s Prio Thread is %d\n",sPrio.getStr(), static_cast<int>(nValueNormal));
+ t_print("nValue in %s Prio Thread is %d\n", sPrio.getStr(), static_cast<int>(nValueNormal2));
+
+ // ThreadHelper::thread_sleep_tenth_sec(1);
+ pThread->join();
+ p2Thread->join();
+
+ delete pThread;
+ delete p2Thread;
+
+ sal_Int32 nDelta = abs(nValueNormal - nValueNormal2);
+ double nQuotient = std::max(nValueNormal, nValueNormal2);
+ CPPUNIT_ASSERT_MESSAGE(
+ "Quotient is zero, which means, there exist no right values.",
+ nQuotient != 0
+ );
+ double nDeltaPercent = nDelta / nQuotient * 100;
+
+ t_print("Delta value %d, percent %f\n", static_cast<int>(nDelta), nDeltaPercent);
+
+ // LLA: it's not a bug if the current OS is not able to handle thread scheduling right and good.
+ // like Windows XP
+ // LLA: CPPUNIT_ASSERT_MESSAGE(
+ // LLA: "Run 2 normal threads, the count diff more than 5 percent.",
+ // LLA: nDeltaPercent <= 5
+ // LLA: );
+ }
+
+ void setPriority_001_1()
+ {
+ check2Threads(osl_Thread_PriorityHighest);
+ }
+ void setPriority_001_2()
+ {
+ check2Threads(osl_Thread_PriorityAboveNormal);
+ }
+ void setPriority_001_3()
+ {
+ check2Threads(osl_Thread_PriorityNormal);
+ }
+ void setPriority_001_4()
+ {
+ check2Threads(osl_Thread_PriorityBelowNormal);
+ }
+ void setPriority_001_5()
+ {
+ check2Threads(osl_Thread_PriorityLowest);
+ }
+
+ void setPriority_002()
+ {
+ // initial 5 threads with different priorities
+
+ OAddThread aHighestThread;
+ OAddThread aAboveNormalThread;
+ OAddThread aNormalThread;
+ //OAddThread *aBelowNormalThread = new OAddThread();
+ //OAddThread *aLowestThread = new OAddThread();
+
+ //Create them and start running at the same time
+ aHighestThread.createSuspended();
+ aHighestThread.setPriority(osl_Thread_PriorityHighest);
+
+ aAboveNormalThread.createSuspended();
+ aAboveNormalThread.setPriority(osl_Thread_PriorityAboveNormal);
+
+ aNormalThread.createSuspended();
+ aNormalThread.setPriority(osl_Thread_PriorityNormal);
+ /*aBelowNormalThread->create();
+ aBelowNormalThread->setPriority(osl_Thread_PriorityBelowNormal);
+ aLowestThread->create();
+ aLowestThread->setPriority(osl_Thread_PriorityLowest);
+ */
+
+ aHighestThread.resume();
+ aAboveNormalThread.resume();
+ aNormalThread.resume();
+
+ ThreadHelper::thread_sleep_tenth_sec(5);
+
+ aHighestThread.suspend();
+ aAboveNormalThread.suspend();
+ aNormalThread.suspend();
+
+ termAndJoinThread(&aNormalThread);
+ termAndJoinThread(&aAboveNormalThread);
+ termAndJoinThread(&aHighestThread);
+ //aBelowNormalThread->terminate();
+ //aLowestThread->terminate();
+
+ sal_Int32 nValueHighest = aHighestThread.getValue();
+
+ sal_Int32 nValueAboveNormal = aAboveNormalThread.getValue();
+
+ sal_Int32 nValueNormal = aNormalThread.getValue();
+
+ t_print("After 10 tenth seconds\n");
+ t_print("nValue in Highest Prio Thread is %d\n", static_cast<int>(nValueHighest));
+ t_print("nValue in AboveNormal Prio Thread is %d\n", static_cast<int>(nValueAboveNormal));
+ t_print("nValue in Normal Prio Thread is %d\n", static_cast<int>(nValueNormal));
+
+#ifndef _WIN32
+ CPPUNIT_ASSERT_MESSAGE(
+ "SetPriority",
+ nValueHighest > 0
+ );
+ CPPUNIT_ASSERT_MESSAGE(
+ "SetPriority",
+ nValueAboveNormal > 0
+ );
+ CPPUNIT_ASSERT_MESSAGE(
+ "SetPriority",
+ nValueNormal > 0
+ );
+#endif
+ }
+
+ void setPriority_003()
+ {
+ // initial 5 threads with different priorities
+ OAddThread pHighestThread;
+ OAddThread pAboveNormalThread;
+ OAddThread pNormalThread;
+ OAddThread pBelowNormalThread;
+ OAddThread pLowestThread;
+
+ //Create them and start running at the same time
+ pHighestThread.createSuspended();
+ pHighestThread.setPriority(osl_Thread_PriorityHighest);
+
+ pAboveNormalThread.createSuspended();
+ pAboveNormalThread.setPriority(osl_Thread_PriorityAboveNormal);
+
+ pNormalThread.createSuspended();
+ pNormalThread.setPriority(osl_Thread_PriorityNormal);
+
+ pBelowNormalThread.createSuspended();
+ pBelowNormalThread.setPriority(osl_Thread_PriorityBelowNormal);
+
+ pLowestThread.createSuspended();
+ pLowestThread.setPriority(osl_Thread_PriorityLowest);
+
+ pHighestThread.resume();
+ pAboveNormalThread.resume();
+ pNormalThread.resume();
+ pBelowNormalThread.resume();
+ pLowestThread.resume();
+
+ ThreadHelper::thread_sleep_tenth_sec(5);
+
+ pHighestThread.suspend();
+ pAboveNormalThread.suspend();
+ pNormalThread.suspend();
+ pBelowNormalThread.suspend();
+ pLowestThread.suspend();
+
+ termAndJoinThread(&pHighestThread);
+ termAndJoinThread(&pAboveNormalThread);
+ termAndJoinThread(&pNormalThread);
+ termAndJoinThread(&pBelowNormalThread);
+ termAndJoinThread(&pLowestThread);
+
+ sal_Int32 nValueHighest = pHighestThread.getValue();
+
+ sal_Int32 nValueAboveNormal = pAboveNormalThread.getValue();
+
+ sal_Int32 nValueNormal = pNormalThread.getValue();
+
+ sal_Int32 nValueBelowNormal = pBelowNormalThread.getValue();
+
+ sal_Int32 nValueLowest = pLowestThread.getValue();
+
+ t_print("After 10 tenth seconds\n");
+ t_print("nValue in Highest Prio Thread is %d\n", static_cast<int>(nValueHighest));
+ t_print("nValue in AboveNormal Prio Thread is %d\n", static_cast<int>(nValueAboveNormal));
+ t_print("nValue in Normal Prio Thread is %d\n", static_cast<int>(nValueNormal));
+ t_print("nValue in BelowNormal Prio Thread is %d\n", static_cast<int>(nValueBelowNormal));
+ t_print("nValue in Lowest Prio Thread is %d\n", static_cast<int>(nValueLowest));
+
+#ifndef _WIN32
+ CPPUNIT_ASSERT_MESSAGE(
+ "SetPriority",
+ nValueHighest > 0
+ );
+ CPPUNIT_ASSERT_MESSAGE(
+ "SetPriority",
+ nValueAboveNormal > 0
+ );
+ CPPUNIT_ASSERT_MESSAGE(
+ "SetPriority",
+ nValueNormal > 0
+ );
+ CPPUNIT_ASSERT_MESSAGE(
+ "SetPriority",
+ nValueBelowNormal > 0
+ );
+ CPPUNIT_ASSERT_MESSAGE(
+ "SetPriority",
+ nValueLowest > 0
+ );
+#endif
+ }
+
+ void setPriority_004()
+ {
+ // initial 5 threads with different priorities
+ // OAddThread *pHighestThread = new OAddThread();
+ OAddThread pAboveNormalThread;
+ OAddThread pNormalThread;
+ OAddThread pBelowNormalThread;
+ OAddThread pLowestThread;
+
+ //Create them and start running at the same time
+ // pHighestThread->createSuspended();
+ // pHighestThread->setPriority(osl_Thread_PriorityHighest);
+
+ pAboveNormalThread.createSuspended();
+ pAboveNormalThread.setPriority(osl_Thread_PriorityAboveNormal);
+
+ pNormalThread.createSuspended();
+ pNormalThread.setPriority(osl_Thread_PriorityNormal);
+
+ pBelowNormalThread.createSuspended();
+ pBelowNormalThread.setPriority(osl_Thread_PriorityBelowNormal);
+
+ pLowestThread.createSuspended();
+ pLowestThread.setPriority(osl_Thread_PriorityLowest);
+
+ // pHighestThread->resume();
+ pAboveNormalThread.resume();
+ pNormalThread.resume();
+ pBelowNormalThread.resume();
+ pLowestThread.resume();
+
+ ThreadHelper::thread_sleep_tenth_sec(5);
+
+ // pHighestThread->suspend();
+ pAboveNormalThread.suspend();
+ pNormalThread.suspend();
+ pBelowNormalThread.suspend();
+ pLowestThread.suspend();
+
+ // termAndJoinThread(pHighestThread);
+ termAndJoinThread(&pAboveNormalThread);
+ termAndJoinThread(&pNormalThread);
+ termAndJoinThread(&pBelowNormalThread);
+ termAndJoinThread(&pLowestThread);
+
+ // sal_Int32 nValueHighest = 0;
+ // nValueHighest = pHighestThread->getValue();
+
+ sal_Int32 nValueAboveNormal = pAboveNormalThread.getValue();
+
+ sal_Int32 nValueNormal = pNormalThread.getValue();
+
+ sal_Int32 nValueBelowNormal = pBelowNormalThread.getValue();
+
+ sal_Int32 nValueLowest = pLowestThread.getValue();
+
+ t_print("After 5 tenth seconds\n");
+ t_print("nValue in AboveNormal Prio Thread is %d\n", static_cast<int>(nValueAboveNormal));
+ t_print("nValue in Normal Prio Thread is %d\n", static_cast<int>(nValueNormal));
+ t_print("nValue in BelowNormal Prio Thread is %d\n", static_cast<int>(nValueBelowNormal));
+ t_print("nValue in Lowest Prio Thread is %d\n", static_cast<int>(nValueLowest));
+
+ // delete pHighestThread;
+
+#ifndef _WIN32
+ CPPUNIT_ASSERT_MESSAGE(
+ "SetPriority",
+ /* nValueHighest > 0 && */
+ nValueAboveNormal > 0
+ );
+ CPPUNIT_ASSERT_MESSAGE(
+ "SetPriority",
+ nValueNormal > 0
+ );
+ CPPUNIT_ASSERT_MESSAGE(
+ "SetPriority",
+ nValueBelowNormal > 0
+ );
+ CPPUNIT_ASSERT_MESSAGE(
+ "SetPriority",
+ nValueLowest > 0
+ );
+#endif
+ }
+ void setPriority_005()
+ {
+ // initial 5 threads with different priorities
+ // OAddThread *pHighestThread = new OAddThread();
+ // OAddThread *pAboveNormalThread = new OAddThread();
+ OAddThread pNormalThread;
+ OAddThread pBelowNormalThread;
+ OAddThread pLowestThread;
+
+ //Create them and start running at the same time
+ // pHighestThread->createSuspended();
+ // pHighestThread->setPriority(osl_Thread_PriorityHighest);
+
+ // pAboveNormalThread->createSuspended();
+ // pAboveNormalThread->setPriority(osl_Thread_PriorityAboveNormal);
+
+ pNormalThread.createSuspended();
+ pNormalThread.setPriority(osl_Thread_PriorityNormal);
+
+ pBelowNormalThread.createSuspended();
+ pBelowNormalThread.setPriority(osl_Thread_PriorityBelowNormal);
+
+ pLowestThread.createSuspended();
+ pLowestThread.setPriority(osl_Thread_PriorityLowest);
+
+ // pHighestThread->resume();
+ // pAboveNormalThread->resume();
+ pNormalThread.resume();
+ pBelowNormalThread.resume();
+ pLowestThread.resume();
+
+ ThreadHelper::thread_sleep_tenth_sec(5);
+
+ // pHighestThread->suspend();
+ // pAboveNormalThread->suspend();
+ pNormalThread.suspend();
+ pBelowNormalThread.suspend();
+ pLowestThread.suspend();
+
+ // termAndJoinThread(pHighestThread);
+ // termAndJoinThread(pAboveNormalThread);
+ termAndJoinThread(&pNormalThread);
+ termAndJoinThread(&pBelowNormalThread);
+ termAndJoinThread(&pLowestThread);
+
+ // sal_Int32 nValueHighest = 0;
+ // nValueHighest = pHighestThread->getValue();
+
+ // sal_Int32 nValueAboveNormal = 0;
+ // nValueAboveNormal = pAboveNormalThread->getValue();
+
+ sal_Int32 nValueNormal = pNormalThread.getValue();
+
+ sal_Int32 nValueBelowNormal = pBelowNormalThread.getValue();
+
+ sal_Int32 nValueLowest = pLowestThread.getValue();
+
+ t_print("After 5 tenth seconds\n");
+ t_print("nValue in Normal Prio Thread is %d\n", static_cast<int>(nValueNormal));
+ t_print("nValue in BelowNormal Prio Thread is %d\n", static_cast<int>(nValueBelowNormal));
+ t_print("nValue in Lowest Prio Thread is %d\n", static_cast<int>(nValueLowest));
+
+#ifndef _WIN32
+ CPPUNIT_ASSERT_MESSAGE(
+ "SetPriority",
+ /* nValueHighest > 0 && */
+ /* nValueAboveNormal > 0 && */
+ nValueNormal > 0
+ );
+ CPPUNIT_ASSERT_MESSAGE(
+ "SetPriority",
+ nValueBelowNormal > 0
+ );
+ CPPUNIT_ASSERT_MESSAGE(
+ "SetPriority",
+ nValueLowest > 0
+ );
+#endif
+ }
+
+ CPPUNIT_TEST_SUITE(setPriority);
+#ifndef __sun
+ CPPUNIT_TEST(setPriority_002);
+ CPPUNIT_TEST(setPriority_003);
+ CPPUNIT_TEST(setPriority_004);
+ CPPUNIT_TEST(setPriority_005);
+#endif
+ CPPUNIT_TEST(setPriority_001_1);
+ CPPUNIT_TEST(setPriority_001_2);
+ CPPUNIT_TEST(setPriority_001_3);
+ CPPUNIT_TEST(setPriority_001_4);
+ CPPUNIT_TEST(setPriority_001_5);
+ CPPUNIT_TEST_SUITE_END();
+ }; // class setPriority
+
+ /** Test of the osl::Thread::getPriority method
+ */
+ class getPriority : public CppUnit::TestFixture
+ {
+ public:
+ // insert your test code here.
+ void getPriority_001()
+ {
+ OAddThread *pHighestThread = new OAddThread();
+
+ //Create them and start running at the same time
+ pHighestThread->create();
+ pHighestThread->setPriority(osl_Thread_PriorityHighest);
+
+ oslThreadPriority aPriority = pHighestThread->getPriority();
+ termAndJoinThread(pHighestThread);
+ delete pHighestThread;
+
+ ThreadHelper::outputPriority(aPriority);
+
+// LLA: Priority settings may not work within some OS versions.
+#if defined(_WIN32) || defined(__sun)
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "getPriority",
+ osl_Thread_PriorityHighest, aPriority
+ );
+#else
+// LLA: Linux
+// NO_PTHREAD_PRIORITY ???
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "getPriority",
+ osl_Thread_PriorityNormal, aPriority
+ );
+#endif
+ }
+
+ CPPUNIT_TEST_SUITE(getPriority);
+ CPPUNIT_TEST(getPriority_001);
+ CPPUNIT_TEST_SUITE_END();
+ }; // class getPriority
+
+ class getIdentifier : public CppUnit::TestFixture
+ {
+ public:
+ // initialise your test code values here.
+
+ void getIdentifier_001()
+ {
+ // insert your test code here.
+ }
+
+ CPPUNIT_TEST_SUITE(getIdentifier);
+ CPPUNIT_TEST(getIdentifier_001);
+ CPPUNIT_TEST_SUITE_END();
+ }; // class getIdentifier
+
+ /** Test of the osl::Thread::getCurrentIdentifier method
+ */
+ class getCurrentIdentifier : public CppUnit::TestFixture
+ {
+ public:
+ void getCurrentIdentifier_001()
+ {
+ oslThreadIdentifier oId;
+ OCountThread* pCountThread = new OCountThread;
+ pCountThread->create();
+ pCountThread->setWait(3);
+ oId = Thread::getCurrentIdentifier();
+ oslThreadIdentifier oIdChild = pCountThread->getIdentifier();
+ termAndJoinThread(pCountThread);
+ delete pCountThread;
+
+ CPPUNIT_ASSERT_MESSAGE(
+ "Get the identifier for the current active thread.",
+ oId != oIdChild);
+ }
+
+ CPPUNIT_TEST_SUITE(getCurrentIdentifier);
+ CPPUNIT_TEST(getCurrentIdentifier_001);
+ CPPUNIT_TEST_SUITE_END();
+ }; // class getCurrentIdentifier
+
+ /** Test of the osl::Thread::wait method
+ */
+ class waittest : public CppUnit::TestFixture
+ {
+ public:
+ /** call wait in the run method
+
+ ALGORITHM:
+ tested thread wait nWaitSec seconds, main thread sleep (2) seconds,
+ then terminate the tested thread, due to the fact that the thread do a sleep(1) + wait(5)
+ it's finish after 6 seconds.
+ */
+ void wait_001()
+ {
+ OCountThread *aCountThread = new OCountThread();
+ sal_Int32 nWaitSec = 5;
+ aCountThread->setWait(nWaitSec);
+ // thread runs at least 5 seconds.
+ bool bRes = aCountThread->create();
+ CPPUNIT_ASSERT_MESSAGE ( "Can't start thread!", bRes );
+
+ //record the time when the running begin
+ StopWatch aStopWatch;
+ aStopWatch.start();
+
+ // wait a little bit, to let the thread the time, to start
+ ThreadHelper::thread_sleep_tenth_sec( 4 );
+
+ // if wait works,
+ // this function returns, after 4 sec. later
+ termAndJoinThread(aCountThread);
+
+ // value should be one.
+ sal_Int32 nValue = aCountThread->getValue();
+
+ aStopWatch.stop();
+
+ // sal_uInt32 nSec = aTimeVal_after.Seconds - aTimeVal_befor.Seconds;
+ double nTenthSec = aStopWatch.getTenthSec();
+ double nSec = aStopWatch.getSeconds();
+ delete aCountThread;
+ t_print("nTenthSec = %f \n", nTenthSec);
+ t_print("nSec = %f \n", nSec);
+ t_print("nValue = %d \n", static_cast<int>(nValue));
+
+ CPPUNIT_ASSERT_MESSAGE(
+ "Wait: Blocks the calling thread for the given number of time.",
+ nTenthSec >= 5
+ );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "Wait: Blocks the calling thread for the given number of time.",
+ sal_Int32(1), nValue
+ );
+
+ }
+
+ CPPUNIT_TEST_SUITE(waittest);
+ CPPUNIT_TEST(wait_001);
+ CPPUNIT_TEST_SUITE_END();
+ }; // class waittest
+
+ /** osl::Thread::yield method: can not design good test scenario to test up to now
+ */
+ class yield : public CppUnit::TestFixture
+ {
+ public:
+ void yield_001()
+ {
+ // insert your test code here.
+ }
+
+ CPPUNIT_TEST_SUITE(yield);
+ CPPUNIT_TEST(yield_001);
+ CPPUNIT_TEST_SUITE_END();
+ }; // class yield
+
+ /** Test of the osl::Thread::schedule method
+ */
+ class schedule : public CppUnit::TestFixture
+ {
+ public:
+
+ /** The requested thread will get terminate the next time schedule() is called.
+
+ Note: on UNX, if call suspend thread is not the to be suspended thread, the to be
+ suspended thread will get suspended the next time schedule() is called,
+ while on w32, it's nothing with schedule.
+
+ check if suspend and terminate work well via schedule
+ */
+ void schedule_001()
+ {
+ OAddThread* aThread = new OAddThread();
+ bool bRes = aThread->create();
+ CPPUNIT_ASSERT_MESSAGE ( "Can't start thread!", bRes );
+
+ ThreadHelper::thread_sleep_tenth_sec(2);
+ aThread->suspend();
+ ThreadHelper::thread_sleep_tenth_sec(1);
+ sal_Int32 nValue = aThread->getValue();
+ ThreadHelper::thread_sleep_tenth_sec(3);
+ sal_Int32 nLaterValue = aThread->getValue();
+ // resumeAndWaitThread(aThread);
+ t_print(" value = %d\n", static_cast<int>(nValue));
+ t_print("later value = %d\n", static_cast<int>(nLaterValue));
+ // if value and latervalue not equal, then the thread would not suspended
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "Schedule: suspend works.",
+ nValue, nLaterValue
+ );
+
+ aThread->resume();
+ ThreadHelper::thread_sleep_tenth_sec(2);
+
+ aThread->terminate();
+ sal_Int32 nValue_term = aThread->getValue();
+
+ aThread->join();
+ sal_Int32 nValue_join = aThread->getValue();
+
+ t_print("value after term = %d\n", static_cast<int>(nValue_term));
+ t_print("value after join = %d\n", static_cast<int>(nValue_join));
+
+ // nValue_term and nValue_join should be the same
+ // but should be differ from nValue
+
+ delete aThread;
+ //check if thread really terminate after call terminate, if join immediately return
+ CPPUNIT_ASSERT_MESSAGE(
+ "Schedule: Returns False if the thread should terminate.",
+ nValue_join - nValue_term <= 1
+ );
+ CPPUNIT_ASSERT_MESSAGE(
+ "Schedule: Returns False if the thread should terminate.",
+ nValue_join - nValue_term >= 0
+ );
+
+ }
+
+ /** design a thread that has not call schedule in the workfunction--run method
+ */
+ void schedule_002()
+ {
+ ONoScheduleThread aThread; // this thread runs 10 sec. (no schedule() used)
+ bool bRes = aThread.create();
+ CPPUNIT_ASSERT_MESSAGE ( "Can't start thread!", bRes );
+
+ ThreadHelper::thread_sleep_tenth_sec(2);
+ aThread.suspend();
+ sal_Int32 nValue = aThread.getValue();
+
+ ThreadHelper::thread_sleep_tenth_sec(3);
+ sal_Int32 nLaterValue = aThread.getValue();
+ ThreadHelper::thread_sleep_tenth_sec(5);
+
+ resumeAndWaitThread(&aThread);
+
+ t_print(" value = %d\n", static_cast<int>(nValue));
+ t_print("later value = %d\n", static_cast<int>(nLaterValue));
+
+ //On windows, suspend works, so the values are same
+#ifdef _WIN32
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "Schedule: don't schedule in thread run method, suspend works.",
+ nValue, nLaterValue
+ );
+#endif
+
+ //On UNX, suspend does not work, so the difference of the values equals to sleep seconds number
+#ifdef UNX
+ aThread.resume();
+ CPPUNIT_ASSERT_MESSAGE(
+ "Schedule: don't schedule in thread run method, suspend does not work too.",
+ nLaterValue > nValue
+ );
+#endif
+
+ // terminate will not work if no schedule in thread's work function
+ termAndJoinThread(&aThread);
+ sal_Int32 nValue_term = aThread.getValue();
+
+ t_print(" value term = %d\n", static_cast<int>(nValue_term));
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "Schedule: don't schedule in thread run method, terminate failed.",
+ static_cast<sal_Int32>(10), nValue_term
+ );
+ }
+
+ CPPUNIT_TEST_SUITE(schedule);
+ CPPUNIT_TEST(schedule_001);
+ CPPUNIT_TEST(schedule_002);
+ CPPUNIT_TEST_SUITE_END();
+ }; // class schedule
+
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::create, "osl_Thread");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::createSuspended, "osl_Thread");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::suspend, "osl_Thread");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::resume, "osl_Thread");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::terminate, "osl_Thread");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::join, "osl_Thread");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::isRunning, "osl_Thread");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::setPriority, "osl_Thread");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::getPriority, "osl_Thread");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::getIdentifier, "osl_Thread");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::getCurrentIdentifier, "osl_Thread");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::waittest, "osl_Thread");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::yield, "osl_Thread");
+ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Thread::schedule, "osl_Thread");
+} // namespace osl_Thread
+
+// destroy function when the binding thread terminate
+static void destroyCallback(void * data)
+{
+ delete[] static_cast<char *>(data);
+}
+
+static ThreadData myThreadData(destroyCallback);
+
+namespace {
+
+class myKeyThread : public Thread
+{
+public:
+ // a public char member for test result checking
+ char m_Char_Test;
+ // for pass thread-special data to thread
+ explicit myKeyThread(const char cData)
+ : m_Char_Test(0)
+ {
+ m_nData = cData;
+ }
+private:
+ char m_nData;
+
+ void SAL_CALL run() override
+ {
+ char * pc = new char[2];
+// strcpy(pc, &m_nData);
+ memcpy(pc, &m_nData, 1);
+ pc[1] = '\0';
+
+ myThreadData.setData(pc);
+ char* pData = static_cast<char*>(myThreadData.getData());
+ m_Char_Test = *pData;
+ // wait for long time to check the data value in main thread
+ ThreadHelper::thread_sleep_tenth_sec(3);
+ }
+public:
+ virtual ~myKeyThread() override
+ {
+ if (isRunning())
+ {
+ t_print("error: not terminated.\n");
+ }
+ }
+};
+
+}
+
+static ThreadData idData;
+
+namespace {
+
+class idThread: public Thread
+{
+public:
+ oslThreadIdentifier m_Id;
+private:
+ void SAL_CALL run() override
+ {
+ std::unique_ptr<oslThreadIdentifier> pId( new oslThreadIdentifier );
+ *pId = getIdentifier();
+ idData.setData(pId.get());
+ oslThreadIdentifier* pIdData = static_cast<oslThreadIdentifier*>(idData.getData());
+ //t_print("Thread %d has Data %d\n", getIdentifier(), *pIdData);
+ m_Id = *pIdData;
+ }
+
+public:
+ virtual ~idThread() override
+ {
+ if (isRunning())
+ {
+ t_print("error: not terminated.\n");
+ }
+ }
+};
+
+}
+
+namespace osl_ThreadData
+{
+
+ class ctors : public CppUnit::TestFixture
+ {
+ public:
+
+ // insert your test code here.
+ void ctor_001()
+ {
+
+ }
+
+ CPPUNIT_TEST_SUITE(ctors);
+ CPPUNIT_TEST(ctor_001);
+ CPPUNIT_TEST_SUITE_END();
+ }; // class ctors
+
+ class setData : public CppUnit::TestFixture
+ {
+ public:
+
+ /** the same instance of the class can have different values in different threads
+ */
+ void setData_001()
+ {
+ idThread aThread1;
+ aThread1.create();
+ idThread aThread2;
+ aThread2.create();
+
+ aThread1.join();
+ aThread2.join();
+
+ oslThreadIdentifier aThreadId1 = aThread1.getIdentifier();
+ oslThreadIdentifier aThreadId2 = aThread2.getIdentifier();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "ThreadData setData: ",
+ aThread1.m_Id, aThreadId1
+ );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "ThreadData setData: ",
+ aThread2.m_Id, aThreadId2
+ );
+
+ }
+
+ void setData_002()
+ {
+ // at first, set the data a value
+ char* pc = new char[2];
+ char nData = 'm';
+ pc[0] = nData;
+ pc[1] = '\0';
+
+ myThreadData.setData(pc);
+
+ myKeyThread aThread1('a');
+ aThread1.create();
+ myKeyThread aThread2('b');
+ aThread2.create();
+ // aThread1 and aThread2 should have not terminated yet, check current data, not 'a' 'b'
+ char* pChar = static_cast<char*>(myThreadData.getData());
+ char aChar = *pChar;
+
+ aThread1.join();
+ aThread2.join();
+
+ // the saved thread data of aThread1 & aThread2, different
+ char cData1 = aThread1.m_Char_Test;
+ char cData2 = aThread2.m_Char_Test;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "ThreadData setData: ",
+ 'a', cData1
+ );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "ThreadData setData: ",
+ 'b', cData2
+ );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "ThreadData setData: ",
+ 'm', aChar
+ );
+
+ }
+ /** setData the second time, and then getData
+ */
+ void setData_003()
+ {
+ // at first, set the data a value
+ char* pc = new char[2];
+ char nData = 'm';
+ memcpy(pc, &nData, 1);
+ pc[1] = '\0';
+ myThreadData.setData(pc);
+
+ myKeyThread aThread1('a');
+ aThread1.create();
+ myKeyThread aThread2('b');
+ aThread2.create();
+ // aThread1 and aThread2 should have not terminated yet
+ // setData the second time
+ char* pc2 = new char[2];
+ nData = 'o';
+ memcpy(pc2, &nData, 1);
+ pc2[1] = '\0';
+
+ myThreadData.setData(pc2);
+ char* pChar = static_cast<char*>(myThreadData.getData());
+ char aChar = *pChar;
+
+ aThread1.join();
+ aThread2.join();
+
+ // the saved thread data of aThread1 & aThread2, different
+ char cData1 = aThread1.m_Char_Test;
+ char cData2 = aThread2.m_Char_Test;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "ThreadData setData: ",
+ 'a', cData1
+ );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "ThreadData setData: ",
+ 'b', cData2
+ );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "ThreadData setData: ",
+ 'o', aChar
+ );
+ }
+
+ CPPUNIT_TEST_SUITE(setData);
+ CPPUNIT_TEST(setData_001);
+ CPPUNIT_TEST(setData_002);
+ CPPUNIT_TEST(setData_003);
+ CPPUNIT_TEST_SUITE_END();
+ }; // class setData
+
+ class getData : public CppUnit::TestFixture
+ {
+ public:
+
+ // After setData in child threads, get Data in the main thread, should be independent
+ void getData_001()
+ {
+ char* pc = new char[2];
+ strcpy(pc, "i");
+ myThreadData.setData(pc);
+
+ myKeyThread aThread1('c');
+ aThread1.create();
+ myKeyThread aThread2('d');
+ aThread2.create();
+
+ aThread1.join();
+ aThread2.join();
+
+ char cData1 = aThread1.m_Char_Test;
+ char cData2 = aThread2.m_Char_Test;
+
+ char* pChar = static_cast<char*>(myThreadData.getData());
+ char aChar = *pChar;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "ThreadData setData: ",
+ 'c', cData1
+ );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "ThreadData setData: ",
+ 'd', cData2
+ );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "ThreadData setData: ",
+ 'i', aChar
+ );
+ }
+
+ // setData then change the value in the address data pointer points,
+ // and then getData, should get the new value
+ void getData_002()
+ {
+ char* pc = new char[2];
+ char nData = 'i';
+ memcpy(pc, &nData, 1);
+ pc[1] = '\0';
+
+ myThreadData.setData(pc);
+
+ myKeyThread aThread1('a');
+ aThread1.create();
+ myKeyThread aThread2('b');
+ aThread2.create();
+
+ // change the value which pc points
+ char nData2 = 'j';
+ memcpy(pc, &nData2, 1);
+ pc[1] = '\0';
+
+ void* pChar = myThreadData.getData();
+ char aChar = *static_cast<char*>(pChar);
+
+ aThread1.join();
+ aThread2.join();
+
+ char cData1 = aThread1.m_Char_Test;
+ char cData2 = aThread2.m_Char_Test;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "ThreadData setData: ",
+ 'a', cData1
+ );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "ThreadData setData: ",
+ 'b', cData2
+ );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "ThreadData setData: ",
+ 'j', aChar
+ );
+
+ }
+
+ CPPUNIT_TEST_SUITE(getData);
+ CPPUNIT_TEST(getData_001);
+ CPPUNIT_TEST(getData_002);
+ CPPUNIT_TEST_SUITE_END();
+ }; // class getData
+
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_ThreadData::ctors);
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_ThreadData::setData);
+ CPPUNIT_TEST_SUITE_REGISTRATION(osl_ThreadData::getData);
+} // namespace osl_ThreadData
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/osl/process/osl_Thread.xsce b/sal/qa/osl/process/osl_Thread.xsce
new file mode 100644
index 000000000..11d0c5da1
--- /dev/null
+++ b/sal/qa/osl/process/osl_Thread.xsce
@@ -0,0 +1,18 @@
+#
+# 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/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+osl_Thread.setPriority.setPriority_001_1 unxsols4
diff --git a/sal/qa/osl/process/osl_process.cxx b/sal/qa/osl/process/osl_process.cxx
new file mode 100644
index 000000000..c396a06b5
--- /dev/null
+++ b/sal/qa/osl/process/osl_process.cxx
@@ -0,0 +1,450 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifdef IOS
+#define CPPUNIT_PLUGIN_EXPORTED_NAME cppunitTest_osl_process
+#endif
+
+#include <sal/types.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <osl/process.h>
+#include <osl/file.hxx>
+#include <osl/thread.h>
+#include <rtl/ustring.hxx>
+#include <signal.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <osl/module.hxx>
+#include <sal/macros.h>
+
+#if defined HAVE_VALGRIND_HEADERS
+#include <valgrind/valgrind.h>
+#elif !defined _WIN32
+#define RUNNING_ON_VALGRIND false
+#endif
+
+#if !defined(_WIN32) // Windows
+#include <unistd.h>
+#endif
+
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <algorithm>
+#include <iterator>
+#include <string>
+
+#ifdef UNX
+#if defined( MACOSX )
+# include <crt_externs.h>
+# define environ (*_NSGetEnviron())
+# else
+ extern char** environ;
+# endif
+#endif
+
+using namespace osl;
+
+/** get binary Path.
+*/
+static OUString getExecutablePath()
+{
+ OUString dirPath;
+ osl::Module::getUrlFromAddress(
+ reinterpret_cast<oslGenericFunction>(&getExecutablePath), dirPath);
+ dirPath = dirPath.copy( 0, dirPath.lastIndexOf('/') );
+ dirPath = OUString::Concat(dirPath.subView( 0, dirPath.lastIndexOf('/') + 1)) +
+ "Executable";
+ return dirPath;
+}
+
+#if !defined _WIN32
+
+namespace {
+
+class exclude
+{
+public:
+
+ explicit exclude(const std::vector<OString>& exclude_list)
+ {
+ for (auto& exclude_list_item : exclude_list)
+ exclude_list_.push_back(env_var_name(exclude_list_item));
+ }
+
+ bool operator() (const OString& env_var) const
+ {
+ return (exclude_list_.end() !=
+ std::find(
+ exclude_list_.begin(),
+ exclude_list_.end(),
+ env_var_name(env_var)));
+ }
+
+private:
+
+ // extract the name from an environment variable
+ // that is given in the form "NAME=VALUE"
+ static OString env_var_name(const OString& env_var)
+ {
+ sal_Int32 pos_equal_sign =
+ env_var.indexOf('=');
+
+ if (pos_equal_sign != -1)
+ return env_var.copy(0, pos_equal_sign);
+
+ return OString();
+ }
+
+private:
+ std::vector<OString> exclude_list_;
+};
+
+ void tidy_container(std::vector<OString> &env_container)
+ {
+ //sort them because there are no guarantees to ordering
+ std::sort(env_container.begin(), env_container.end());
+ if (RUNNING_ON_VALGRIND)
+ {
+ env_container.erase(
+ std::remove_if(
+ env_container.begin(), env_container.end(),
+ [](OString const & s) {
+ return s.startsWith("LD_PRELOAD=")
+ || s.startsWith("VALGRIND_LIB="); }),
+ env_container.end());
+ }
+ }
+}
+
+ static void read_parent_environment(std::vector<OString>* env_container)
+ {
+ for (int i = 0; environ[i] != nullptr; i++)
+ env_container->push_back(OString(environ[i]));
+ tidy_container(*env_container);
+ }
+
+#endif
+
+class Test_osl_executeProcess : public CppUnit::TestFixture
+{
+ const OUString env_param_;
+
+ OUString temp_file_url_;
+ OUString temp_file_path_;
+ rtl_uString* parameters_[2];
+ static const int parameters_count_ = 2;
+ OUString suCWD;
+ OUString suExecutableFileURL;
+
+public:
+
+ // ctor
+ Test_osl_executeProcess() :
+ env_param_(OUString("-env")), suCWD(getExecutablePath())
+ {
+ parameters_[0] = env_param_.pData;
+
+#if defined(_WIN32)
+ suExecutableFileURL = suCWD + "/" "osl_process_child.exe";
+#else
+ suExecutableFileURL = suCWD + "/" "osl_process_child";
+#endif
+ }
+
+ virtual void setUp() override
+ {
+ temp_file_path_ = create_temp_file(temp_file_url_);
+ parameters_[1] = temp_file_path_.pData;
+ }
+
+ virtual void tearDown() override
+ {
+ osl::File::remove(temp_file_url_);
+ }
+
+ OUString create_temp_file(OUString &temp_file_url)
+ {
+ FileBase::RC rc = FileBase::createTempFile(nullptr, nullptr, &temp_file_url);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("createTempFile failed", FileBase::E_None, rc);
+
+ OUString temp_file_path;
+ rc = FileBase::getSystemPathFromFileURL(temp_file_url, temp_file_path);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("getSystemPathFromFileURL failed", FileBase::E_None, rc);
+
+ return temp_file_path;
+ }
+
+#if !defined _WIN32
+
+ void read_child_environment(std::vector<OString>* env_container)
+ {
+ OString temp_file_name = OUStringToOString(OUString(
+ parameters_[1]), osl_getThreadTextEncoding());
+ std::ifstream file(temp_file_name.getStr());
+
+ CPPUNIT_ASSERT_MESSAGE
+ (
+ "I/O error, cannot open child environment file",
+ file.is_open()
+ );
+
+ std::string line;
+ line.reserve(1024);
+ while (std::getline(file, line, '\0'))
+ env_container->push_back(OString(line.c_str()));
+ tidy_container(*env_container);
+ }
+
+ // environment of the child process that was
+ // started. The child process writes his
+ // environment into a file
+ void compare_environments()
+ {
+ std::vector<OString> parent_env;
+ read_parent_environment(&parent_env);
+
+ std::vector<OString> child_env;
+ read_child_environment(&child_env);
+
+ OString msg(
+ OString::number(parent_env.size()) + "/"
+ + OString::number(child_env.size()));
+ auto min = std::min(parent_env.size(), child_env.size());
+ for (decltype(min) i = 0; i != min; ++i) {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ msg.getStr(), parent_env[i], child_env[i]);
+ }
+ if (parent_env.size() != child_env.size()) {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ (parent_env.size() >= child_env.size()
+ ? parent_env.back() : child_env.back()).getStr(),
+ parent_env.size(), child_env.size());
+ }
+ }
+
+ // compare the equal environment parts and the
+ // different part of the child environment
+ bool compare_merged_environments(const std::vector<OString>& different_env_vars)
+ {
+ std::vector<OString> parent_env;
+ read_parent_environment(&parent_env);
+
+ for (auto& env : parent_env)
+ std::cout << "initially parent env: " << env << "\n";
+
+ //remove the environment variables that we have changed
+ //in the child environment from the read parent environment
+ parent_env.erase(
+ std::remove_if(parent_env.begin(), parent_env.end(), exclude(different_env_vars)),
+ parent_env.end());
+
+ for (auto& env : parent_env)
+ std::cout << "stripped parent env: " << env << "\n";
+
+ //read the child environment and exclude the variables that
+ //are different
+ std::vector<OString> child_env;
+ read_child_environment(&child_env);
+
+ for (auto& env : child_env)
+ std::cout << "initial child env: " << env << "\n";
+ //partition the child environment into the variables that
+ //are different to the parent environment (they come first)
+ //and the variables that should be equal between parent
+ //and child environment
+ auto iter_logical_end =
+ std::stable_partition(child_env.begin(), child_env.end(), exclude(different_env_vars));
+
+ std::vector<OString> different_child_env_vars(child_env.begin(), iter_logical_end);
+ child_env.erase(child_env.begin(), iter_logical_end);
+
+ for (auto& env : child_env)
+ std::cout << "stripped child env: " << env << "\n";
+
+ bool common_env_size_equals = (parent_env.size() == child_env.size());
+ bool common_env_content_equals = std::equal(child_env.begin(), child_env.end(), parent_env.begin());
+
+ for (auto& env_var : different_env_vars)
+ std::cout << "different should be: " << env_var << "\n";
+
+ for (auto& env_var : different_child_env_vars)
+ std::cout << "different are: " << env_var << "\n";
+
+ bool different_env_size_equals = (different_child_env_vars.size() == different_env_vars.size());
+ bool different_env_content_equals =
+ std::equal(different_env_vars.begin(), different_env_vars.end(), different_child_env_vars.begin());
+
+ return (common_env_size_equals && common_env_content_equals &&
+ different_env_size_equals && different_env_content_equals);
+ }
+
+ // test that parent and child process have the
+ // same environment when osl_executeProcess will
+ // be called without setting new environment
+ // variables
+ void osl_execProc_parent_equals_child_environment()
+ {
+ oslProcess process;
+ oslProcessError osl_error = osl_executeProcess(
+ suExecutableFileURL.pData,
+ parameters_,
+ parameters_count_,
+ osl_Process_NORMAL,
+ nullptr,
+ suCWD.pData,
+ nullptr,
+ 0,
+ &process);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE
+ (
+ "osl_createProcess failed",
+ osl_Process_E_None, osl_error
+ );
+
+ osl_error = ::osl_joinProcess(process);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE
+ (
+ "osl_joinProcess returned with failure",
+ osl_Process_E_None, osl_error
+ );
+
+ osl_freeProcessHandle(process);
+
+ compare_environments();
+ }
+
+ #define ENV1 "PAT=a:\\"
+ #define ENV2 "PATHb=b:\\"
+ #define ENV3 "Patha=c:\\"
+ #define ENV4 "Patha=d:\\"
+
+ void osl_execProc_merged_child_environment()
+ {
+ rtl_uString* child_env[4];
+ OUString env1(ENV1);
+ OUString env2(ENV2);
+ OUString env3(ENV3);
+ OUString env4(ENV4);
+
+ child_env[0] = env1.pData;
+ child_env[1] = env2.pData;
+ child_env[2] = env3.pData;
+ child_env[3] = env4.pData;
+
+ oslProcess process;
+ oslProcessError osl_error = osl_executeProcess(
+ suExecutableFileURL.pData,
+ parameters_,
+ parameters_count_,
+ osl_Process_NORMAL,
+ nullptr,
+ suCWD.pData,
+ child_env,
+ SAL_N_ELEMENTS(child_env),
+ &process);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE
+ (
+ "osl_createProcess failed",
+ osl_Process_E_None, osl_error
+ );
+
+ osl_error = ::osl_joinProcess(process);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE
+ (
+ "osl_joinProcess returned with failure",
+ osl_Process_E_None, osl_error
+ );
+
+ osl_freeProcessHandle(process);
+
+ std::vector<OString> different_child_env_vars
+ {
+ ENV1,
+ ENV2,
+ ENV4
+ };
+
+ CPPUNIT_ASSERT_MESSAGE
+ (
+ "osl_execProc_merged_child_environment",
+ compare_merged_environments(different_child_env_vars)
+ );
+ }
+
+#endif
+
+ void osl_execProc_test_batch()
+ {
+ oslProcess process;
+#if defined(_WIN32)
+ OUString suBatch = suCWD + "/batch.bat";
+#else
+ OUString suBatch = suCWD + "/batch.sh";
+#endif
+ oslProcessError osl_error = osl_executeProcess(
+ suBatch.pData,
+ nullptr,
+ 0,
+ osl_Process_NORMAL,
+ nullptr,
+ suCWD.pData,
+ nullptr,
+ 0,
+ &process);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE
+ (
+ "osl_createProcess failed",
+ osl_Process_E_None, osl_error
+ );
+
+ osl_error = ::osl_joinProcess(process);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE
+ (
+ "osl_joinProcess returned with failure",
+ osl_Process_E_None, osl_error
+ );
+
+ osl_freeProcessHandle(process);
+ }
+
+ CPPUNIT_TEST_SUITE(Test_osl_executeProcess);
+ //TODO: Repair these (at least under Windows)
+#if !defined(_WIN32)
+ CPPUNIT_TEST(osl_execProc_parent_equals_child_environment);
+ CPPUNIT_TEST(osl_execProc_merged_child_environment);
+#endif
+ CPPUNIT_TEST(osl_execProc_test_batch);
+ ///TODO: Repair test (or tested function ;-) - test fails.
+ CPPUNIT_TEST_SUITE_END();
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test_osl_executeProcess);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/osl/process/osl_process_child.cxx b/sal/qa/osl/process/osl_process_child.cxx
new file mode 100644
index 000000000..17f749bc2
--- /dev/null
+++ b/sal/qa/osl/process/osl_process_child.cxx
@@ -0,0 +1,101 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#if defined(_WIN32) // Windows
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#else
+# include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fstream>
+#include <string.h>
+
+
+#ifdef UNX
+#if defined( MACOSX )
+# include <crt_externs.h>
+# define environ (*_NSGetEnviron())
+# else
+ extern char** environ;
+# endif
+#endif
+
+#ifdef _WIN32
+# define SLEEP(t) (Sleep((t)*1000))
+#else
+# define SLEEP(t) (sleep((t)))
+#endif
+
+static void wait_for_seconds(char* time)
+{
+ SLEEP(atoi(time));
+}
+
+#ifdef _WIN32
+
+static void w_to_a(LPCWSTR strW, LPSTR strA, DWORD size)
+{
+ WideCharToMultiByte(CP_ACP, 0, strW, -1, strA, size, nullptr, nullptr);
+}
+
+ static void dump_env(char* file_path)
+ {
+ LPWSTR env = GetEnvironmentStringsW();
+ LPWSTR p = env;
+
+ std::ofstream file(file_path);
+
+ char buffer[32767];
+ while (size_t l = wcslen(p))
+ {
+ w_to_a(p, buffer, sizeof(buffer));
+ file << buffer << '\0';
+ p += l + 1;
+ }
+ FreeEnvironmentStringsW(env);
+ }
+#else
+ static void dump_env(char* file_path)
+ {
+ std::ofstream file(file_path);
+ for (int i = 0; environ[i] != nullptr; ++i)
+ file << environ[i] << '\0';
+ }
+#endif
+
+int main(int argc, char* argv[])
+{
+ if (argc > 2)
+ {
+ if (strcmp("-join", argv[1]) == 0)
+ {
+ // coverity[tainted_data] - this is a build-time only test tool
+ wait_for_seconds(argv[2]);
+ }
+ else if (strcmp("-env", argv[1]) == 0)
+ dump_env(argv[2]);
+ }
+
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/osl/profile/osl_old_testprofile.cxx b/sal/qa/osl/profile/osl_old_testprofile.cxx
new file mode 100644
index 000000000..d1556bb15
--- /dev/null
+++ b/sal/qa/osl/profile/osl_old_testprofile.cxx
@@ -0,0 +1,62 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/types.h>
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <osl/profile.h>
+#include <rtl/bootstrap.hxx>
+
+namespace osl_Profile
+{
+ class oldtests : public CppUnit::TestFixture
+ {
+ public:
+ void test_profile();
+
+ CPPUNIT_TEST_SUITE( oldtests );
+ CPPUNIT_TEST( test_profile );
+ CPPUNIT_TEST_SUITE_END( );
+ };
+
+void oldtests::test_profile()
+{
+ OUString baseUrl;
+ CPPUNIT_ASSERT(rtl::Bootstrap::get("UserInstallation", baseUrl));
+
+ // successful write
+ oslProfile hProfile = osl_openProfile( OUString(baseUrl + "/soffice.ini").pData, osl_Profile_WRITELOCK );
+ CPPUNIT_ASSERT(hProfile != nullptr);
+ CPPUNIT_ASSERT_MESSAGE(
+ "cannot write into init file",
+ osl_writeProfileBool( hProfile, "testsection", "testbool", true ));
+ CPPUNIT_ASSERT(osl_closeProfile( hProfile ));
+
+ // unsuccessful open
+ CPPUNIT_ASSERT_EQUAL(oslProfile(nullptr), osl_openProfile( OUString(baseUrl + "/not_existing_path/soffice.ini").pData, osl_Profile_WRITELOCK ));
+}
+
+} // namespace osl_Profile
+
+CPPUNIT_TEST_SUITE_REGISTRATION( osl_Profile::oldtests );
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/osl/security/TODO.h b/sal/qa/osl/security/TODO.h
new file mode 100644
index 000000000..082c54633
--- /dev/null
+++ b/sal/qa/osl/security/TODO.h
@@ -0,0 +1,8 @@
+#include "sal/types.h"
+#define T1(x) do { x; } while (0)
+#define T2(x) do { x; } while (sal_False)
+#define T3(x) do { x; } while (false)
+#define T4(x, y) do { x; } while (y)
+#define T5(x) T4(x, 0)
+#define T6(x) T4(x, sal_False)
+#define T7(x) T4(x, false)
diff --git a/sal/qa/osl/security/osl_Security.cxx b/sal/qa/osl/security/osl_Security.cxx
new file mode 100644
index 000000000..34417cd14
--- /dev/null
+++ b/sal/qa/osl/security/osl_Security.cxx
@@ -0,0 +1,624 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <algorithm>
+#ifdef _WIN32
+#if !defined WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <sddl.h>
+#undef min
+#endif
+#include "osl_Security_Const.h"
+#include <osl/thread.h>
+#include <rtl/process.h>
+#include <rtl/strbuf.hxx>
+#include <sal/log.hxx>
+#include <o3tl/char16_t2wchar_t.hxx>
+
+using namespace osl;
+using namespace rtl;
+
+/** print a UNICODE String.
+*/
+static void printUString( const OUString & str )
+{
+ //t_print("#printUString_u# " );
+ OString aString = OUStringToOString( str, RTL_TEXTENCODING_ASCII_US );
+ t_print("%s\n", aString.getStr( ) );
+}
+
+// test code start here
+
+namespace osl_Security
+{
+
+ /** testing the method:
+ Security()
+ */
+ class ctors : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ void ctors_001( )
+ {
+ ::osl::Security aSec;
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: create a security its handle should not be NULL.",
+ aSec.getHandle( ) != nullptr );
+ }
+
+ CPPUNIT_TEST_SUITE( ctors );
+ CPPUNIT_TEST( ctors_001 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class ctors
+
+ /** testing the methods:
+ inline sal_Bool SAL_CALL logonUser(const OUString& strName,
+ const OUString& strPasswd);
+ inline sal_Bool SAL_CALL logonUser(const OUString & strName,
+ const OUString & strPasswd,
+ const OUString & strFileServer);
+ */
+ class logonUser : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes;
+
+ void logonUser_user_pwd( )
+ {
+ ::osl::Security aSec;
+ bRes = aSec.logonUser( aLogonUser, aLogonPasswd );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: check logon user through forwarded user name, pwd, passed in (UNX), failed in (W32).",
+ bRes );
+ }
+
+ void logonUser_user_pwd_server( )
+ {
+ ::osl::Security aSec;
+ bRes = aSec.logonUser( aLogonUser, aLogonPasswd, aFileServer );
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: check logon user through forwarded user name, pwd and server name, failed in (UNX)(W32).",
+ bRes );
+ }
+
+ CPPUNIT_TEST_SUITE( logonUser );
+ if ( !aStringForward.isEmpty() && aStringForward.indexOf( ' ' ) != -1 && ( aStringForward.indexOf( ' ' ) == aStringForward.lastIndexOf( ' ' ) ) )
+ /// if user name and passwd are forwarded
+ {
+ CPPUNIT_TEST( logonUser_user_pwd );
+ }
+ if ( !aStringForward.isEmpty() && aStringForward.indexOf( ' ' ) != -1 && ( aStringForward.indexOf( ' ' ) != aStringForward.lastIndexOf( ' ' ) ) )
+ /// if user name and passwd and file server are forwarded
+ {
+ CPPUNIT_TEST( logonUser_user_pwd_server );
+ }
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class logonUser
+
+ /** testing the method:
+ inline sal_Bool Security::getUserIdent( OUString& strIdent) const
+ */
+ class getUserIdent : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ void getUserIdent_001( )
+ {
+ ::osl::Security aSec;
+ OUString strID;
+ bRes = aSec.getUserIdent( strID );
+
+ OString aMessage = "strUserID: " +
+ OUStringToOString(strUserID, osl_getThreadTextEncoding()) +
+ ", strID: " +
+ OUStringToOString(strID, osl_getThreadTextEncoding()) +
+ ", bRes: " +
+ OString::boolean(bRes);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( aMessage.getStr(), strUserID, strID );
+ CPPUNIT_ASSERT_MESSAGE( aMessage.getStr(), bRes );
+ }
+
+ CPPUNIT_TEST_SUITE( getUserIdent );
+ CPPUNIT_TEST( getUserIdent_001 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class getUserIdent
+
+ /** testing the method:
+ inline sal_Bool SAL_CALL getUserName( OUString& strName) const;
+ */
+ class getUserName : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ void getUserName_001( )
+ {
+ ::osl::Security aSec;
+#ifdef _WIN32
+ OUString strName( strUserName ), strGetName;
+#else
+ OUString strName( strUserName ), strGetName;
+#endif
+ bRes = aSec.getUserName( strGetName );
+
+ sal_Int32 nPos = -1;
+ if (!strName.isEmpty())
+ {
+ nPos = strGetName.indexOf(strName);
+ }
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: get UserName and compare it with names got at the beginning of the test.",
+ ( nPos >= 0 ) );
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: get UserName and compare it with names got at the beginning of the test.",
+ bRes );
+ }
+
+ CPPUNIT_TEST_SUITE( getUserName );
+ CPPUNIT_TEST( getUserName_001 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class getUserName
+
+ /** testing the method:
+ inline sal_Bool Security::getConfigDir( OUString& strDirectory ) const
+ */
+ class getConfigDir : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes, bRes1;
+
+ void getConfigDir_001( )
+ {
+ ::osl::Security aSec;
+ OUString strConfig;
+ bRes = aSec.getConfigDir( strConfig );
+
+ CPPUNIT_ASSERT_MESSAGE( "failed to find a ConfigDir!", bRes );
+ }
+
+ CPPUNIT_TEST_SUITE( getConfigDir );
+ CPPUNIT_TEST( getConfigDir_001 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class getConfigDir
+
+ /** testing the method:
+ inline sal_Bool SAL_CALL isAdministrator() const;
+ */
+ class isAdministrator : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes;
+
+ void isAdministrator_001( )
+ {
+ ::osl::Security aSec;
+ bRes = aSec.isAdministrator( );
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "#test comment#: check if the user is administrator at beginning, compare here.",
+ isAdmin, bRes );
+ }
+
+ CPPUNIT_TEST_SUITE( isAdministrator );
+ CPPUNIT_TEST( isAdministrator_001 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class isAdministrator
+
+ /** testing the method:
+ inline oslSecurity getHandle() const;
+ */
+ class getHandle : public CppUnit::TestFixture
+ {
+ public:
+ bool bRes;
+
+ void getHandle_001( )
+ {
+ ::osl::Security aSec;
+ bRes = aSec.isAdministrator( ) == bool(osl_isAdministrator( aSec.getHandle( ) ));
+
+ CPPUNIT_ASSERT_MESSAGE( "#test comment#: use getHandle function to call C API.",
+ bRes );
+ }
+
+ CPPUNIT_TEST_SUITE( getHandle );
+ CPPUNIT_TEST( getHandle_001 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class getHandle
+
+ class UserProfile : public CppUnit::TestFixture
+ {
+ public:
+
+ void loadUserProfile( )
+ {
+ ::osl::Security aSec;
+ bool bValue = osl_loadUserProfile(aSec.getHandle());
+
+ CPPUNIT_ASSERT_MESSAGE( "empty function.", !bValue );
+ }
+
+ void unloadUserProfile( )
+ {
+ ::osl::Security aSec;
+ osl_unloadUserProfile(aSec.getHandle());
+ CPPUNIT_ASSERT_MESSAGE( "empty function.", true );
+ }
+
+ CPPUNIT_TEST_SUITE( UserProfile );
+ CPPUNIT_TEST( loadUserProfile );
+ CPPUNIT_TEST( unloadUserProfile );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class UserProfile
+
+ class loginUserOnFileServer : public CppUnit::TestFixture
+ {
+ public:
+
+ void loginUserOnFileServer_001( )
+ {
+ OUString suUserName;
+ OUString suPassword;
+ OUString suFileServer;
+ ::osl::Security aSec;
+ oslSecurity pSec = aSec.getHandle();
+
+ oslSecurityError erg = osl_loginUserOnFileServer(suUserName.pData, suPassword.pData, suFileServer.pData, &pSec);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "empty function.", osl_Security_E_UserUnknown, erg );
+ }
+
+ CPPUNIT_TEST_SUITE( loginUserOnFileServer );
+ CPPUNIT_TEST( loginUserOnFileServer_001 );
+ CPPUNIT_TEST_SUITE_END( );
+ }; // class loginUserOnFileServer
+
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::ctors);
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::logonUser);
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::getUserIdent);
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::getUserName);
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::getConfigDir);
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::isAdministrator);
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::getHandle);
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::UserProfile);
+CPPUNIT_TEST_SUITE_REGISTRATION(osl_Security::loginUserOnFileServer);
+
+} // namespace osl_Security
+
+/* This defines an own TestPlugIn implementation with an own initialize()
+ method that will be called after loading the PlugIn
+ */
+#include <cppunit/plugin/TestPlugInDefaultImpl.h>
+
+namespace {
+
+class MyTestPlugInImpl: public CPPUNIT_NS::TestPlugInDefaultImpl
+{
+ public:
+ MyTestPlugInImpl() {};
+ void initialize( CPPUNIT_NS::TestFactoryRegistry *registry,
+ const CPPUNIT_NS::PlugInParameters &parameters ) override;
+};
+
+}
+
+void MyTestPlugInImpl::initialize( CPPUNIT_NS::TestFactoryRegistry *,
+ const CPPUNIT_NS::PlugInParameters & )
+{
+ /// start message
+ t_print("#Initializing ...\n" );
+ t_print("#\n#logonUser function need root/Administrator account to test.\n" );
+ t_print("#You can test by login with root/Administrator, and execute:\n" );
+ t_print("#testshl2 -forward \"username password\" ../../../wntmsci9/bin/Security.dll\n" );
+ t_print("# where username and password are forwarded account info.\n" );
+ t_print("#if no text forwarded, this function will be skipped.\n" );
+
+ /// get system information
+#if ( defined UNX )
+ /// some initialization work for UNIX OS
+
+ struct passwd* pw;
+ CPPUNIT_ASSERT_MESSAGE( "getpwuid: no password entry\n",( pw = getpwuid( getuid() ) ) != nullptr );
+
+ /// get user ID;
+ strUserID = OUString::number( getuid( ) );
+
+ /// get user Name;
+ strUserName = OUString::createFromAscii( pw->pw_name );
+
+ /// get home directory;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "#Convert from system path to URL failed.",
+ ::osl::File::E_None, ::osl::File::getFileURLFromSystemPath( OUString::createFromAscii( pw->pw_dir ), strHomeDirectory ) );
+
+ /// get config directory;
+ strConfigDirectory = strHomeDirectory.copy(0);
+
+ /// is administrator;
+ if( !getuid( ) )
+ isAdmin = true;
+
+#endif
+#if defined(_WIN32)
+ /// some initialization work for Windows OS
+
+ /// Get the user name, computer name, user home directory.
+ LPWSTR lpszSystemInfo; // pointer to system information string
+ DWORD cchBuff = BUFSIZE; // size of computer or user name
+ WCHAR wchBuffer[BUFSIZE]; // buffer for string
+
+ lpszSystemInfo = wchBuffer;
+ if( GetUserNameW(lpszSystemInfo, &cchBuff) )
+ strUserName = o3tl::toU(lpszSystemInfo);
+
+ cchBuff = BUFSIZE;
+ if( GetComputerNameW(lpszSystemInfo, &cchBuff) )
+ strComputerName = o3tl::toU(lpszSystemInfo);
+
+ /// Get user home directory.
+ HKEY hRegKey;
+ if (RegOpenKeyW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", &hRegKey) == ERROR_SUCCESS)
+ {
+ sal_Unicode PathW[_MAX_PATH];
+ LSTATUS lRet;
+ DWORD lSize = sizeof(PathW);
+ DWORD Type;
+
+ lRet = RegQueryValueExW(hRegKey, L"AppData", nullptr, &Type, reinterpret_cast<unsigned char *>(PathW), &lSize);
+ if ( ( lRet == ERROR_SUCCESS ) && ( Type == REG_SZ ) && ( _waccess( o3tl::toW(PathW), 0 ) == 0 ) )
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "#Convert from system path to URL failed.",
+ ::osl::File::E_None, ::osl::File::getFileURLFromSystemPath( OUString(PathW), strConfigDirectory ) );
+ }
+
+ lSize = sizeof(PathW);
+ lRet = RegQueryValueExW(hRegKey, L"Personal", nullptr, &Type, reinterpret_cast<unsigned char *>(PathW), &lSize);
+ if ( ( lRet == ERROR_SUCCESS ) && ( Type == REG_SZ ) && ( _waccess( o3tl::toW(PathW), 0 ) == 0 ) )
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "#Convert from system path to URL failed.",
+ ::osl::File::E_None, ::osl::File::getFileURLFromSystemPath( OUString(PathW), strHomeDirectory ) );
+ }
+
+ RegCloseKey(hRegKey);
+ }
+
+ /// Get user Security ID:
+
+ // Create buffers that may be large enough. If a buffer is too small, the count parameter will be set to the size needed.
+ const DWORD INITIAL_SIZE = 32;
+ DWORD cbSid = 0;
+ DWORD dwSidBufferSize = INITIAL_SIZE;
+ DWORD cchDomainName = 0;
+ DWORD dwDomainBufferSize = INITIAL_SIZE;
+ WCHAR * wszDomainName = nullptr;
+ SID_NAME_USE eSidType;
+ DWORD dwErrorCode = 0;
+
+ OUString sLookupUserName = strUserName;
+ LPCWSTR wszAccName = o3tl::toW(sLookupUserName.getStr( ));
+
+ // Create buffers for the SID and the domain name.
+ PSID pSid = static_cast<PSID>(new BYTE[dwSidBufferSize]);
+ memset( pSid, 0, dwSidBufferSize);
+
+ wszDomainName = new WCHAR[dwDomainBufferSize];
+ memset(wszDomainName, 0, dwDomainBufferSize*sizeof(WCHAR));
+
+ // Obtain the SID for the account name passed.
+ for ( ; ; )
+ {
+ // Set the count variables to the buffer sizes and retrieve the SID.
+ cbSid = dwSidBufferSize;
+ cchDomainName = dwDomainBufferSize;
+ if (LookupAccountNameW(
+ nullptr, // Computer name. NULL for the local computer
+ wszAccName,
+ pSid, // Pointer to the SID buffer. Use NULL to get the size needed,
+ &cbSid, // Size of the SID buffer needed.
+ wszDomainName, // wszDomainName,
+ &cchDomainName,
+ &eSidType
+ ))
+ {
+ if (eSidType == SID_NAME_USE::SidTypeDomain)
+ {
+ // LookupAccountNameW returned SID of a domain; likely the hostname is the same as
+ // username (case-insensitive): something like "JOHNSMITH\JohnSmith", so looking up
+ // for "JohnSmith" without domain returns domain itself. Try getting the SID of the
+ // user using fully qualified name (the case of user of another domain having name
+ // identical this hostname is not handled).
+ sLookupUserName = OUString::Concat(o3tl::toU(wszDomainName)) + u"\\" + strUserName;
+ wszAccName = o3tl::toW(sLookupUserName.getStr());
+ continue;
+ }
+ if (IsValidSid( pSid) == FALSE)
+ wprintf(L"# The SID for %s is invalid.\n", wszAccName);
+ break;
+ }
+ dwErrorCode = GetLastError();
+
+ // Check if one of the buffers was too small.
+ if (dwErrorCode == ERROR_INSUFFICIENT_BUFFER)
+ {
+ if (cbSid > dwSidBufferSize)
+ {
+ // Reallocate memory for the SID buffer.
+ wprintf(L"# The SID buffer was too small. It will be reallocated.\n");
+ delete[] static_cast<BYTE*>(pSid);
+ pSid = static_cast<PSID>(new BYTE[cbSid]);
+ memset( pSid, 0, cbSid);
+ dwSidBufferSize = cbSid;
+ }
+ if (cchDomainName > dwDomainBufferSize)
+ {
+ // Reallocate memory for the domain name buffer.
+ wprintf(L"# The domain name buffer was too small. It will be reallocated.\n");
+ delete [] wszDomainName;
+ wszDomainName = new WCHAR[cchDomainName];
+ memset(wszDomainName, 0, cchDomainName*sizeof(WCHAR));
+ dwDomainBufferSize = cchDomainName;
+ }
+ }
+ else
+ {
+ wprintf(L"# LookupAccountNameW failed. GetLastError returned: %d\n", dwErrorCode);
+ break;
+ }
+ }
+
+ LPWSTR pSidStr = nullptr;
+ if (ConvertSidToStringSidW(pSid, &pSidStr))
+ {
+ strUserID = o3tl::toU(pSidStr);
+ LocalFree(pSidStr);
+ }
+ else
+ {
+ wprintf(L"# ConvertSidToStringSidW failed. GetLastError returned: %d\n", GetLastError());
+ }
+
+ delete [] static_cast<BYTE*>(pSid);
+ delete [] wszDomainName;
+
+ /// check if logged in user is administrator:
+
+ BOOL b;
+ SID_IDENTIFIER_AUTHORITY NtAuthority = { SECURITY_NT_AUTHORITY };
+ PSID AdministratorsGroup;
+ b = AllocateAndInitializeSid(
+ &NtAuthority,
+ 2,
+ SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_ADMINS,
+ 0, 0, 0, 0, 0, 0,
+ &AdministratorsGroup);
+ if(b)
+ {
+ if (!CheckTokenMembership( nullptr, AdministratorsGroup, &b))
+ {
+ b = FALSE;
+ }
+ FreeSid(AdministratorsGroup);
+ }
+
+ isAdmin = b;
+
+#endif
+
+ /// print the information.
+ t_print("#\n#Retrieved system information is below:\n");
+
+ t_print("Computer Name: ");
+ if ( strComputerName.isEmpty())
+ t_print("Not retrieved\n" );
+ else
+ printUString( strComputerName );
+
+ t_print("Current User Name: ");
+ if ( strUserName.isEmpty())
+ t_print("Not retrieved\n" );
+ else
+ printUString( strUserName );
+
+ t_print("Current User Home Directory:");
+ if ( strHomeDirectory.isEmpty())
+ t_print("Not retrieved\n" );
+ else
+ printUString( strHomeDirectory );
+
+ t_print("Current Config Directory: ");
+ if ( strConfigDirectory.isEmpty())
+ t_print("Not retrieved\n" );
+ else
+ printUString( strConfigDirectory );
+
+ t_print("Current UserID: ");
+ if ( strUserID.isEmpty())
+ t_print("Not retrieved\n" );
+ else
+ printUString( strUserID );
+
+ t_print("Current User is: ");
+ if ( !isAdmin )
+ t_print("NOT Administrator.\n" );
+ else
+ t_print("Administrator.\n" );
+
+ /// get and display forwarded text if available.
+ OUString args[ 3 ];
+ int argsCount = 0;
+ sal_uInt32 n = rtl_getAppCommandArgCount();
+ for (sal_uInt32 i = 0; i < n; ++i)
+ {
+ OUString arg;
+ rtl_getAppCommandArg(i, &arg.pData);
+ if( arg.startsWith("-") )
+ continue;
+ if( argsCount >= 3 )
+ {
+ SAL_WARN( "sal.osl", "Too many test arguments" );
+ continue;
+ }
+ args[ argsCount++ ] = arg;
+ }
+ /// only forwarded two parameters, username and password.
+ if( argsCount == 2 )
+ {
+ aLogonUser = args[ 0 ];
+ t_print("\n#Forwarded username: ");
+ printUString( aLogonUser);
+
+ aLogonPasswd = args[ 1 ];
+ t_print("#Forwarded password: ");
+ for (int i = 0; i < aLogonPasswd.getLength(); ++i)
+ t_print("*");
+ t_print("\n" );
+ }
+ else if( argsCount == 3 )
+ /// forwarded three parameters, username, password and fileserver.
+ {
+ aLogonUser = args[ 0 ];
+ t_print("#Forwarded username: ");
+ printUString( aLogonUser);
+
+ aLogonPasswd = args[ 1 ];
+ t_print("#Forwarded password: ");
+ for (int i = 0; i < aLogonPasswd.getLength(); ++i)
+ t_print("*");
+ t_print("\n" );
+
+ aFileServer = args[ 2 ];
+ t_print("#Forwarded FileServer: ");
+ printUString( aFileServer );
+ }
+ t_print("#\n#Initialization Done.\n" );
+
+}
+
+/* Instantiate and register the own TestPlugIn and instantiate the default
+ main() function.
+ (This is done by CPPUNIT_PLUGIN_IMPLEMENT() for TestPlugInDefaultImpl)
+ */
+
+CPPUNIT_PLUGIN_EXPORTED_FUNCTION_IMPL( MyTestPlugInImpl );
+CPPUNIT_PLUGIN_IMPLEMENT_MAIN();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/osl/security/osl_Security_Const.h b/sal/qa/osl/security/osl_Security_Const.h
new file mode 100644
index 000000000..8329962a3
--- /dev/null
+++ b/sal/qa/osl/security/osl_Security_Const.h
@@ -0,0 +1,58 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SAL_QA_OSL_SECURITY_OSL_SECURITY_CONST_H
+#define INCLUDED_SAL_QA_OSL_SECURITY_OSL_SECURITY_CONST_H
+
+#if defined(_WIN32) // Windows
+#include <io.h>
+#endif
+
+#include <sal/types.h>
+#include <rtl/ustring.hxx>
+#include <osl/file.hxx>
+#include <osl/security.hxx>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#if (defined UNX)
+#include <unistd.h>
+#include <pwd.h>
+#endif
+
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+#include <cppunit/plugin/TestPlugInDefaultImpl.h>
+
+#define t_print printf
+
+#define BUFSIZE 1024
+const char pTestString[17] = "Sun Microsystems";
+
+OUString aLogonUser, aLogonPasswd, aFileServer, aStringForward;
+OUString strUserName, strComputerName, strHomeDirectory;
+OUString strConfigDirectory, strUserID;
+
+bool isAdmin = false;
+
+#endif // INCLUDED_SAL_QA_OSL_SECURITY_OSL_SECURITY_CONST_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/osl/setthreadname/test-setthreadname.cxx b/sal/qa/osl/setthreadname/test-setthreadname.cxx
new file mode 100644
index 000000000..9af8793eb
--- /dev/null
+++ b/sal/qa/osl/setthreadname/test-setthreadname.cxx
@@ -0,0 +1,79 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cstdlib>
+#include <iostream>
+#include <limits>
+
+#include <sal/types.h>
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+#include <osl/thread.hxx>
+
+namespace {
+
+class TestThread: public osl::Thread {
+private:
+ virtual void SAL_CALL run() override;
+public:
+ TestThread() = default;
+ TestThread(const TestThread&) = delete;
+ TestThread& operator=(const TestThread&) = delete;
+};
+
+void TestThread::run() {
+#if defined(_WIN32)
+ if (std::getenv("URE_TEST_SETTHREADNAME") != nullptr) {
+ // On Windows, setting thread names appears to only take effect when the
+ // process is being debugged, so attach a debugger now:
+ std::cout << "set: ";
+ std::cin.ignore(std::numeric_limits< int >::max(), '\n');
+ }
+#endif
+ setName("TestThread");
+ if (std::getenv("URE_TEST_SETTHREADNAME") != nullptr) {
+ // On Linux, the thread name can now be observed with "ps -L"; on
+ // Windows, the thread name can now be observed in a debugger.
+ std::cout << "stop: ";
+ std::cin.ignore(std::numeric_limits< int >::max(), '\n');
+ }
+}
+
+class Test: public CppUnit::TestFixture {
+private:
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(test);
+ CPPUNIT_TEST_SUITE_END();
+
+ void test();
+};
+
+void Test::test() {
+ TestThread t;
+ t.create();
+ t.join();
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/qa/osl/socket.cxx b/sal/qa/osl/socket.cxx
new file mode 100644
index 000000000..ed31c9ede
--- /dev/null
+++ b/sal/qa/osl/socket.cxx
@@ -0,0 +1,58 @@
+/* -*- 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 <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <osl/socket.h>
+#include <rtl/ustring.hxx>
+
+namespace
+{
+class SocketTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(SocketTest);
+ CPPUNIT_TEST(test_createInetSocketAddr);
+ CPPUNIT_TEST(test_createInetBroadcastAddr);
+ CPPUNIT_TEST_SUITE_END();
+
+ void test_createInetSocketAddr()
+ {
+ OUString const in("123.4.56.78");
+ auto const addr = osl_createInetSocketAddr(in.pData, 100);
+ CPPUNIT_ASSERT(addr != nullptr);
+ CPPUNIT_ASSERT_EQUAL(osl_Socket_FamilyInet, osl_getFamilyOfSocketAddr(addr));
+ OUString out;
+ auto const res = osl_getDottedInetAddrOfSocketAddr(addr, &out.pData);
+ CPPUNIT_ASSERT_EQUAL(osl_Socket_Ok, res);
+ CPPUNIT_ASSERT_EQUAL(in, out);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(100), osl_getInetPortOfSocketAddr(addr));
+ osl_destroySocketAddr(addr);
+ }
+
+ void test_createInetBroadcastAddr()
+ {
+ OUString const in("123.4.56.78");
+ auto const addr = osl_createInetBroadcastAddr(in.pData, 100);
+ CPPUNIT_ASSERT(addr != nullptr);
+ CPPUNIT_ASSERT_EQUAL(osl_Socket_FamilyInet, osl_getFamilyOfSocketAddr(addr));
+ OUString out;
+ auto const res = osl_getDottedInetAddrOfSocketAddr(addr, &out.pData);
+ CPPUNIT_ASSERT_EQUAL(osl_Socket_Ok, res);
+ CPPUNIT_ASSERT_EQUAL(OUString("123.255.255.255"), out);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(100), osl_getInetPortOfSocketAddr(addr));
+ osl_destroySocketAddr(addr);
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SocketTest);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sal/qa/osl/thread/test_thread.cxx b/sal/qa/osl/thread/test_thread.cxx
new file mode 100644
index 000000000..12ddafc6d
--- /dev/null
+++ b/sal/qa/osl/thread/test_thread.cxx
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/types.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+#include "osl/conditn.hxx"
+#include "osl/thread.hxx"
+#include "osl/time.h"
+#include <chrono>
+
+namespace {
+
+osl::Condition global;
+
+class Thread: public osl::Thread {
+public:
+ explicit Thread(osl::Condition & cond): m_cond(cond) {}
+
+private:
+ virtual void SAL_CALL run() {}
+
+ virtual void SAL_CALL onTerminated() {
+ m_cond.set();
+ CPPUNIT_ASSERT_EQUAL(osl::Condition::result_ok, global.wait());
+ }
+
+ osl::Condition & m_cond;
+};
+
+class Test: public CppUnit::TestFixture {
+public:
+ // Nondeterministic, best effort test that an osl::Thread can be destroyed
+ // (and in particular osl_destroyThread---indirectly---be called) before the
+ // corresponding thread has terminated:
+ void test() {
+ for (int i = 0; i < 50; ++i) {
+ osl::Condition c;
+ Thread t(c);
+ CPPUNIT_ASSERT(t.create());
+ // Make sure virtual Thread::run/onTerminated are called before
+ // Thread::~Thread:
+ CPPUNIT_ASSERT_EQUAL(osl::Condition::result_ok, c.wait());
+ }
+ // Make sure Thread::~Thread is called before each spawned thread
+ // terminates:
+ global.set();
+ // Give the spawned threads enough time to terminate:
+ osl::Thread::wait(std::chrono::seconds(20));
+ }
+
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(test);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */