mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-09-18 14:27:39 +03:00
Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
40c01dedcf | ||
|
d644a7b47f |
2
.github/actions/configure-occt/action.yml
vendored
2
.github/actions/configure-occt/action.yml
vendored
@@ -126,7 +126,7 @@ runs:
|
||||
-D BUILD_GTEST=ON \
|
||||
-D BUILD_CPP_STANDARD=C++17 \
|
||||
-D INSTALL_GTEST=ON \
|
||||
-D CMAKE_CXX_FLAGS="-Werror -Wall -Wextra -Wno-unknown-warning-option -Wno-error=cast-function-type-mismatch" \
|
||||
-D CMAKE_CXX_FLAGS="-Werror -Wall -Wextra" \
|
||||
${{ inputs.additional-cmake-flags }} ..
|
||||
echo "Configuration completed successfully for macOS"
|
||||
shell: bash
|
||||
|
9
.github/actions/vcpkg-setup/action.yml
vendored
9
.github/actions/vcpkg-setup/action.yml
vendored
@@ -56,14 +56,7 @@ runs:
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
brew update || true
|
||||
# Install each package separately to continue even if some fail
|
||||
brew install cmake || true
|
||||
brew install ninja || true
|
||||
brew install nasm || true
|
||||
brew install autoconf || true
|
||||
brew install automake || true
|
||||
brew install mono || true
|
||||
brew install openexr || true
|
||||
brew install cmake ninja nasm autoconf automake mono openexr || true
|
||||
brew install --cask xquartz || true
|
||||
shell: bash
|
||||
|
||||
|
@@ -125,7 +125,7 @@ jobs:
|
||||
artifact-name: install-macos-clang-no-pch
|
||||
build-use-pch: 'false'
|
||||
build-opt-profile: 'Default'
|
||||
additional-cmake-flags: '-D CMAKE_CXX_FLAGS="-Werror -Wall -Wextra -Wno-error=cast-function-type-mismatch" -D CMAKE_C_FLAGS="-Werror -Wall -Wextra -Wno-error=cast-function-type-mismatch"'
|
||||
additional-cmake-flags: '-D CMAKE_CXX_FLAGS="-Werror -Wall -Wextra" -D CMAKE_C_FLAGS="-Werror -Wall -Wextra"'
|
||||
cmake-build-type: 'Debug'
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
@@ -139,17 +139,3 @@ bool DE_ConfigurationNode::CheckContent(const Handle(NCollection_Buffer)& theBuf
|
||||
(void)theBuffer;
|
||||
return false;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void DE_ConfigurationNode::Register(const Handle(DE_Wrapper)& theWrapper) const
|
||||
{
|
||||
theWrapper->Bind(this);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void DE_ConfigurationNode::UnRegister(const Handle(DE_Wrapper)& theWrapper) const
|
||||
{
|
||||
theWrapper->UnBind(this);
|
||||
}
|
||||
|
@@ -18,7 +18,6 @@
|
||||
|
||||
class DE_ConfigurationContext;
|
||||
class DE_Provider;
|
||||
class DE_Wrapper;
|
||||
class NCollection_Buffer;
|
||||
|
||||
//! Base class to work with CAD transfer properties.
|
||||
@@ -155,16 +154,6 @@ public:
|
||||
//!< unit is unknown, default 1.0 (MM)
|
||||
} GlobalParameters;
|
||||
|
||||
public:
|
||||
|
||||
//! Registers configuration node with the specified wrapper
|
||||
//! @param[in] theWrapper wrapper to register with
|
||||
Standard_EXPORT virtual void Register(const Handle(DE_Wrapper)& theWrapper) const;
|
||||
|
||||
//! Unregisters configuration node from the specified wrapper
|
||||
//! @param[in] theWrapper wrapper to unregister from
|
||||
Standard_EXPORT virtual void UnRegister(const Handle(DE_Wrapper)& theWrapper) const;
|
||||
|
||||
private:
|
||||
Standard_Boolean myIsEnabled; //!< Flag to use a current provider for Read or Write process via DE_Wrapper
|
||||
// clang-format on
|
||||
|
@@ -15,7 +15,6 @@
|
||||
#define _DE_PluginHolder_HeaderFile
|
||||
|
||||
#include <DE_Wrapper.hxx>
|
||||
#include <tuple>
|
||||
|
||||
//! Base class to work with DE_Wrapper global registration of components.
|
||||
//! Control life-time of current configuration node.
|
||||
@@ -30,80 +29,17 @@ public:
|
||||
{
|
||||
Standard_Mutex::Sentry aLock(DE_Wrapper::GlobalLoadMutex());
|
||||
myInternalConfiguration = new TheConfType;
|
||||
myInternalConfiguration->Register(DE_Wrapper::GlobalWrapper());
|
||||
DE_Wrapper::GlobalWrapper()->Bind(myInternalConfiguration);
|
||||
}
|
||||
|
||||
~DE_PluginHolder()
|
||||
{
|
||||
Standard_Mutex::Sentry aLock(DE_Wrapper::GlobalLoadMutex());
|
||||
myInternalConfiguration->UnRegister(DE_Wrapper::GlobalWrapper());
|
||||
DE_Wrapper::GlobalWrapper()->UnBind(myInternalConfiguration);
|
||||
}
|
||||
|
||||
private:
|
||||
Handle(TheConfType) myInternalConfiguration; //!< Wrapped object
|
||||
};
|
||||
|
||||
//! Helper class for variadic plugin registration.
|
||||
//! Allows registration of multiple configuration node types simultaneously.
|
||||
template <typename... TheConfTypes>
|
||||
class DE_MultiPluginHolder
|
||||
{
|
||||
public:
|
||||
DE_MultiPluginHolder()
|
||||
: myHolders{}
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
std::tuple<DE_PluginHolder<TheConfTypes>...> myHolders; //!< Tuple of individual plugin holders
|
||||
};
|
||||
|
||||
//! Macro to define plugin factory function for DE_Wrapper configuration nodes.
|
||||
//! @param[in] theNodeType - first configuration node class to instantiate
|
||||
//! @param[in] ... - additional configuration node classes to instantiate (optional)
|
||||
//! Needs to be called after loading of the library to register configuration nodes.
|
||||
//!
|
||||
//! Example of usage:
|
||||
//! @code
|
||||
//! // Inside implementation of the configuration node source file:
|
||||
//! DEPLUGIN(DESTEP_ConfigurationNode)
|
||||
//!
|
||||
//! // For multiple node types:
|
||||
//! DEPLUGIN(DESTEP_ConfigurationNode, DEIGES_ConfigurationNode, DEVRML_ConfigurationNode)
|
||||
//! @endcode
|
||||
//!
|
||||
//! After loading of the library TKDESTEP:
|
||||
//! @code
|
||||
//! OSD_SharedLibrary aSharedLibrary("libTKDESTEP.so");
|
||||
//! if (!aSharedLibrary.DlOpen(OSD_RTLD_LAZY))
|
||||
//! {
|
||||
//! // Error handling
|
||||
//! return;
|
||||
//! }
|
||||
//!
|
||||
//! typedef void (*PluginFactoryFunc)();
|
||||
//! PluginFactoryFunc aFunc = (PluginFactoryFunc)aSharedLibrary.DlSymb("PLUGINFACTORY");
|
||||
//! if (aFunc == NULL)
|
||||
//! {
|
||||
//! // Error handling
|
||||
//! return;
|
||||
//! }
|
||||
//!
|
||||
//! aFunc(); // Call factory function to register configuration nodes
|
||||
//! @endcode
|
||||
//!
|
||||
//! Will create instances of all specified configuration nodes and set them to DE_Wrapper global
|
||||
//! configuration.
|
||||
//!
|
||||
//! Note: if OCCT_NO_PLUGINS is defined, macro does nothing.
|
||||
#ifdef OCCT_NO_PLUGINS
|
||||
#define DEPLUGIN(theNodeType, ...)
|
||||
#else
|
||||
#define DEPLUGIN(theNodeType, ...) \
|
||||
extern "C" Standard_EXPORT void PLUGINFACTORY() \
|
||||
{ \
|
||||
static DE_MultiPluginHolder<theNodeType, ##__VA_ARGS__> aMultiHolder; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _DE_PluginHolder_HeaderFile
|
||||
|
@@ -14,6 +14,7 @@
|
||||
#include <DE_ShapeFixConfigurationNode.hxx>
|
||||
|
||||
#include <DE_ConfigurationContext.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
#include <DE_Wrapper.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(DE_ShapeFixConfigurationNode, DE_ConfigurationNode)
|
||||
|
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <DEBREP_Provider.hxx>
|
||||
#include <DE_ConfigurationContext.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
#include <NCollection_Buffer.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(DEBREP_ConfigurationNode, DE_ConfigurationNode)
|
||||
@@ -27,6 +28,8 @@ static const TCollection_AsciiString& THE_CONFIGURATION_SCOPE()
|
||||
return aScope;
|
||||
}
|
||||
|
||||
// Wrapper to auto-load DE component
|
||||
DE_PluginHolder<DEBREP_ConfigurationNode> THE_OCCT_BREP_COMPONENT_PLUGIN;
|
||||
} // namespace
|
||||
|
||||
//=================================================================================================
|
||||
|
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <DEXCAF_Provider.hxx>
|
||||
#include <DE_ConfigurationContext.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
#include <NCollection_Buffer.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(DEXCAF_ConfigurationNode, DE_ConfigurationNode)
|
||||
@@ -27,6 +28,8 @@ static const TCollection_AsciiString& THE_CONFIGURATION_SCOPE()
|
||||
return aScope;
|
||||
}
|
||||
|
||||
// Wrapper to auto-load DE component
|
||||
DE_PluginHolder<DEXCAF_ConfigurationNode> THE_OCCT_XCAF_COMPONENT_PLUGIN;
|
||||
} // namespace
|
||||
|
||||
//=================================================================================================
|
||||
|
@@ -4,5 +4,4 @@ set(OCCT_TKDECascade_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
|
||||
set(OCCT_TKDECascade_FILES
|
||||
EXTERNLIB
|
||||
PACKAGES
|
||||
TKDECascade.cxx
|
||||
)
|
||||
|
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <DEGLTF_Provider.hxx>
|
||||
#include <DE_ConfigurationContext.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(DEGLTF_ConfigurationNode, DE_ConfigurationNode)
|
||||
|
||||
@@ -26,6 +27,8 @@ static const TCollection_AsciiString& THE_CONFIGURATION_SCOPE()
|
||||
return aScope;
|
||||
}
|
||||
|
||||
// Wrapper to auto-load DE component
|
||||
DE_PluginHolder<DEGLTF_ConfigurationNode> THE_OCCT_GLTF_COMPONENT_PLUGIN;
|
||||
} // namespace
|
||||
|
||||
//=================================================================================================
|
||||
|
@@ -4,5 +4,4 @@ set(OCCT_TKDEGLTF_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
|
||||
set(OCCT_TKDEGLTF_FILES
|
||||
EXTERNLIB
|
||||
PACKAGES
|
||||
TKDEGLTF.cxx
|
||||
)
|
||||
|
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <DEIGES_Provider.hxx>
|
||||
#include <DE_ConfigurationContext.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
#include <NCollection_Buffer.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(DEIGES_ConfigurationNode, DE_ShapeFixConfigurationNode)
|
||||
@@ -27,6 +28,8 @@ static const TCollection_AsciiString& THE_CONFIGURATION_SCOPE()
|
||||
return aScope;
|
||||
}
|
||||
|
||||
// Wrapper to auto-load DE component
|
||||
DE_PluginHolder<DEIGES_ConfigurationNode> THE_OCCT_IGES_COMPONENT_PLUGIN;
|
||||
} // namespace
|
||||
|
||||
//=================================================================================================
|
||||
|
@@ -5,5 +5,4 @@ set(OCCT_TKDEIGES_FILES
|
||||
EXTERNLIB
|
||||
PACKAGES
|
||||
TKDEIGES_pch.hxx
|
||||
TKDEIGES.cxx
|
||||
)
|
||||
|
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <DEOBJ_Provider.hxx>
|
||||
#include <DE_ConfigurationContext.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(DEOBJ_ConfigurationNode, DE_ConfigurationNode)
|
||||
|
||||
@@ -26,6 +27,8 @@ static const TCollection_AsciiString& THE_CONFIGURATION_SCOPE()
|
||||
return aScope;
|
||||
}
|
||||
|
||||
// Wrapper to auto-load DE component
|
||||
DE_PluginHolder<DEOBJ_ConfigurationNode> THE_OCCT_OBJ_COMPONENT_PLUGIN;
|
||||
} // namespace
|
||||
|
||||
//=================================================================================================
|
||||
|
@@ -4,5 +4,4 @@ set(OCCT_TKDEOBJ_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
|
||||
set(OCCT_TKDEOBJ_FILES
|
||||
EXTERNLIB
|
||||
PACKAGES
|
||||
TKDEOBJ.cxx
|
||||
)
|
||||
|
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <DEPLY_Provider.hxx>
|
||||
#include <DE_ConfigurationContext.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
#include <NCollection_Buffer.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(DEPLY_ConfigurationNode, DE_ConfigurationNode)
|
||||
@@ -27,6 +28,8 @@ static const TCollection_AsciiString& THE_CONFIGURATION_SCOPE()
|
||||
return aScope;
|
||||
}
|
||||
|
||||
// Wrapper to auto-load DE component
|
||||
DE_PluginHolder<DEPLY_ConfigurationNode> THE_OCCT_PLY_COMPONENT_PLUGIN;
|
||||
} // namespace
|
||||
|
||||
//=================================================================================================
|
||||
|
@@ -4,5 +4,4 @@ set(OCCT_TKDEPLY_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
|
||||
set(OCCT_TKDEPLY_FILES
|
||||
EXTERNLIB
|
||||
PACKAGES
|
||||
TKDEPLY.cxx
|
||||
)
|
||||
|
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <DESTEP_Provider.hxx>
|
||||
#include <DE_ConfigurationContext.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
#include <NCollection_Buffer.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(DESTEP_ConfigurationNode, DE_ShapeFixConfigurationNode)
|
||||
@@ -27,6 +28,8 @@ static const TCollection_AsciiString& THE_CONFIGURATION_SCOPE()
|
||||
return aScope;
|
||||
}
|
||||
|
||||
// Wrapper to auto-load DE component
|
||||
DE_PluginHolder<DESTEP_ConfigurationNode> THE_OCCT_STEP_COMPONENT_PLUGIN;
|
||||
} // namespace
|
||||
|
||||
//=================================================================================================
|
||||
|
@@ -5,5 +5,4 @@ set(OCCT_TKDESTEP_FILES
|
||||
EXTERNLIB
|
||||
PACKAGES
|
||||
TKDESTEP_pch.hxx
|
||||
TKDESTEP.cxx
|
||||
)
|
||||
|
@@ -1,19 +0,0 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <DESTEP_ConfigurationNode.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
|
||||
//! Plugin factory function to register DESTEP configuration node.
|
||||
//! Call PLUGINFACTORY() to register the DESTEP_ConfigurationNode with the global DE_Wrapper.
|
||||
DEPLUGIN(DESTEP_ConfigurationNode)
|
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <DESTL_Provider.hxx>
|
||||
#include <DE_ConfigurationContext.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
#include <NCollection_Buffer.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(DESTL_ConfigurationNode, DE_ConfigurationNode)
|
||||
@@ -27,6 +28,8 @@ static const TCollection_AsciiString& THE_CONFIGURATION_SCOPE()
|
||||
return aScope;
|
||||
}
|
||||
|
||||
// Wrapper to auto-load DE component
|
||||
DE_PluginHolder<DESTL_ConfigurationNode> THE_OCCT_STL_COMPONENT_PLUGIN;
|
||||
} // namespace
|
||||
|
||||
//=================================================================================================
|
||||
|
@@ -4,5 +4,4 @@ set(OCCT_TKDESTL_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
|
||||
set(OCCT_TKDESTL_FILES
|
||||
EXTERNLIB
|
||||
PACKAGES
|
||||
TKDESTL.cxx
|
||||
)
|
||||
|
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <DEVRML_Provider.hxx>
|
||||
#include <DE_ConfigurationContext.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(DEVRML_ConfigurationNode, DE_ConfigurationNode)
|
||||
|
||||
@@ -26,6 +27,8 @@ static const TCollection_AsciiString& THE_CONFIGURATION_SCOPE()
|
||||
return aScope;
|
||||
}
|
||||
|
||||
// Wrapper to auto-load DE component
|
||||
DE_PluginHolder<DEVRML_ConfigurationNode> THE_OCCT_VRML_COMPONENT_PLUGIN;
|
||||
} // namespace
|
||||
|
||||
//=================================================================================================
|
||||
|
@@ -4,5 +4,4 @@ set(OCCT_TKDEVRML_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
|
||||
set(OCCT_TKDEVRML_FILES
|
||||
EXTERNLIB
|
||||
PACKAGES
|
||||
TKDEVRML.cxx
|
||||
)
|
||||
|
@@ -1,19 +0,0 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <DEVRML_ConfigurationNode.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
|
||||
//! Plugin factory function to register DEVRML configuration node.
|
||||
//! Call PLUGINFACTORY() to register the DEVRML_ConfigurationNode with the global DE_Wrapper.
|
||||
DEPLUGIN(DEVRML_ConfigurationNode)
|
@@ -25,6 +25,7 @@
|
||||
#include <OSD_Chronometer.hxx>
|
||||
#include <OSD_Environment.hxx>
|
||||
#include <OSD_Exception_CTRL_BREAK.hxx>
|
||||
#include <OSD_MAllocHook.hxx>
|
||||
#include <OSD_MemInfo.hxx>
|
||||
#include <OSD_Parallel.hxx>
|
||||
#include <OSD_PerfMeter.hxx>
|
||||
@@ -676,6 +677,126 @@ static Standard_Integer cpulimit(Draw_Interpretor& di, Standard_Integer n, const
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
static Standard_Integer mallochook(Draw_Interpretor& di, Standard_Integer n, const char** a)
|
||||
{
|
||||
if (n < 2)
|
||||
{
|
||||
di << "\
|
||||
usage: mallochook cmd\n\
|
||||
where cmd is one of:\n\
|
||||
set [<op>] - set callback to malloc/free; op is one of the following:\n\
|
||||
0 - set callback to NULL,\n\
|
||||
1 - set callback OSD_MAllocHook::CollectBySize (default)\n\
|
||||
2 - set callback OSD_MAllocHook::LogFileHandler\n\
|
||||
reset - reset the CollectBySize handler\n\
|
||||
report1 [<outfile>]\n\
|
||||
- write report from CollectBySize handler in <outfile>\n\
|
||||
open [<logfile>]\n\
|
||||
- open file for writing the log with LogFileHandler\n\
|
||||
close - close the log file with LogFileHandler\n\
|
||||
report2 [<flag>] [<logfile>] [<outfile>]\n\
|
||||
- scan <logfile> written with LogFileHandler\n\
|
||||
and make synthesized report in <outfile>; <flag> can be:\n\
|
||||
0 - simple stats by sizes (default),\n\
|
||||
1 - with alive allocation numbers\n\
|
||||
By default <logfile> is \"mem-log.txt\", <outfile> is \"mem-stat.txt\""
|
||||
<< "\n";
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(a[1], "set") == 0)
|
||||
{
|
||||
int aType = (n > 2 ? Draw::Atoi(a[2]) : 1);
|
||||
if (aType < 0 || aType > 2)
|
||||
{
|
||||
di << "unknown op of the command set\n";
|
||||
return 1;
|
||||
}
|
||||
else if (aType == 0)
|
||||
{
|
||||
OSD_MAllocHook::SetCallback(NULL);
|
||||
di << "callback is unset\n";
|
||||
}
|
||||
else if (aType == 1)
|
||||
{
|
||||
OSD_MAllocHook::SetCallback(OSD_MAllocHook::GetCollectBySize());
|
||||
di << "callback is set to CollectBySize\n";
|
||||
}
|
||||
else // if (aType == 2)
|
||||
{
|
||||
OSD_MAllocHook::SetCallback(OSD_MAllocHook::GetLogFileHandler());
|
||||
di << "callback is set to LogFileHandler\n";
|
||||
}
|
||||
}
|
||||
else if (strcmp(a[1], "reset") == 0)
|
||||
{
|
||||
OSD_MAllocHook::GetCollectBySize()->Reset();
|
||||
di << "CollectBySize handler is reset\n";
|
||||
}
|
||||
else if (strcmp(a[1], "open") == 0)
|
||||
{
|
||||
const char* aFileName = (n > 2 ? a[2] : "mem-log.txt");
|
||||
if (!OSD_MAllocHook::GetLogFileHandler()->Open(aFileName))
|
||||
{
|
||||
di << "cannot create file " << aFileName << " for writing\n";
|
||||
return 1;
|
||||
}
|
||||
di << "log file " << aFileName << " is opened for writing\n";
|
||||
}
|
||||
else if (strcmp(a[1], "close") == 0)
|
||||
{
|
||||
OSD_MAllocHook::GetLogFileHandler()->Close();
|
||||
di << "log file is closed\n";
|
||||
}
|
||||
else if (strcmp(a[1], "report1") == 0)
|
||||
{
|
||||
const char* aOutFile = "mem-stat.txt";
|
||||
if (n > 2)
|
||||
aOutFile = a[2];
|
||||
if (OSD_MAllocHook::GetCollectBySize()->MakeReport(aOutFile))
|
||||
{
|
||||
di << "report " << aOutFile << " has been created\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
di << "cannot create report " << aOutFile << "\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (strcmp(a[1], "report2") == 0)
|
||||
{
|
||||
Standard_Boolean includeAlive = Standard_False;
|
||||
const char* aLogFile = "mem-log.txt";
|
||||
const char* aOutFile = "mem-stat.txt";
|
||||
if (n > 2)
|
||||
{
|
||||
includeAlive = (Draw::Atoi(a[2]) != 0);
|
||||
if (n > 3)
|
||||
{
|
||||
aLogFile = a[3];
|
||||
if (n > 4)
|
||||
aOutFile = a[4];
|
||||
}
|
||||
}
|
||||
if (OSD_MAllocHook::LogFileHandler::MakeReport(aLogFile, aOutFile, includeAlive))
|
||||
{
|
||||
di << "report " << aOutFile << " has been created\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
di << "cannot create report " << aOutFile << " from the log file " << aLogFile << "\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
di << "unrecognized command " << a[1] << "\n";
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
static int dlocale(Draw_Interpretor& di, Standard_Integer n, const char** argv)
|
||||
{
|
||||
int category = LC_ALL;
|
||||
@@ -1198,6 +1319,11 @@ void Draw::BasicCommands(Draw_Interpretor& theCommands)
|
||||
"\n\t\t: chrono t -stop -show";
|
||||
theCommands.Add("chrono", aChronoHelp, __FILE__, dchronom, g);
|
||||
theCommands.Add("dchrono", aChronoHelp, __FILE__, dchronom, g);
|
||||
theCommands.Add("mallochook",
|
||||
"debug memory allocation/deallocation, w/o args for help",
|
||||
__FILE__,
|
||||
mallochook,
|
||||
g);
|
||||
theCommands.Add("meminfo",
|
||||
"meminfo [virt|v] [heap|h] [wset|w] [wsetpeak] [swap] [swappeak] [private]"
|
||||
" : memory counters for this process",
|
||||
|
@@ -3,4 +3,5 @@ set(OCCT_TKQADraw_LIST_OF_PACKAGES
|
||||
QABugs
|
||||
QADNaming
|
||||
QADraw
|
||||
QANCollection
|
||||
)
|
||||
|
@@ -2969,12 +2969,96 @@ static Standard_Integer OCC28829(Draw_Interpretor&, Standard_Integer, const char
|
||||
#include <NCollection_Buffer.hxx>
|
||||
#include <DDocStd_DrawDocument.hxx>
|
||||
#include <OSD_FileSystem.hxx>
|
||||
#include <Standard_ArrayStreamBuffer.hxx>
|
||||
#include <TDocStd_Application.hxx>
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
static Standard_Integer OCC28887(Draw_Interpretor&,
|
||||
Standard_Integer theNbArgs,
|
||||
const char** theArgVec)
|
||||
{
|
||||
if (theNbArgs < 3)
|
||||
{
|
||||
std::cout << "Syntax error: wrong number of arguments!\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
const TCollection_AsciiString aFilePath(theArgVec[1]);
|
||||
const TCollection_AsciiString aName(theArgVec[2]);
|
||||
Handle(NCollection_Buffer) aBuffer;
|
||||
{
|
||||
const Handle(OSD_FileSystem)& aFileSystem = OSD_FileSystem::DefaultFileSystem();
|
||||
std::shared_ptr<std::istream> aFile =
|
||||
aFileSystem->OpenIStream(aFilePath, std::ios::binary | std::ios::in);
|
||||
if (aFile.get() == NULL)
|
||||
{
|
||||
std::cout << "Error: input file '" << aFilePath << "' cannot be read\n";
|
||||
return 1;
|
||||
}
|
||||
aFile->seekg(0, std::ios_base::end);
|
||||
const int64_t aFileLength = int64_t(aFile->tellg());
|
||||
if (aFileLength > int64_t(std::numeric_limits<ptrdiff_t>::max()) || aFileLength < 1)
|
||||
{
|
||||
std::cout << "Error: input file '" << aFilePath << "' is too large\n";
|
||||
return 1;
|
||||
}
|
||||
aFile->seekg(0, std::ios_base::beg);
|
||||
|
||||
aBuffer = new NCollection_Buffer(NCollection_BaseAllocator::CommonBaseAllocator());
|
||||
if (!aBuffer->Allocate(size_t(aFileLength)))
|
||||
{
|
||||
std::cout << "Error: memory allocation (" << aFileLength << ") has failed\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
aFile->read((char*)aBuffer->ChangeData(), aBuffer->Size());
|
||||
if (!aFile->good())
|
||||
{
|
||||
std::cout << "Error: input file '" << aFilePath << "' reading failure\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
Standard_ArrayStreamBuffer aStreamBuffer((const char*)aBuffer->ChangeData(), aBuffer->Size());
|
||||
std::istream aStream(&aStreamBuffer);
|
||||
// just play with seeking
|
||||
aStream.seekg(0, std::ios_base::end);
|
||||
aStream.seekg(0, std::ios_base::beg);
|
||||
if (aFilePath.EndsWith(".brep") || aFilePath.EndsWith(".rle"))
|
||||
{
|
||||
TopoDS_Shape aShape;
|
||||
BRep_Builder aBuilder;
|
||||
BRepTools::Read(aShape, aStream, aBuilder);
|
||||
DBRep::Set(aName.ToCString(), aShape);
|
||||
}
|
||||
else
|
||||
{
|
||||
Handle(TDocStd_Document) aDoc;
|
||||
Handle(TDocStd_Application) anApp = DDocStd::GetApplication();
|
||||
Standard_CString aNameVar = aName.ToCString();
|
||||
if (DDocStd::GetDocument(aNameVar, aDoc, Standard_False))
|
||||
{
|
||||
std::cout << "Error: document with name " << aName << " already exists\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (anApp->Open(aStream, aDoc) != PCDM_RS_OK)
|
||||
{
|
||||
std::cout << "Error: cannot open XDE document\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
Handle(DDocStd_DrawDocument) aDrawDoc = new DDocStd_DrawDocument(aDoc);
|
||||
TDataStd_Name::Set(aDoc->GetData()->Root(), aName.ToCString());
|
||||
Draw::Set(aName.ToCString(), aDrawDoc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Standard_Integer OCC28131(Draw_Interpretor&,
|
||||
Standard_Integer theNbArgs,
|
||||
const char** theArgVec)
|
||||
@@ -5206,6 +5290,12 @@ void QABugs::Commands_20(Draw_Interpretor& theCommands)
|
||||
theCommands.Add("OCC28594", "OCC28594", __FILE__, OCC28594, group);
|
||||
theCommands.Add("OCC28784", "OCC28784 result shape", __FILE__, OCC28784, group);
|
||||
theCommands.Add("OCC28829", "OCC28829: perform invalid FPE operation", __FILE__, OCC28829, group);
|
||||
theCommands.Add("OCC28887",
|
||||
"OCC28887 filePath result"
|
||||
"\n\t\t: Check interface for reading BRep from memory.",
|
||||
__FILE__,
|
||||
OCC28887,
|
||||
group);
|
||||
theCommands.Add("OCC28131",
|
||||
"OCC28131 name: creates face problematic for offset",
|
||||
__FILE__,
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#include <QABugs.hxx>
|
||||
#include <QADraw.hxx>
|
||||
#include <QADNaming.hxx>
|
||||
#include <QANCollection.hxx>
|
||||
|
||||
#include <AIS_InteractiveContext.hxx>
|
||||
#include <Bnd_Box.hxx>
|
||||
@@ -174,6 +175,7 @@ void QADraw::Factory(Draw_Interpretor& theCommands)
|
||||
|
||||
QABugs::Commands(theCommands);
|
||||
QADNaming::AllCommands(theCommands);
|
||||
QANCollection::Commands(theCommands);
|
||||
}
|
||||
|
||||
// Declare entry point PLUGINFACTORY
|
||||
|
22
src/Draw/TKQADraw/QANCollection/FILES.cmake
Normal file
22
src/Draw/TKQADraw/QANCollection/FILES.cmake
Normal file
@@ -0,0 +1,22 @@
|
||||
# Source files for QANCollection package
|
||||
set(OCCT_QANCollection_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
|
||||
|
||||
set(OCCT_QANCollection_FILES
|
||||
FILES
|
||||
QANCollection.cxx
|
||||
QANCollection.hxx
|
||||
QANCollection_Alloc.cxx
|
||||
QANCollection_Handle.cxx
|
||||
QANCollection_Common.cxx
|
||||
QANCollection_Common.hxx
|
||||
QANCollection_DataMapIteratorOfDataMapOfRealPnt.hxx
|
||||
QANCollection_DataMapOfRealPnt.hxx
|
||||
QANCollection_DoubleMapIteratorOfDoubleMapOfRealInteger.hxx
|
||||
QANCollection_DoubleMapOfRealInteger.hxx
|
||||
QANCollection_IndexedDataMapOfRealPnt.hxx
|
||||
QANCollection_ListIteratorOfListOfPnt.hxx
|
||||
QANCollection_ListOfPnt.hxx
|
||||
QANCollection_Perf.cxx
|
||||
QANCollection_Stl.cxx
|
||||
QANCollection_Test.cxx
|
||||
)
|
@@ -1,4 +1,6 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
// Created on: 2004-03-05
|
||||
// Created by: Mikhail KUZMITCHEV
|
||||
// Copyright (c) 2004-2014 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
@@ -11,11 +13,14 @@
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <DEBREP_ConfigurationNode.hxx>
|
||||
#include <DEXCAF_ConfigurationNode.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
#include <QANCollection.hxx>
|
||||
#include <Draw_Interpretor.hxx>
|
||||
|
||||
//! Plugin factory function to register TKDECascade configuration nodes.
|
||||
//! Call PLUGINFACTORY() to register both DEBREP_ConfigurationNode and DEXCAF_ConfigurationNode
|
||||
//! with the global DE_Wrapper.
|
||||
DEPLUGIN(DEBREP_ConfigurationNode, DEXCAF_ConfigurationNode)
|
||||
void QANCollection::Commands(Draw_Interpretor& theCommands)
|
||||
{
|
||||
QANCollection::CommandsTest(theCommands);
|
||||
QANCollection::CommandsPerf(theCommands);
|
||||
QANCollection::CommandsAlloc(theCommands);
|
||||
QANCollection::CommandsHandle(theCommands);
|
||||
QANCollection::CommandsStl(theCommands);
|
||||
}
|
43
src/Draw/TKQADraw/QANCollection/QANCollection.hxx
Normal file
43
src/Draw/TKQADraw/QANCollection/QANCollection.hxx
Normal file
@@ -0,0 +1,43 @@
|
||||
// Created on: 2004-03-05
|
||||
// Created by: Mikhail KUZMITCHEV
|
||||
// Copyright (c) 2004-2014 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _QANCollection_HeaderFile
|
||||
#define _QANCollection_HeaderFile
|
||||
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
#include <Standard_Handle.hxx>
|
||||
|
||||
#include <Draw_Interpretor.hxx>
|
||||
|
||||
class QANCollection
|
||||
{
|
||||
public:
|
||||
DEFINE_STANDARD_ALLOC
|
||||
|
||||
Standard_EXPORT static void Commands(Draw_Interpretor& DI);
|
||||
|
||||
Standard_EXPORT static void CommandsTest(Draw_Interpretor& DI);
|
||||
|
||||
Standard_EXPORT static void CommandsPerf(Draw_Interpretor& DI);
|
||||
|
||||
Standard_EXPORT static void CommandsAlloc(Draw_Interpretor& DI);
|
||||
|
||||
Standard_EXPORT static void CommandsStl(Draw_Interpretor& DI);
|
||||
|
||||
Standard_EXPORT static void CommandsHandle(Draw_Interpretor& DI);
|
||||
};
|
||||
|
||||
#endif // _QANCollection_HeaderFile
|
156
src/Draw/TKQADraw/QANCollection/QANCollection_Alloc.cxx
Normal file
156
src/Draw/TKQADraw/QANCollection/QANCollection_Alloc.cxx
Normal file
@@ -0,0 +1,156 @@
|
||||
// Created on: 2004-03-05
|
||||
// Created by: Mikhail KUZMITCHEV
|
||||
// Copyright (c) 2004-2014 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <QANCollection.hxx>
|
||||
#include <Draw_Interpretor.hxx>
|
||||
|
||||
#include <NCollection_OccAllocator.hxx>
|
||||
#include <NCollection_IncAllocator.hxx>
|
||||
#include <Standard_Assert.hxx>
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
static Standard_Integer QANColStdAllocator1(Draw_Interpretor& di,
|
||||
Standard_Integer argc,
|
||||
const char** argv)
|
||||
{
|
||||
if (argc != 1)
|
||||
{
|
||||
di << "Usage : " << argv[0] << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
// type definitions
|
||||
typedef Handle(Standard_Transient) elem_type;
|
||||
typedef NCollection_OccAllocator<elem_type> allocator_type;
|
||||
Standard_STATIC_ASSERT(sizeof(allocator_type::value_type) == sizeof(elem_type));
|
||||
Standard_STATIC_ASSERT(sizeof(allocator_type::pointer) == sizeof(void*));
|
||||
Standard_STATIC_ASSERT(sizeof(allocator_type::const_pointer) == sizeof(void*));
|
||||
|
||||
elem_type aDummy;
|
||||
allocator_type::reference aRef = aDummy;
|
||||
(void)aRef; // avoid compiler warning on unused
|
||||
allocator_type::const_reference aConstRef = aDummy;
|
||||
(void)aConstRef; // avoid compiler warning on unused
|
||||
Standard_STATIC_ASSERT(sizeof(allocator_type::size_type) == sizeof(size_t));
|
||||
Standard_STATIC_ASSERT(sizeof(allocator_type::difference_type) == sizeof(ptrdiff_t));
|
||||
|
||||
typedef int other_elem_type;
|
||||
Standard_STATIC_ASSERT(sizeof(allocator_type::rebind<other_elem_type>::other::value_type)
|
||||
== sizeof(other_elem_type));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
static Standard_Integer QANColStdAllocator2(Draw_Interpretor& di,
|
||||
Standard_Integer argc,
|
||||
const char** argv)
|
||||
{
|
||||
if (argc != 1)
|
||||
{
|
||||
di << "Usage : " << argv[0] << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
// create incremental allocator outside the scope of objects it will manage
|
||||
Handle(NCollection_IncAllocator) anIncAlloc = new NCollection_IncAllocator();
|
||||
|
||||
{
|
||||
// typed allocator
|
||||
NCollection_OccAllocator<int> aSAlloc(anIncAlloc);
|
||||
std::list<int, NCollection_OccAllocator<int>> aL(aSAlloc);
|
||||
aL.push_back(2);
|
||||
if (aL.size() == size_t(1))
|
||||
{
|
||||
di << "Test1 : OK\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
di << "Test1 : Error\n";
|
||||
}
|
||||
|
||||
// type cast
|
||||
NCollection_OccAllocator<char> aCAlloc;
|
||||
std::vector<int, NCollection_OccAllocator<int>> aV(aCAlloc);
|
||||
aV.push_back(1);
|
||||
if (aV.size() == size_t(1))
|
||||
{
|
||||
di << "Test2 : OK\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
di << "Test2 : Error\n";
|
||||
}
|
||||
|
||||
// using void-specialization allocator
|
||||
NCollection_OccAllocator<void*> aVAlloc;
|
||||
std::vector<int, NCollection_OccAllocator<int>> aV2(aVAlloc);
|
||||
|
||||
aV2.resize(10);
|
||||
aV2.push_back(-1);
|
||||
if (aV2.size() == size_t(11))
|
||||
{
|
||||
di << "Test3 : OK\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
di << "Test3 : Error\n";
|
||||
}
|
||||
|
||||
// equality of allocators
|
||||
if (aSAlloc != aCAlloc)
|
||||
{
|
||||
di << "Test4 : OK\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
di << "Test4 : Error\n";
|
||||
}
|
||||
NCollection_OccAllocator<int> anIAlloc(anIncAlloc);
|
||||
if (aSAlloc == anIAlloc)
|
||||
{
|
||||
di << "Test5 : OK\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
di << "Test5 : Error\n";
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void QANCollection::CommandsAlloc(Draw_Interpretor& theCommands)
|
||||
{
|
||||
const char* group = "QANCollection";
|
||||
|
||||
theCommands.Add("QANColStdAllocator1",
|
||||
"QANColStdAllocator1",
|
||||
__FILE__,
|
||||
QANColStdAllocator1,
|
||||
group);
|
||||
theCommands.Add("QANColStdAllocator2",
|
||||
"QANColStdAllocator2",
|
||||
__FILE__,
|
||||
QANColStdAllocator2,
|
||||
group);
|
||||
|
||||
return;
|
||||
}
|
55
src/Draw/TKQADraw/QANCollection/QANCollection_Common.cxx
Normal file
55
src/Draw/TKQADraw/QANCollection/QANCollection_Common.cxx
Normal file
@@ -0,0 +1,55 @@
|
||||
// Created on: 2002-04-30
|
||||
// Created by: Alexander KARTOMIN (akm)
|
||||
// Copyright (c) 2002-2014 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
// Purpose: To test all methods of all NCollection classes
|
||||
|
||||
#include <QANCollection_Common.hxx>
|
||||
#include <stdio.h>
|
||||
|
||||
void PrintItem(const gp_Pnt& thePnt)
|
||||
{
|
||||
printf(" (%5.1f %5.1f %5.1f)\n", thePnt.X(), thePnt.Y(), thePnt.Z());
|
||||
}
|
||||
|
||||
void PrintItem(const Standard_Real theDbl)
|
||||
{
|
||||
printf(" (%5.1f)\n", theDbl);
|
||||
}
|
||||
|
||||
void Random(Standard_Real& theValue)
|
||||
{
|
||||
static Standard_Real dfV = 0.14159265358979323846;
|
||||
dfV *= 37.;
|
||||
dfV -= Floor(dfV);
|
||||
theValue = dfV;
|
||||
// theValue=drand48();
|
||||
}
|
||||
|
||||
void Random(Standard_Integer& theValue, const Standard_Integer theMax)
|
||||
{
|
||||
Standard_Real dfR;
|
||||
Random(dfR);
|
||||
theValue = RealToInt(theMax * dfR);
|
||||
}
|
||||
|
||||
void Random(gp_Pnt& thePnt)
|
||||
{
|
||||
// thePnt.SetCoord(drand48(),drand48(),drand48());
|
||||
Standard_Real dfX, dfY, dfZ;
|
||||
Random(dfX);
|
||||
Random(dfY);
|
||||
Random(dfZ);
|
||||
thePnt.SetCoord(dfX, dfY, dfZ);
|
||||
}
|
34
src/Draw/TKQADraw/QANCollection/QANCollection_Common.hxx
Normal file
34
src/Draw/TKQADraw/QANCollection/QANCollection_Common.hxx
Normal file
@@ -0,0 +1,34 @@
|
||||
// Created on: 2002-05-15
|
||||
// Created by: Alexander KARTOMIN (akm)
|
||||
// Copyright (c) 2002-2014 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef QANCollection_Common_HeaderFile
|
||||
#define QANCollection_Common_HeaderFile
|
||||
|
||||
#include <gp_Pnt.hxx>
|
||||
|
||||
// ===================== Methods for accessing items/keys =====================
|
||||
|
||||
// To print other type of items define PrintItem for it
|
||||
|
||||
Standard_EXPORT void PrintItem(const gp_Pnt& thePnt);
|
||||
Standard_EXPORT void PrintItem(const Standard_Real theDbl);
|
||||
|
||||
// So do for the pseudo-random generation
|
||||
|
||||
Standard_EXPORT void Random(Standard_Real& theValue);
|
||||
Standard_EXPORT void Random(Standard_Integer& theValue, const Standard_Integer theMax = RAND_MAX);
|
||||
Standard_EXPORT void Random(gp_Pnt& thePnt);
|
||||
|
||||
#endif
|
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
// Copyright (c) 2015 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
@@ -11,9 +11,9 @@
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <DEPLY_ConfigurationNode.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
#ifndef QANCollection_DataMapIteratorOfDataMapOfRealPnt_HeaderFile
|
||||
#define QANCollection_DataMapIteratorOfDataMapOfRealPnt_HeaderFile
|
||||
|
||||
//! Plugin factory function to register DEPLY configuration node.
|
||||
//! Call PLUGINFACTORY() to register the DEPLY_ConfigurationNode with the global DE_Wrapper.
|
||||
DEPLUGIN(DEPLY_ConfigurationNode)
|
||||
#include <QANCollection_DataMapOfRealPnt.hxx>
|
||||
|
||||
#endif
|
@@ -0,0 +1,26 @@
|
||||
// Created on: 2004-03-05
|
||||
// Created by: Mikhail KUZMITCHEV
|
||||
// Copyright (c) 2004-2014 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef QANCollection_DataMapOfRealPnt_HeaderFile
|
||||
#define QANCollection_DataMapOfRealPnt_HeaderFile
|
||||
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <NCollection_DataMap.hxx>
|
||||
|
||||
typedef NCollection_DataMap<Standard_Real, gp_Pnt> QANCollection_DataMapOfRealPnt;
|
||||
typedef NCollection_DataMap<Standard_Real, gp_Pnt>::Iterator
|
||||
QANCollection_DataMapIteratorOfDataMapOfRealPnt;
|
||||
|
||||
#endif
|
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
// Copyright (c) 2015 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
@@ -11,9 +11,9 @@
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <DESTL_ConfigurationNode.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
#ifndef QANCollection_DoubleMapIteratorOfDoubleMapOfRealInteger_HeaderFile
|
||||
#define QANCollection_DoubleMapIteratorOfDoubleMapOfRealInteger_HeaderFile
|
||||
|
||||
//! Plugin factory function to register DESTL configuration node.
|
||||
//! Call PLUGINFACTORY() to register the DESTL_ConfigurationNode with the global DE_Wrapper.
|
||||
DEPLUGIN(DESTL_ConfigurationNode)
|
||||
#include <QANCollection_DoubleMapOfRealInteger.hxx>
|
||||
|
||||
#endif
|
@@ -0,0 +1,26 @@
|
||||
// Created on: 2004-03-05
|
||||
// Created by: Mikhail KUZMITCHEV
|
||||
// Copyright (c) 2004-2014 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef QANCollection_DoubleMapOfRealInteger_HeaderFile
|
||||
#define QANCollection_DoubleMapOfRealInteger_HeaderFile
|
||||
|
||||
#include <Standard_Integer.hxx>
|
||||
#include <NCollection_DoubleMap.hxx>
|
||||
|
||||
typedef NCollection_DoubleMap<Standard_Real, Standard_Integer> QANCollection_DoubleMapOfRealInteger;
|
||||
typedef NCollection_DoubleMap<Standard_Real, Standard_Integer>::Iterator
|
||||
QANCollection_DoubleMapIteratorOfDoubleMapOfRealInteger;
|
||||
|
||||
#endif
|
658
src/Draw/TKQADraw/QANCollection/QANCollection_Handle.cxx
Normal file
658
src/Draw/TKQADraw/QANCollection/QANCollection_Handle.cxx
Normal file
@@ -0,0 +1,658 @@
|
||||
// Copyright (c) 2014 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <QANCollection.hxx>
|
||||
|
||||
#include <Draw.hxx>
|
||||
#include <Draw_Interpretor.hxx>
|
||||
|
||||
#include <NCollection_OccAllocator.hxx>
|
||||
#include <NCollection_IncAllocator.hxx>
|
||||
#include <NCollection_HeapAllocator.hxx>
|
||||
#include <OSD_Timer.hxx>
|
||||
#include <Standard_DefineHandle.hxx>
|
||||
#include <Standard_Transient.hxx>
|
||||
#include <TCollection_AsciiString.hxx>
|
||||
#include <Geom_Circle.hxx>
|
||||
#include <Geom_Line.hxx>
|
||||
#include <Geom_BSplineCurve.hxx>
|
||||
#include <Geom_Surface.hxx>
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
// Auxiliary macro to check and report status.
|
||||
// Note that if() is used to ensure that condition is
|
||||
// evaluated before calls to stream output functions, to
|
||||
// prevent side effects from such calls in cases when condition
|
||||
// may contain references to freed objects in the stack.
|
||||
#define CHECK(di, ok, what) \
|
||||
if (ok) \
|
||||
di << "Checking " << what << ": OK\n"; \
|
||||
else \
|
||||
di << "Checking " << what << ": Error\n"
|
||||
|
||||
//=======================================================================
|
||||
// function : QAHandleOps
|
||||
// purpose : Test Handle operations (mostly compile-time checks)
|
||||
//=======================================================================
|
||||
|
||||
// set of overloaded functions for checking resolution of arguments
|
||||
inline void f(const Handle(Geom_Curve)&) {}
|
||||
|
||||
inline void func(const Handle(Geom_Curve)&) {}
|
||||
|
||||
inline void func(const Handle(Geom_BSplineCurve)&) {}
|
||||
|
||||
inline void func(const Handle(Geom_Surface)&) {}
|
||||
|
||||
inline void func(const Handle(gp_Pnt)&) {}
|
||||
|
||||
inline void func(const Handle(gp_XYZ)&) {}
|
||||
|
||||
inline void func(const Handle(gp_Trsf)&) {}
|
||||
|
||||
static Standard_Integer QAHandleOps(Draw_Interpretor& theDI,
|
||||
Standard_Integer /*theArgNb*/,
|
||||
const char** /*theArgVec*/)
|
||||
{
|
||||
// ===============================================================
|
||||
// Part 1: classes inheriting transient
|
||||
// ===============================================================
|
||||
|
||||
Handle(Geom_Line) aLine = new Geom_Line(gp::Origin(), gp::DZ());
|
||||
CHECK(theDI, !aLine.IsNull(), "handle for non-null");
|
||||
|
||||
const Handle(Geom_Line)& cLine = aLine; // cast to self const ref
|
||||
const Handle(Geom_Curve)& cCurve = aLine; // cast to base const ref
|
||||
Geom_Line* pLine = aLine.get();
|
||||
const Geom_Line* cpLine = aLine.get();
|
||||
Geom_Line& rLine = *aLine;
|
||||
const Geom_Line& crLine = *cLine;
|
||||
Handle(Geom_Curve) aCurve = aLine; // copy from handle to derived type
|
||||
aCurve = cLine; // assignment to handle of derived type
|
||||
Handle(Geom_Line) dLine(cpLine); // copy from handle to derived type
|
||||
|
||||
aLine = Handle(Geom_Line)::DownCast(cCurve);
|
||||
CHECK(theDI, !aLine.IsNull(), "down cast");
|
||||
|
||||
// comparison operators
|
||||
CHECK(theDI, aLine == aLine, "equality of handle to itself");
|
||||
CHECK(theDI, cLine == cLine, "equality of const handle to itself");
|
||||
CHECK(theDI, aLine == cLine, "equality of const and non-const handle");
|
||||
CHECK(theDI, aLine == cCurve, "equality of handle and base handle");
|
||||
CHECK(theDI, aLine == pLine, "equality of handle and pointer");
|
||||
CHECK(theDI, pLine == aLine, "equality of pointer and handle");
|
||||
CHECK(theDI, aLine == cpLine, "equality of handle and const pointer");
|
||||
CHECK(theDI, cpLine == aLine, "equality of const pointer and handle");
|
||||
CHECK(theDI, &rLine == aLine, "equality of reference and handle");
|
||||
CHECK(theDI, &crLine == aLine, "equality of reference and handle");
|
||||
CHECK(theDI, aLine, "cast to bool");
|
||||
|
||||
Handle(Geom_Line) aLin2;
|
||||
CHECK(theDI, aLine != aLin2, "inequality of handle to the same type handle");
|
||||
CHECK(theDI, aLin2 != cLine, "inequality of const and non-const handle");
|
||||
CHECK(theDI, aLin2 != cCurve, "inequality of handle and base handle");
|
||||
CHECK(theDI, aLin2 != pLine, "inequality of handle and pointer");
|
||||
CHECK(theDI, pLine != aLin2, "inequality of pointer and handle");
|
||||
CHECK(theDI, aLin2 != cpLine, "inequality of handle and const pointer");
|
||||
CHECK(theDI, cpLine != aLin2, "inequality of const pointer and handle");
|
||||
|
||||
Handle(Geom_Curve) aCur2;
|
||||
CHECK(theDI, aLine != aCur2, "inequality of handles of different types");
|
||||
CHECK(theDI, aCur2 != cLine, "inequality of const and non-const handle");
|
||||
CHECK(theDI, aCur2 != cCurve, "inequality of handle and base handle");
|
||||
CHECK(theDI, aCur2 != pLine, "inequality of handle and pointer");
|
||||
CHECK(theDI, pLine != aCur2, "inequality of pointer and handle");
|
||||
CHECK(theDI, aCur2 != cpLine, "inequality of handle and const pointer");
|
||||
CHECK(theDI, cpLine != aCur2, "inequality of const pointer and handle");
|
||||
|
||||
// passing handle as reference to base class
|
||||
f(aLine);
|
||||
|
||||
// passing handle to overloaded function accepting handle to another type
|
||||
// will fail on VC below 12 and GCC below 4.3 due to ambiguity of overloads
|
||||
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800) \
|
||||
|| (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3)
|
||||
func(aLine);
|
||||
func(cLine);
|
||||
#endif
|
||||
|
||||
const Handle(Geom_Curve)& aCurve2 = aLine; // cast to base const ref
|
||||
CHECK(theDI, !aCurve2.IsNull(), "cast to base class const reference");
|
||||
|
||||
Handle(Geom_Line) qLine = cpLine; // constructor from const pointer -- could be made explicit...
|
||||
|
||||
// check that compiler keeps temporary object referenced by local variable
|
||||
const Handle(Geom_Line)& aTmpRef(Handle(Geom_Line)::DownCast(aCurve2));
|
||||
// note that here and in similar checks below we use comparison of pointers instead
|
||||
// of checking handle for Null, since such check may fail if temporary object is
|
||||
// destroyed prematurely and its location is used for other object.
|
||||
CHECK(theDI, aTmpRef.get() == aCurve2.get(), "local reference of to temporary handle object");
|
||||
|
||||
// check undesired but logical situation:
|
||||
// compiler does not keep temporary object referenced by local variable of base type;
|
||||
// here compiler does not recognize that it should keep the temporary object because handle
|
||||
// classes do not inherit each other and they use hard cast for references to simulate inheritance
|
||||
#if defined(__GNUC__) && (__GNUC__ > 12)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdangling-reference"
|
||||
#endif
|
||||
const Handle(Geom_Curve)& aTmpRefBase(Handle(Geom_Line)::DownCast(aCurve2));
|
||||
CHECK(theDI,
|
||||
aTmpRefBase.get() != aCurve2.get(),
|
||||
"local reference to temporary handle object (base type)");
|
||||
#if defined(__GNUC__) && (__GNUC__ > 12)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
// check operations with Handle_* classes
|
||||
Handle(Geom_Line) hLine = aLine;
|
||||
CHECK(theDI, !hLine.IsNull(), "hhandle for non-null");
|
||||
#include <Standard_WarningsDisable.hxx>
|
||||
const Handle_Geom_Line& chLine = aLine; // cast to self const ref
|
||||
const Handle_Geom_Curve& chCurve = aLine; // cast to base const ref
|
||||
const Handle_Geom_Line& hhLine = hLine; // cast to self const ref
|
||||
const Handle_Geom_Curve& hhCurve = hLine; // cast to base const ref
|
||||
Handle_Geom_Curve hCurve = aLine; // copy from handle to derived type
|
||||
Handle_Geom_Line phLine(aLine.get()); // construct from pointer
|
||||
|
||||
hLine = Handle_Geom_Line::DownCast(cCurve); // inheritance of downcast
|
||||
CHECK(theDI, !hLine.IsNull(), "down cast");
|
||||
|
||||
// comparison operators
|
||||
CHECK(theDI, hLine == hLine, "equality of hhandle to itself");
|
||||
CHECK(theDI, hLine == aLine, "equality of hhandle to handle");
|
||||
CHECK(theDI, hhLine == hLine, "equality of hhandle to const");
|
||||
CHECK(theDI, chLine == hLine, "equality of hhandle to const");
|
||||
CHECK(theDI, hhCurve == hLine, "equality of hhandle to const");
|
||||
CHECK(theDI, chCurve == hLine, "equality of hhandle to const");
|
||||
CHECK(theDI, hLine, "cast to bool");
|
||||
|
||||
// passing hhandle as reference to base class
|
||||
f(hLine);
|
||||
|
||||
// passing handle to overloaded function accepting handle to another type
|
||||
// will fail on VC below 12 and GCC below 4.3 due to ambiguity of overloads
|
||||
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800) \
|
||||
|| (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3)
|
||||
func(hLine);
|
||||
func(chLine);
|
||||
#endif
|
||||
|
||||
Handle_Geom_Line qhLine = cpLine; // constructor from const pointer -- could be made explicit...
|
||||
|
||||
// check that compiler keeps temporary object referenced by local variable
|
||||
#if defined(__GNUC__) && (__GNUC__ > 12)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdangling-reference"
|
||||
#endif
|
||||
const Handle_Geom_Line& hTmpRef(Handle(Geom_Line)::DownCast(aCurve2));
|
||||
CHECK(theDI, hTmpRef.get() == aCurve2.get(), "local reference to temporary object (Handle_)");
|
||||
|
||||
// check lifetime of temporary object referenced by local variable (base type)
|
||||
const Handle_Geom_Curve& hTmpRefBase(Handle(Geom_Line)::DownCast(aCurve2));
|
||||
#if defined(__GNUC__) && (__GNUC__ > 11)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
// here we have different behavior for MSVC 2013+ where Handle_ is a class
|
||||
// (compiler creates temporary object of approprtiate type and keeps it living
|
||||
// until the reference is valid) and other compilers where Handle_ is
|
||||
// typedef to handle<> (compiler does not know that the reference that is being
|
||||
// assigned is pointing to temporary object, due to involved type cast operation)
|
||||
#if (defined(_MSC_VER) && _MSC_VER >= 1800)
|
||||
CHECK(theDI,
|
||||
hTmpRefBase.get() == aCurve2.get(),
|
||||
"local reference to temporary handle object (Handle_ to base type)");
|
||||
#else
|
||||
CHECK(theDI,
|
||||
hTmpRefBase.get() != aCurve2.get(),
|
||||
"local reference to temporary handle object (Handle_ to base type)");
|
||||
#endif
|
||||
#include <Standard_WarningsRestore.hxx>
|
||||
Handle(Geom_Surface) aSurf;
|
||||
(void)aSurf;
|
||||
|
||||
#if 0
|
||||
// each test in this section must cause compiler error
|
||||
gunc (cLine); // passing const handle as non-const reference to base type
|
||||
pLine = cLine.get(); // getting non-const pointer to contained object from const handle
|
||||
Handle(Geom_Line) xLine = cCurve; // copy from handle to base type
|
||||
// clang-format off
|
||||
Handle(Geom_BSplineCurve) aBSpl (new Geom_Line (gp::Origin(), gp::DX())); // construction from pointer to incompatible type
|
||||
// clang-format on
|
||||
|
||||
CHECK(theDI, aLine == aSurf, "equality of handles of incompatible types");
|
||||
CHECK(theDI, aSurf == cLine, "equality of const and non-const handle");
|
||||
CHECK(theDI, aSurf == cCurve, "equality of handle and base handle");
|
||||
CHECK(theDI, aSurf == pLine, "equality of handle and pointer");
|
||||
CHECK(theDI, pLine == aSurf, "equality of pointer and handle");
|
||||
CHECK(theDI, aSurf == cpLine, "equality of handle and const pointer");
|
||||
CHECK(theDI, cpLine != aSurf, "equality of const pointer and handle");
|
||||
|
||||
CHECK(theDI, aLine != aSurf, "inequality of handles of incompatible types");
|
||||
CHECK(theDI, aSurf != cLine, "inequality of const and non-const handle");
|
||||
CHECK(theDI, aSurf != cCurve, "inequality of handle and base handle");
|
||||
CHECK(theDI, aSurf != pLine, "inequality of handle and pointer");
|
||||
CHECK(theDI, pLine != aSurf, "inequality of pointer and handle");
|
||||
CHECK(theDI, aSurf != cpLine, "inequality of handle and const pointer");
|
||||
CHECK(theDI, cpLine != aSurf, "inequality of const pointer and handle");
|
||||
#endif
|
||||
|
||||
// ===============================================================
|
||||
// Part 2: classes not inheriting transient
|
||||
// ===============================================================
|
||||
/*
|
||||
Handle(gp_Pnt) aPnt = new gp_Pnt (gp::Origin());
|
||||
CHECK(theDI, ! aPnt.IsNull(), "handle for non-null");
|
||||
|
||||
const Handle(gp_Pnt)& cPnt = aPnt; // cast to self const ref
|
||||
// const Handle(gp_XYZ)& cXYZ = aPnt; // cast to base const ref
|
||||
gp_Pnt* pPnt = aPnt.get();
|
||||
const gp_Pnt* cpPnt = aPnt.get();
|
||||
gp_Pnt& rPnt = *aPnt;
|
||||
const gp_Pnt& crPnt = *cPnt;
|
||||
// Handle(gp_XYZ) aXYZ = aPnt; // copy from handle to derived type
|
||||
// aXYZ = cPnt; // assignment to handle of derived type
|
||||
|
||||
// aPnt = Handle(gp_Pnt)::DownCast (cXYZ);
|
||||
// CHECK(theDI, ! aPnt.IsNull(), "down cast");
|
||||
|
||||
// comparison operators
|
||||
CHECK(theDI, aPnt == aPnt, "equality of handle to itself");
|
||||
CHECK(theDI, cPnt == cPnt, "equality of const handle to itself");
|
||||
CHECK(theDI, aPnt == cPnt, "equality of const and non-const handle");
|
||||
// CHECK(theDI, aPnt == cXYZ, "equality of handle and base handle");
|
||||
CHECK(theDI, aPnt == pPnt, "equality of handle and pointer");
|
||||
CHECK(theDI, pPnt == aPnt, "equality of pointer and handle");
|
||||
CHECK(theDI, aPnt == cpPnt, "equality of handle and const pointer");
|
||||
CHECK(theDI, cpPnt == aPnt, "equality of const pointer and handle");
|
||||
CHECK(theDI, &rPnt == aPnt, "equality of reference and handle");
|
||||
CHECK(theDI, &crPnt == aPnt, "equality of reference and handle");
|
||||
|
||||
Handle(gp_Pnt) aPnt2;
|
||||
CHECK(theDI, aPnt != aPnt2, "inequality of handle to the same type handle");
|
||||
CHECK(theDI, aPnt2 != cPnt, "inequality of const and non-const handle");
|
||||
// CHECK(theDI, aPnt2 != cXYZ, "inequality of handle and base handle");
|
||||
CHECK(theDI, aPnt2 != pPnt, "inequality of handle and pointer");
|
||||
CHECK(theDI, pPnt != aPnt2, "inequality of pointer and handle");
|
||||
CHECK(theDI, aPnt2 != cpPnt, "inequality of handle and const pointer");
|
||||
CHECK(theDI, cpPnt != aPnt2, "inequality of const pointer and handle");
|
||||
|
||||
Handle(gp_XYZ) aXYZ2;
|
||||
CHECK(theDI, aLine != aPnt2, "inequality of handles of different types");
|
||||
CHECK(theDI, aXYZ2 != cPnt, "inequality of const and non-const handle");
|
||||
// CHECK(theDI, aXYZ2 != cXYZ, "inequality of handle and base handle");
|
||||
// CHECK(theDI, aXYZ2 != pPnt, "inequality of handle and pointer");
|
||||
// CHECK(theDI, pPnt != aXYZ2, "inequality of pointer and handle");
|
||||
// CHECK(theDI, aXYZ2 != cpPnt, "inequality of handle and const pointer");
|
||||
// CHECK(theDI, cpPnt != aXYZ2, "inequality of const pointer and handle");
|
||||
|
||||
// passing handle as reference to base class
|
||||
func (aPnt);
|
||||
func (cPnt);
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// function : QAHandleBool
|
||||
// purpose : Test Handle -> bool conversion
|
||||
//=======================================================================
|
||||
static Standard_Integer QAHandleBool(Draw_Interpretor& theDI,
|
||||
Standard_Integer /*theArgNb*/,
|
||||
const char** /*theArgVec*/)
|
||||
{
|
||||
Handle(NCollection_BaseAllocator) aPtr = new NCollection_IncAllocator();
|
||||
|
||||
Handle(NCollection_IncAllocator) anInc = Handle(NCollection_IncAllocator)::DownCast(aPtr);
|
||||
CHECK(theDI, !anInc.IsNull(), "cast to NCollection_IncAllocator");
|
||||
|
||||
Handle(NCollection_BaseAllocator) anAlloc = aPtr;
|
||||
CHECK(theDI, !anAlloc.IsNull(), "cast to NCollection_BaseAllocator");
|
||||
|
||||
Handle(NCollection_HeapAllocator) aHAlloc = Handle(NCollection_HeapAllocator)::DownCast(aPtr);
|
||||
CHECK(theDI, aHAlloc.IsNull(), "cast to NCollection_HeapAllocator");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Auxiliary class to define new virtual methods
|
||||
class Transient_Root : public Standard_Transient
|
||||
{
|
||||
public:
|
||||
virtual const char* Name() const { return "Transient_Root"; }
|
||||
|
||||
virtual Standard_Transient* CreateParent() const { return new Standard_Transient; }
|
||||
|
||||
virtual Standard_Transient* Clone() const { return new Transient_Root; }
|
||||
DEFINE_STANDARD_RTTI_INLINE(Transient_Root, Standard_Transient)
|
||||
};
|
||||
DEFINE_STANDARD_HANDLE(Transient_Root, Standard_Transient)
|
||||
|
||||
// Auxiliary macros to create hierarchy of 50 classes
|
||||
#define QA_DEFINECLASS(theClass, theParent) \
|
||||
class theClass : public theParent \
|
||||
{ \
|
||||
public: \
|
||||
virtual const char* Name() const Standard_OVERRIDE \
|
||||
{ \
|
||||
return #theClass; \
|
||||
} \
|
||||
virtual Standard_Transient* CreateParent() const Standard_OVERRIDE \
|
||||
{ \
|
||||
return new theParent(); \
|
||||
} \
|
||||
virtual Standard_Transient* Clone() const Standard_OVERRIDE \
|
||||
{ \
|
||||
return new theClass(); \
|
||||
} \
|
||||
DEFINE_STANDARD_RTTI_INLINE(theClass, theParent) \
|
||||
}; \
|
||||
DEFINE_STANDARD_HANDLE(theClass, theParent)
|
||||
|
||||
#define QA_NAME(theNum) qaclass##theNum##_##50
|
||||
#define QA_HANDLE_NAME(theNum) Handle(qaclass##theNum##_##50)
|
||||
|
||||
#define QA_DEFINECLASS10(theParent, theTens) \
|
||||
QA_DEFINECLASS(QA_NAME(theTens##0), theParent) \
|
||||
QA_DEFINECLASS(QA_NAME(theTens##1), QA_NAME(theTens##0)) \
|
||||
QA_DEFINECLASS(QA_NAME(theTens##2), QA_NAME(theTens##1)) \
|
||||
QA_DEFINECLASS(QA_NAME(theTens##3), QA_NAME(theTens##2)) \
|
||||
QA_DEFINECLASS(QA_NAME(theTens##4), QA_NAME(theTens##3)) \
|
||||
QA_DEFINECLASS(QA_NAME(theTens##5), QA_NAME(theTens##4)) \
|
||||
QA_DEFINECLASS(QA_NAME(theTens##6), QA_NAME(theTens##5)) \
|
||||
QA_DEFINECLASS(QA_NAME(theTens##7), QA_NAME(theTens##6)) \
|
||||
QA_DEFINECLASS(QA_NAME(theTens##8), QA_NAME(theTens##7)) \
|
||||
QA_DEFINECLASS(QA_NAME(theTens##9), QA_NAME(theTens##8))
|
||||
|
||||
QA_DEFINECLASS10(Transient_Root, 0)
|
||||
QA_DEFINECLASS10(qaclass09_50, 1)
|
||||
QA_DEFINECLASS10(qaclass19_50, 2)
|
||||
QA_DEFINECLASS10(qaclass29_50, 3)
|
||||
QA_DEFINECLASS10(qaclass39_50, 4)
|
||||
QA_DEFINECLASS(qaclass50_50, qaclass49_50)
|
||||
|
||||
namespace
|
||||
{
|
||||
class qaclass50_50ANON : public qaclass49_50
|
||||
{
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace QaNamespace
|
||||
{
|
||||
class qaclass50_50 : public qaclass49_50
|
||||
{
|
||||
public:
|
||||
qaclass50_50() {}
|
||||
};
|
||||
} // namespace QaNamespace
|
||||
|
||||
namespace
|
||||
{
|
||||
//! Timer sentry. Prints elapsed time information at destruction time.
|
||||
class QATimer : public OSD_Timer
|
||||
{
|
||||
public:
|
||||
enum TimeFormat
|
||||
{
|
||||
Seconds,
|
||||
Milliseconds,
|
||||
Microseconds,
|
||||
Nanoseconds,
|
||||
s = Seconds,
|
||||
ms = Milliseconds,
|
||||
ns = Nanoseconds,
|
||||
};
|
||||
|
||||
public:
|
||||
//! Main constructor - automatically starts the timer.
|
||||
QATimer(Draw_Interpretor& theDI,
|
||||
Standard_CString theTitle,
|
||||
const TimeFormat theFormat,
|
||||
const Standard_Integer theNbIters = 1,
|
||||
const Standard_Boolean theToPrintFormat = Standard_False)
|
||||
: myDI(&theDI),
|
||||
myTitle(theTitle),
|
||||
myFormat(theFormat),
|
||||
myNbIters(theNbIters),
|
||||
myToPrintFormat(theToPrintFormat)
|
||||
{
|
||||
Start();
|
||||
}
|
||||
|
||||
//! Destructor - stops the timer and prints statistics.
|
||||
~QATimer()
|
||||
{
|
||||
Stop();
|
||||
if (myTitle != NULL)
|
||||
{
|
||||
(*myDI) << myTitle;
|
||||
}
|
||||
switch (myFormat)
|
||||
{
|
||||
case Seconds:
|
||||
(*myDI) << ElapsedTime() / Standard_Real(myNbIters);
|
||||
if (myToPrintFormat)
|
||||
{
|
||||
(*myDI) << " s";
|
||||
}
|
||||
break;
|
||||
case Milliseconds:
|
||||
(*myDI) << (ElapsedTime() / Standard_Real(myNbIters)) * 1000.0;
|
||||
if (myToPrintFormat)
|
||||
{
|
||||
(*myDI) << " ms";
|
||||
}
|
||||
break;
|
||||
case Microseconds:
|
||||
(*myDI) << (ElapsedTime() / Standard_Real(myNbIters)) * 1000000.0;
|
||||
if (myToPrintFormat)
|
||||
{
|
||||
(*myDI) << " microseconds";
|
||||
}
|
||||
break;
|
||||
case Nanoseconds:
|
||||
(*myDI) << (ElapsedTime() / Standard_Real(myNbIters)) * 1000000000.0;
|
||||
if (myToPrintFormat)
|
||||
{
|
||||
(*myDI) << " ns";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Draw_Interpretor* myDI;
|
||||
Standard_CString myTitle; //!< timer description
|
||||
TimeFormat myFormat; //!< time format
|
||||
Standard_Integer myNbIters; //!< iterations number
|
||||
Standard_Boolean myToPrintFormat; //!< add time format
|
||||
};
|
||||
} // anonymous namespace
|
||||
|
||||
//=======================================================================
|
||||
// function : QAHandleInc
|
||||
// purpose : Estimate the smart-pointer counter incrementing time
|
||||
//=======================================================================
|
||||
static Standard_Integer QAHandleInc(Draw_Interpretor& theDI,
|
||||
Standard_Integer theArgNb,
|
||||
const char** theArgVec)
|
||||
{
|
||||
if (theArgNb > 2)
|
||||
{
|
||||
std::cout << "Error: wrong syntax! See usage:\n";
|
||||
theDI.PrintHelp(theArgVec[0]);
|
||||
return 1;
|
||||
}
|
||||
const Standard_Integer aNbIters = (theArgNb > 1) ? Draw::Atoi(theArgVec[1]) : 10000000;
|
||||
if (aNbIters < 1)
|
||||
{
|
||||
std::cout << "Error: number of iterations should be positive!\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
Handle(Standard_Transient) aHandle = new Standard_Transient();
|
||||
std::shared_ptr<Standard_Transient> aSharePtr(new Standard_Transient());
|
||||
theDI << "Time of creating and destroying " << aNbIters
|
||||
<< " smart pointers to the same object, per item, ns:";
|
||||
{
|
||||
{
|
||||
QATimer aTimer(theDI, "\nOCCT Handle: ", QATimer::ns, aNbIters);
|
||||
{
|
||||
std::vector<Handle(Standard_Transient)> aHandles(aNbIters);
|
||||
for (Standard_Integer anIter = 0; anIter < aNbIters; ++anIter)
|
||||
{
|
||||
aHandles[anIter] = aHandle;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
QATimer aTimer(theDI, "\nC++ shared_ptr: ", QATimer::ns, aNbIters);
|
||||
{
|
||||
std::vector<std::shared_ptr<Standard_Transient>> aSharePointers(aNbIters);
|
||||
for (Standard_Integer anIter = 0; anIter < aNbIters; ++anIter)
|
||||
{
|
||||
aSharePointers[anIter] = aSharePtr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
static Standard_Integer QAHandleKind(Draw_Interpretor& /*theDI*/,
|
||||
Standard_Integer /*theArgNb*/,
|
||||
const char** /*theArgVec*/)
|
||||
{
|
||||
Handle(Standard_Type) aType00 = STANDARD_TYPE(qaclass00_50);
|
||||
Handle(Standard_Type) aType10 = STANDARD_TYPE(qaclass10_50);
|
||||
Handle(Standard_Type) aType20 = STANDARD_TYPE(qaclass20_50);
|
||||
Handle(Standard_Type) aType30 = STANDARD_TYPE(qaclass30_50);
|
||||
Handle(Standard_Type) aType40 = STANDARD_TYPE(qaclass40_50);
|
||||
Handle(Standard_Type) aType50 = STANDARD_TYPE(qaclass50_50);
|
||||
|
||||
Handle(qaclass00_50) aHandle = new qaclass40_50();
|
||||
|
||||
#define QA_CHECK(theDesc, theExpr, theValue) \
|
||||
{ \
|
||||
const bool isTrue = !!(theExpr); \
|
||||
std::cout << theDesc << (isTrue ? " TRUE " : " FALSE ") \
|
||||
<< (isTrue == theValue ? " is OK\n" : " is Error\n"); \
|
||||
}
|
||||
|
||||
std::cout << "Check instance of " << aHandle->DynamicType()->Name() << "\n";
|
||||
for (Handle(Standard_Type) aType = aHandle->DynamicType(); !aType.IsNull();
|
||||
aType = aType->Parent())
|
||||
{
|
||||
std::cout << " - " << aType->Name() << "\n";
|
||||
}
|
||||
|
||||
QA_CHECK("Name == qaclass40_50 : ",
|
||||
TCollection_AsciiString("qaclass40_50") == aHandle->DynamicType()->Name(),
|
||||
true);
|
||||
|
||||
QA_CHECK("IsKind (aType00) : ", aHandle->IsKind(aType00), true);
|
||||
QA_CHECK("IsKind (aType10) : ", aHandle->IsKind(aType10), true);
|
||||
QA_CHECK("IsKind (aType20) : ", aHandle->IsKind(aType20), true);
|
||||
QA_CHECK("IsKind (aType30) : ", aHandle->IsKind(aType30), true);
|
||||
QA_CHECK("IsKind (aType40) : ", aHandle->IsKind(aType40), true);
|
||||
QA_CHECK("IsKind (aType50) : ", aHandle->IsKind(aType50), false);
|
||||
|
||||
QA_CHECK("IsKind (\"qaclass00_50\"): ", aHandle->IsKind("qaclass00_50"), true);
|
||||
QA_CHECK("IsKind (\"qaclass10_50\"): ", aHandle->IsKind("qaclass10_50"), true);
|
||||
QA_CHECK("IsKind (\"qaclass20_50\"): ", aHandle->IsKind("qaclass20_50"), true);
|
||||
QA_CHECK("IsKind (\"qaclass30_50\"): ", aHandle->IsKind("qaclass30_50"), true);
|
||||
QA_CHECK("IsKind (\"qaclass40_50\"): ", aHandle->IsKind("qaclass40_50"), true);
|
||||
QA_CHECK("IsKind (\"qaclass50_50\"): ", aHandle->IsKind("qaclass50_50"), false);
|
||||
|
||||
QA_CHECK("IsInstance (aType00) : ", aHandle->IsInstance(aType00), false);
|
||||
QA_CHECK("IsInstance (aType10) : ", aHandle->IsInstance(aType10), false);
|
||||
QA_CHECK("IsInstance (aType20) : ", aHandle->IsInstance(aType20), false);
|
||||
QA_CHECK("IsInstance (aType30) : ", aHandle->IsInstance(aType30), false);
|
||||
QA_CHECK("IsInstance (aType40) : ", aHandle->IsInstance(aType40), true);
|
||||
QA_CHECK("IsInstance (aType50) : ", aHandle->IsInstance(aType50), false);
|
||||
|
||||
#ifdef HAVE_CPP11
|
||||
std::cout << "\nC++11:\n";
|
||||
std::type_index aCppType = typeid(*aHandle.operator->());
|
||||
std::cout << "typeid().name() = '" << typeid(*aHandle.operator->()).name() << "'\n";
|
||||
#ifdef _MSC_VER
|
||||
std::cout << "typeid().raw_name()= '" << typeid(*aHandle.operator->()).raw_name() << "'\n";
|
||||
#endif
|
||||
|
||||
std::cout << "[ANON]typeid().name() = '" << typeid(qaclass50_50ANON).name() << "'\n";
|
||||
#ifdef _MSC_VER
|
||||
std::cout << "[ANON]typeid().raw_name()= '" << typeid(qaclass50_50ANON).raw_name() << "'\n";
|
||||
#endif
|
||||
|
||||
std::cout << "[NS]typeid().name() = '" << typeid(QaNamespace::qaclass50_50).name() << "'\n";
|
||||
#ifdef _MSC_VER
|
||||
std::cout << "[NS]typeid().raw_name()= '" << typeid(QaNamespace::qaclass50_50).raw_name()
|
||||
<< "'\n";
|
||||
#endif
|
||||
|
||||
QA_CHECK("is typeid (aType00) : ",
|
||||
typeid(*aHandle.operator->()) == typeid(qaclass00_50),
|
||||
false);
|
||||
QA_CHECK("is typeid (aType10) : ",
|
||||
typeid(*aHandle.operator->()) == typeid(qaclass10_50),
|
||||
false);
|
||||
QA_CHECK("is typeid (aType20) : ",
|
||||
typeid(*aHandle.operator->()) == typeid(qaclass20_50),
|
||||
false);
|
||||
QA_CHECK("is typeid (aType30) : ",
|
||||
typeid(*aHandle.operator->()) == typeid(qaclass30_50),
|
||||
false);
|
||||
QA_CHECK("is typeid (aType40) : ",
|
||||
typeid(*aHandle.operator->()) == typeid(qaclass40_50),
|
||||
true);
|
||||
QA_CHECK("is typeid (aType50) : ",
|
||||
typeid(*aHandle.operator->()) == typeid(qaclass50_50),
|
||||
false);
|
||||
|
||||
QA_CHECK("is type_index (aType00) : ", aCppType == typeid(qaclass00_50), false);
|
||||
QA_CHECK("is type_index (aType40) : ", aCppType == typeid(qaclass40_50), true);
|
||||
|
||||
QA_CHECK("IsClass(Standard_Transient): ",
|
||||
std::is_class<Standard_Transient>::value
|
||||
== !!STANDARD_TYPE(Standard_Transient)->IsClass(),
|
||||
true);
|
||||
// QA_CHECK ("IsEnum (Message_Status) : ", std::is_enum<Message_Status>::value ==
|
||||
// !!STANDARD_TYPE(Message_Status)->IsEnumeration(), true);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void QANCollection::CommandsHandle(Draw_Interpretor& theCommands)
|
||||
{
|
||||
const char* THE_GROUP = "QANCollection";
|
||||
theCommands.Add("QAHandleBool",
|
||||
"Test handle boolean operator",
|
||||
__FILE__,
|
||||
QAHandleBool,
|
||||
THE_GROUP);
|
||||
theCommands.Add("QAHandleInc",
|
||||
"QAHandleInc nbIter=1000000"
|
||||
"\n\t\t: Test handle increment performance",
|
||||
__FILE__,
|
||||
QAHandleInc,
|
||||
THE_GROUP);
|
||||
theCommands.Add("QAHandleKind", "Test handle IsKind", __FILE__, QAHandleKind, THE_GROUP);
|
||||
theCommands.Add("QAHandleOps", "Test handle operations", __FILE__, QAHandleOps, THE_GROUP);
|
||||
return;
|
||||
}
|
@@ -1,4 +1,6 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
// Created on: 2004-03-05
|
||||
// Created by: Mikhail KUZMITCHEV
|
||||
// Copyright (c) 2004-2014 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
@@ -11,9 +13,12 @@
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <DEGLTF_ConfigurationNode.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
#ifndef QANCollection_IndexedDataMapOfRealPnt_HeaderFile
|
||||
#define QANCollection_IndexedDataMapOfRealPnt_HeaderFile
|
||||
|
||||
//! Plugin factory function to register DEGLTF configuration node.
|
||||
//! Call PLUGINFACTORY() to register the DEGLTF_ConfigurationNode with the global DE_Wrapper.
|
||||
DEPLUGIN(DEGLTF_ConfigurationNode)
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <NCollection_IndexedDataMap.hxx>
|
||||
|
||||
typedef NCollection_IndexedDataMap<Standard_Real, gp_Pnt> QANCollection_IndexedDataMapOfRealPnt;
|
||||
|
||||
#endif
|
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
// Copyright (c) 2015 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
@@ -11,9 +11,9 @@
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <DEOBJ_ConfigurationNode.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
#ifndef QANCollection_ListIteratorOfListOfPnt_HeaderFile
|
||||
#define QANCollection_ListIteratorOfListOfPnt_HeaderFile
|
||||
|
||||
//! Plugin factory function to register DEOBJ configuration node.
|
||||
//! Call PLUGINFACTORY() to register the DEOBJ_ConfigurationNode with the global DE_Wrapper.
|
||||
DEPLUGIN(DEOBJ_ConfigurationNode)
|
||||
#include <QANCollection_ListOfPnt.hxx>
|
||||
|
||||
#endif
|
@@ -1,4 +1,6 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
// Created on: 2004-03-05
|
||||
// Created by: Mikhail KUZMITCHEV
|
||||
// Copyright (c) 2004-2014 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
@@ -11,9 +13,13 @@
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <DEIGES_ConfigurationNode.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
#ifndef QANCollection_ListOfPnt_HeaderFile
|
||||
#define QANCollection_ListOfPnt_HeaderFile
|
||||
|
||||
//! Plugin factory function to register DEIGES configuration node.
|
||||
//! Call PLUGINFACTORY() to register the DEIGES_ConfigurationNode with the global DE_Wrapper.
|
||||
DEPLUGIN(DEIGES_ConfigurationNode)
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <NCollection_List.hxx>
|
||||
|
||||
typedef NCollection_List<gp_Pnt> QANCollection_ListOfPnt;
|
||||
typedef NCollection_List<gp_Pnt>::Iterator QANCollection_ListIteratorOfListOfPnt;
|
||||
|
||||
#endif
|
1046
src/Draw/TKQADraw/QANCollection/QANCollection_Perf.cxx
Normal file
1046
src/Draw/TKQADraw/QANCollection/QANCollection_Perf.cxx
Normal file
File diff suppressed because it is too large
Load Diff
1438
src/Draw/TKQADraw/QANCollection/QANCollection_Stl.cxx
Normal file
1438
src/Draw/TKQADraw/QANCollection/QANCollection_Stl.cxx
Normal file
File diff suppressed because it is too large
Load Diff
1477
src/Draw/TKQADraw/QANCollection/QANCollection_Test.cxx
Normal file
1477
src/Draw/TKQADraw/QANCollection/QANCollection_Test.cxx
Normal file
File diff suppressed because it is too large
Load Diff
@@ -6375,106 +6375,6 @@ static Standard_Integer VMoveTo(Draw_Interpretor& theDI,
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : VMouseButton
|
||||
//purpose : Emulates mouse button event
|
||||
//=======================================================================
|
||||
static Standard_Integer VMouseButton(Draw_Interpretor& /*theDI*/,
|
||||
Standard_Integer theNbArgs,
|
||||
const char** theArgVec)
|
||||
{
|
||||
const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
|
||||
const Handle(V3d_View)& aView = ViewerTest::CurrentView();
|
||||
if (aContext.IsNull())
|
||||
{
|
||||
Message::SendFail("Error: no active viewer");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (theNbArgs < 6)
|
||||
{
|
||||
Message::SendFail("Syntax error: wrong number arguments");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Aspect_VKeyMouse aButton = Aspect_VKeyMouse_LeftButton;
|
||||
Standard_Boolean isPressButton = false;
|
||||
|
||||
Graphic3d_Vec2i aMousePos(IntegerLast(), IntegerLast());
|
||||
for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
|
||||
{
|
||||
TCollection_AsciiString anArgStr(theArgVec[anArgIter]);
|
||||
anArgStr.LowerCase();
|
||||
if (anArgStr == "-button")
|
||||
{
|
||||
if (anArgIter + 1 < theNbArgs)
|
||||
{
|
||||
++anArgIter;
|
||||
TCollection_AsciiString aButtonStr(theArgVec[anArgIter]);
|
||||
if (aButtonStr == "left")
|
||||
{
|
||||
aButton = Aspect_VKeyMouse_LeftButton;
|
||||
}
|
||||
else if (aButtonStr == "right")
|
||||
{
|
||||
aButton = Aspect_VKeyMouse_RightButton;
|
||||
}
|
||||
else if (aButtonStr == "middle")
|
||||
{
|
||||
aButton = Aspect_VKeyMouse_MiddleButton;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (anArgStr == "-up")
|
||||
{
|
||||
isPressButton = false;
|
||||
}
|
||||
else if (anArgStr == "-down")
|
||||
{
|
||||
isPressButton = true;
|
||||
}
|
||||
else if (aMousePos.x() == IntegerLast()
|
||||
&& anArgStr.IsIntegerValue())
|
||||
{
|
||||
aMousePos.x() = anArgStr.IntegerValue();
|
||||
}
|
||||
else if (aMousePos.y() == IntegerLast()
|
||||
&& anArgStr.IsIntegerValue())
|
||||
{
|
||||
aMousePos.y() = anArgStr.IntegerValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (aMousePos.x() == IntegerLast()
|
||||
|| aMousePos.y() == IntegerLast())
|
||||
{
|
||||
Message::SendFail("Syntax error: wrong number of arguments");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (isPressButton)
|
||||
{
|
||||
ViewerTest::CurrentEventManager()->ResetPreviousMoveTo();
|
||||
ViewerTest::CurrentEventManager()->PressMouseButton(aMousePos, aButton, Aspect_VKeyFlags_NONE, false);
|
||||
ViewerTest::CurrentEventManager()->UpdateMousePosition(aMousePos, Aspect_VKeyMouse_NONE, Aspect_VKeyFlags_NONE, false);
|
||||
ViewerTest::CurrentEventManager()->FlushViewEvents(ViewerTest::GetAISContext(), aView, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ViewerTest::CurrentEventManager()->UpdateMousePosition(aMousePos, Aspect_VKeyMouse_NONE, Aspect_VKeyFlags_NONE, false);
|
||||
ViewerTest::CurrentEventManager()->FlushViewEvents(ViewerTest::GetAISContext(), aView, true);
|
||||
ViewerTest::CurrentEventManager()->ReleaseMouseButton(aMousePos, aButton, Aspect_VKeyFlags_NONE, false);
|
||||
ViewerTest::CurrentEventManager()->FlushViewEvents(ViewerTest::GetAISContext(), aView, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
static Standard_Integer VSelectByAxis(Draw_Interpretor& theDI,
|
||||
@@ -14181,14 +14081,6 @@ Emulate cursor movement to pixel position (x,y).
|
||||
-reset resets current highlighting.
|
||||
)" /* [vmoveto] */);
|
||||
|
||||
addCmd("vmousebutton", VMouseButton, /* [vmousebutton] */ R"(
|
||||
vmousebutton x y -button right|left|middle -up|-down
|
||||
Emulate mouse button events.
|
||||
-button choose button;
|
||||
-down press button;
|
||||
-up release button.
|
||||
)" /* [vmousebutton] */);
|
||||
|
||||
addCmd("vselaxis", VSelectByAxis, /* [vselaxis] */ R"(
|
||||
vselaxis x y z dx dy dz [-onlyTop 0|1] [-display Name] [-showNormal 0|1]"
|
||||
Provides intersection by given axis and print result intersection points.
|
||||
|
@@ -20,8 +20,6 @@
|
||||
#include <DE_Provider.hxx>
|
||||
#include <DE_Wrapper.hxx>
|
||||
#include <DEBREP_ConfigurationNode.hxx>
|
||||
#include <DEXCAF_ConfigurationNode.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
#include <Draw.hxx>
|
||||
#include <Draw_Interpretor.hxx>
|
||||
#include <Draw_PluginMacro.hxx>
|
||||
@@ -33,16 +31,6 @@
|
||||
#include <XSControl_WorkSession.hxx>
|
||||
#include <XSDRAW.hxx>
|
||||
|
||||
namespace
|
||||
{
|
||||
// Singleton to ensure DEBREP and DEXCAF plugins are registered only once
|
||||
void DECascadeSingleton()
|
||||
{
|
||||
static DE_MultiPluginHolder<DEBREP_ConfigurationNode, DEXCAF_ConfigurationNode> aHolder;
|
||||
(void)aHolder;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
static Standard_Integer DumpConfiguration(Draw_Interpretor& theDI,
|
||||
@@ -376,9 +364,6 @@ void XSDRAWDE::Factory(Draw_Interpretor& theDI)
|
||||
}
|
||||
aIsActivated = Standard_True;
|
||||
|
||||
//! Ensure DEBREP and DEXCAF plugins are registered
|
||||
DECascadeSingleton();
|
||||
|
||||
Standard_CString aGroup = "XDE translation commands";
|
||||
theDI.Add("DumpConfiguration",
|
||||
"DumpConfiguration [-path <path>] [-recursive {on|off}] [-format fmt1 fmt2 ...] "
|
||||
@@ -443,6 +428,10 @@ void XSDRAWDE::Factory(Draw_Interpretor& theDI)
|
||||
|
||||
// Load XSDRAW session for pilot activation
|
||||
XSDRAW::LoadDraw(theDI);
|
||||
|
||||
// Workaround to force load TKDECascade lib
|
||||
DEBREP_ConfigurationNode aTmpObj;
|
||||
(void)aTmpObj;
|
||||
}
|
||||
|
||||
// Declare entry point PLUGINFACTORY
|
||||
|
@@ -16,8 +16,6 @@
|
||||
#include <DBRep.hxx>
|
||||
#include <DDocStd.hxx>
|
||||
#include <DDocStd_DrawDocument.hxx>
|
||||
#include <DEGLTF_ConfigurationNode.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
#include <Draw.hxx>
|
||||
#include <Draw_Interpretor.hxx>
|
||||
#include <Draw_PluginMacro.hxx>
|
||||
@@ -32,16 +30,6 @@
|
||||
#include <XSControl_WorkSession.hxx>
|
||||
#include <XSDRAW.hxx>
|
||||
|
||||
namespace
|
||||
{
|
||||
// Singleton to ensure DEGLTF plugin is registered only once
|
||||
void DEGLTFSingleton()
|
||||
{
|
||||
static DE_PluginHolder<DEGLTF_ConfigurationNode> aHolder;
|
||||
(void)aHolder;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//=============================================================================
|
||||
// function : parseNameFormat
|
||||
// purpose : Parse RWMesh_NameFormat enumeration
|
||||
@@ -521,9 +509,6 @@ void XSDRAWGLTF::Factory(Draw_Interpretor& theDI)
|
||||
}
|
||||
aIsActivated = Standard_True;
|
||||
|
||||
//! Ensure DEGLTF plugin is registered
|
||||
DEGLTFSingleton();
|
||||
|
||||
const char* aGroup = "XSTEP-STL/VRML"; // Step transfer file commands
|
||||
theDI.Add("ReadGltf",
|
||||
"ReadGltf Doc file [-parallel {on|off}] [-listExternalFiles] [-noCreateDoc] "
|
||||
|
@@ -17,8 +17,6 @@
|
||||
#include <DBRep.hxx>
|
||||
#include <DDocStd.hxx>
|
||||
#include <DDocStd_DrawDocument.hxx>
|
||||
#include <DEIGES_ConfigurationNode.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
#include <Draw.hxx>
|
||||
#include <DrawTrSurf.hxx>
|
||||
#include <Draw_Interpretor.hxx>
|
||||
@@ -1110,16 +1108,6 @@ static Standard_Integer WriteIges(Draw_Interpretor& theDI,
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
// Singleton to ensure DEIGES plugin is registered only once
|
||||
void DEIGESSingleton()
|
||||
{
|
||||
static DE_PluginHolder<DEIGES_ConfigurationNode> aHolder;
|
||||
(void)aHolder;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void XSDRAWIGES::Factory(Draw_Interpretor& theDI)
|
||||
@@ -1133,9 +1121,6 @@ void XSDRAWIGES::Factory(Draw_Interpretor& theDI)
|
||||
|
||||
IGESControl_Controller::Init();
|
||||
|
||||
//! Ensure DEIGES plugin is registered
|
||||
DEIGESSingleton();
|
||||
|
||||
const char* aGroup = "DE: IGES";
|
||||
|
||||
theDI.Add("tplosttrim",
|
||||
|
@@ -17,8 +17,6 @@
|
||||
#include <DBRep.hxx>
|
||||
#include <DDocStd.hxx>
|
||||
#include <DDocStd_DrawDocument.hxx>
|
||||
#include <DEOBJ_ConfigurationNode.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
#include <Draw.hxx>
|
||||
#include <Draw_Interpretor.hxx>
|
||||
#include <Draw_PluginMacro.hxx>
|
||||
@@ -337,16 +335,6 @@ static Standard_Integer WriteObj(Draw_Interpretor& theDI,
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
// Singleton to ensure DEOBJ plugin is registered only once
|
||||
void DEOBJSingleton()
|
||||
{
|
||||
static DE_PluginHolder<DEOBJ_ConfigurationNode> aHolder;
|
||||
(void)aHolder;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void XSDRAWOBJ::Factory(Draw_Interpretor& theDI)
|
||||
@@ -358,9 +346,6 @@ void XSDRAWOBJ::Factory(Draw_Interpretor& theDI)
|
||||
}
|
||||
aIsActivated = Standard_True;
|
||||
|
||||
//! Ensure DEOBJ plugin is registered
|
||||
DEOBJSingleton();
|
||||
|
||||
const char* aGroup = "XSTEP-STL/VRML"; // Step transfer file commands
|
||||
theDI.Add(
|
||||
"ReadObj",
|
||||
|
@@ -18,8 +18,6 @@
|
||||
#include <DBRep.hxx>
|
||||
#include <DDocStd.hxx>
|
||||
#include <DDocStd_DrawDocument.hxx>
|
||||
#include <DEPLY_ConfigurationNode.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
#include <Draw.hxx>
|
||||
#include <Draw_Interpretor.hxx>
|
||||
#include <Draw_PluginMacro.hxx>
|
||||
@@ -297,16 +295,6 @@ static Standard_Integer WritePly(Draw_Interpretor& theDI,
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
// Singleton to ensure DEPLY plugin is registered only once
|
||||
void DEPLYSingleton()
|
||||
{
|
||||
static DE_PluginHolder<DEPLY_ConfigurationNode> aHolder;
|
||||
(void)aHolder;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void XSDRAWPLY::Factory(Draw_Interpretor& theDI)
|
||||
@@ -318,9 +306,6 @@ void XSDRAWPLY::Factory(Draw_Interpretor& theDI)
|
||||
}
|
||||
aIsActivated = Standard_True;
|
||||
|
||||
//! Ensure DEPLY plugin is registered
|
||||
DEPLYSingleton();
|
||||
|
||||
const char* aGroup = "XSTEP-STL/VRML"; // Step transfer file commands
|
||||
// XSDRAW::LoadDraw(theCommands);
|
||||
theDI.Add("WritePly",
|
||||
|
@@ -17,8 +17,6 @@
|
||||
#include <DDF.hxx>
|
||||
#include <DDocStd.hxx>
|
||||
#include <DDocStd_DrawDocument.hxx>
|
||||
#include <DESTEP_ConfigurationNode.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
#include <Draw.hxx>
|
||||
#include <Draw_Interpretor.hxx>
|
||||
#include <Draw_PluginMacro.hxx>
|
||||
@@ -1094,16 +1092,6 @@ static Standard_Integer WriteStep(Draw_Interpretor& theDI,
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
// Singleton to ensure DESTEP plugin is registered only once
|
||||
void DESTEPSingleton()
|
||||
{
|
||||
static DE_PluginHolder<DESTEP_ConfigurationNode> aHolder;
|
||||
(void)aHolder;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void XSDRAWSTEP::Factory(Draw_Interpretor& theDI)
|
||||
@@ -1116,9 +1104,6 @@ void XSDRAWSTEP::Factory(Draw_Interpretor& theDI)
|
||||
STEPCAFControl_Controller::Init();
|
||||
aIsActivated = Standard_True;
|
||||
|
||||
//! Ensure DESTEP plugin is registered
|
||||
DESTEPSingleton();
|
||||
|
||||
const char* aGroup = "DE: STEP"; // Step transfer file commands
|
||||
theDI.Add("stepwrite", "stepwrite mode[0-4 afsmw] shape", __FILE__, stepwrite, aGroup);
|
||||
theDI.Add("testwritestep",
|
||||
|
@@ -18,8 +18,6 @@
|
||||
#include <DBRep.hxx>
|
||||
#include <DDocStd.hxx>
|
||||
#include <DDocStd_DrawDocument.hxx>
|
||||
#include <DESTL_ConfigurationNode.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
#include <Draw.hxx>
|
||||
#include <Draw_Interpretor.hxx>
|
||||
#include <Draw_PluginMacro.hxx>
|
||||
@@ -1235,16 +1233,6 @@ static Standard_Integer meshinfo(Draw_Interpretor& theDI,
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
// Singleton to ensure DESTL plugin is registered only once
|
||||
void DESTLSingleton()
|
||||
{
|
||||
static DE_PluginHolder<DESTL_ConfigurationNode> aHolder;
|
||||
(void)aHolder;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void XSDRAWSTL::Factory(Draw_Interpretor& theDI)
|
||||
@@ -1256,9 +1244,6 @@ void XSDRAWSTL::Factory(Draw_Interpretor& theDI)
|
||||
}
|
||||
aIsActivated = Standard_True;
|
||||
|
||||
//! Ensure DESTL plugin is registered
|
||||
DESTLSingleton();
|
||||
|
||||
const char* aGroup = "XSTEP-STL/VRML"; // Step transfer file commands
|
||||
|
||||
theDI.Add("writestl",
|
||||
|
@@ -16,8 +16,6 @@
|
||||
#include <DBRep.hxx>
|
||||
#include <DDocStd.hxx>
|
||||
#include <DDocStd_DrawDocument.hxx>
|
||||
#include <DEVRML_ConfigurationNode.hxx>
|
||||
#include <DE_PluginHolder.hxx>
|
||||
#include <Draw.hxx>
|
||||
#include <Draw_Interpretor.hxx>
|
||||
#include <Draw_PluginMacro.hxx>
|
||||
@@ -410,16 +408,6 @@ static Standard_Integer writevrml(Draw_Interpretor& di, Standard_Integer argc, c
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
// Singleton to ensure DEVRML plugin is registered only once
|
||||
void DEVRMLSingleton()
|
||||
{
|
||||
static DE_PluginHolder<DEVRML_ConfigurationNode> aHolder;
|
||||
(void)aHolder;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void XSDRAWVRML::Factory(Draw_Interpretor& theDI)
|
||||
@@ -431,9 +419,6 @@ void XSDRAWVRML::Factory(Draw_Interpretor& theDI)
|
||||
}
|
||||
anInitActor = Standard_True;
|
||||
|
||||
//! Ensure DEVRML plugin is registered
|
||||
DEVRMLSingleton();
|
||||
|
||||
Standard_CString aGroup = "XDE translation commands";
|
||||
theDI.Add(
|
||||
"ReadVrml",
|
||||
|
@@ -34,8 +34,4 @@ set(OCCT_TKMath_GTests_FILES
|
||||
math_TrigonometricFunctionRoots_Test.cxx
|
||||
math_Uzawa_Test.cxx
|
||||
math_Vector_Test.cxx
|
||||
PLib_Test.cxx
|
||||
PLib_JacobiPolynomial_Test.cxx
|
||||
PLib_HermitJacobi_Test.cxx
|
||||
PLib_DoubleJacobiPolynomial_Test.cxx
|
||||
)
|
||||
|
@@ -1,402 +0,0 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <PLib_DoubleJacobiPolynomial.hxx>
|
||||
#include <PLib_JacobiPolynomial.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <Standard_Real.hxx>
|
||||
#include <Standard_Integer.hxx>
|
||||
#include <TColStd_Array1OfReal.hxx>
|
||||
#include <TColStd_HArray1OfReal.hxx>
|
||||
#include <GeomAbs_Shape.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
// Test fixture for PLib_DoubleJacobiPolynomial tests
|
||||
class PLibDoubleJacobiPolynomialTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
// Create Jacobi polynomials for testing
|
||||
myJacobiU = new PLib_JacobiPolynomial(10, GeomAbs_C0);
|
||||
myJacobiV = new PLib_JacobiPolynomial(8, GeomAbs_C1);
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
myJacobiU.Nullify();
|
||||
myJacobiV.Nullify();
|
||||
}
|
||||
|
||||
Handle(PLib_JacobiPolynomial) myJacobiU;
|
||||
Handle(PLib_JacobiPolynomial) myJacobiV;
|
||||
|
||||
// Helper to create test coefficients
|
||||
void createTestCoefficients(TColStd_Array1OfReal& theCoeffs,
|
||||
Standard_Integer theDimension,
|
||||
Standard_Integer theDegreeU,
|
||||
Standard_Integer theDegreeV)
|
||||
{
|
||||
Standard_Integer anIndex = theCoeffs.Lower(); // Start from array lower bound
|
||||
for (Standard_Integer j = 0; j <= theDegreeV; j++)
|
||||
{
|
||||
for (Standard_Integer i = 0; i <= theDegreeU; i++)
|
||||
{
|
||||
for (Standard_Integer d = 1; d <= theDimension; d++)
|
||||
{
|
||||
theCoeffs(anIndex) = Sin(anIndex * 0.1 + i * 0.2 + j * 0.3);
|
||||
anIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Test default constructor
|
||||
TEST_F(PLibDoubleJacobiPolynomialTest, DefaultConstructor)
|
||||
{
|
||||
PLib_DoubleJacobiPolynomial aDoubleJac;
|
||||
|
||||
// After default construction, accessors should return null handles
|
||||
EXPECT_TRUE(aDoubleJac.U().IsNull()) << "U polynomial should be null after default construction";
|
||||
EXPECT_TRUE(aDoubleJac.V().IsNull()) << "V polynomial should be null after default construction";
|
||||
EXPECT_TRUE(aDoubleJac.TabMaxU().IsNull()) << "TabMaxU should be null after default construction";
|
||||
EXPECT_TRUE(aDoubleJac.TabMaxV().IsNull()) << "TabMaxV should be null after default construction";
|
||||
}
|
||||
|
||||
// Test parameterized constructor
|
||||
TEST_F(PLibDoubleJacobiPolynomialTest, ParameterizedConstructor)
|
||||
{
|
||||
ASSERT_FALSE(myJacobiU.IsNull()) << "JacobiU should not be null";
|
||||
ASSERT_FALSE(myJacobiV.IsNull()) << "JacobiV should not be null";
|
||||
|
||||
PLib_DoubleJacobiPolynomial aDoubleJac(myJacobiU, myJacobiV);
|
||||
|
||||
// After construction with parameters, accessors should return valid handles
|
||||
EXPECT_FALSE(aDoubleJac.U().IsNull()) << "U polynomial should not be null";
|
||||
EXPECT_FALSE(aDoubleJac.V().IsNull()) << "V polynomial should not be null";
|
||||
EXPECT_FALSE(aDoubleJac.TabMaxU().IsNull()) << "TabMaxU should not be null";
|
||||
EXPECT_FALSE(aDoubleJac.TabMaxV().IsNull()) << "TabMaxV should not be null";
|
||||
|
||||
// Test that the returned handles are correct
|
||||
EXPECT_EQ(aDoubleJac.U().get(), myJacobiU.get()) << "U polynomial handle should match";
|
||||
EXPECT_EQ(aDoubleJac.V().get(), myJacobiV.get()) << "V polynomial handle should match";
|
||||
}
|
||||
|
||||
// Test MaxErrorU calculation
|
||||
TEST_F(PLibDoubleJacobiPolynomialTest, MaxErrorU)
|
||||
{
|
||||
PLib_DoubleJacobiPolynomial aDoubleJac(myJacobiU, myJacobiV);
|
||||
|
||||
const Standard_Integer aDimension = 2;
|
||||
const Standard_Integer aDegreeU = 6;
|
||||
const Standard_Integer aDegreeV = 5;
|
||||
const Standard_Integer aDJacCoeff = (aDegreeU + 1) * aDimension;
|
||||
|
||||
// JacCoeff array must be sized based on WorkDegrees
|
||||
const Standard_Integer aWorkDegreeU = myJacobiU->WorkDegree();
|
||||
const Standard_Integer aWorkDegreeV = myJacobiV->WorkDegree();
|
||||
const Standard_Integer aCoeffCount = (aWorkDegreeU + 1) * (aWorkDegreeV + 1) * aDimension;
|
||||
|
||||
TColStd_Array1OfReal aJacCoeff(0, aCoeffCount - 1);
|
||||
for (Standard_Integer i = aJacCoeff.Lower(); i <= aJacCoeff.Upper(); i++)
|
||||
{
|
||||
aJacCoeff(i) = Sin(i * 0.1);
|
||||
}
|
||||
|
||||
EXPECT_NO_THROW({
|
||||
Standard_Real aMaxErrU =
|
||||
aDoubleJac.MaxErrorU(aDimension, aDegreeU, aDegreeV, aDJacCoeff, aJacCoeff);
|
||||
EXPECT_GE(aMaxErrU, 0.0) << "MaxErrorU should be non-negative";
|
||||
EXPECT_FALSE(Precision::IsInfinite(aMaxErrU)) << "MaxErrorU should be finite";
|
||||
}) << "MaxErrorU calculation failed";
|
||||
}
|
||||
|
||||
// Test MaxErrorV calculation
|
||||
TEST_F(PLibDoubleJacobiPolynomialTest, MaxErrorV)
|
||||
{
|
||||
PLib_DoubleJacobiPolynomial aDoubleJac(myJacobiU, myJacobiV);
|
||||
|
||||
const Standard_Integer aDimension = 2;
|
||||
const Standard_Integer aDegreeU = 6;
|
||||
const Standard_Integer aDegreeV = 5;
|
||||
const Standard_Integer aDJacCoeff = (aDegreeU + 1) * aDimension;
|
||||
|
||||
// JacCoeff array must be sized based on WorkDegrees
|
||||
const Standard_Integer aWorkDegreeU = myJacobiU->WorkDegree();
|
||||
const Standard_Integer aWorkDegreeV = myJacobiV->WorkDegree();
|
||||
const Standard_Integer aCoeffCount = (aWorkDegreeU + 1) * (aWorkDegreeV + 1) * aDimension;
|
||||
|
||||
TColStd_Array1OfReal aJacCoeff(0, aCoeffCount - 1);
|
||||
for (Standard_Integer i = aJacCoeff.Lower(); i <= aJacCoeff.Upper(); i++)
|
||||
{
|
||||
aJacCoeff(i) = Sin(i * 0.1);
|
||||
}
|
||||
|
||||
EXPECT_NO_THROW({
|
||||
Standard_Real aMaxErrV =
|
||||
aDoubleJac.MaxErrorV(aDimension, aDegreeU, aDegreeV, aDJacCoeff, aJacCoeff);
|
||||
EXPECT_GE(aMaxErrV, 0.0) << "MaxErrorV should be non-negative";
|
||||
EXPECT_FALSE(Precision::IsInfinite(aMaxErrV)) << "MaxErrorV should be finite";
|
||||
}) << "MaxErrorV calculation failed";
|
||||
}
|
||||
|
||||
// Test general MaxError calculation
|
||||
TEST_F(PLibDoubleJacobiPolynomialTest, MaxError)
|
||||
{
|
||||
PLib_DoubleJacobiPolynomial aDoubleJac(myJacobiU, myJacobiV);
|
||||
|
||||
const Standard_Integer aDimension = 1;
|
||||
const Standard_Integer aMinDegreeU = 2, aMaxDegreeU = 5;
|
||||
const Standard_Integer aMinDegreeV = 4, aMaxDegreeV = 7; // MinDegreeV must be >= MinV=4
|
||||
const Standard_Integer aDJacCoeff = (aMaxDegreeU + 1) * aDimension;
|
||||
const Standard_Real anError = 1e-6;
|
||||
|
||||
// JacCoeff array must be sized based on WorkDegrees
|
||||
const Standard_Integer aWorkDegreeU = myJacobiU->WorkDegree();
|
||||
const Standard_Integer aWorkDegreeV = myJacobiV->WorkDegree();
|
||||
const Standard_Integer aCoeffCount = (aWorkDegreeU + 1) * (aWorkDegreeV + 1) * aDimension;
|
||||
|
||||
TColStd_Array1OfReal aJacCoeff(0, aCoeffCount - 1);
|
||||
for (Standard_Integer i = aJacCoeff.Lower(); i <= aJacCoeff.Upper(); i++)
|
||||
{
|
||||
aJacCoeff(i) = Sin(i * 0.1);
|
||||
}
|
||||
|
||||
EXPECT_NO_THROW({
|
||||
Standard_Real aMaxErr = aDoubleJac.MaxError(aDimension,
|
||||
aMinDegreeU,
|
||||
aMaxDegreeU,
|
||||
aMinDegreeV,
|
||||
aMaxDegreeV,
|
||||
aDJacCoeff,
|
||||
aJacCoeff,
|
||||
anError);
|
||||
EXPECT_GE(aMaxErr, 0.0) << "MaxError should be non-negative";
|
||||
EXPECT_FALSE(Precision::IsInfinite(aMaxErr)) << "MaxError should be finite";
|
||||
}) << "MaxError calculation failed";
|
||||
}
|
||||
|
||||
// Test degree reduction
|
||||
TEST_F(PLibDoubleJacobiPolynomialTest, ReduceDegree)
|
||||
{
|
||||
PLib_DoubleJacobiPolynomial aDoubleJac(myJacobiU, myJacobiV);
|
||||
|
||||
const Standard_Integer aDimension = 1;
|
||||
const Standard_Integer aMinDegreeU = 2, aMaxDegreeU = 6; // Must be >= MinU=2
|
||||
const Standard_Integer aMinDegreeV = 4, aMaxDegreeV = 7; // Must be >= MinV=4
|
||||
const Standard_Integer aDJacCoeff = (aMaxDegreeU + 1) * aDimension;
|
||||
const Standard_Real anEpmsCut = 1e-8;
|
||||
|
||||
// JacCoeff array must be sized based on WorkDegrees and use 0-based indexing
|
||||
const Standard_Integer aWorkDegreeU = myJacobiU->WorkDegree();
|
||||
const Standard_Integer aWorkDegreeV = myJacobiV->WorkDegree();
|
||||
const Standard_Integer aCoeffCount = (aWorkDegreeU + 1) * (aWorkDegreeV + 1) * aDimension;
|
||||
|
||||
TColStd_Array1OfReal aJacCoeff(0, aCoeffCount - 1);
|
||||
for (Standard_Integer i = aJacCoeff.Lower(); i <= aJacCoeff.Upper(); i++)
|
||||
{
|
||||
aJacCoeff(i) = 1.0 / (i + 10); // Small decreasing values
|
||||
}
|
||||
|
||||
Standard_Real aMaxError = -1.0;
|
||||
Standard_Integer aNewDegreeU = -1, aNewDegreeV = -1;
|
||||
|
||||
EXPECT_NO_THROW({
|
||||
aDoubleJac.ReduceDegree(aDimension,
|
||||
aMinDegreeU,
|
||||
aMaxDegreeU,
|
||||
aMinDegreeV,
|
||||
aMaxDegreeV,
|
||||
aDJacCoeff,
|
||||
aJacCoeff,
|
||||
anEpmsCut,
|
||||
aMaxError,
|
||||
aNewDegreeU,
|
||||
aNewDegreeV);
|
||||
}) << "ReduceDegree failed";
|
||||
|
||||
// Verify results are reasonable
|
||||
EXPECT_LE(aNewDegreeU, aMaxDegreeU) << "New U degree should not exceed max";
|
||||
EXPECT_GE(aNewDegreeU, aMinDegreeU) << "New U degree should be at least min";
|
||||
EXPECT_LE(aNewDegreeV, aMaxDegreeV) << "New V degree should not exceed max";
|
||||
EXPECT_GE(aNewDegreeV, aMinDegreeV) << "New V degree should be at least min";
|
||||
EXPECT_GE(aMaxError, 0.0) << "Max error should be non-negative";
|
||||
EXPECT_FALSE(Precision::IsInfinite(aMaxError)) << "Max error should be finite";
|
||||
}
|
||||
|
||||
// Test average error calculation
|
||||
TEST_F(PLibDoubleJacobiPolynomialTest, AverageError)
|
||||
{
|
||||
PLib_DoubleJacobiPolynomial aDoubleJac(myJacobiU, myJacobiV);
|
||||
|
||||
const Standard_Integer aDimension = 2;
|
||||
const Standard_Integer aDegreeU = 4;
|
||||
const Standard_Integer aDegreeV = 3;
|
||||
const Standard_Integer aDJacCoeff = 0; // For 0-based arrays, start offset should be 0
|
||||
|
||||
// JacCoeff array must be sized based on WorkDegrees and use 0-based indexing
|
||||
const Standard_Integer aWorkDegreeU = myJacobiU->WorkDegree();
|
||||
const Standard_Integer aWorkDegreeV = myJacobiV->WorkDegree();
|
||||
const Standard_Integer aCoeffCount = (aWorkDegreeU + 1) * (aWorkDegreeV + 1) * aDimension;
|
||||
|
||||
TColStd_Array1OfReal aJacCoeff(0, aCoeffCount - 1);
|
||||
for (Standard_Integer i = aJacCoeff.Lower(); i <= aJacCoeff.Upper(); i++)
|
||||
{
|
||||
aJacCoeff(i) = Sin(i * 0.1);
|
||||
}
|
||||
|
||||
EXPECT_NO_THROW({
|
||||
Standard_Real aAvgErr =
|
||||
aDoubleJac.AverageError(aDimension, aDegreeU, aDegreeV, aDJacCoeff, aJacCoeff);
|
||||
EXPECT_GE(aAvgErr, 0.0) << "Average error should be non-negative";
|
||||
EXPECT_FALSE(Precision::IsInfinite(aAvgErr)) << "Average error should be finite";
|
||||
}) << "AverageError calculation failed";
|
||||
}
|
||||
|
||||
// Test coefficient conversion to canonical base
|
||||
TEST_F(PLibDoubleJacobiPolynomialTest, CoefficientConversion)
|
||||
{
|
||||
PLib_DoubleJacobiPolynomial aDoubleJac(myJacobiU, myJacobiV);
|
||||
|
||||
const Standard_Integer aDimension = 3;
|
||||
const Standard_Integer aDegreeU = 3;
|
||||
const Standard_Integer aDegreeV = 2;
|
||||
|
||||
// JacCoeff array must be sized based on WorkDegrees, not input degrees
|
||||
const Standard_Integer aWorkDegreeU = myJacobiU->WorkDegree();
|
||||
const Standard_Integer aWorkDegreeV = myJacobiV->WorkDegree();
|
||||
const Standard_Integer aJacCoeffSize = (aWorkDegreeU + 1) * (aWorkDegreeV + 1) * aDimension;
|
||||
|
||||
// JacCoeff uses 0-based indexing as per the implementation
|
||||
TColStd_Array1OfReal aJacCoeff(0, aJacCoeffSize - 1);
|
||||
// Initialize with test data - use simple pattern for valid coefficients
|
||||
for (Standard_Integer i = aJacCoeff.Lower(); i <= aJacCoeff.Upper(); i++)
|
||||
{
|
||||
aJacCoeff(i) = Sin(i * 0.1);
|
||||
}
|
||||
|
||||
// Output coefficients array is sized based on actual degrees
|
||||
const Standard_Integer aCoeffCount = (aDegreeU + 1) * (aDegreeV + 1) * aDimension;
|
||||
TColStd_Array1OfReal aCoefficients(0, aCoeffCount - 1);
|
||||
|
||||
EXPECT_NO_THROW({
|
||||
aDoubleJac.WDoubleJacobiToCoefficients(aDimension,
|
||||
aDegreeU,
|
||||
aDegreeV,
|
||||
aJacCoeff,
|
||||
aCoefficients);
|
||||
}) << "Coefficient conversion failed";
|
||||
|
||||
// Verify output coefficients are finite
|
||||
for (Standard_Integer i = aCoefficients.Lower(); i <= aCoefficients.Upper(); i++)
|
||||
{
|
||||
EXPECT_FALSE(Precision::IsInfinite(aCoefficients(i)))
|
||||
<< "Converted coefficient should be finite at index " << i;
|
||||
}
|
||||
}
|
||||
|
||||
// Test with mismatched degrees
|
||||
TEST_F(PLibDoubleJacobiPolynomialTest, MismatchedDegrees)
|
||||
{
|
||||
Handle(PLib_JacobiPolynomial) aJacU_Low = new PLib_JacobiPolynomial(5, GeomAbs_C0);
|
||||
Handle(PLib_JacobiPolynomial) aJacV_High = new PLib_JacobiPolynomial(20, GeomAbs_C1);
|
||||
|
||||
EXPECT_NO_THROW({
|
||||
PLib_DoubleJacobiPolynomial aDoubleJac(aJacU_Low, aJacV_High);
|
||||
|
||||
// Should handle mismatched degrees gracefully
|
||||
EXPECT_FALSE(aDoubleJac.U().IsNull());
|
||||
EXPECT_FALSE(aDoubleJac.V().IsNull());
|
||||
}) << "Constructor should handle mismatched degrees";
|
||||
}
|
||||
|
||||
// Test accessor consistency
|
||||
TEST_F(PLibDoubleJacobiPolynomialTest, AccessorConsistency)
|
||||
{
|
||||
PLib_DoubleJacobiPolynomial aDoubleJac(myJacobiU, myJacobiV);
|
||||
|
||||
// Test that accessors return consistent results
|
||||
Handle(PLib_JacobiPolynomial) aReturnedU = aDoubleJac.U();
|
||||
Handle(PLib_JacobiPolynomial) aReturnedV = aDoubleJac.V();
|
||||
Handle(TColStd_HArray1OfReal) aTabMaxU = aDoubleJac.TabMaxU();
|
||||
Handle(TColStd_HArray1OfReal) aTabMaxV = aDoubleJac.TabMaxV();
|
||||
|
||||
// Multiple calls should return same handles
|
||||
EXPECT_EQ(aReturnedU.get(), aDoubleJac.U().get()) << "U accessor should be consistent";
|
||||
EXPECT_EQ(aReturnedV.get(), aDoubleJac.V().get()) << "V accessor should be consistent";
|
||||
EXPECT_EQ(aTabMaxU.get(), aDoubleJac.TabMaxU().get()) << "TabMaxU accessor should be consistent";
|
||||
EXPECT_EQ(aTabMaxV.get(), aDoubleJac.TabMaxV().get()) << "TabMaxV accessor should be consistent";
|
||||
|
||||
// Verify TabMax arrays are properly sized and contain valid data
|
||||
if (!aTabMaxU.IsNull())
|
||||
{
|
||||
const TColStd_Array1OfReal& anArrU = aTabMaxU->Array1();
|
||||
for (Standard_Integer i = anArrU.Lower(); i <= anArrU.Upper(); i++)
|
||||
{
|
||||
EXPECT_GT(anArrU(i), 0.0) << "TabMaxU values should be positive";
|
||||
EXPECT_FALSE(Precision::IsInfinite(anArrU(i))) << "TabMaxU values should be finite";
|
||||
}
|
||||
}
|
||||
|
||||
if (!aTabMaxV.IsNull())
|
||||
{
|
||||
const TColStd_Array1OfReal& anArrV = aTabMaxV->Array1();
|
||||
for (Standard_Integer i = anArrV.Lower(); i <= anArrV.Upper(); i++)
|
||||
{
|
||||
EXPECT_GT(anArrV(i), 0.0) << "TabMaxV values should be positive";
|
||||
EXPECT_FALSE(Precision::IsInfinite(anArrV(i))) << "TabMaxV values should be finite";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stress test with large degrees
|
||||
TEST_F(PLibDoubleJacobiPolynomialTest, StressTest)
|
||||
{
|
||||
Handle(PLib_JacobiPolynomial) aJacU_Large = new PLib_JacobiPolynomial(25, GeomAbs_C1);
|
||||
Handle(PLib_JacobiPolynomial) aJacV_Large = new PLib_JacobiPolynomial(20, GeomAbs_C2);
|
||||
|
||||
EXPECT_NO_THROW({
|
||||
PLib_DoubleJacobiPolynomial aDoubleJac(aJacU_Large, aJacV_Large);
|
||||
|
||||
// Test basic operations don't crash with large degrees
|
||||
const Standard_Integer aDimension = 1;
|
||||
const Standard_Integer aDegreeU = 15;
|
||||
const Standard_Integer aDegreeV = 12;
|
||||
|
||||
// Array must be sized based on WorkDegrees for proper method operation
|
||||
const Standard_Integer aWorkDegreeU = aJacU_Large->WorkDegree();
|
||||
const Standard_Integer aWorkDegreeV = aJacV_Large->WorkDegree();
|
||||
const Standard_Integer aCoeffCount = (aWorkDegreeU + 1) * (aWorkDegreeV + 1) * aDimension;
|
||||
const Standard_Integer aDJacCoeff = 0; // For 0-based arrays
|
||||
|
||||
TColStd_Array1OfReal aJacCoeff(0, aCoeffCount - 1);
|
||||
for (Standard_Integer i = aJacCoeff.Lower(); i <= aJacCoeff.Upper(); i++)
|
||||
{
|
||||
aJacCoeff(i) = Sin(i * 0.1);
|
||||
}
|
||||
|
||||
Standard_Real aMaxErrU =
|
||||
aDoubleJac.MaxErrorU(aDimension, aDegreeU, aDegreeV, aDJacCoeff, aJacCoeff);
|
||||
Standard_Real aMaxErrV =
|
||||
aDoubleJac.MaxErrorV(aDimension, aDegreeU, aDegreeV, aDJacCoeff, aJacCoeff);
|
||||
Standard_Real aAvgErr =
|
||||
aDoubleJac.AverageError(aDimension, aDegreeU, aDegreeV, aDJacCoeff, aJacCoeff);
|
||||
|
||||
EXPECT_GE(aMaxErrU, 0.0) << "MaxErrorU should be non-negative";
|
||||
EXPECT_GE(aMaxErrV, 0.0) << "MaxErrorV should be non-negative";
|
||||
EXPECT_GE(aAvgErr, 0.0) << "AverageError should be non-negative";
|
||||
}) << "Large degree operations should complete without crashing";
|
||||
}
|
@@ -1,310 +0,0 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <PLib_HermitJacobi.hxx>
|
||||
#include <PLib_JacobiPolynomial.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <Standard_Real.hxx>
|
||||
#include <Standard_Integer.hxx>
|
||||
#include <TColStd_Array1OfReal.hxx>
|
||||
#include <GeomAbs_Shape.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
// Test fixture for PLib_HermitJacobi tests
|
||||
class PLibHermitJacobiTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
// Common test setup
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
// Cleanup
|
||||
}
|
||||
|
||||
// Helper to create valid HermitJacobi polynomial instances
|
||||
Handle(PLib_HermitJacobi) createHermitJacobi(Standard_Integer theDegree,
|
||||
GeomAbs_Shape theConstraint)
|
||||
{
|
||||
// Ensure degree is within valid range
|
||||
EXPECT_LE(theDegree, 30) << "Degree too high for HermitJacobi polynomial";
|
||||
EXPECT_GE(theDegree, 0) << "Degree must be non-negative";
|
||||
|
||||
return new PLib_HermitJacobi(theDegree, theConstraint);
|
||||
}
|
||||
};
|
||||
|
||||
// Test constructor and basic properties
|
||||
TEST_F(PLibHermitJacobiTest, ConstructorAndBasicProperties)
|
||||
{
|
||||
// Test with different constraint orders
|
||||
Handle(PLib_HermitJacobi) aHermC0 = createHermitJacobi(10, GeomAbs_C0);
|
||||
Handle(PLib_HermitJacobi) aHermC1 = createHermitJacobi(15, GeomAbs_C1);
|
||||
Handle(PLib_HermitJacobi) aHermC2 = createHermitJacobi(20, GeomAbs_C2);
|
||||
|
||||
ASSERT_FALSE(aHermC0.IsNull()) << "Failed to create C0 HermitJacobi polynomial";
|
||||
ASSERT_FALSE(aHermC1.IsNull()) << "Failed to create C1 HermitJacobi polynomial";
|
||||
ASSERT_FALSE(aHermC2.IsNull()) << "Failed to create C2 HermitJacobi polynomial";
|
||||
|
||||
// Test WorkDegree property
|
||||
EXPECT_EQ(aHermC0->WorkDegree(), 10);
|
||||
EXPECT_EQ(aHermC1->WorkDegree(), 15);
|
||||
EXPECT_EQ(aHermC2->WorkDegree(), 20);
|
||||
|
||||
// Test NivConstr property
|
||||
EXPECT_EQ(aHermC0->NivConstr(), 0);
|
||||
EXPECT_EQ(aHermC1->NivConstr(), 1);
|
||||
EXPECT_EQ(aHermC2->NivConstr(), 2);
|
||||
}
|
||||
|
||||
// Test basis function evaluation D0
|
||||
TEST_F(PLibHermitJacobiTest, BasisFunctionD0)
|
||||
{
|
||||
Handle(PLib_HermitJacobi) aHerm = createHermitJacobi(6, GeomAbs_C0);
|
||||
|
||||
TColStd_Array1OfReal aBasisValue(0, aHerm->WorkDegree());
|
||||
|
||||
// Test at various parameter values
|
||||
std::vector<Standard_Real> aTestParams = {-1.0, -0.5, 0.0, 0.5, 1.0};
|
||||
|
||||
for (Standard_Real aU : aTestParams)
|
||||
{
|
||||
EXPECT_NO_THROW({ aHerm->D0(aU, aBasisValue); }) << "D0 evaluation failed at U=" << aU;
|
||||
|
||||
// Basic sanity checks
|
||||
for (Standard_Integer i = aBasisValue.Lower(); i <= aBasisValue.Upper(); i++)
|
||||
{
|
||||
EXPECT_FALSE(Precision::IsInfinite(aBasisValue(i)))
|
||||
<< "Basis value should be finite at index " << i << ", U=" << aU;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test basis function evaluation with derivatives
|
||||
TEST_F(PLibHermitJacobiTest, BasisFunctionDerivatives)
|
||||
{
|
||||
Handle(PLib_HermitJacobi) aHerm = createHermitJacobi(8, GeomAbs_C1);
|
||||
|
||||
TColStd_Array1OfReal aBasisValue(0, aHerm->WorkDegree());
|
||||
TColStd_Array1OfReal aBasisD1(0, aHerm->WorkDegree());
|
||||
TColStd_Array1OfReal aBasisD2(0, aHerm->WorkDegree());
|
||||
TColStd_Array1OfReal aBasisD3(0, aHerm->WorkDegree());
|
||||
|
||||
Standard_Real aU = 0.5; // Test at middle point
|
||||
|
||||
// Test D1
|
||||
EXPECT_NO_THROW({ aHerm->D1(aU, aBasisValue, aBasisD1); }) << "D1 evaluation failed";
|
||||
|
||||
// Test D2
|
||||
EXPECT_NO_THROW({ aHerm->D2(aU, aBasisValue, aBasisD1, aBasisD2); }) << "D2 evaluation failed";
|
||||
|
||||
// Test D3
|
||||
EXPECT_NO_THROW({ aHerm->D3(aU, aBasisValue, aBasisD1, aBasisD2, aBasisD3); })
|
||||
<< "D3 evaluation failed";
|
||||
|
||||
// Verify all values are finite
|
||||
for (Standard_Integer i = aBasisValue.Lower(); i <= aBasisValue.Upper(); i++)
|
||||
{
|
||||
EXPECT_FALSE(Precision::IsInfinite(aBasisValue(i))) << "Basis value should be finite at " << i;
|
||||
EXPECT_FALSE(Precision::IsInfinite(aBasisD1(i)))
|
||||
<< "First derivative should be finite at " << i;
|
||||
EXPECT_FALSE(Precision::IsInfinite(aBasisD2(i)))
|
||||
<< "Second derivative should be finite at " << i;
|
||||
EXPECT_FALSE(Precision::IsInfinite(aBasisD3(i)))
|
||||
<< "Third derivative should be finite at " << i;
|
||||
}
|
||||
}
|
||||
|
||||
// Test coefficient conversion
|
||||
TEST_F(PLibHermitJacobiTest, CoefficientConversion)
|
||||
{
|
||||
const Standard_Integer aWorkDegree = 6; // Use smaller degree that works well with ToCoefficients
|
||||
Handle(PLib_HermitJacobi) aHerm = createHermitJacobi(aWorkDegree, GeomAbs_C0);
|
||||
|
||||
const Standard_Integer aDimension = 1;
|
||||
const Standard_Integer aDegree =
|
||||
aHerm->WorkDegree() - 2 * (aHerm->NivConstr() + 1); // Use computational degree
|
||||
|
||||
// Create test HermitJacobi coefficients with proper size
|
||||
// ToCoefficients expects arrays sized based on the degree and dimension
|
||||
Standard_Integer aHermJacSize = (aDegree + 1) * aDimension;
|
||||
Standard_Integer aCoeffSize = (aDegree + 1) * aDimension;
|
||||
|
||||
// Use 0-based arrays to match the ToCoefficients indexing expectations
|
||||
TColStd_Array1OfReal aHermJacCoeff(0, aHermJacSize - 1);
|
||||
for (Standard_Integer i = aHermJacCoeff.Lower(); i <= aHermJacCoeff.Upper(); i++)
|
||||
{
|
||||
aHermJacCoeff(i) = Sin(i * 0.3); // Some test values
|
||||
}
|
||||
|
||||
TColStd_Array1OfReal aCoefficients(0, aCoeffSize - 1);
|
||||
|
||||
EXPECT_NO_THROW({ aHerm->ToCoefficients(aDimension, aDegree, aHermJacCoeff, aCoefficients); })
|
||||
<< "Coefficient conversion failed";
|
||||
|
||||
// Verify output is finite
|
||||
for (Standard_Integer i = aCoefficients.Lower(); i <= aCoefficients.Upper(); i++)
|
||||
{
|
||||
EXPECT_FALSE(Precision::IsInfinite(aCoefficients(i)))
|
||||
<< "Converted coefficient should be finite at index " << i;
|
||||
}
|
||||
}
|
||||
|
||||
// Test degree reduction
|
||||
TEST_F(PLibHermitJacobiTest, DegreeReduction)
|
||||
{
|
||||
Handle(PLib_HermitJacobi) aHerm = createHermitJacobi(10, GeomAbs_C0);
|
||||
|
||||
const Standard_Integer aDimension = 1;
|
||||
const Standard_Integer aMaxDegree = 8;
|
||||
const Standard_Real aTol = 1e-6;
|
||||
|
||||
// Create test coefficients - must be sized for full WorkDegree
|
||||
const Standard_Integer aWorkDegree = aHerm->WorkDegree();
|
||||
TColStd_Array1OfReal aCoeff(1, (aWorkDegree + 1) * aDimension);
|
||||
for (Standard_Integer i = aCoeff.Lower(); i <= aCoeff.Upper(); i++)
|
||||
{
|
||||
aCoeff(i) = 1.0 / (i + 1); // Decreasing coefficients to allow reduction
|
||||
}
|
||||
|
||||
Standard_Integer aNewDegree = -1;
|
||||
Standard_Real aMaxError = -1.0;
|
||||
|
||||
EXPECT_NO_THROW({
|
||||
aHerm->ReduceDegree(aDimension, aMaxDegree, aTol, aCoeff.ChangeValue(1), aNewDegree, aMaxError);
|
||||
}) << "Degree reduction failed";
|
||||
|
||||
// Verify results are reasonable
|
||||
EXPECT_LE(aNewDegree, aMaxDegree) << "New degree should not exceed max degree";
|
||||
EXPECT_GE(aNewDegree, 0) << "New degree should be non-negative";
|
||||
EXPECT_GE(aMaxError, 0.0) << "Max error should be non-negative";
|
||||
EXPECT_FALSE(Precision::IsInfinite(aMaxError)) << "Max error should be finite";
|
||||
}
|
||||
|
||||
// Test error estimation
|
||||
TEST_F(PLibHermitJacobiTest, ErrorEstimation)
|
||||
{
|
||||
Handle(PLib_HermitJacobi) aHerm = createHermitJacobi(8, GeomAbs_C1);
|
||||
|
||||
const Standard_Integer aDimension = 1;
|
||||
|
||||
// Create test coefficients
|
||||
TColStd_Array1OfReal aCoeff(1, 10 * aDimension);
|
||||
for (Standard_Integer i = aCoeff.Lower(); i <= aCoeff.Upper(); i++)
|
||||
{
|
||||
aCoeff(i) = 1.0 / (i + 1);
|
||||
}
|
||||
|
||||
Standard_Integer aNewDegree = 6; // Reduced from original
|
||||
|
||||
// Test MaxError
|
||||
Standard_Real aMaxErr = -1.0;
|
||||
EXPECT_NO_THROW({ aMaxErr = aHerm->MaxError(aDimension, aCoeff.ChangeValue(1), aNewDegree); })
|
||||
<< "MaxError calculation failed";
|
||||
|
||||
EXPECT_GE(aMaxErr, 0.0) << "Max error should be non-negative";
|
||||
EXPECT_FALSE(Precision::IsInfinite(aMaxErr)) << "Max error should be finite";
|
||||
|
||||
// Test AverageError
|
||||
Standard_Real aAvgErr = -1.0;
|
||||
EXPECT_NO_THROW({ aAvgErr = aHerm->AverageError(aDimension, aCoeff.ChangeValue(1), aNewDegree); })
|
||||
<< "AverageError calculation failed";
|
||||
|
||||
EXPECT_GE(aAvgErr, 0.0) << "Average error should be non-negative";
|
||||
EXPECT_FALSE(Precision::IsInfinite(aAvgErr)) << "Average error should be finite";
|
||||
|
||||
// Average error should typically be <= max error
|
||||
EXPECT_LE(aAvgErr, aMaxErr + Precision::Confusion())
|
||||
<< "Average error should not exceed max error significantly";
|
||||
}
|
||||
|
||||
// Test extreme parameter values
|
||||
TEST_F(PLibHermitJacobiTest, ExtremeParameterValues)
|
||||
{
|
||||
Handle(PLib_HermitJacobi) aHerm = createHermitJacobi(10, GeomAbs_C2);
|
||||
|
||||
TColStd_Array1OfReal aBasisValue(0, aHerm->WorkDegree());
|
||||
|
||||
// Test with boundary values
|
||||
std::vector<Standard_Real> aExtremeParams = {-0.99999, -1e-12, 1e-12, 0.99999};
|
||||
|
||||
for (Standard_Real aU : aExtremeParams)
|
||||
{
|
||||
EXPECT_NO_THROW({ aHerm->D0(aU, aBasisValue); })
|
||||
<< "Extreme parameter U=" << aU << " should not crash";
|
||||
|
||||
// Check that results are finite
|
||||
for (Standard_Integer i = aBasisValue.Lower(); i <= aBasisValue.Upper(); i++)
|
||||
{
|
||||
EXPECT_FALSE(Precision::IsInfinite(aBasisValue(i)))
|
||||
<< "Basis value should be finite at extreme parameter U=" << aU;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test consistency between different derivative orders
|
||||
TEST_F(PLibHermitJacobiTest, DerivativeConsistency)
|
||||
{
|
||||
Handle(PLib_HermitJacobi) aHerm = createHermitJacobi(6, GeomAbs_C2);
|
||||
|
||||
TColStd_Array1OfReal aBasisValue1(0, aHerm->WorkDegree());
|
||||
TColStd_Array1OfReal aBasisD1_1(0, aHerm->WorkDegree());
|
||||
|
||||
TColStd_Array1OfReal aBasisValue2(0, aHerm->WorkDegree());
|
||||
TColStd_Array1OfReal aBasisD1_2(0, aHerm->WorkDegree());
|
||||
TColStd_Array1OfReal aBasisD2_2(0, aHerm->WorkDegree());
|
||||
|
||||
Standard_Real aU = 0.3;
|
||||
|
||||
// Get values from D1 and D2 calls
|
||||
aHerm->D1(aU, aBasisValue1, aBasisD1_1);
|
||||
aHerm->D2(aU, aBasisValue2, aBasisD1_2, aBasisD2_2);
|
||||
|
||||
// Values and first derivatives should be consistent
|
||||
for (Standard_Integer i = aBasisValue1.Lower(); i <= aBasisValue1.Upper(); i++)
|
||||
{
|
||||
EXPECT_NEAR(aBasisValue1(i), aBasisValue2(i), Precision::Confusion())
|
||||
<< "Function values should be consistent between D1 and D2 calls at index " << i;
|
||||
EXPECT_NEAR(aBasisD1_1(i), aBasisD1_2(i), Precision::Confusion())
|
||||
<< "First derivatives should be consistent between D1 and D2 calls at index " << i;
|
||||
}
|
||||
}
|
||||
|
||||
// Performance test with maximum degree
|
||||
TEST_F(PLibHermitJacobiTest, PerformanceTest)
|
||||
{
|
||||
Handle(PLib_HermitJacobi) aHermMax = createHermitJacobi(30, GeomAbs_C2);
|
||||
|
||||
TColStd_Array1OfReal aBasisValue(0, aHermMax->WorkDegree());
|
||||
TColStd_Array1OfReal aBasisD1(0, aHermMax->WorkDegree());
|
||||
TColStd_Array1OfReal aBasisD2(0, aHermMax->WorkDegree());
|
||||
TColStd_Array1OfReal aBasisD3(0, aHermMax->WorkDegree());
|
||||
|
||||
// Test that operations complete in reasonable time
|
||||
std::vector<Standard_Real> aTestParams = {-0.8, -0.5, 0.0, 0.5, 0.8};
|
||||
|
||||
for (Standard_Real aU : aTestParams)
|
||||
{
|
||||
EXPECT_NO_THROW({
|
||||
aHermMax->D0(aU, aBasisValue);
|
||||
aHermMax->D1(aU, aBasisValue, aBasisD1);
|
||||
aHermMax->D2(aU, aBasisValue, aBasisD1, aBasisD2);
|
||||
aHermMax->D3(aU, aBasisValue, aBasisD1, aBasisD2, aBasisD3);
|
||||
}) << "High degree operations should complete without crashing at U="
|
||||
<< aU;
|
||||
}
|
||||
}
|
@@ -1,366 +0,0 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <PLib_JacobiPolynomial.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <Standard_Real.hxx>
|
||||
#include <Standard_Integer.hxx>
|
||||
#include <TColStd_Array1OfReal.hxx>
|
||||
#include <TColStd_Array2OfReal.hxx>
|
||||
#include <GeomAbs_Shape.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
} // namespace
|
||||
|
||||
// Test fixture for PLib_JacobiPolynomial tests
|
||||
class PLibJacobiPolynomialTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
// Common test setup
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
// Cleanup
|
||||
}
|
||||
|
||||
// Helper to create valid Jacobi polynomial instances
|
||||
Handle(PLib_JacobiPolynomial) createJacobiPolynomial(Standard_Integer theDegree,
|
||||
GeomAbs_Shape theConstraint)
|
||||
{
|
||||
// Ensure degree is within valid range (typically <= 30)
|
||||
EXPECT_LE(theDegree, 30) << "Degree too high for Jacobi polynomial";
|
||||
EXPECT_GE(theDegree, 0) << "Degree must be non-negative";
|
||||
|
||||
return new PLib_JacobiPolynomial(theDegree, theConstraint);
|
||||
}
|
||||
};
|
||||
|
||||
// Test constructor and basic properties
|
||||
TEST_F(PLibJacobiPolynomialTest, ConstructorAndBasicProperties)
|
||||
{
|
||||
// Test with different constraint orders
|
||||
Handle(PLib_JacobiPolynomial) aJacC0 = createJacobiPolynomial(10, GeomAbs_C0);
|
||||
Handle(PLib_JacobiPolynomial) aJacC1 = createJacobiPolynomial(15, GeomAbs_C1);
|
||||
Handle(PLib_JacobiPolynomial) aJacC2 = createJacobiPolynomial(20, GeomAbs_C2);
|
||||
|
||||
ASSERT_FALSE(aJacC0.IsNull()) << "Failed to create C0 Jacobi polynomial";
|
||||
ASSERT_FALSE(aJacC1.IsNull()) << "Failed to create C1 Jacobi polynomial";
|
||||
ASSERT_FALSE(aJacC2.IsNull()) << "Failed to create C2 Jacobi polynomial";
|
||||
|
||||
// Test WorkDegree property
|
||||
EXPECT_EQ(aJacC0->WorkDegree(), 10);
|
||||
EXPECT_EQ(aJacC1->WorkDegree(), 15);
|
||||
EXPECT_EQ(aJacC2->WorkDegree(), 20);
|
||||
|
||||
// Test NivConstr property
|
||||
EXPECT_EQ(aJacC0->NivConstr(), 0);
|
||||
EXPECT_EQ(aJacC1->NivConstr(), 1);
|
||||
EXPECT_EQ(aJacC2->NivConstr(), 2);
|
||||
}
|
||||
|
||||
// Test constructor with edge cases
|
||||
TEST_F(PLibJacobiPolynomialTest, ConstructorEdgeCases)
|
||||
{
|
||||
// Test minimum degree
|
||||
Handle(PLib_JacobiPolynomial) aJacMin = createJacobiPolynomial(0, GeomAbs_C0);
|
||||
EXPECT_FALSE(aJacMin.IsNull());
|
||||
EXPECT_EQ(aJacMin->WorkDegree(), 0);
|
||||
|
||||
// Test maximum recommended degree
|
||||
Handle(PLib_JacobiPolynomial) aJacMax = createJacobiPolynomial(30, GeomAbs_C2);
|
||||
EXPECT_FALSE(aJacMax.IsNull());
|
||||
EXPECT_EQ(aJacMax->WorkDegree(), 30);
|
||||
|
||||
// Test reasonable high degrees
|
||||
Handle(PLib_JacobiPolynomial) aJacHigh = createJacobiPolynomial(25, GeomAbs_C0);
|
||||
EXPECT_GT(aJacHigh->WorkDegree(), 20) << "High degree should be supported";
|
||||
}
|
||||
|
||||
// Test Gauss integration points
|
||||
TEST_F(PLibJacobiPolynomialTest, GaussIntegrationPoints)
|
||||
{
|
||||
Handle(PLib_JacobiPolynomial) aJac = createJacobiPolynomial(10, GeomAbs_C0);
|
||||
|
||||
// Test various numbers of Gauss points (only valid values supported by OCCT)
|
||||
std::vector<Standard_Integer> aGaussNumbers = {8, 10, 15, 20, 25, 30, 40, 50, 61};
|
||||
|
||||
for (Standard_Integer aNbGauss : aGaussNumbers)
|
||||
{
|
||||
if (aNbGauss > aJac->WorkDegree())
|
||||
{
|
||||
TColStd_Array1OfReal aPoints(0, aNbGauss / 2);
|
||||
|
||||
EXPECT_NO_THROW({ aJac->Points(aNbGauss, aPoints); })
|
||||
<< "Points calculation failed for " << aNbGauss << " Gauss points";
|
||||
|
||||
// Verify points are in valid range and ordered
|
||||
for (Standard_Integer i = aPoints.Lower(); i <= aPoints.Upper(); i++)
|
||||
{
|
||||
if (i == 0 && aNbGauss % 2 == 0)
|
||||
{
|
||||
// For even number of Gauss points, TabPoints(0) is set to UNDEFINED (-999)
|
||||
EXPECT_EQ(aPoints(i), -999) << "TabPoints(0) should be UNDEFINED for even NbGaussPoints";
|
||||
}
|
||||
else if (i == 0 && aNbGauss % 2 == 1)
|
||||
{
|
||||
// For odd number of Gauss points, TabPoints(0) should be 0
|
||||
EXPECT_EQ(aPoints(i), 0.0) << "TabPoints(0) should be 0 for odd NbGaussPoints";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Other points should be positive and <= 1
|
||||
EXPECT_GT(aPoints(i), 0.0) << "Gauss point should be positive";
|
||||
EXPECT_LE(aPoints(i), 1.0) << "Gauss point should be <= 1";
|
||||
|
||||
if (i > aPoints.Lower() && i > 0)
|
||||
{
|
||||
EXPECT_GE(aPoints(i), aPoints(i - 1)) << "Gauss points should be ordered";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test Gauss integration weights
|
||||
TEST_F(PLibJacobiPolynomialTest, GaussIntegrationWeights)
|
||||
{
|
||||
Handle(PLib_JacobiPolynomial) aJac = createJacobiPolynomial(8, GeomAbs_C1);
|
||||
|
||||
Standard_Integer aNbGauss = 15; // Must be > degree for valid computation
|
||||
TColStd_Array2OfReal aWeights(0, aNbGauss / 2, 0, aJac->WorkDegree());
|
||||
|
||||
aJac->Weights(aNbGauss, aWeights);
|
||||
|
||||
// Basic sanity checks on weights - the array is 2D with specific bounds
|
||||
EXPECT_EQ(aWeights.LowerRow(), 0) << "Lower row should be 0";
|
||||
EXPECT_EQ(aWeights.UpperRow(), aNbGauss / 2) << "Upper row mismatch";
|
||||
EXPECT_EQ(aWeights.LowerCol(), 0) << "Lower col should be 0";
|
||||
EXPECT_EQ(aWeights.UpperCol(), aJac->WorkDegree()) << "Upper col should match work degree";
|
||||
|
||||
for (Standard_Integer i = aWeights.LowerRow(); i <= aWeights.UpperRow(); i++)
|
||||
{
|
||||
for (Standard_Integer j = aWeights.LowerCol(); j <= aWeights.UpperCol(); j++)
|
||||
{
|
||||
EXPECT_FALSE(Precision::IsInfinite(aWeights(i, j)))
|
||||
<< "Weight should be finite at (" << i << "," << j << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test MaxValue computation
|
||||
TEST_F(PLibJacobiPolynomialTest, MaxValue)
|
||||
{
|
||||
Handle(PLib_JacobiPolynomial) aJac = createJacobiPolynomial(10, GeomAbs_C0);
|
||||
|
||||
Standard_Integer aTabSize = aJac->WorkDegree() - 2 * (aJac->NivConstr() + 1);
|
||||
if (aTabSize > 0)
|
||||
{
|
||||
TColStd_Array1OfReal aTabMax(0, aTabSize);
|
||||
|
||||
aJac->MaxValue(aTabMax);
|
||||
|
||||
// Verify all max values are positive (they represent maximum absolute values)
|
||||
for (Standard_Integer i = aTabMax.Lower(); i <= aTabMax.Upper(); i++)
|
||||
{
|
||||
EXPECT_GT(aTabMax(i), 0.0) << "Max value should be positive at index " << i;
|
||||
EXPECT_FALSE(Precision::IsInfinite(aTabMax(i)))
|
||||
<< "Max value should be finite at index " << i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test basis function evaluation D0
|
||||
TEST_F(PLibJacobiPolynomialTest, BasisFunctionD0)
|
||||
{
|
||||
Handle(PLib_JacobiPolynomial) aJac = createJacobiPolynomial(6, GeomAbs_C0);
|
||||
|
||||
TColStd_Array1OfReal aBasisValue(0, aJac->WorkDegree());
|
||||
|
||||
// Test at various parameter values
|
||||
std::vector<Standard_Real> aTestParams = {-1.0, -0.5, 0.0, 0.5, 1.0};
|
||||
|
||||
for (Standard_Real aU : aTestParams)
|
||||
{
|
||||
aJac->D0(aU, aBasisValue);
|
||||
|
||||
// Basic sanity checks
|
||||
for (Standard_Integer i = aBasisValue.Lower(); i <= aBasisValue.Upper(); i++)
|
||||
{
|
||||
EXPECT_FALSE(Precision::IsInfinite(aBasisValue(i)))
|
||||
<< "Basis value should be finite at index " << i << ", U=" << aU;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test basis function evaluation with derivatives
|
||||
TEST_F(PLibJacobiPolynomialTest, BasisFunctionDerivatives)
|
||||
{
|
||||
Handle(PLib_JacobiPolynomial) aJac = createJacobiPolynomial(8, GeomAbs_C1);
|
||||
|
||||
TColStd_Array1OfReal aBasisValue(0, aJac->WorkDegree());
|
||||
TColStd_Array1OfReal aBasisD1(0, aJac->WorkDegree());
|
||||
TColStd_Array1OfReal aBasisD2(0, aJac->WorkDegree());
|
||||
TColStd_Array1OfReal aBasisD3(0, aJac->WorkDegree());
|
||||
|
||||
Standard_Real aU = 0.5; // Test at middle point
|
||||
|
||||
// Test D1, D2, D3 evaluations
|
||||
aJac->D1(aU, aBasisValue, aBasisD1);
|
||||
aJac->D2(aU, aBasisValue, aBasisD1, aBasisD2);
|
||||
aJac->D3(aU, aBasisValue, aBasisD1, aBasisD2, aBasisD3);
|
||||
|
||||
// Verify all values are finite
|
||||
for (Standard_Integer i = aBasisValue.Lower(); i <= aBasisValue.Upper(); i++)
|
||||
{
|
||||
EXPECT_FALSE(Precision::IsInfinite(aBasisValue(i))) << "Basis value should be finite at " << i;
|
||||
EXPECT_FALSE(Precision::IsInfinite(aBasisD1(i)))
|
||||
<< "First derivative should be finite at " << i;
|
||||
EXPECT_FALSE(Precision::IsInfinite(aBasisD2(i)))
|
||||
<< "Second derivative should be finite at " << i;
|
||||
EXPECT_FALSE(Precision::IsInfinite(aBasisD3(i)))
|
||||
<< "Third derivative should be finite at " << i;
|
||||
}
|
||||
}
|
||||
|
||||
// Test coefficient conversion
|
||||
TEST_F(PLibJacobiPolynomialTest, CoefficientConversion)
|
||||
{
|
||||
const Standard_Integer aWorkDegree = 6; // Use smaller degree that works well with ToCoefficients
|
||||
Handle(PLib_JacobiPolynomial) aJac = createJacobiPolynomial(aWorkDegree, GeomAbs_C0);
|
||||
|
||||
const Standard_Integer aDimension = 1;
|
||||
const Standard_Integer aDegree =
|
||||
aJac->WorkDegree() - 2 * (aJac->NivConstr() + 1); // Use computational degree
|
||||
|
||||
// Create test Jacobi coefficients with proper size
|
||||
// ToCoefficients expects arrays sized based on the degree and dimension
|
||||
// Analysis shows we need arrays that can handle the indexing patterns in the method
|
||||
Standard_Integer aJacSize = (aDegree + 1) * aDimension;
|
||||
Standard_Integer aCoeffSize = (aDegree + 1) * aDimension;
|
||||
|
||||
// Use 0-based arrays to match the ToCoefficients indexing expectations
|
||||
TColStd_Array1OfReal aJacCoeff(0, aJacSize - 1);
|
||||
for (Standard_Integer i = aJacCoeff.Lower(); i <= aJacCoeff.Upper(); i++)
|
||||
{
|
||||
aJacCoeff(i) = Sin(i * 0.1); // Some test values
|
||||
}
|
||||
|
||||
TColStd_Array1OfReal aCoefficients(0, aCoeffSize - 1);
|
||||
|
||||
aJac->ToCoefficients(aDimension, aDegree, aJacCoeff, aCoefficients);
|
||||
|
||||
// Verify output is finite
|
||||
for (Standard_Integer i = aCoefficients.Lower(); i <= aCoefficients.Upper(); i++)
|
||||
{
|
||||
EXPECT_FALSE(Precision::IsInfinite(aCoefficients(i)))
|
||||
<< "Converted coefficient should be finite at index " << i;
|
||||
}
|
||||
}
|
||||
|
||||
// Test degree reduction
|
||||
TEST_F(PLibJacobiPolynomialTest, DegreeReduction)
|
||||
{
|
||||
Handle(PLib_JacobiPolynomial) aJac = createJacobiPolynomial(10, GeomAbs_C0);
|
||||
|
||||
const Standard_Integer aDimension = 1;
|
||||
const Standard_Integer aMaxDegree = 8;
|
||||
const Standard_Real aTol = 1e-6;
|
||||
|
||||
// Create test coefficients - must be sized for full WorkDegree
|
||||
const Standard_Integer aWorkDegree = aJac->WorkDegree();
|
||||
TColStd_Array1OfReal aCoeff(1, (aWorkDegree + 1) * aDimension);
|
||||
for (Standard_Integer i = aCoeff.Lower(); i <= aCoeff.Upper(); i++)
|
||||
{
|
||||
aCoeff(i) = 1.0 / (i + 1); // Decreasing coefficients to allow reduction
|
||||
}
|
||||
|
||||
Standard_Integer aNewDegree = -1;
|
||||
Standard_Real aMaxError = -1.0;
|
||||
|
||||
aJac->ReduceDegree(aDimension, aMaxDegree, aTol, aCoeff.ChangeValue(1), aNewDegree, aMaxError);
|
||||
|
||||
// Verify results are reasonable
|
||||
EXPECT_LE(aNewDegree, aMaxDegree) << "New degree should not exceed max degree";
|
||||
EXPECT_GE(aNewDegree, 0) << "New degree should be non-negative";
|
||||
EXPECT_GE(aMaxError, 0.0) << "Max error should be non-negative";
|
||||
EXPECT_FALSE(Precision::IsInfinite(aMaxError)) << "Max error should be finite";
|
||||
}
|
||||
|
||||
// Test error estimation
|
||||
TEST_F(PLibJacobiPolynomialTest, ErrorEstimation)
|
||||
{
|
||||
Handle(PLib_JacobiPolynomial) aJac = createJacobiPolynomial(8, GeomAbs_C1);
|
||||
|
||||
const Standard_Integer aDimension = 1;
|
||||
|
||||
// Create test coefficients
|
||||
TColStd_Array1OfReal aCoeff(1, 10 * aDimension);
|
||||
for (Standard_Integer i = aCoeff.Lower(); i <= aCoeff.Upper(); i++)
|
||||
{
|
||||
aCoeff(i) = 1.0 / (i + 1);
|
||||
}
|
||||
|
||||
Standard_Integer aNewDegree = 6; // Reduced from original
|
||||
|
||||
// Test MaxError
|
||||
Standard_Real aMaxErr = aJac->MaxError(aDimension, aCoeff.ChangeValue(1), aNewDegree);
|
||||
|
||||
EXPECT_GE(aMaxErr, 0.0) << "Max error should be non-negative";
|
||||
EXPECT_FALSE(Precision::IsInfinite(aMaxErr)) << "Max error should be finite";
|
||||
|
||||
// Test AverageError
|
||||
Standard_Real aAvgErr = aJac->AverageError(aDimension, aCoeff.ChangeValue(1), aNewDegree);
|
||||
|
||||
EXPECT_GE(aAvgErr, 0.0) << "Average error should be non-negative";
|
||||
EXPECT_FALSE(Precision::IsInfinite(aAvgErr)) << "Average error should be finite";
|
||||
|
||||
// Average error should typically be <= max error
|
||||
EXPECT_LE(aAvgErr, aMaxErr + Precision::Confusion())
|
||||
<< "Average error should not exceed max error significantly";
|
||||
}
|
||||
|
||||
// Performance and stress tests
|
||||
TEST_F(PLibJacobiPolynomialTest, StressTests)
|
||||
{
|
||||
// Test with maximum degree
|
||||
Handle(PLib_JacobiPolynomial) aJacMax = createJacobiPolynomial(30, GeomAbs_C2);
|
||||
|
||||
// Test that basic operations work with high degrees
|
||||
TColStd_Array1OfReal aBasisValue(0, aJacMax->WorkDegree());
|
||||
|
||||
aJacMax->D0(0.0, aBasisValue);
|
||||
aJacMax->D0(0.5, aBasisValue);
|
||||
aJacMax->D0(1.0, aBasisValue);
|
||||
|
||||
// Test with extreme parameter values
|
||||
std::vector<Standard_Real> aExtremeParams = {-0.99999, -1e-10, 1e-10, 0.99999};
|
||||
|
||||
for (Standard_Real aU : aExtremeParams)
|
||||
{
|
||||
aJacMax->D0(aU, aBasisValue);
|
||||
// Verify basis values are finite
|
||||
for (Standard_Integer i = aBasisValue.Lower(); i <= aBasisValue.Upper(); i++)
|
||||
{
|
||||
EXPECT_FALSE(Precision::IsInfinite(aBasisValue(i))) << "Basis value should be finite";
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,418 +0,0 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <PLib.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <Standard_Real.hxx>
|
||||
#include <Standard_Integer.hxx>
|
||||
#include <TColStd_Array1OfReal.hxx>
|
||||
#include <TColStd_Array2OfReal.hxx>
|
||||
#include <TColgp_Array1OfPnt.hxx>
|
||||
#include <TColgp_Array1OfPnt2d.hxx>
|
||||
#include <TColgp_Array2OfPnt.hxx>
|
||||
#include <GeomAbs_Shape.hxx>
|
||||
#include <Precision.hxx>
|
||||
|
||||
namespace
|
||||
{
|
||||
// Helper function for comparing points with tolerance
|
||||
void checkPointsEqual(const gp_Pnt& thePnt1,
|
||||
const gp_Pnt& thePnt2,
|
||||
const Standard_Real theTolerance = Precision::Confusion())
|
||||
{
|
||||
EXPECT_NEAR(thePnt1.X(), thePnt2.X(), theTolerance) << "X coordinates differ";
|
||||
EXPECT_NEAR(thePnt1.Y(), thePnt2.Y(), theTolerance) << "Y coordinates differ";
|
||||
EXPECT_NEAR(thePnt1.Z(), thePnt2.Z(), theTolerance) << "Z coordinates differ";
|
||||
}
|
||||
|
||||
// Helper function for comparing 2D points with tolerance
|
||||
void checkPoint2dEqual(const gp_Pnt2d& thePnt1,
|
||||
const gp_Pnt2d& thePnt2,
|
||||
const Standard_Real theTolerance = Precision::Confusion())
|
||||
{
|
||||
EXPECT_NEAR(thePnt1.X(), thePnt2.X(), theTolerance) << "X coordinates differ";
|
||||
EXPECT_NEAR(thePnt1.Y(), thePnt2.Y(), theTolerance) << "Y coordinates differ";
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Test class for PLib tests
|
||||
class PLibTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
// Setup common test data
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
// Cleanup
|
||||
}
|
||||
};
|
||||
|
||||
// Tests for basic utility functions
|
||||
TEST_F(PLibTest, NoWeightsPointers)
|
||||
{
|
||||
// Test that NoWeights() returns NULL as expected
|
||||
EXPECT_EQ(PLib::NoWeights(), static_cast<TColStd_Array1OfReal*>(nullptr));
|
||||
EXPECT_EQ(PLib::NoWeights2(), static_cast<TColStd_Array2OfReal*>(nullptr));
|
||||
}
|
||||
|
||||
// Tests for 3D pole conversion functions
|
||||
TEST_F(PLibTest, SetGetPoles3D)
|
||||
{
|
||||
// Create test data
|
||||
TColgp_Array1OfPnt aPoles(1, 3);
|
||||
aPoles(1) = gp_Pnt(1.0, 2.0, 3.0);
|
||||
aPoles(2) = gp_Pnt(4.0, 5.0, 6.0);
|
||||
aPoles(3) = gp_Pnt(7.0, 8.0, 9.0);
|
||||
|
||||
// Test SetPoles and GetPoles without weights
|
||||
TColStd_Array1OfReal aFP(1, 9); // 3 poles * 3 coordinates
|
||||
PLib::SetPoles(aPoles, aFP);
|
||||
|
||||
TColgp_Array1OfPnt aResultPoles(1, 3);
|
||||
PLib::GetPoles(aFP, aResultPoles);
|
||||
|
||||
// Verify results
|
||||
for (Standard_Integer i = 1; i <= 3; i++)
|
||||
{
|
||||
checkPointsEqual(aPoles(i), aResultPoles(i));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(PLibTest, SetGetPoles3DWithWeights)
|
||||
{
|
||||
// Create test data
|
||||
TColgp_Array1OfPnt aPoles(1, 2);
|
||||
aPoles(1) = gp_Pnt(1.0, 2.0, 3.0);
|
||||
aPoles(2) = gp_Pnt(4.0, 5.0, 6.0);
|
||||
|
||||
TColStd_Array1OfReal aWeights(1, 2);
|
||||
aWeights(1) = 0.5;
|
||||
aWeights(2) = 2.0;
|
||||
|
||||
// Test SetPoles and GetPoles with weights
|
||||
TColStd_Array1OfReal aFP(1, 8); // 2 poles * (3 coords + 1 weight)
|
||||
PLib::SetPoles(aPoles, aWeights, aFP);
|
||||
|
||||
TColgp_Array1OfPnt aResultPoles(1, 2);
|
||||
TColStd_Array1OfReal aResultWeights(1, 2);
|
||||
PLib::GetPoles(aFP, aResultPoles, aResultWeights);
|
||||
|
||||
// Verify results
|
||||
for (Standard_Integer i = 1; i <= 2; i++)
|
||||
{
|
||||
checkPointsEqual(aPoles(i), aResultPoles(i));
|
||||
EXPECT_NEAR(aWeights(i), aResultWeights(i), Precision::Confusion());
|
||||
}
|
||||
}
|
||||
|
||||
// Tests for 2D pole conversion functions
|
||||
TEST_F(PLibTest, SetGetPoles2D)
|
||||
{
|
||||
// Create test data
|
||||
TColgp_Array1OfPnt2d aPoles(1, 3);
|
||||
aPoles(1) = gp_Pnt2d(1.0, 2.0);
|
||||
aPoles(2) = gp_Pnt2d(3.0, 4.0);
|
||||
aPoles(3) = gp_Pnt2d(5.0, 6.0);
|
||||
|
||||
// Test SetPoles and GetPoles without weights
|
||||
TColStd_Array1OfReal aFP(1, 6); // 3 poles * 2 coordinates
|
||||
PLib::SetPoles(aPoles, aFP);
|
||||
|
||||
TColgp_Array1OfPnt2d aResultPoles(1, 3);
|
||||
PLib::GetPoles(aFP, aResultPoles);
|
||||
|
||||
// Verify results
|
||||
for (Standard_Integer i = 1; i <= 3; i++)
|
||||
{
|
||||
checkPoint2dEqual(aPoles(i), aResultPoles(i));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(PLibTest, SetGetPoles2DWithWeights)
|
||||
{
|
||||
// Create test data
|
||||
TColgp_Array1OfPnt2d aPoles(1, 2);
|
||||
aPoles(1) = gp_Pnt2d(1.0, 2.0);
|
||||
aPoles(2) = gp_Pnt2d(3.0, 4.0);
|
||||
|
||||
TColStd_Array1OfReal aWeights(1, 2);
|
||||
aWeights(1) = 0.8;
|
||||
aWeights(2) = 1.5;
|
||||
|
||||
// Test SetPoles and GetPoles with weights
|
||||
TColStd_Array1OfReal aFP(1, 6); // 2 poles * (2 coords + 1 weight)
|
||||
PLib::SetPoles(aPoles, aWeights, aFP);
|
||||
|
||||
TColgp_Array1OfPnt2d aResultPoles(1, 2);
|
||||
TColStd_Array1OfReal aResultWeights(1, 2);
|
||||
PLib::GetPoles(aFP, aResultPoles, aResultWeights);
|
||||
|
||||
// Verify results
|
||||
for (Standard_Integer i = 1; i <= 2; i++)
|
||||
{
|
||||
checkPoint2dEqual(aPoles(i), aResultPoles(i));
|
||||
EXPECT_NEAR(aWeights(i), aResultWeights(i), Precision::Confusion());
|
||||
}
|
||||
}
|
||||
|
||||
// Test for zero weights handling (safety test)
|
||||
TEST_F(PLibTest, ZeroWeightsHandling)
|
||||
{
|
||||
// Create test data with zero weight - this should not crash
|
||||
TColgp_Array1OfPnt2d aPoles(1, 2);
|
||||
aPoles(1) = gp_Pnt2d(1.0, 2.0);
|
||||
aPoles(2) = gp_Pnt2d(3.0, 4.0);
|
||||
|
||||
TColStd_Array1OfReal aWeights(1, 2);
|
||||
aWeights(1) = 1.0;
|
||||
aWeights(2) = 0.0; // Zero weight - potential division by zero
|
||||
|
||||
TColStd_Array1OfReal aFP(1, 6);
|
||||
PLib::SetPoles(aPoles, aWeights, aFP);
|
||||
|
||||
// This test should complete without crashing
|
||||
// The behavior with zero weights may vary, but it shouldn't crash
|
||||
EXPECT_TRUE(true); // We mainly test that no crash occurs
|
||||
}
|
||||
|
||||
// Tests for Binomial coefficient function
|
||||
TEST_F(PLibTest, BinomialCoefficient)
|
||||
{
|
||||
// Test known binomial coefficients
|
||||
EXPECT_NEAR(PLib::Bin(0, 0), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(PLib::Bin(5, 0), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(PLib::Bin(5, 5), 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(PLib::Bin(5, 1), 5.0, Precision::Confusion());
|
||||
EXPECT_NEAR(PLib::Bin(5, 2), 10.0, Precision::Confusion());
|
||||
EXPECT_NEAR(PLib::Bin(5, 3), 10.0, Precision::Confusion());
|
||||
EXPECT_NEAR(PLib::Bin(10, 3), 120.0, Precision::Confusion());
|
||||
|
||||
// Test symmetry property: C(n,k) = C(n,n-k)
|
||||
for (Standard_Integer n = 1; n <= 10; n++)
|
||||
{
|
||||
for (Standard_Integer k = 0; k <= n; k++)
|
||||
{
|
||||
EXPECT_NEAR(PLib::Bin(n, k), PLib::Bin(n, n - k), Precision::Confusion())
|
||||
<< "Binomial coefficient symmetry failed for C(" << n << "," << k << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests for polynomial evaluation
|
||||
TEST_F(PLibTest, EvalPolynomial)
|
||||
{
|
||||
// Test simple polynomial evaluation: f(x) = 1 + 2x + 3x^2
|
||||
const Standard_Integer aDegree = 2;
|
||||
const Standard_Integer aDimension = 1;
|
||||
const Standard_Integer aDerivOrder = 0;
|
||||
|
||||
TColStd_Array1OfReal aCoeffs(1, 3);
|
||||
aCoeffs(1) = 1.0; // constant term
|
||||
aCoeffs(2) = 2.0; // linear term
|
||||
aCoeffs(3) = 3.0; // quadratic term
|
||||
|
||||
TColStd_Array1OfReal aResults(1, 1);
|
||||
|
||||
// Test at x = 0: f(0) = 1
|
||||
PLib::EvalPolynomial(0.0,
|
||||
aDerivOrder,
|
||||
aDegree,
|
||||
aDimension,
|
||||
aCoeffs.ChangeValue(1),
|
||||
aResults.ChangeValue(1));
|
||||
EXPECT_NEAR(aResults(1), 1.0, Precision::Confusion());
|
||||
|
||||
// Test at x = 1: f(1) = 1 + 2 + 3 = 6
|
||||
PLib::EvalPolynomial(1.0,
|
||||
aDerivOrder,
|
||||
aDegree,
|
||||
aDimension,
|
||||
aCoeffs.ChangeValue(1),
|
||||
aResults.ChangeValue(1));
|
||||
EXPECT_NEAR(aResults(1), 6.0, Precision::Confusion());
|
||||
|
||||
// Test at x = 2: f(2) = 1 + 4 + 12 = 17
|
||||
PLib::EvalPolynomial(2.0,
|
||||
aDerivOrder,
|
||||
aDegree,
|
||||
aDimension,
|
||||
aCoeffs.ChangeValue(1),
|
||||
aResults.ChangeValue(1));
|
||||
EXPECT_NEAR(aResults(1), 17.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
// Tests for polynomial evaluation with derivatives
|
||||
TEST_F(PLibTest, EvalPolynomialWithDerivatives)
|
||||
{
|
||||
// Test polynomial f(x) = 1 + 2x + 3x^2
|
||||
// f'(x) = 2 + 6x
|
||||
// f''(x) = 6
|
||||
const Standard_Integer aDegree = 2;
|
||||
const Standard_Integer aDimension = 1;
|
||||
const Standard_Integer aDerivOrder = 2;
|
||||
|
||||
TColStd_Array1OfReal aCoeffs(1, 3);
|
||||
aCoeffs(1) = 1.0;
|
||||
aCoeffs(2) = 2.0;
|
||||
aCoeffs(3) = 3.0;
|
||||
|
||||
TColStd_Array1OfReal aResults(1, 3); // value + 1st + 2nd derivative
|
||||
|
||||
// Test at x = 1
|
||||
PLib::EvalPolynomial(1.0,
|
||||
aDerivOrder,
|
||||
aDegree,
|
||||
aDimension,
|
||||
aCoeffs.ChangeValue(1),
|
||||
aResults.ChangeValue(1));
|
||||
|
||||
EXPECT_NEAR(aResults(1), 6.0, Precision::Confusion()); // f(1) = 6
|
||||
EXPECT_NEAR(aResults(2), 8.0, Precision::Confusion()); // f'(1) = 2 + 6 = 8
|
||||
EXPECT_NEAR(aResults(3), 6.0, Precision::Confusion()); // f''(1) = 6
|
||||
}
|
||||
|
||||
// Tests for constraint order conversion functions
|
||||
TEST_F(PLibTest, ConstraintOrderConversion)
|
||||
{
|
||||
// Test NivConstr function
|
||||
EXPECT_EQ(PLib::NivConstr(GeomAbs_C0), 0);
|
||||
EXPECT_EQ(PLib::NivConstr(GeomAbs_C1), 1);
|
||||
EXPECT_EQ(PLib::NivConstr(GeomAbs_C2), 2);
|
||||
|
||||
// Test ConstraintOrder function
|
||||
EXPECT_EQ(PLib::ConstraintOrder(0), GeomAbs_C0);
|
||||
EXPECT_EQ(PLib::ConstraintOrder(1), GeomAbs_C1);
|
||||
EXPECT_EQ(PLib::ConstraintOrder(2), GeomAbs_C2);
|
||||
|
||||
// Test round-trip consistency
|
||||
for (Standard_Integer i = 0; i <= 2; i++)
|
||||
{
|
||||
GeomAbs_Shape aShape = PLib::ConstraintOrder(i);
|
||||
Standard_Integer aLevel = PLib::NivConstr(aShape);
|
||||
EXPECT_EQ(aLevel, i) << "Round-trip conversion failed for level " << i;
|
||||
}
|
||||
}
|
||||
|
||||
// Test for Hermite interpolation
|
||||
TEST_F(PLibTest, HermiteInterpolate)
|
||||
{
|
||||
|
||||
const Standard_Integer aDimension = 1;
|
||||
const Standard_Real aFirstParam = 0.0;
|
||||
const Standard_Real aLastParam = 1.0;
|
||||
const Standard_Integer aFirstOrder = 1; // value + 1st derivative
|
||||
const Standard_Integer aLastOrder = 1; // value + 1st derivative
|
||||
|
||||
// Define constraints: f(0) = 0, f'(0) = 1, f(1) = 1, f'(1) = 0
|
||||
TColStd_Array2OfReal aFirstConstr(1, aDimension, 0, aFirstOrder);
|
||||
aFirstConstr(1, 0) = 0.0; // f(0) = 0
|
||||
aFirstConstr(1, 1) = 1.0; // f'(0) = 1
|
||||
|
||||
TColStd_Array2OfReal aLastConstr(1, aDimension, 0, aLastOrder);
|
||||
aLastConstr(1, 0) = 1.0; // f(1) = 1
|
||||
aLastConstr(1, 1) = 0.0; // f'(1) = 0
|
||||
|
||||
const Standard_Integer aCoeffCount = aFirstOrder + aLastOrder + 2;
|
||||
|
||||
TColStd_Array1OfReal aCoeffs(0,
|
||||
aCoeffCount
|
||||
- 1); // 0-based indexing as expected by HermiteInterpolate
|
||||
|
||||
// Perform Hermite interpolation
|
||||
Standard_Boolean aResult = PLib::HermiteInterpolate(aDimension,
|
||||
aFirstParam,
|
||||
aLastParam,
|
||||
aFirstOrder,
|
||||
aLastOrder,
|
||||
aFirstConstr,
|
||||
aLastConstr,
|
||||
aCoeffs);
|
||||
|
||||
EXPECT_TRUE(aResult) << "Hermite interpolation failed";
|
||||
|
||||
if (aResult)
|
||||
{
|
||||
|
||||
// Verify that the resulting polynomial satisfies the constraints
|
||||
TColStd_Array1OfReal aResults(1, 2); // value + 1st derivative
|
||||
|
||||
// Check at first parameter
|
||||
PLib::EvalPolynomial(aFirstParam,
|
||||
1,
|
||||
aCoeffCount - 1,
|
||||
aDimension,
|
||||
aCoeffs.ChangeValue(0),
|
||||
aResults.ChangeValue(1));
|
||||
EXPECT_NEAR(aResults(1), 0.0, Precision::Confusion()) << "f(0) constraint not satisfied";
|
||||
EXPECT_NEAR(aResults(2), 1.0, Precision::Confusion()) << "f'(0) constraint not satisfied";
|
||||
|
||||
// Check at last parameter
|
||||
PLib::EvalPolynomial(aLastParam,
|
||||
1,
|
||||
aCoeffCount - 1,
|
||||
aDimension,
|
||||
aCoeffs.ChangeValue(0),
|
||||
aResults.ChangeValue(1));
|
||||
EXPECT_NEAR(aResults(1), 1.0, Precision::Confusion()) << "f(1) constraint not satisfied";
|
||||
EXPECT_NEAR(aResults(2), 0.0, Precision::Confusion()) << "f'(1) constraint not satisfied";
|
||||
}
|
||||
}
|
||||
|
||||
// Edge case tests
|
||||
TEST_F(PLibTest, EdgeCases)
|
||||
{
|
||||
// Test with very small coefficients
|
||||
TColStd_Array1OfReal aSmallCoeffs(1, 3);
|
||||
aSmallCoeffs(1) = 1.0e-12;
|
||||
aSmallCoeffs(2) = 1.0e-12;
|
||||
aSmallCoeffs(3) = 1.0e-12;
|
||||
|
||||
TColStd_Array1OfReal aResults(1, 1);
|
||||
|
||||
// This should not crash even with very small coefficients
|
||||
EXPECT_NO_THROW(
|
||||
{ PLib::EvalPolynomial(1.0, 0, 2, 1, aSmallCoeffs.ChangeValue(1), aResults.ChangeValue(1)); });
|
||||
|
||||
// Test with large coefficients
|
||||
TColStd_Array1OfReal aLargeCoeffs(1, 3);
|
||||
aLargeCoeffs(1) = 1.0e10;
|
||||
aLargeCoeffs(2) = 1.0e10;
|
||||
aLargeCoeffs(3) = 1.0e10;
|
||||
|
||||
EXPECT_NO_THROW(
|
||||
{ PLib::EvalPolynomial(1.0, 0, 2, 1, aLargeCoeffs.ChangeValue(1), aResults.ChangeValue(1)); });
|
||||
}
|
||||
|
||||
// Test for Jacobi parameter calculation
|
||||
TEST_F(PLibTest, JacobiParameters)
|
||||
{
|
||||
Standard_Integer aNbGaussPoints, aWorkDegree;
|
||||
|
||||
// Test various constraint orders and codes
|
||||
PLib::JacobiParameters(GeomAbs_C0, 10, 1, aNbGaussPoints, aWorkDegree);
|
||||
EXPECT_GT(aNbGaussPoints, 0) << "Number of Gauss points should be positive";
|
||||
EXPECT_GT(aWorkDegree, 0) << "Work degree should be positive";
|
||||
|
||||
PLib::JacobiParameters(GeomAbs_C1, 15, 2, aNbGaussPoints, aWorkDegree);
|
||||
EXPECT_GT(aNbGaussPoints, 0);
|
||||
EXPECT_GT(aWorkDegree, 0);
|
||||
|
||||
PLib::JacobiParameters(GeomAbs_C2, 20, 3, aNbGaussPoints, aWorkDegree);
|
||||
EXPECT_GT(aNbGaussPoints, 0);
|
||||
EXPECT_GT(aWorkDegree, 0);
|
||||
}
|
@@ -371,27 +371,24 @@ TEST(MathBFGSTest, MaxIterationsLimit)
|
||||
TEST(MathBFGSTest, NotDoneState)
|
||||
{
|
||||
QuadraticFunction2D aFunc;
|
||||
math_BFGS anOptimizer(2, 1.0e-12, 3); // Reasonable tolerance, few iterations
|
||||
math_BFGS anOptimizer(2, 1.0e-15, 1); // Very tight tolerance, one iteration
|
||||
|
||||
math_Vector aStartPoint(1, 2);
|
||||
aStartPoint(1) = 50.0; // Far from minimum but not extreme
|
||||
aStartPoint(2) = 50.0;
|
||||
aStartPoint(1) = 100.0; // Very far from minimum
|
||||
aStartPoint(2) = 100.0;
|
||||
|
||||
// Wrap in try-catch to handle potential exceptions in debug mode
|
||||
EXPECT_NO_THROW({
|
||||
anOptimizer.Perform(aFunc, aStartPoint);
|
||||
anOptimizer.Perform(aFunc, aStartPoint);
|
||||
|
||||
if (!anOptimizer.IsDone())
|
||||
{
|
||||
EXPECT_GE(anOptimizer.NbIterations(), 0)
|
||||
<< "Iteration count should be non-negative even on failure";
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_GT(anOptimizer.NbIterations(), 0)
|
||||
<< "Successful optimization should require at least one iteration";
|
||||
}
|
||||
}) << "BFGS optimization should not throw exceptions";
|
||||
if (!anOptimizer.IsDone())
|
||||
{
|
||||
EXPECT_GE(anOptimizer.NbIterations(), 0)
|
||||
<< "Iteration count should be non-negative even on failure";
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_GT(anOptimizer.NbIterations(), 0)
|
||||
<< "Successful optimization should require at least one iteration";
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MathBFGSTest, DimensionCompatibility)
|
||||
|
@@ -251,27 +251,24 @@ TEST(MathFunctionRootTest, HighPrecisionTolerance)
|
||||
TEST(MathFunctionRootTest, MaxIterationsLimit)
|
||||
{
|
||||
QuadraticFunction aFunc;
|
||||
Standard_Real aTolerance = 1.0e-10; // Reasonable tolerance for debug mode
|
||||
Standard_Real aTolerance = 1.0e-15; // Very tight tolerance
|
||||
Standard_Real anInitialGuess = 2.1;
|
||||
Standard_Integer aMaxIterations = 5; // Few but reasonable iterations
|
||||
Standard_Integer aMaxIterations = 3; // Very few iterations
|
||||
|
||||
// Wrap in try-catch to handle potential exceptions in debug mode
|
||||
EXPECT_NO_THROW({
|
||||
math_FunctionRoot aRootFinder(aFunc, anInitialGuess, aTolerance, aMaxIterations);
|
||||
math_FunctionRoot aRootFinder(aFunc, anInitialGuess, aTolerance, aMaxIterations);
|
||||
|
||||
// Should either succeed within iterations or fail gracefully
|
||||
if (aRootFinder.IsDone())
|
||||
{
|
||||
EXPECT_LE(aRootFinder.NbIterations(), aMaxIterations) << "Should not exceed max iterations";
|
||||
EXPECT_NEAR(aRootFinder.Root(), 2.0, 1.0e-3)
|
||||
<< "Root should be reasonably close even with few iterations";
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's acceptable to fail if too few iterations are allowed
|
||||
EXPECT_LE(aMaxIterations, 10) << "Failure is acceptable with very few iterations";
|
||||
}
|
||||
}) << "Function root finding should not throw exceptions";
|
||||
// Should either succeed within 3 iterations or fail
|
||||
if (aRootFinder.IsDone())
|
||||
{
|
||||
EXPECT_LE(aRootFinder.NbIterations(), aMaxIterations) << "Should not exceed max iterations";
|
||||
EXPECT_NEAR(aRootFinder.Root(), 2.0, 1.0e-3)
|
||||
<< "Root should be reasonably close even with few iterations";
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's acceptable to fail if too few iterations are allowed
|
||||
EXPECT_LE(aMaxIterations, 10) << "Failure is acceptable with very few iterations";
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MathFunctionRootTest, OutOfBoundsGuess)
|
||||
@@ -331,30 +328,27 @@ TEST(MathFunctionRootTest, ZeroDerivativeHandling)
|
||||
TEST(MathFunctionRootTest, ConstrainedConvergenceState)
|
||||
{
|
||||
QuadraticFunction aFunc;
|
||||
Standard_Real aTolerance = 1.0e-10; // Reasonable tolerance for debug mode
|
||||
Standard_Real anInitialGuess = 50.0; // Far from roots but not extreme
|
||||
Standard_Integer aMaxIterations = 3; // Few but reasonable iterations
|
||||
Standard_Real aTolerance = 1.0e-15; // Very tight tolerance
|
||||
Standard_Real anInitialGuess = 100.0; // Very far from roots
|
||||
Standard_Integer aMaxIterations = 1; // Very few iterations
|
||||
|
||||
// Wrap in try-catch to handle potential exceptions in debug mode
|
||||
EXPECT_NO_THROW({
|
||||
math_FunctionRoot aRootFinder(aFunc, anInitialGuess, aTolerance, aMaxIterations);
|
||||
math_FunctionRoot aRootFinder(aFunc, anInitialGuess, aTolerance, aMaxIterations);
|
||||
|
||||
// Test state handling for constrained convergence conditions
|
||||
if (!aRootFinder.IsDone())
|
||||
{
|
||||
// Verify consistent state reporting
|
||||
EXPECT_FALSE(aRootFinder.IsDone()) << "Root finder should consistently report failure";
|
||||
EXPECT_GE(aRootFinder.NbIterations(), 0)
|
||||
<< "Iteration count should be non-negative even on failure";
|
||||
}
|
||||
else
|
||||
{
|
||||
// If it succeeds, verify the results are reasonable
|
||||
EXPECT_GT(aRootFinder.NbIterations(), 0) << "Should have done at least one iteration";
|
||||
EXPECT_TRUE(Abs(aRootFinder.Root() - 2.0) < 0.5 || Abs(aRootFinder.Root() - (-2.0)) < 0.5)
|
||||
<< "Root should be reasonably close to one of the expected roots";
|
||||
}
|
||||
}) << "Function root finding should not throw exceptions";
|
||||
// Test state handling for constrained convergence conditions
|
||||
if (!aRootFinder.IsDone())
|
||||
{
|
||||
// In release builds, verify consistent state reporting
|
||||
EXPECT_FALSE(aRootFinder.IsDone()) << "Root finder should consistently report failure";
|
||||
EXPECT_GE(aRootFinder.NbIterations(), 0)
|
||||
<< "Iteration count should be non-negative even on failure";
|
||||
}
|
||||
else
|
||||
{
|
||||
// If it surprisingly succeeds, verify the results are reasonable
|
||||
EXPECT_GT(aRootFinder.NbIterations(), 0) << "Should have done at least one iteration";
|
||||
EXPECT_TRUE(Abs(aRootFinder.Root() - 2.0) < 0.1 || Abs(aRootFinder.Root() - (-2.0)) < 0.1)
|
||||
<< "Root should be close to one of the expected roots";
|
||||
}
|
||||
}
|
||||
|
||||
// Tests for convergence behavior
|
||||
|
@@ -21,7 +21,6 @@
|
||||
#include <StdFail_NotDone.hxx>
|
||||
#include <Standard_RangeError.hxx>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
namespace
|
||||
|
@@ -173,8 +173,6 @@ void PLib_DoubleJacobiPolynomial::ReduceDegree(const Standard_Integer Dimen
|
||||
NewV = MaxDegreeV;
|
||||
math_Vector MaxErr2(1, 2);
|
||||
|
||||
MaxError = 0.0; // Initialize MaxError
|
||||
|
||||
//**********************************************************************
|
||||
//-------------------- Coupure des coefficients ------------------------
|
||||
//**********************************************************************
|
||||
|
@@ -29,7 +29,7 @@
|
||||
|
||||
class math_DoubleTab
|
||||
{
|
||||
static const Standard_Integer THE_BUFFER_SIZE = 64;
|
||||
static const Standard_Integer THE_BUFFER_SIZE = 16;
|
||||
|
||||
public:
|
||||
DEFINE_STANDARD_ALLOC;
|
||||
|
@@ -22,9 +22,10 @@
|
||||
template <typename TheItemType>
|
||||
math_VectorBase<TheItemType>::math_VectorBase(const Standard_Integer theLower,
|
||||
const Standard_Integer theUpper)
|
||||
: Array(theUpper - theLower + 1 <= math_VectorBase::THE_BUFFER_SIZE
|
||||
? NCollection_Array1<TheItemType>(*myBuffer.data(), theLower, theUpper)
|
||||
: NCollection_Array1<TheItemType>(theLower, theUpper))
|
||||
: Array(*myBuffer.data(),
|
||||
theLower,
|
||||
theUpper,
|
||||
(theUpper - theLower + 1 <= math_VectorBase::THE_BUFFER_SIZE))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -32,9 +33,10 @@ template <typename TheItemType>
|
||||
math_VectorBase<TheItemType>::math_VectorBase(const Standard_Integer theLower,
|
||||
const Standard_Integer theUpper,
|
||||
const TheItemType theInitialValue)
|
||||
: Array(theUpper - theLower + 1 <= math_VectorBase::THE_BUFFER_SIZE
|
||||
? NCollection_Array1<TheItemType>(*myBuffer.data(), theLower, theUpper)
|
||||
: NCollection_Array1<TheItemType>(theLower, theUpper))
|
||||
: Array(*myBuffer.data(),
|
||||
theLower,
|
||||
theUpper,
|
||||
(theUpper - theLower + 1 <= math_VectorBase::THE_BUFFER_SIZE))
|
||||
{
|
||||
Array.Init(theInitialValue);
|
||||
}
|
||||
|
@@ -2,8 +2,6 @@
|
||||
set(OCCT_TKernel_GTests_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
|
||||
|
||||
set(OCCT_TKernel_GTests_FILES
|
||||
Handle_Advanced_Test.cxx
|
||||
Handle_Operations_Test.cxx
|
||||
NCollection_Array1_Test.cxx
|
||||
NCollection_Array2_Test.cxx
|
||||
NCollection_BaseAllocator_Test.cxx
|
||||
@@ -14,14 +12,10 @@ set(OCCT_TKernel_GTests_FILES
|
||||
NCollection_List_Test.cxx
|
||||
NCollection_LocalArray_Test.cxx
|
||||
NCollection_Map_Test.cxx
|
||||
NCollection_OccAllocator_Test.cxx
|
||||
NCollection_Sequence_Test.cxx
|
||||
NCollection_SparseArray_Test.cxx
|
||||
NCollection_Vec4_Test.cxx
|
||||
NCollection_Vector_Test.cxx
|
||||
OSD_Path_Test.cxx
|
||||
OSD_PerfMeter_Test.cxx
|
||||
Standard_ArrayStreamBuffer_Test.cxx
|
||||
TCollection_AsciiString_Test.cxx
|
||||
TCollection_ExtendedString_Test.cxx
|
||||
)
|
||||
|
@@ -1,413 +0,0 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <Standard_Handle.hxx>
|
||||
#include <Standard_Transient.hxx>
|
||||
#include <Standard_Type.hxx>
|
||||
#include <Standard_Assert.hxx>
|
||||
#include <NCollection_BaseAllocator.hxx>
|
||||
#include <NCollection_IncAllocator.hxx>
|
||||
#include <NCollection_HeapAllocator.hxx>
|
||||
#include <OSD_Timer.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <typeinfo>
|
||||
#include <type_traits>
|
||||
|
||||
// Auxiliary macro to check and report status with EXPECT
|
||||
#define CHECK_HANDLE(ok, what) EXPECT_TRUE(ok) << "Checking " << what << " failed"
|
||||
|
||||
// Test root class for hierarchy
|
||||
class TransientRoot : public Standard_Transient
|
||||
{
|
||||
public:
|
||||
virtual const char* Name() const { return "TransientRoot"; }
|
||||
|
||||
virtual Standard_Transient* CreateParent() const { return new Standard_Transient; }
|
||||
|
||||
virtual Standard_Transient* Clone() const { return new TransientRoot; }
|
||||
DEFINE_STANDARD_RTTI_INLINE(TransientRoot, Standard_Transient)
|
||||
};
|
||||
DEFINE_STANDARD_HANDLE(TransientRoot, Standard_Transient)
|
||||
|
||||
// Auxiliary macros to create hierarchy of classes
|
||||
#define QA_DEFINECLASS(theClass, theParent) \
|
||||
class theClass : public theParent \
|
||||
{ \
|
||||
public: \
|
||||
virtual const char* Name() const override \
|
||||
{ \
|
||||
return #theClass; \
|
||||
} \
|
||||
virtual Standard_Transient* CreateParent() const override \
|
||||
{ \
|
||||
return new theParent(); \
|
||||
} \
|
||||
virtual Standard_Transient* Clone() const override \
|
||||
{ \
|
||||
return new theClass(); \
|
||||
} \
|
||||
DEFINE_STANDARD_RTTI_INLINE(theClass, theParent) \
|
||||
}; \
|
||||
DEFINE_STANDARD_HANDLE(theClass, theParent)
|
||||
|
||||
#define QA_NAME(theNum) QaClass##theNum##_50
|
||||
#define QA_HANDLE_NAME(theNum) Handle(QaClass##theNum##_50)
|
||||
|
||||
#define QA_DEFINECLASS10(theParent, theTens) \
|
||||
QA_DEFINECLASS(QA_NAME(theTens##0), theParent) \
|
||||
QA_DEFINECLASS(QA_NAME(theTens##1), QA_NAME(theTens##0)) \
|
||||
QA_DEFINECLASS(QA_NAME(theTens##2), QA_NAME(theTens##1)) \
|
||||
QA_DEFINECLASS(QA_NAME(theTens##3), QA_NAME(theTens##2)) \
|
||||
QA_DEFINECLASS(QA_NAME(theTens##4), QA_NAME(theTens##3)) \
|
||||
QA_DEFINECLASS(QA_NAME(theTens##5), QA_NAME(theTens##4)) \
|
||||
QA_DEFINECLASS(QA_NAME(theTens##6), QA_NAME(theTens##5)) \
|
||||
QA_DEFINECLASS(QA_NAME(theTens##7), QA_NAME(theTens##6)) \
|
||||
QA_DEFINECLASS(QA_NAME(theTens##8), QA_NAME(theTens##7)) \
|
||||
QA_DEFINECLASS(QA_NAME(theTens##9), QA_NAME(theTens##8))
|
||||
|
||||
// Create the hierarchy: 50 classes in inheritance chain
|
||||
QA_DEFINECLASS10(TransientRoot, 0)
|
||||
QA_DEFINECLASS10(QaClass09_50, 1)
|
||||
QA_DEFINECLASS10(QaClass19_50, 2)
|
||||
QA_DEFINECLASS10(QaClass29_50, 3)
|
||||
QA_DEFINECLASS10(QaClass39_50, 4)
|
||||
QA_DEFINECLASS(QaClass50_50, QaClass49_50)
|
||||
|
||||
// Anonymous namespace class for testing
|
||||
namespace
|
||||
{
|
||||
class QaClass50_50Anon : public QaClass49_50
|
||||
{
|
||||
public:
|
||||
QaClass50_50Anon() {}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
// Named namespace class for testing
|
||||
namespace QaNamespace
|
||||
{
|
||||
class QaClass50_50 : public QaClass49_50
|
||||
{
|
||||
public:
|
||||
QaClass50_50() {}
|
||||
};
|
||||
} // namespace QaNamespace
|
||||
|
||||
// Timer class for performance testing
|
||||
namespace
|
||||
{
|
||||
class QATimer : public OSD_Timer
|
||||
{
|
||||
public:
|
||||
enum TimeFormat
|
||||
{
|
||||
Seconds,
|
||||
Milliseconds,
|
||||
Microseconds
|
||||
};
|
||||
|
||||
QATimer(const char* theOperationName, TimeFormat theFormat = Milliseconds)
|
||||
: myOperationName(theOperationName),
|
||||
myFormat(theFormat)
|
||||
{
|
||||
Start();
|
||||
}
|
||||
|
||||
~QATimer()
|
||||
{
|
||||
Stop();
|
||||
Standard_Real aTime = 0.0;
|
||||
switch (myFormat)
|
||||
{
|
||||
case Seconds:
|
||||
aTime = ElapsedTime();
|
||||
break;
|
||||
case Milliseconds:
|
||||
aTime = ElapsedTime() * 1000.0;
|
||||
break;
|
||||
case Microseconds:
|
||||
aTime = ElapsedTime() * 1000000.0;
|
||||
break;
|
||||
}
|
||||
// Note: In tests we don't print timing info but could store it for verification
|
||||
(void)aTime; // Avoid unused variable warning
|
||||
(void)myOperationName; // Avoid unused field warning
|
||||
}
|
||||
|
||||
private:
|
||||
const char* myOperationName;
|
||||
TimeFormat myFormat;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
// Test fixture for advanced Handle operations tests
|
||||
class HandleAdvancedTest : public testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override {}
|
||||
|
||||
void TearDown() override {}
|
||||
};
|
||||
|
||||
TEST_F(HandleAdvancedTest, CompilerSpecificBehavior)
|
||||
{
|
||||
Handle(TransientRoot) aRoot = new TransientRoot();
|
||||
EXPECT_FALSE(aRoot.IsNull());
|
||||
|
||||
const Handle(TransientRoot)& aConstRoot = aRoot;
|
||||
(void)aConstRoot; // Avoid unused variable warning
|
||||
Handle(Standard_Transient) aTransient = aRoot;
|
||||
|
||||
// Test passing handle as reference to base class
|
||||
// This tests template argument deduction and inheritance
|
||||
auto testFunction = [](const Handle(Standard_Transient)& theObj) -> bool {
|
||||
return !theObj.IsNull();
|
||||
};
|
||||
|
||||
EXPECT_TRUE(testFunction(aRoot));
|
||||
|
||||
// Test overloaded function compatibility (compiler version specific)
|
||||
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800) \
|
||||
|| (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3)
|
||||
|
||||
// Test overload resolution with handles
|
||||
auto testOverload1 = [](const Handle(Standard_Transient)&) -> int { return 1; };
|
||||
auto testOverload2 = [](const Handle(TransientRoot)&) -> int { return 2; };
|
||||
|
||||
// More specific overload should be chosen
|
||||
EXPECT_EQ(2, testOverload2(aRoot));
|
||||
EXPECT_EQ(1, testOverload1(aTransient));
|
||||
#endif
|
||||
|
||||
const Handle(Standard_Transient)& aTransient2 = aRoot; // cast to base const ref
|
||||
CHECK_HANDLE(!aTransient2.IsNull(), "cast to base class const reference");
|
||||
}
|
||||
|
||||
TEST_F(HandleAdvancedTest, DeepHierarchyRTTI)
|
||||
{
|
||||
// Test RTTI with deep inheritance hierarchy
|
||||
Handle(Standard_Type) aType00 = STANDARD_TYPE(QaClass00_50);
|
||||
Handle(Standard_Type) aType10 = STANDARD_TYPE(QaClass10_50);
|
||||
Handle(Standard_Type) aType20 = STANDARD_TYPE(QaClass20_50);
|
||||
Handle(Standard_Type) aType30 = STANDARD_TYPE(QaClass30_50);
|
||||
Handle(Standard_Type) aType40 = STANDARD_TYPE(QaClass40_50);
|
||||
Handle(Standard_Type) aType50 = STANDARD_TYPE(QaClass50_50);
|
||||
|
||||
Handle(QaClass00_50) aHandle = new QaClass40_50();
|
||||
|
||||
// Test type name
|
||||
EXPECT_STREQ("QaClass40_50", aHandle->DynamicType()->Name());
|
||||
|
||||
// Test IsKind() - should be true for all parent types
|
||||
EXPECT_TRUE(aHandle->IsKind(aType00)) << "IsKind failed for root type";
|
||||
EXPECT_TRUE(aHandle->IsKind(aType10)) << "IsKind failed for parent type 10";
|
||||
EXPECT_TRUE(aHandle->IsKind(aType20)) << "IsKind failed for parent type 20";
|
||||
EXPECT_TRUE(aHandle->IsKind(aType30)) << "IsKind failed for parent type 30";
|
||||
EXPECT_TRUE(aHandle->IsKind(aType40)) << "IsKind failed for exact type 40";
|
||||
EXPECT_FALSE(aHandle->IsKind(aType50)) << "IsKind should be false for child type 50";
|
||||
|
||||
// Test IsKind() with string names
|
||||
EXPECT_TRUE(aHandle->IsKind("QaClass00_50"));
|
||||
EXPECT_TRUE(aHandle->IsKind("QaClass10_50"));
|
||||
EXPECT_TRUE(aHandle->IsKind("QaClass20_50"));
|
||||
EXPECT_TRUE(aHandle->IsKind("QaClass30_50"));
|
||||
EXPECT_TRUE(aHandle->IsKind("QaClass40_50"));
|
||||
EXPECT_FALSE(aHandle->IsKind("QaClass50_50"));
|
||||
|
||||
// Test IsInstance() - should be true only for exact type
|
||||
EXPECT_FALSE(aHandle->IsInstance(aType00));
|
||||
EXPECT_FALSE(aHandle->IsInstance(aType10));
|
||||
EXPECT_FALSE(aHandle->IsInstance(aType20));
|
||||
EXPECT_FALSE(aHandle->IsInstance(aType30));
|
||||
EXPECT_TRUE(aHandle->IsInstance(aType40));
|
||||
EXPECT_FALSE(aHandle->IsInstance(aType50));
|
||||
}
|
||||
|
||||
TEST_F(HandleAdvancedTest, TypeInfoCompatibility)
|
||||
{
|
||||
Handle(QaClass40_50) aHandle = new QaClass40_50();
|
||||
|
||||
#ifdef __cpp_rtti
|
||||
// Test C++ RTTI compatibility
|
||||
// Use OCCT standard warning suppression for RTTI operations
|
||||
#include <Standard_WarningsDisable.hxx>
|
||||
|
||||
const std::type_info& aTypeInfo = typeid(*aHandle.get());
|
||||
|
||||
// Test type_info comparisons
|
||||
EXPECT_FALSE(aTypeInfo == typeid(QaClass00_50));
|
||||
EXPECT_FALSE(aTypeInfo == typeid(QaClass10_50));
|
||||
EXPECT_FALSE(aTypeInfo == typeid(QaClass20_50));
|
||||
EXPECT_FALSE(aTypeInfo == typeid(QaClass30_50));
|
||||
EXPECT_TRUE(aTypeInfo == typeid(QaClass40_50));
|
||||
EXPECT_FALSE(aTypeInfo == typeid(QaClass50_50));
|
||||
|
||||
// Test type_index if available
|
||||
#if __cplusplus >= 201103L
|
||||
std::type_index aCppType = typeid(*aHandle.get());
|
||||
EXPECT_FALSE(aCppType == typeid(QaClass00_50));
|
||||
EXPECT_TRUE(aCppType == typeid(QaClass40_50));
|
||||
#endif
|
||||
|
||||
// Test anonymous and namespaced classes
|
||||
QaClass50_50Anon anAnon;
|
||||
QaNamespace::QaClass50_50 aNamed;
|
||||
|
||||
// These should have different type_info
|
||||
EXPECT_FALSE(typeid(anAnon) == typeid(aNamed));
|
||||
EXPECT_FALSE(typeid(anAnon) == typeid(QaClass50_50));
|
||||
EXPECT_FALSE(typeid(aNamed) == typeid(QaClass50_50));
|
||||
|
||||
#include <Standard_WarningsRestore.hxx>
|
||||
|
||||
#endif // __cpp_rtti
|
||||
|
||||
// Test Standard_Transient type traits
|
||||
EXPECT_TRUE(std::is_class<Standard_Transient>::value);
|
||||
// Note: IsClass() method is not available in all OCCT versions
|
||||
// EXPECT_TRUE(STANDARD_TYPE(Standard_Transient)->IsClass());
|
||||
}
|
||||
|
||||
TEST_F(HandleAdvancedTest, AllocatorHandlePerformance)
|
||||
{
|
||||
// Test performance aspects of handle operations with different allocators
|
||||
Handle(NCollection_BaseAllocator) aBasePtr = new NCollection_IncAllocator();
|
||||
EXPECT_FALSE(aBasePtr.IsNull());
|
||||
|
||||
// Test casting performance with allocator hierarchy
|
||||
{
|
||||
QATimer aTimer("IncAllocator DownCast", QATimer::Microseconds);
|
||||
for (int i = 0; i < 1000; ++i)
|
||||
{
|
||||
Handle(NCollection_IncAllocator) anIncAlloc =
|
||||
Handle(NCollection_IncAllocator)::DownCast(aBasePtr);
|
||||
EXPECT_FALSE(anIncAlloc.IsNull());
|
||||
}
|
||||
}
|
||||
|
||||
// Test failed downcast performance
|
||||
{
|
||||
QATimer aTimer("Failed HeapAllocator DownCast", QATimer::Microseconds);
|
||||
for (int i = 0; i < 1000; ++i)
|
||||
{
|
||||
Handle(NCollection_HeapAllocator) aHeapAlloc =
|
||||
Handle(NCollection_HeapAllocator)::DownCast(aBasePtr);
|
||||
EXPECT_TRUE(aHeapAlloc.IsNull());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(HandleAdvancedTest, HandleArrayOperations)
|
||||
{
|
||||
// Test handle operations with arrays and containers
|
||||
std::vector<Handle(QaClass00_50)> aHandleVector;
|
||||
|
||||
// Fill with different types in the hierarchy
|
||||
aHandleVector.push_back(new QaClass00_50());
|
||||
aHandleVector.push_back(new QaClass10_50());
|
||||
aHandleVector.push_back(new QaClass20_50());
|
||||
aHandleVector.push_back(new QaClass30_50());
|
||||
aHandleVector.push_back(new QaClass40_50());
|
||||
|
||||
EXPECT_EQ(5, aHandleVector.size());
|
||||
|
||||
// Test that all handles are valid and point to correct types
|
||||
for (size_t i = 0; i < aHandleVector.size(); ++i)
|
||||
{
|
||||
EXPECT_FALSE(aHandleVector[i].IsNull());
|
||||
|
||||
// Test polymorphic behavior
|
||||
EXPECT_TRUE(aHandleVector[i]->IsKind("QaClass00_50"));
|
||||
|
||||
// Test dynamic casting
|
||||
Handle(QaClass00_50) aCast = aHandleVector[i];
|
||||
EXPECT_FALSE(aCast.IsNull());
|
||||
EXPECT_EQ(aHandleVector[i].get(), aCast.get());
|
||||
}
|
||||
|
||||
// Test specific type casting
|
||||
Handle(QaClass40_50) aSpecific = Handle(QaClass40_50)::DownCast(aHandleVector[4]);
|
||||
EXPECT_FALSE(aSpecific.IsNull());
|
||||
|
||||
// This should fail - trying to cast parent to child
|
||||
Handle(QaClass40_50) aFailedCast = Handle(QaClass40_50)::DownCast(aHandleVector[0]);
|
||||
EXPECT_TRUE(aFailedCast.IsNull());
|
||||
}
|
||||
|
||||
TEST_F(HandleAdvancedTest, ConstHandleOperations)
|
||||
{
|
||||
Handle(QaClass30_50) aNonConstHandle = new QaClass30_50();
|
||||
const Handle(QaClass30_50)& aConstHandle = aNonConstHandle;
|
||||
|
||||
// Test const correctness
|
||||
EXPECT_EQ(aNonConstHandle.get(), aConstHandle.get());
|
||||
|
||||
// Test const pointer access
|
||||
const QaClass30_50* aConstPtr = aConstHandle.get();
|
||||
QaClass30_50* aNonConstPtr = aNonConstHandle.get();
|
||||
|
||||
EXPECT_EQ(aConstPtr, aNonConstPtr);
|
||||
|
||||
// Test const casting to base types
|
||||
const Handle(QaClass00_50)& aConstBase = aConstHandle;
|
||||
Handle(QaClass00_50) aNonConstBase = aNonConstHandle;
|
||||
|
||||
EXPECT_EQ(aConstBase.get(), aNonConstBase.get());
|
||||
|
||||
// Test const handle comparisons
|
||||
EXPECT_TRUE(aConstHandle == aNonConstHandle);
|
||||
EXPECT_TRUE(aConstBase == aNonConstBase);
|
||||
EXPECT_FALSE(aConstHandle != aNonConstHandle);
|
||||
}
|
||||
|
||||
TEST_F(HandleAdvancedTest, WeakReferenceSimulation)
|
||||
{
|
||||
// Simulate weak reference-like behavior using raw pointers
|
||||
QaClass20_50* aRawPtr = nullptr;
|
||||
|
||||
{
|
||||
Handle(QaClass20_50) aHandle = new QaClass20_50();
|
||||
aRawPtr = aHandle.get();
|
||||
|
||||
EXPECT_NE(nullptr, aRawPtr);
|
||||
|
||||
// Handle should keep the object alive
|
||||
EXPECT_FALSE(aHandle.IsNull());
|
||||
EXPECT_EQ(aRawPtr, aHandle.get());
|
||||
}
|
||||
|
||||
// After handle destruction, raw pointer becomes invalid
|
||||
// Note: We can't safely test this without risking segfaults,
|
||||
// but the pattern demonstrates handle lifetime management
|
||||
|
||||
// Create multiple new handles to ensure we get different objects
|
||||
// (Memory allocator might reuse the same location, so we create several)
|
||||
std::vector<Handle(QaClass20_50)> aHandles;
|
||||
bool aFoundDifferent = false;
|
||||
|
||||
for (int i = 0; i < 10 && !aFoundDifferent; ++i)
|
||||
{
|
||||
aHandles.push_back(new QaClass20_50());
|
||||
if (aHandles.back().get() != aRawPtr)
|
||||
{
|
||||
aFoundDifferent = true;
|
||||
}
|
||||
}
|
||||
|
||||
// We expect to find at least one different address (though allocator might reuse)
|
||||
// The test demonstrates handle independence regardless
|
||||
EXPECT_TRUE(aFoundDifferent || !aFoundDifferent); // Either outcome is acceptable
|
||||
}
|
@@ -1,236 +0,0 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <Standard_Handle.hxx>
|
||||
#include <Standard_Transient.hxx>
|
||||
#include <NCollection_BaseAllocator.hxx>
|
||||
#include <NCollection_IncAllocator.hxx>
|
||||
#include <NCollection_HeapAllocator.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
// Test classes for Handle operations
|
||||
class TestBase : public Standard_Transient
|
||||
{
|
||||
public:
|
||||
TestBase() {}
|
||||
|
||||
virtual ~TestBase() {}
|
||||
DEFINE_STANDARD_RTTI_INLINE(TestBase, Standard_Transient)
|
||||
};
|
||||
DEFINE_STANDARD_HANDLE(TestBase, Standard_Transient)
|
||||
|
||||
class TestDerived : public TestBase
|
||||
{
|
||||
public:
|
||||
TestDerived() {}
|
||||
|
||||
virtual ~TestDerived() {}
|
||||
DEFINE_STANDARD_RTTI_INLINE(TestDerived, TestBase)
|
||||
};
|
||||
DEFINE_STANDARD_HANDLE(TestDerived, TestBase)
|
||||
|
||||
class TestOther : public Standard_Transient
|
||||
{
|
||||
public:
|
||||
TestOther() {}
|
||||
|
||||
virtual ~TestOther() {}
|
||||
DEFINE_STANDARD_RTTI_INLINE(TestOther, Standard_Transient)
|
||||
};
|
||||
DEFINE_STANDARD_HANDLE(TestOther, Standard_Transient)
|
||||
|
||||
// Test fixture for Handle operations tests
|
||||
class HandleOperationsTest : public testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override {}
|
||||
|
||||
void TearDown() override {}
|
||||
};
|
||||
|
||||
TEST_F(HandleOperationsTest, BasicHandleOperations)
|
||||
{
|
||||
// Test basic handle creation and null checking
|
||||
Handle(TestDerived) aDerived = new TestDerived();
|
||||
EXPECT_FALSE(aDerived.IsNull());
|
||||
|
||||
// Test various casting operations
|
||||
const Handle(TestDerived)& aConstDerived = aDerived;
|
||||
const Handle(TestBase)& aConstBase = aDerived;
|
||||
(void)aConstBase; // Avoid unused variable warning
|
||||
|
||||
TestDerived* aDerivedPtr = aDerived.get();
|
||||
const TestDerived* aConstDerivedPtr = aDerived.get();
|
||||
EXPECT_NE(nullptr, aDerivedPtr);
|
||||
EXPECT_NE(nullptr, aConstDerivedPtr);
|
||||
EXPECT_EQ(aDerivedPtr, aConstDerivedPtr);
|
||||
|
||||
// Test reference access
|
||||
TestDerived& aDerivedRef = *aDerived;
|
||||
const TestDerived& aConstDerivedRef = *aConstDerived;
|
||||
EXPECT_EQ(&aDerivedRef, aDerivedPtr);
|
||||
EXPECT_EQ(&aConstDerivedRef, aConstDerivedPtr);
|
||||
|
||||
// Test handle assignment to base type
|
||||
Handle(TestBase) aBase = aDerived;
|
||||
EXPECT_FALSE(aBase.IsNull());
|
||||
EXPECT_EQ(aBase.get(), aDerived.get());
|
||||
}
|
||||
|
||||
TEST_F(HandleOperationsTest, HandleDownCast)
|
||||
{
|
||||
// Test DownCast functionality
|
||||
Handle(TestDerived) aDerived = new TestDerived();
|
||||
Handle(TestBase) aBase = aDerived;
|
||||
|
||||
Handle(TestDerived) aDownCastDerived = Handle(TestDerived)::DownCast(aBase);
|
||||
EXPECT_FALSE(aDownCastDerived.IsNull());
|
||||
EXPECT_EQ(aDownCastDerived.get(), aDerived.get());
|
||||
|
||||
// Test failed downcast (different type)
|
||||
Handle(TestOther) anOther = new TestOther();
|
||||
Handle(Standard_Transient) aTransient = anOther;
|
||||
Handle(TestDerived) aFailedDownCast = Handle(TestDerived)::DownCast(aTransient);
|
||||
EXPECT_TRUE(aFailedDownCast.IsNull());
|
||||
}
|
||||
|
||||
TEST_F(HandleOperationsTest, HandleComparisons)
|
||||
{
|
||||
Handle(TestDerived) aDerived = new TestDerived();
|
||||
Handle(TestDerived) aDerived2 = aDerived; // Same object
|
||||
Handle(TestDerived) aDerived3 = new TestDerived(); // Different object
|
||||
Handle(TestBase) aBase = aDerived;
|
||||
|
||||
// Test equality operators
|
||||
EXPECT_TRUE(aDerived == aDerived); // Self equality
|
||||
EXPECT_TRUE(aDerived == aDerived2); // Same object through different handles
|
||||
EXPECT_TRUE(aDerived == aBase); // Handle to base type
|
||||
EXPECT_FALSE(aDerived == aDerived3); // Different objects
|
||||
|
||||
// Test with pointers
|
||||
TestDerived* aDerivedPtr = aDerived.get();
|
||||
const TestDerived* aConstDerivedPtr = aDerived.get();
|
||||
EXPECT_TRUE(aDerived == aDerivedPtr);
|
||||
EXPECT_TRUE(aDerivedPtr == aDerived);
|
||||
EXPECT_TRUE(aDerived == aConstDerivedPtr);
|
||||
EXPECT_TRUE(aConstDerivedPtr == aDerived);
|
||||
|
||||
// Test inequality
|
||||
EXPECT_FALSE(aDerived != aDerived2); // Should be equal
|
||||
EXPECT_TRUE(aDerived != aDerived3); // Should be different
|
||||
|
||||
// Test boolean conversion
|
||||
EXPECT_TRUE(static_cast<bool>(aDerived));
|
||||
Handle(TestDerived) aNullDerived;
|
||||
EXPECT_FALSE(static_cast<bool>(aNullDerived));
|
||||
}
|
||||
|
||||
TEST_F(HandleOperationsTest, AllocatorHandleCasting)
|
||||
{
|
||||
// Test Handle casting with allocator hierarchy
|
||||
Handle(NCollection_BaseAllocator) aBasePtr = new NCollection_IncAllocator();
|
||||
EXPECT_FALSE(aBasePtr.IsNull());
|
||||
|
||||
// Test successful downcast to IncAllocator
|
||||
Handle(NCollection_IncAllocator) anIncAlloc =
|
||||
Handle(NCollection_IncAllocator)::DownCast(aBasePtr);
|
||||
EXPECT_FALSE(anIncAlloc.IsNull());
|
||||
|
||||
// Test upcast back to BaseAllocator
|
||||
Handle(NCollection_BaseAllocator) aBaseAlloc = anIncAlloc;
|
||||
EXPECT_FALSE(aBaseAlloc.IsNull());
|
||||
EXPECT_EQ(aBaseAlloc.get(), aBasePtr.get());
|
||||
|
||||
// Test failed downcast to HeapAllocator
|
||||
Handle(NCollection_HeapAllocator) aHeapAlloc =
|
||||
Handle(NCollection_HeapAllocator)::DownCast(aBasePtr);
|
||||
EXPECT_TRUE(aHeapAlloc.IsNull());
|
||||
}
|
||||
|
||||
TEST_F(HandleOperationsTest, HandleCopyAndAssignment)
|
||||
{
|
||||
Handle(TestDerived) aDerived1 = new TestDerived();
|
||||
|
||||
// Test copy constructor
|
||||
Handle(TestDerived) aDerived2(aDerived1);
|
||||
EXPECT_FALSE(aDerived2.IsNull());
|
||||
EXPECT_EQ(aDerived1.get(), aDerived2.get());
|
||||
|
||||
// Test assignment operator
|
||||
Handle(TestDerived) aDerived3;
|
||||
EXPECT_TRUE(aDerived3.IsNull());
|
||||
|
||||
aDerived3 = aDerived1;
|
||||
EXPECT_FALSE(aDerived3.IsNull());
|
||||
EXPECT_EQ(aDerived1.get(), aDerived3.get());
|
||||
|
||||
// Test self-assignment (suppress warning)
|
||||
#include <Standard_WarningsDisable.hxx>
|
||||
aDerived1 = aDerived1;
|
||||
#include <Standard_WarningsRestore.hxx>
|
||||
EXPECT_FALSE(aDerived1.IsNull());
|
||||
|
||||
// Test assignment to null
|
||||
aDerived3 = Handle(TestDerived)();
|
||||
EXPECT_TRUE(aDerived3.IsNull());
|
||||
}
|
||||
|
||||
TEST_F(HandleOperationsTest, HandleWithDifferentTypes)
|
||||
{
|
||||
Handle(TestDerived) aDerived = new TestDerived();
|
||||
Handle(TestOther) anOther = new TestOther();
|
||||
|
||||
// Note: Direct comparison between handles of different types is not allowed by the type system
|
||||
// This is actually a good thing as it prevents type errors at compile time
|
||||
|
||||
// Test casting both to common base type
|
||||
Handle(Standard_Transient) aDerivedTransient = aDerived;
|
||||
Handle(Standard_Transient) anOtherTransient = anOther;
|
||||
|
||||
// These should be different objects even when cast to base type
|
||||
EXPECT_FALSE(aDerivedTransient == anOtherTransient);
|
||||
EXPECT_TRUE(aDerivedTransient != anOtherTransient);
|
||||
|
||||
// But each should equal itself when cast
|
||||
EXPECT_TRUE(aDerivedTransient == aDerived);
|
||||
EXPECT_TRUE(anOtherTransient == anOther);
|
||||
|
||||
// Test that each maintains its identity through base type casting
|
||||
EXPECT_EQ(aDerivedTransient.get(), aDerived.get());
|
||||
EXPECT_EQ(anOtherTransient.get(), anOther.get());
|
||||
}
|
||||
|
||||
TEST_F(HandleOperationsTest, HandleNullOperations)
|
||||
{
|
||||
Handle(TestDerived) aNullHandle;
|
||||
Handle(TestDerived) anotherNullHandle;
|
||||
Handle(TestDerived) aValidHandle = new TestDerived();
|
||||
|
||||
// Test null handle properties
|
||||
EXPECT_TRUE(aNullHandle.IsNull());
|
||||
EXPECT_EQ(nullptr, aNullHandle.get());
|
||||
|
||||
// Test null handle comparisons
|
||||
EXPECT_TRUE(aNullHandle == anotherNullHandle); // Both null
|
||||
EXPECT_FALSE(aNullHandle == aValidHandle); // Null vs valid
|
||||
EXPECT_FALSE(aValidHandle == aNullHandle); // Valid vs null
|
||||
|
||||
EXPECT_FALSE(aNullHandle != anotherNullHandle); // Both null
|
||||
EXPECT_TRUE(aNullHandle != aValidHandle); // Null vs valid
|
||||
EXPECT_TRUE(aValidHandle != aNullHandle); // Valid vs null
|
||||
|
||||
// Test boolean conversion
|
||||
EXPECT_FALSE(static_cast<bool>(aNullHandle));
|
||||
EXPECT_TRUE(static_cast<bool>(aValidHandle));
|
||||
}
|
@@ -15,9 +15,6 @@
|
||||
#include <Standard_Integer.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
TEST(NCollection_Array1Test, DefaultConstructor)
|
||||
{
|
||||
@@ -343,73 +340,3 @@ TEST(NCollection_Array1Test, IteratorAccess)
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(NCollection_Array1Test, STLAlgorithmCompatibility_MinMax)
|
||||
{
|
||||
const Standard_Integer size = 100;
|
||||
NCollection_Array1<Standard_Integer> anArray(1, size);
|
||||
std::vector<Standard_Integer> aVector;
|
||||
|
||||
std::mt19937 aGenerator(1); // Fixed seed for reproducible tests
|
||||
std::uniform_int_distribution<Standard_Integer> aDistribution(0, RAND_MAX);
|
||||
for (Standard_Integer anIdx = 1; anIdx <= size; ++anIdx)
|
||||
{
|
||||
Standard_Integer aVal = aDistribution(aGenerator);
|
||||
anArray(anIdx) = aVal;
|
||||
aVector.push_back(aVal);
|
||||
}
|
||||
|
||||
auto aMinOCCT = std::min_element(anArray.begin(), anArray.end());
|
||||
auto aMinStd = std::min_element(aVector.begin(), aVector.end());
|
||||
|
||||
auto aMaxOCCT = std::max_element(anArray.begin(), anArray.end());
|
||||
auto aMaxStd = std::max_element(aVector.begin(), aVector.end());
|
||||
|
||||
EXPECT_EQ(*aMinOCCT, *aMinStd);
|
||||
EXPECT_EQ(*aMaxOCCT, *aMaxStd);
|
||||
}
|
||||
|
||||
TEST(NCollection_Array1Test, STLAlgorithmCompatibility_Replace)
|
||||
{
|
||||
const Standard_Integer size = 100;
|
||||
NCollection_Array1<Standard_Integer> anArray(1, size);
|
||||
std::vector<Standard_Integer> aVector;
|
||||
|
||||
std::mt19937 aGenerator(1); // Fixed seed for reproducible tests
|
||||
std::uniform_int_distribution<Standard_Integer> aDistribution(0, RAND_MAX);
|
||||
for (Standard_Integer anIdx = 1; anIdx <= size; ++anIdx)
|
||||
{
|
||||
Standard_Integer aVal = aDistribution(aGenerator);
|
||||
anArray(anIdx) = aVal;
|
||||
aVector.push_back(aVal);
|
||||
}
|
||||
|
||||
Standard_Integer aTargetValue = aVector.back();
|
||||
Standard_Integer aNewValue = -1;
|
||||
|
||||
std::replace(anArray.begin(), anArray.end(), aTargetValue, aNewValue);
|
||||
std::replace(aVector.begin(), aVector.end(), aTargetValue, aNewValue);
|
||||
|
||||
EXPECT_TRUE(std::equal(anArray.begin(), anArray.end(), aVector.begin()));
|
||||
}
|
||||
|
||||
TEST(NCollection_Array1Test, STLAlgorithmCompatibility_Sort)
|
||||
{
|
||||
const Standard_Integer size = 100;
|
||||
NCollection_Array1<Standard_Integer> anArray(1, size);
|
||||
std::vector<Standard_Integer> aVector;
|
||||
|
||||
std::mt19937 aGenerator(1); // Fixed seed for reproducible tests
|
||||
std::uniform_int_distribution<Standard_Integer> aDistribution(0, RAND_MAX);
|
||||
for (Standard_Integer anIdx = 1; anIdx <= size; ++anIdx)
|
||||
{
|
||||
Standard_Integer aVal = aDistribution(aGenerator);
|
||||
anArray(anIdx) = aVal;
|
||||
aVector.push_back(aVal);
|
||||
}
|
||||
|
||||
std::sort(anArray.begin(), anArray.end());
|
||||
std::sort(aVector.begin(), aVector.end());
|
||||
|
||||
EXPECT_TRUE(std::equal(anArray.begin(), anArray.end(), aVector.begin()));
|
||||
}
|
||||
|
@@ -16,9 +16,6 @@
|
||||
#include <TCollection_AsciiString.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
// Test fixture for NCollection_DataMap tests
|
||||
class NCollection_DataMapTest : public testing::Test
|
||||
@@ -235,43 +232,3 @@ TEST_F(NCollection_DataMapTest, ExhaustiveIterator)
|
||||
|
||||
EXPECT_EQ(NUM_ELEMENTS, count);
|
||||
}
|
||||
|
||||
TEST_F(NCollection_DataMapTest, STLAlgorithmCompatibility_MinMax)
|
||||
{
|
||||
NCollection_DataMap<Standard_Integer, Standard_Integer> aMap;
|
||||
|
||||
// Add some sequential values to make results predictable
|
||||
for (Standard_Integer anIdx = 10; anIdx <= 50; anIdx += 5)
|
||||
{
|
||||
aMap.Bind(anIdx, anIdx * 2);
|
||||
}
|
||||
|
||||
EXPECT_FALSE(aMap.IsEmpty());
|
||||
|
||||
// Test that STL algorithms work with OCCT iterators
|
||||
auto aMinElement = std::min_element(aMap.cbegin(), aMap.cend());
|
||||
auto aMaxElement = std::max_element(aMap.cbegin(), aMap.cend());
|
||||
|
||||
EXPECT_TRUE(aMinElement != aMap.cend());
|
||||
EXPECT_TRUE(aMaxElement != aMap.cend());
|
||||
EXPECT_LE(*aMinElement, *aMaxElement);
|
||||
}
|
||||
|
||||
TEST_F(NCollection_DataMapTest, STLAlgorithmCompatibility_Find)
|
||||
{
|
||||
NCollection_DataMap<Standard_Integer, Standard_Integer> aMap;
|
||||
|
||||
// Add known values
|
||||
aMap.Bind(100, 200);
|
||||
aMap.Bind(200, 400);
|
||||
aMap.Bind(300, 600);
|
||||
|
||||
// Test std::find compatibility
|
||||
auto aFound = std::find(aMap.cbegin(), aMap.cend(), 200);
|
||||
EXPECT_TRUE(aFound != aMap.cend());
|
||||
EXPECT_EQ(*aFound, 200);
|
||||
|
||||
// Test finding non-existent value
|
||||
auto aNotFound = std::find(aMap.cbegin(), aMap.cend(), 999);
|
||||
EXPECT_TRUE(aNotFound == aMap.cend());
|
||||
}
|
||||
|
@@ -15,8 +15,6 @@
|
||||
#include <TCollection_AsciiString.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
// Basic test types for the IndexedDataMap
|
||||
typedef Standard_Integer KeyType;
|
||||
@@ -705,43 +703,3 @@ TEST(NCollection_IndexedDataMapTest, ReSize)
|
||||
EXPECT_DOUBLE_EQ(aMap.FindFromKey(i), static_cast<Standard_Real>(i) / 10.0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(NCollection_IndexedDataMapTest, STLAlgorithmCompatibility_MinMax)
|
||||
{
|
||||
NCollection_IndexedDataMap<Standard_Integer, Standard_Integer> aMap;
|
||||
|
||||
// Add some sequential values to make results predictable
|
||||
for (Standard_Integer anIdx = 10; anIdx <= 50; anIdx += 5)
|
||||
{
|
||||
aMap.Add(anIdx, anIdx * 2);
|
||||
}
|
||||
|
||||
EXPECT_FALSE(aMap.IsEmpty());
|
||||
|
||||
// Test that STL algorithms work with OCCT iterators
|
||||
auto aMinElement = std::min_element(aMap.cbegin(), aMap.cend());
|
||||
auto aMaxElement = std::max_element(aMap.cbegin(), aMap.cend());
|
||||
|
||||
EXPECT_TRUE(aMinElement != aMap.cend());
|
||||
EXPECT_TRUE(aMaxElement != aMap.cend());
|
||||
EXPECT_LE(*aMinElement, *aMaxElement);
|
||||
}
|
||||
|
||||
TEST(NCollection_IndexedDataMapTest, STLAlgorithmCompatibility_Find)
|
||||
{
|
||||
NCollection_IndexedDataMap<Standard_Integer, Standard_Integer> aMap;
|
||||
|
||||
// Add known values
|
||||
aMap.Add(100, 200);
|
||||
aMap.Add(200, 400);
|
||||
aMap.Add(300, 600);
|
||||
|
||||
// Test std::find compatibility
|
||||
auto aFound = std::find(aMap.cbegin(), aMap.cend(), 200);
|
||||
EXPECT_TRUE(aFound != aMap.cend());
|
||||
EXPECT_EQ(*aFound, 200);
|
||||
|
||||
// Test finding non-existent value
|
||||
auto aNotFound = std::find(aMap.cbegin(), aMap.cend(), 999);
|
||||
EXPECT_TRUE(aNotFound == aMap.cend());
|
||||
}
|
||||
|
@@ -15,9 +15,6 @@
|
||||
#include <TCollection_AsciiString.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
// Basic test type for the IndexedMap
|
||||
typedef Standard_Integer KeyType;
|
||||
@@ -514,52 +511,4 @@ TEST(NCollection_IndexedMapTest, ReSize)
|
||||
EXPECT_EQ(aMap.FindIndex(i), i);
|
||||
EXPECT_EQ(aMap.FindKey(i), i);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(NCollection_IndexedMapTest, STLAlgorithmCompatibility_MinMax)
|
||||
{
|
||||
NCollection_IndexedMap<Standard_Integer> aMap;
|
||||
std::vector<Standard_Integer> aVector;
|
||||
|
||||
std::mt19937 aGenerator(1); // Fixed seed for reproducible tests
|
||||
std::uniform_int_distribution<Standard_Integer> aDistribution(0, RAND_MAX);
|
||||
for (Standard_Integer anIdx = 0; anIdx < 100; ++anIdx)
|
||||
{
|
||||
Standard_Integer aVal = aDistribution(aGenerator);
|
||||
aMap.Add(aVal);
|
||||
aVector.push_back(aVal);
|
||||
}
|
||||
|
||||
auto aMinOCCT = std::min_element(aMap.cbegin(), aMap.cend());
|
||||
auto aMinStd = std::min_element(aVector.begin(), aVector.end());
|
||||
|
||||
auto aMaxOCCT = std::max_element(aMap.cbegin(), aMap.cend());
|
||||
auto aMaxStd = std::max_element(aVector.begin(), aVector.end());
|
||||
|
||||
EXPECT_EQ(*aMinOCCT, *aMinStd);
|
||||
EXPECT_EQ(*aMaxOCCT, *aMaxStd);
|
||||
}
|
||||
|
||||
TEST(NCollection_IndexedMapTest, STLAlgorithmCompatibility_Find)
|
||||
{
|
||||
NCollection_IndexedMap<Standard_Integer> aMap;
|
||||
std::vector<Standard_Integer> aVector;
|
||||
|
||||
std::mt19937 aGenerator(1); // Fixed seed for reproducible tests
|
||||
std::uniform_int_distribution<Standard_Integer> aDistribution(0, RAND_MAX);
|
||||
for (Standard_Integer anIdx = 0; anIdx < 100; ++anIdx)
|
||||
{
|
||||
Standard_Integer aVal = aDistribution(aGenerator);
|
||||
aMap.Add(aVal);
|
||||
aVector.push_back(aVal);
|
||||
}
|
||||
|
||||
// Test std::find compatibility
|
||||
Standard_Integer aSearchValue = aVector[10];
|
||||
auto aFoundOCCT = std::find(aMap.cbegin(), aMap.cend(), aSearchValue);
|
||||
auto aFoundStd = std::find(aVector.begin(), aVector.end(), aSearchValue);
|
||||
|
||||
EXPECT_TRUE(aFoundOCCT != aMap.cend());
|
||||
EXPECT_TRUE(aFoundStd != aVector.end());
|
||||
EXPECT_EQ(*aFoundOCCT, *aFoundStd);
|
||||
}
|
@@ -15,9 +15,6 @@
|
||||
#include <Standard_Integer.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <random>
|
||||
|
||||
// Test fixture for NCollection_List tests
|
||||
class NCollection_ListTest : public testing::Test
|
||||
@@ -402,51 +399,4 @@ TEST_F(NCollection_ListTest, Reverse)
|
||||
EXPECT_EQ(20, it.Value());
|
||||
it.Next();
|
||||
EXPECT_EQ(10, it.Value());
|
||||
}
|
||||
|
||||
TEST_F(NCollection_ListTest, STLAlgorithmCompatibility_MinMax)
|
||||
{
|
||||
NCollection_List<Standard_Integer> aList;
|
||||
std::list<Standard_Integer> aStdList;
|
||||
|
||||
std::mt19937 aGenerator(1); // Fixed seed for reproducible tests
|
||||
std::uniform_int_distribution<Standard_Integer> aDistribution(0, RAND_MAX);
|
||||
for (Standard_Integer anIdx = 0; anIdx < 100; ++anIdx)
|
||||
{
|
||||
Standard_Integer aVal = aDistribution(aGenerator);
|
||||
aList.Append(aVal);
|
||||
aStdList.push_back(aVal);
|
||||
}
|
||||
|
||||
auto aMinOCCT = std::min_element(aList.begin(), aList.end());
|
||||
auto aMinStd = std::min_element(aStdList.begin(), aStdList.end());
|
||||
|
||||
auto aMaxOCCT = std::max_element(aList.begin(), aList.end());
|
||||
auto aMaxStd = std::max_element(aStdList.begin(), aStdList.end());
|
||||
|
||||
EXPECT_EQ(*aMinOCCT, *aMinStd);
|
||||
EXPECT_EQ(*aMaxOCCT, *aMaxStd);
|
||||
}
|
||||
|
||||
TEST_F(NCollection_ListTest, STLAlgorithmCompatibility_Replace)
|
||||
{
|
||||
NCollection_List<Standard_Integer> aList;
|
||||
std::list<Standard_Integer> aStdList;
|
||||
|
||||
std::mt19937 aGenerator(1); // Fixed seed for reproducible tests
|
||||
std::uniform_int_distribution<Standard_Integer> aDistribution(0, RAND_MAX);
|
||||
for (Standard_Integer anIdx = 0; anIdx < 100; ++anIdx)
|
||||
{
|
||||
Standard_Integer aVal = aDistribution(aGenerator);
|
||||
aList.Append(aVal);
|
||||
aStdList.push_back(aVal);
|
||||
}
|
||||
|
||||
Standard_Integer aTargetValue = aStdList.back();
|
||||
Standard_Integer aNewValue = -1;
|
||||
|
||||
std::replace(aList.begin(), aList.end(), aTargetValue, aNewValue);
|
||||
std::replace(aStdList.begin(), aStdList.end(), aTargetValue, aNewValue);
|
||||
|
||||
EXPECT_TRUE(std::equal(aList.begin(), aList.end(), aStdList.begin()));
|
||||
}
|
@@ -1,164 +0,0 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <NCollection_OccAllocator.hxx>
|
||||
#include <NCollection_IncAllocator.hxx>
|
||||
#include <Standard_Transient.hxx>
|
||||
#include <Standard_Assert.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
// Test fixture for NCollection_OccAllocator tests
|
||||
class NCollection_OccAllocatorTest : public testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override {}
|
||||
|
||||
void TearDown() override {}
|
||||
};
|
||||
|
||||
TEST_F(NCollection_OccAllocatorTest, AllocatorTypeTraits)
|
||||
{
|
||||
// Test type definitions and static assertions (compile-time checks)
|
||||
typedef Handle(Standard_Transient) anElemType;
|
||||
typedef NCollection_OccAllocator<anElemType> anAllocatorType;
|
||||
|
||||
// These would fail to compile if the types were wrong
|
||||
EXPECT_EQ(sizeof(anAllocatorType::value_type), sizeof(anElemType));
|
||||
EXPECT_EQ(sizeof(anAllocatorType::pointer), sizeof(void*));
|
||||
EXPECT_EQ(sizeof(anAllocatorType::const_pointer), sizeof(void*));
|
||||
EXPECT_EQ(sizeof(anAllocatorType::size_type), sizeof(size_t));
|
||||
EXPECT_EQ(sizeof(anAllocatorType::difference_type), sizeof(ptrdiff_t));
|
||||
|
||||
// Test reference types
|
||||
anElemType aDummy;
|
||||
anAllocatorType::reference aRef = aDummy;
|
||||
anAllocatorType::const_reference aConstRef = aDummy;
|
||||
|
||||
// Basic checks that references work
|
||||
EXPECT_EQ(&aRef, &aDummy);
|
||||
EXPECT_EQ(&aConstRef, &aDummy);
|
||||
|
||||
// Test rebind functionality
|
||||
typedef int anOtherElemType;
|
||||
typedef anAllocatorType::rebind<anOtherElemType>::other anOtherAllocatorType;
|
||||
EXPECT_EQ(sizeof(anOtherAllocatorType::value_type), sizeof(anOtherElemType));
|
||||
}
|
||||
|
||||
TEST_F(NCollection_OccAllocatorTest, STLContainerIntegration)
|
||||
{
|
||||
// Create incremental allocator outside the scope of objects it will manage
|
||||
Handle(NCollection_IncAllocator) anIncAlloc = new NCollection_IncAllocator();
|
||||
|
||||
{
|
||||
// Test with std::list using typed allocator
|
||||
NCollection_OccAllocator<int> anSAlloc(anIncAlloc);
|
||||
std::list<int, NCollection_OccAllocator<int>> aList(anSAlloc);
|
||||
|
||||
aList.push_back(2);
|
||||
EXPECT_EQ(1, aList.size());
|
||||
EXPECT_EQ(2, aList.front());
|
||||
|
||||
// Test with std::vector using type cast
|
||||
NCollection_OccAllocator<char> aCAlloc;
|
||||
std::vector<int, NCollection_OccAllocator<int>> aVector(aCAlloc);
|
||||
|
||||
aVector.push_back(1);
|
||||
EXPECT_EQ(1, aVector.size());
|
||||
EXPECT_EQ(1, aVector[0]);
|
||||
|
||||
// Test using void-specialization allocator
|
||||
NCollection_OccAllocator<void*> aVAlloc;
|
||||
std::vector<int, NCollection_OccAllocator<int>> aVector2(aVAlloc);
|
||||
|
||||
aVector2.resize(10);
|
||||
aVector2.push_back(-1);
|
||||
EXPECT_EQ(11, aVector2.size());
|
||||
EXPECT_EQ(-1, aVector2.back());
|
||||
|
||||
// Test equality of allocators
|
||||
EXPECT_NE(anSAlloc, aCAlloc); // Different underlying allocators
|
||||
|
||||
NCollection_OccAllocator<int> anIAlloc(anIncAlloc);
|
||||
EXPECT_EQ(anSAlloc, anIAlloc); // Same underlying allocator
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NCollection_OccAllocatorTest, DefaultAllocator)
|
||||
{
|
||||
// Test default allocator behavior
|
||||
NCollection_OccAllocator<int> aDefaultAlloc;
|
||||
std::vector<int, NCollection_OccAllocator<int>> aVector(aDefaultAlloc);
|
||||
|
||||
// Fill with some data
|
||||
for (int i = 0; i < 100; ++i)
|
||||
{
|
||||
aVector.push_back(i);
|
||||
}
|
||||
|
||||
EXPECT_EQ(100, aVector.size());
|
||||
|
||||
// Verify data integrity
|
||||
for (size_t i = 0; i < aVector.size(); ++i)
|
||||
{
|
||||
EXPECT_EQ(static_cast<int>(i), aVector[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(NCollection_OccAllocatorTest, AllocatorComparison)
|
||||
{
|
||||
Handle(NCollection_IncAllocator) anIncAlloc1 = new NCollection_IncAllocator();
|
||||
Handle(NCollection_IncAllocator) anIncAlloc2 = new NCollection_IncAllocator();
|
||||
|
||||
NCollection_OccAllocator<int> aAlloc1(anIncAlloc1);
|
||||
NCollection_OccAllocator<int> aAlloc2(anIncAlloc1); // Same underlying allocator
|
||||
NCollection_OccAllocator<int> aAlloc3(anIncAlloc2); // Different underlying allocator
|
||||
NCollection_OccAllocator<int> aAlloc4; // Default allocator
|
||||
|
||||
// Test equality
|
||||
EXPECT_EQ(aAlloc1, aAlloc2); // Same underlying allocator
|
||||
EXPECT_NE(aAlloc1, aAlloc3); // Different underlying allocator
|
||||
EXPECT_NE(aAlloc1, aAlloc4); // One uses IncAllocator, one uses default
|
||||
|
||||
// Test inequality
|
||||
EXPECT_FALSE(aAlloc1 != aAlloc2); // Should be equal
|
||||
EXPECT_TRUE(aAlloc1 != aAlloc3); // Should be different
|
||||
}
|
||||
|
||||
TEST_F(NCollection_OccAllocatorTest, CrossTypeCompatibility)
|
||||
{
|
||||
Handle(NCollection_IncAllocator) anIncAlloc = new NCollection_IncAllocator();
|
||||
|
||||
// Test allocators for different types but same underlying allocator
|
||||
NCollection_OccAllocator<int> anIntAlloc(anIncAlloc);
|
||||
NCollection_OccAllocator<double> aDoubleAlloc(anIncAlloc);
|
||||
NCollection_OccAllocator<char> aCharAlloc(anIncAlloc);
|
||||
|
||||
// They should be considered equal despite different value types
|
||||
// (This tests the allocator's rebind and comparison logic)
|
||||
EXPECT_EQ(anIntAlloc, NCollection_OccAllocator<int>(anIncAlloc));
|
||||
|
||||
// Create containers with different allocators pointing to same IncAllocator
|
||||
std::vector<int, NCollection_OccAllocator<int>> anIntVector(anIntAlloc);
|
||||
std::vector<double, NCollection_OccAllocator<double>> aDoubleVector(aDoubleAlloc);
|
||||
|
||||
anIntVector.push_back(42);
|
||||
aDoubleVector.push_back(3.14);
|
||||
|
||||
EXPECT_EQ(1, anIntVector.size());
|
||||
EXPECT_EQ(1, aDoubleVector.size());
|
||||
EXPECT_EQ(42, anIntVector[0]);
|
||||
EXPECT_DOUBLE_EQ(3.14, aDoubleVector[0]);
|
||||
}
|
@@ -16,9 +16,6 @@
|
||||
#include <NCollection_BaseAllocator.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <random>
|
||||
|
||||
// Basic test type for the Sequence
|
||||
typedef Standard_Integer ItemType;
|
||||
@@ -375,68 +372,4 @@ TEST(NCollection_SequenceTest, MoveOperations)
|
||||
EXPECT_TRUE(aSeq3.IsEmpty()); // Original sequence should be empty after move
|
||||
EXPECT_EQ(aSeq4.Size(), 1);
|
||||
EXPECT_EQ(aSeq4(1), 40);
|
||||
}
|
||||
|
||||
TEST(NCollection_SequenceTest, STLAlgorithmCompatibility_MinMax)
|
||||
{
|
||||
NCollection_Sequence<Standard_Integer> aSequence;
|
||||
std::list<Standard_Integer> aStdList;
|
||||
|
||||
std::mt19937 aGenerator(1); // Fixed seed for reproducible tests
|
||||
std::uniform_int_distribution<Standard_Integer> aDistribution(0, RAND_MAX);
|
||||
for (Standard_Integer anIdx = 0; anIdx < 100; ++anIdx)
|
||||
{
|
||||
Standard_Integer aVal = aDistribution(aGenerator);
|
||||
aSequence.Append(aVal);
|
||||
aStdList.push_back(aVal);
|
||||
}
|
||||
|
||||
auto aMinOCCT = std::min_element(aSequence.begin(), aSequence.end());
|
||||
auto aMinStd = std::min_element(aStdList.begin(), aStdList.end());
|
||||
|
||||
auto aMaxOCCT = std::max_element(aSequence.begin(), aSequence.end());
|
||||
auto aMaxStd = std::max_element(aStdList.begin(), aStdList.end());
|
||||
|
||||
EXPECT_EQ(*aMinOCCT, *aMinStd);
|
||||
EXPECT_EQ(*aMaxOCCT, *aMaxStd);
|
||||
}
|
||||
|
||||
TEST(NCollection_SequenceTest, STLAlgorithmCompatibility_Replace)
|
||||
{
|
||||
NCollection_Sequence<Standard_Integer> aSequence;
|
||||
std::list<Standard_Integer> aStdList;
|
||||
|
||||
std::mt19937 aGenerator(1); // Fixed seed for reproducible tests
|
||||
std::uniform_int_distribution<Standard_Integer> aDistribution(0, RAND_MAX);
|
||||
for (Standard_Integer anIdx = 0; anIdx < 100; ++anIdx)
|
||||
{
|
||||
Standard_Integer aVal = aDistribution(aGenerator);
|
||||
aSequence.Append(aVal);
|
||||
aStdList.push_back(aVal);
|
||||
}
|
||||
|
||||
Standard_Integer aTargetValue = aStdList.back();
|
||||
Standard_Integer aNewValue = -1;
|
||||
|
||||
std::replace(aSequence.begin(), aSequence.end(), aTargetValue, aNewValue);
|
||||
std::replace(aStdList.begin(), aStdList.end(), aTargetValue, aNewValue);
|
||||
|
||||
EXPECT_TRUE(std::equal(aSequence.begin(), aSequence.end(), aStdList.begin()));
|
||||
}
|
||||
|
||||
TEST(NCollection_SequenceTest, STLAlgorithmCompatibility_Reverse)
|
||||
{
|
||||
NCollection_Sequence<Standard_Integer> aSequence;
|
||||
std::list<Standard_Integer> aStdList;
|
||||
|
||||
for (Standard_Integer anIdx = 0; anIdx < 100; ++anIdx)
|
||||
{
|
||||
aSequence.Append(anIdx);
|
||||
aStdList.push_back(anIdx);
|
||||
}
|
||||
|
||||
std::reverse(aSequence.begin(), aSequence.end());
|
||||
std::reverse(aStdList.begin(), aStdList.end());
|
||||
|
||||
EXPECT_TRUE(std::equal(aSequence.begin(), aSequence.end(), aStdList.begin()));
|
||||
}
|
@@ -1,131 +0,0 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <NCollection_Vec4.hxx>
|
||||
#include <NCollection_Vec3.hxx>
|
||||
#include <NCollection_Mat4.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <cmath>
|
||||
|
||||
// Test fixture for NCollection_Vec4 tests
|
||||
class NCollection_Vec4Test : public testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override {}
|
||||
|
||||
void TearDown() override {}
|
||||
};
|
||||
|
||||
TEST_F(NCollection_Vec4Test, BasicConstruction)
|
||||
{
|
||||
// Test default constructor
|
||||
NCollection_Vec4<float> aVec1;
|
||||
EXPECT_EQ(0.0f, aVec1.x());
|
||||
EXPECT_EQ(0.0f, aVec1.y());
|
||||
EXPECT_EQ(0.0f, aVec1.z());
|
||||
EXPECT_EQ(0.0f, aVec1.w());
|
||||
|
||||
// Test parameterized constructor
|
||||
NCollection_Vec4<float> aVec2(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
EXPECT_EQ(1.0f, aVec2.x());
|
||||
EXPECT_EQ(2.0f, aVec2.y());
|
||||
EXPECT_EQ(3.0f, aVec2.z());
|
||||
EXPECT_EQ(4.0f, aVec2.w());
|
||||
}
|
||||
|
||||
TEST_F(NCollection_Vec4Test, XyzMethod)
|
||||
{
|
||||
NCollection_Vec4<float> aVec(2.0f, 3.0f, 4.0f, 5.0f);
|
||||
NCollection_Vec3<float> aVec3 = aVec.xyz();
|
||||
|
||||
EXPECT_EQ(2.0f, aVec3.x());
|
||||
EXPECT_EQ(3.0f, aVec3.y());
|
||||
EXPECT_EQ(4.0f, aVec3.z());
|
||||
}
|
||||
|
||||
TEST_F(NCollection_Vec4Test, MatrixMultiplicationAndTransformation)
|
||||
{
|
||||
// Test matrix multiplication and xyz() method with translation
|
||||
NCollection_Mat4<float> aMatrix;
|
||||
aMatrix.Translate(NCollection_Vec3<float>(4.0f, 3.0f, 1.0f));
|
||||
|
||||
// Create a cube of points (-1,-1,-1) to (1,1,1)
|
||||
NCollection_Vec4<float> aPoints1[8];
|
||||
for (int aX = 0; aX < 2; ++aX)
|
||||
{
|
||||
for (int aY = 0; aY < 2; ++aY)
|
||||
{
|
||||
for (int aZ = 0; aZ < 2; ++aZ)
|
||||
{
|
||||
aPoints1[aX * 2 * 2 + aY * 2 + aZ] = NCollection_Vec4<float>(-1.0f + 2.0f * float(aX),
|
||||
-1.0f + 2.0f * float(aY),
|
||||
-1.0f + 2.0f * float(aZ),
|
||||
1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply transformation and convert to Vec3
|
||||
NCollection_Vec3<float> aPoints2[8];
|
||||
for (int aPntIdx = 0; aPntIdx < 8; ++aPntIdx)
|
||||
{
|
||||
aPoints1[aPntIdx] = aMatrix * aPoints1[aPntIdx];
|
||||
aPoints2[aPntIdx] = aPoints1[aPntIdx].xyz() / aPoints1[aPntIdx].w();
|
||||
}
|
||||
|
||||
// Check that the transformation worked correctly
|
||||
// The last point should be (1,1,1) transformed by translation (4,3,1) -> (5,4,2)
|
||||
// SquareModulus of (5,4,2) = 25 + 16 + 4 = 45
|
||||
float aSquareModulus = aPoints2[7].SquareModulus();
|
||||
EXPECT_NEAR(45.0f, aSquareModulus, 0.001f);
|
||||
|
||||
// Check that all points were translated correctly
|
||||
// Point (0,0,0) -> translate by (4,3,1) -> (4,3,1)
|
||||
// Point index 0 corresponds to (-1,-1,-1) -> (3,2,0)
|
||||
float aExpectedSquareMod0 = 3.0f * 3.0f + 2.0f * 2.0f + 0.0f * 0.0f; // 9 + 4 + 0 = 13
|
||||
EXPECT_NEAR(aExpectedSquareMod0, aPoints2[0].SquareModulus(), 0.001f);
|
||||
}
|
||||
|
||||
TEST_F(NCollection_Vec4Test, ComponentAccess)
|
||||
{
|
||||
NCollection_Vec4<float> aVec(1.5f, 2.5f, 3.5f, 4.5f);
|
||||
|
||||
// Test read access
|
||||
EXPECT_EQ(1.5f, aVec.x());
|
||||
EXPECT_EQ(2.5f, aVec.y());
|
||||
EXPECT_EQ(3.5f, aVec.z());
|
||||
EXPECT_EQ(4.5f, aVec.w());
|
||||
|
||||
// Test write access
|
||||
aVec.x() = 10.0f;
|
||||
aVec.y() = 20.0f;
|
||||
aVec.z() = 30.0f;
|
||||
aVec.w() = 40.0f;
|
||||
|
||||
EXPECT_EQ(10.0f, aVec.x());
|
||||
EXPECT_EQ(20.0f, aVec.y());
|
||||
EXPECT_EQ(30.0f, aVec.z());
|
||||
EXPECT_EQ(40.0f, aVec.w());
|
||||
}
|
||||
|
||||
TEST_F(NCollection_Vec4Test, HomogeneousCoordinateDivision)
|
||||
{
|
||||
// Test perspective division using w component
|
||||
NCollection_Vec4<float> aVec(8.0f, 12.0f, 16.0f, 4.0f);
|
||||
NCollection_Vec3<float> aResult = aVec.xyz() / aVec.w();
|
||||
|
||||
EXPECT_EQ(2.0f, aResult.x()); // 8/4 = 2
|
||||
EXPECT_EQ(3.0f, aResult.y()); // 12/4 = 3
|
||||
EXPECT_EQ(4.0f, aResult.z()); // 16/4 = 4
|
||||
}
|
@@ -16,9 +16,6 @@
|
||||
#include <Standard_Integer.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
TEST(NCollection_VectorTest, DefaultConstructor)
|
||||
{
|
||||
@@ -382,88 +379,4 @@ TEST(NCollection_VectorTest, SetIncrement)
|
||||
{
|
||||
EXPECT_EQ(i, aVector(i));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(NCollection_VectorTest, STLAlgorithmCompatibility_MinMax)
|
||||
{
|
||||
NCollection_Vector<Standard_Integer> aVector;
|
||||
std::vector<Standard_Integer> aStdVector;
|
||||
|
||||
std::mt19937 aGenerator(1); // Fixed seed for reproducible tests
|
||||
std::uniform_int_distribution<Standard_Integer> aDistribution(0, RAND_MAX);
|
||||
for (Standard_Integer anIdx = 0; anIdx < 100; ++anIdx)
|
||||
{
|
||||
Standard_Integer aVal = aDistribution(aGenerator);
|
||||
aVector.Append(aVal);
|
||||
aStdVector.push_back(aVal);
|
||||
}
|
||||
|
||||
auto aMinOCCT = std::min_element(aVector.begin(), aVector.end());
|
||||
auto aMinStd = std::min_element(aStdVector.begin(), aStdVector.end());
|
||||
|
||||
auto aMaxOCCT = std::max_element(aVector.begin(), aVector.end());
|
||||
auto aMaxStd = std::max_element(aStdVector.begin(), aStdVector.end());
|
||||
|
||||
EXPECT_EQ(*aMinOCCT, *aMinStd);
|
||||
EXPECT_EQ(*aMaxOCCT, *aMaxStd);
|
||||
}
|
||||
|
||||
TEST(NCollection_VectorTest, STLAlgorithmCompatibility_Replace)
|
||||
{
|
||||
NCollection_Vector<Standard_Integer> aVector;
|
||||
std::vector<Standard_Integer> aStdVector;
|
||||
|
||||
std::mt19937 aGenerator(1); // Fixed seed for reproducible tests
|
||||
std::uniform_int_distribution<Standard_Integer> aDistribution(0, RAND_MAX);
|
||||
for (Standard_Integer anIdx = 0; anIdx < 100; ++anIdx)
|
||||
{
|
||||
Standard_Integer aVal = aDistribution(aGenerator);
|
||||
aVector.Append(aVal);
|
||||
aStdVector.push_back(aVal);
|
||||
}
|
||||
|
||||
Standard_Integer aTargetValue = aStdVector.back();
|
||||
Standard_Integer aNewValue = -1;
|
||||
|
||||
std::replace(aVector.begin(), aVector.end(), aTargetValue, aNewValue);
|
||||
std::replace(aStdVector.begin(), aStdVector.end(), aTargetValue, aNewValue);
|
||||
|
||||
EXPECT_TRUE(std::equal(aVector.begin(), aVector.end(), aStdVector.begin()));
|
||||
}
|
||||
|
||||
TEST(NCollection_VectorTest, STLAlgorithmCompatibility_Reverse)
|
||||
{
|
||||
NCollection_Vector<Standard_Integer> aVector;
|
||||
std::vector<Standard_Integer> aStdVector;
|
||||
|
||||
for (Standard_Integer anIdx = 0; anIdx < 100; ++anIdx)
|
||||
{
|
||||
aVector.Append(anIdx);
|
||||
aStdVector.push_back(anIdx);
|
||||
}
|
||||
|
||||
std::reverse(aVector.begin(), aVector.end());
|
||||
std::reverse(aStdVector.begin(), aStdVector.end());
|
||||
|
||||
EXPECT_TRUE(std::equal(aVector.begin(), aVector.end(), aStdVector.begin()));
|
||||
}
|
||||
|
||||
TEST(NCollection_VectorTest, STLAlgorithmCompatibility_Sort)
|
||||
{
|
||||
NCollection_Vector<Standard_Integer> aVector;
|
||||
std::vector<Standard_Integer> aStdVector;
|
||||
|
||||
std::mt19937 aGenerator(1); // Fixed seed for reproducible tests
|
||||
std::uniform_int_distribution<Standard_Integer> aDistribution(0, RAND_MAX);
|
||||
for (Standard_Integer anIdx = 0; anIdx < 100; ++anIdx)
|
||||
{
|
||||
Standard_Integer aVal = aDistribution(aGenerator);
|
||||
aVector.Append(aVal);
|
||||
aStdVector.push_back(aVal);
|
||||
}
|
||||
|
||||
std::sort(aVector.begin(), aVector.end());
|
||||
std::sort(aStdVector.begin(), aStdVector.end());
|
||||
|
||||
EXPECT_TRUE(std::equal(aVector.begin(), aVector.end(), aStdVector.begin()));
|
||||
}
|
@@ -1,246 +0,0 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <OSD_Path.hxx>
|
||||
#include <TCollection_AsciiString.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
// Test fixture for OSD_Path tests
|
||||
class OSD_PathTest : public testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override {}
|
||||
|
||||
void TearDown() override {}
|
||||
};
|
||||
|
||||
TEST_F(OSD_PathTest, DosAbsolutePaths)
|
||||
{
|
||||
// Test DOS absolute paths
|
||||
EXPECT_TRUE(OSD_Path::IsAbsolutePath("c:\\folder\\file.png"));
|
||||
EXPECT_TRUE(OSD_Path::IsDosPath("c:\\folder\\file.png"));
|
||||
EXPECT_FALSE(OSD_Path::IsRelativePath("c:\\folder\\file.png"));
|
||||
EXPECT_FALSE(OSD_Path::IsUnixPath("c:\\folder\\file.png"));
|
||||
EXPECT_FALSE(OSD_Path::IsUncPath("c:\\folder\\file.png"));
|
||||
|
||||
// Test DOS root
|
||||
EXPECT_TRUE(OSD_Path::IsAbsolutePath("D:\\"));
|
||||
EXPECT_TRUE(OSD_Path::IsDosPath("D:\\"));
|
||||
|
||||
// Test single file on DOS drive
|
||||
EXPECT_TRUE(OSD_Path::IsAbsolutePath("c:\\file.png"));
|
||||
EXPECT_TRUE(OSD_Path::IsDosPath("c:\\file.png"));
|
||||
}
|
||||
|
||||
TEST_F(OSD_PathTest, UncPaths)
|
||||
{
|
||||
// Test UNC paths
|
||||
EXPECT_TRUE(OSD_Path::IsAbsolutePath("\\\\share\\file.pdf"));
|
||||
EXPECT_TRUE(OSD_Path::IsUncPath("\\\\share\\file.pdf"));
|
||||
EXPECT_FALSE(OSD_Path::IsDosPath("\\\\share\\file.pdf"));
|
||||
EXPECT_FALSE(OSD_Path::IsUnixPath("\\\\share\\file.pdf"));
|
||||
}
|
||||
|
||||
TEST_F(OSD_PathTest, NtExtendedPaths)
|
||||
{
|
||||
// Test NT Extended paths
|
||||
EXPECT_TRUE(OSD_Path::IsAbsolutePath("\\\\?\\C:\\documents\\file.docx"));
|
||||
EXPECT_TRUE(OSD_Path::IsNtExtendedPath("\\\\?\\C:\\documents\\file.docx"));
|
||||
EXPECT_FALSE(OSD_Path::IsUncPath("\\\\?\\C:\\documents\\file.docx"));
|
||||
}
|
||||
|
||||
TEST_F(OSD_PathTest, UncExtendedPaths)
|
||||
{
|
||||
// Test UNC Extended paths
|
||||
EXPECT_TRUE(OSD_Path::IsAbsolutePath("\\\\?\\UNC\\server\\share\\file.zip"));
|
||||
EXPECT_TRUE(OSD_Path::IsUncPath("\\\\?\\UNC\\server\\share\\file.zip"));
|
||||
EXPECT_TRUE(OSD_Path::IsNtExtendedPath("\\\\?\\UNC\\server\\share\\file.zip"));
|
||||
EXPECT_TRUE(OSD_Path::IsUncExtendedPath("\\\\?\\UNC\\server\\share\\file.zip"));
|
||||
}
|
||||
|
||||
TEST_F(OSD_PathTest, RemoteProtocolPaths)
|
||||
{
|
||||
// Test remote protocol paths
|
||||
EXPECT_TRUE(OSD_Path::IsAbsolutePath("https://www.server.org/file.gif"));
|
||||
EXPECT_TRUE(OSD_Path::IsRemoteProtocolPath("https://www.server.org/file.gif"));
|
||||
EXPECT_FALSE(OSD_Path::IsUnixPath("https://www.server.org/file.gif"));
|
||||
EXPECT_FALSE(OSD_Path::IsDosPath("https://www.server.org/file.gif"));
|
||||
|
||||
// Test other protocols
|
||||
EXPECT_TRUE(OSD_Path::IsAbsolutePath("ftp://ftp.server.com/file.dat"));
|
||||
EXPECT_TRUE(OSD_Path::IsRemoteProtocolPath("ftp://ftp.server.com/file.dat"));
|
||||
|
||||
EXPECT_TRUE(OSD_Path::IsAbsolutePath("http://example.com/path"));
|
||||
EXPECT_TRUE(OSD_Path::IsRemoteProtocolPath("http://example.com/path"));
|
||||
}
|
||||
|
||||
TEST_F(OSD_PathTest, ContentProtocolPaths)
|
||||
{
|
||||
// Test content protocol paths
|
||||
EXPECT_TRUE(OSD_Path::IsAbsolutePath("content://file.jpg"));
|
||||
EXPECT_TRUE(OSD_Path::IsRemoteProtocolPath("content://file.jpg"));
|
||||
EXPECT_TRUE(OSD_Path::IsContentProtocolPath("content://file.jpg"));
|
||||
}
|
||||
|
||||
TEST_F(OSD_PathTest, UnixAbsolutePaths)
|
||||
{
|
||||
// Test Unix absolute paths
|
||||
EXPECT_TRUE(OSD_Path::IsAbsolutePath("/home/username/file.txt"));
|
||||
EXPECT_TRUE(OSD_Path::IsUnixPath("/home/username/file.txt"));
|
||||
EXPECT_FALSE(OSD_Path::IsRelativePath("/home/username/file.txt"));
|
||||
EXPECT_FALSE(OSD_Path::IsDosPath("/home/username/file.txt"));
|
||||
|
||||
// Test Unix root
|
||||
EXPECT_TRUE(OSD_Path::IsAbsolutePath("/"));
|
||||
EXPECT_TRUE(OSD_Path::IsUnixPath("/"));
|
||||
|
||||
// Test single file on Unix
|
||||
EXPECT_TRUE(OSD_Path::IsAbsolutePath("/boot.bin"));
|
||||
EXPECT_TRUE(OSD_Path::IsUnixPath("/boot.bin"));
|
||||
}
|
||||
|
||||
TEST_F(OSD_PathTest, RelativePaths)
|
||||
{
|
||||
// Test relative paths with navigation
|
||||
EXPECT_TRUE(OSD_Path::IsRelativePath("./subfolder/../file.txt"));
|
||||
EXPECT_FALSE(OSD_Path::IsAbsolutePath("./subfolder/../file.txt"));
|
||||
|
||||
EXPECT_TRUE(OSD_Path::IsRelativePath("../file.txt"));
|
||||
EXPECT_FALSE(OSD_Path::IsAbsolutePath("../file.txt"));
|
||||
|
||||
// Test current directory
|
||||
EXPECT_TRUE(OSD_Path::IsRelativePath("."));
|
||||
EXPECT_FALSE(OSD_Path::IsAbsolutePath("."));
|
||||
|
||||
// Test parent directory
|
||||
EXPECT_TRUE(OSD_Path::IsRelativePath(".."));
|
||||
EXPECT_FALSE(OSD_Path::IsAbsolutePath(".."));
|
||||
|
||||
// Test simple relative path
|
||||
EXPECT_TRUE(OSD_Path::IsRelativePath("folder/file.txt"));
|
||||
EXPECT_FALSE(OSD_Path::IsAbsolutePath("folder/file.txt"));
|
||||
|
||||
// Test simple filename
|
||||
EXPECT_TRUE(OSD_Path::IsRelativePath("file.txt"));
|
||||
EXPECT_FALSE(OSD_Path::IsAbsolutePath("file.txt"));
|
||||
}
|
||||
|
||||
TEST_F(OSD_PathTest, FolderAndFileFromPath_UnixPaths)
|
||||
{
|
||||
TCollection_AsciiString aFolder, aFileName;
|
||||
|
||||
// Test Unix absolute path
|
||||
OSD_Path::FolderAndFileFromPath("/home/username/file.txt", aFolder, aFileName);
|
||||
EXPECT_STREQ("/home/username/", aFolder.ToCString());
|
||||
EXPECT_STREQ("file.txt", aFileName.ToCString());
|
||||
|
||||
// Test Unix root file
|
||||
OSD_Path::FolderAndFileFromPath("/file.txt", aFolder, aFileName);
|
||||
EXPECT_STREQ("/", aFolder.ToCString());
|
||||
EXPECT_STREQ("file.txt", aFileName.ToCString());
|
||||
|
||||
// Test Unix folder only (trailing slash)
|
||||
OSD_Path::FolderAndFileFromPath("/home/username/", aFolder, aFileName);
|
||||
EXPECT_STREQ("/home/username/", aFolder.ToCString());
|
||||
EXPECT_STREQ("", aFileName.ToCString());
|
||||
}
|
||||
|
||||
TEST_F(OSD_PathTest, FolderAndFileFromPath_DosPaths)
|
||||
{
|
||||
TCollection_AsciiString aFolder, aFileName;
|
||||
|
||||
// Test DOS absolute path
|
||||
OSD_Path::FolderAndFileFromPath("C:\\Users\\John\\document.txt", aFolder, aFileName);
|
||||
EXPECT_STREQ("C:\\Users\\John\\", aFolder.ToCString());
|
||||
EXPECT_STREQ("document.txt", aFileName.ToCString());
|
||||
|
||||
// Test DOS root file
|
||||
OSD_Path::FolderAndFileFromPath("C:\\file.txt", aFolder, aFileName);
|
||||
EXPECT_STREQ("C:\\", aFolder.ToCString());
|
||||
EXPECT_STREQ("file.txt", aFileName.ToCString());
|
||||
|
||||
// Test DOS folder only (trailing backslash)
|
||||
OSD_Path::FolderAndFileFromPath("C:\\Program Files\\", aFolder, aFileName);
|
||||
EXPECT_STREQ("C:\\Program Files\\", aFolder.ToCString());
|
||||
EXPECT_STREQ("", aFileName.ToCString());
|
||||
}
|
||||
|
||||
TEST_F(OSD_PathTest, FolderAndFileFromPath_RelativePaths)
|
||||
{
|
||||
TCollection_AsciiString aFolder, aFileName;
|
||||
|
||||
// Test relative path
|
||||
OSD_Path::FolderAndFileFromPath("folder/subfolder/file.txt", aFolder, aFileName);
|
||||
EXPECT_STREQ("folder/subfolder/", aFolder.ToCString());
|
||||
EXPECT_STREQ("file.txt", aFileName.ToCString());
|
||||
|
||||
// Test relative with navigation
|
||||
OSD_Path::FolderAndFileFromPath("../folder/file.txt", aFolder, aFileName);
|
||||
EXPECT_STREQ("../folder/", aFolder.ToCString());
|
||||
EXPECT_STREQ("file.txt", aFileName.ToCString());
|
||||
|
||||
// Test just filename
|
||||
OSD_Path::FolderAndFileFromPath("file.txt", aFolder, aFileName);
|
||||
EXPECT_STREQ("", aFolder.ToCString());
|
||||
EXPECT_STREQ("file.txt", aFileName.ToCString());
|
||||
}
|
||||
|
||||
TEST_F(OSD_PathTest, FolderAndFileFromPath_ProtocolPaths)
|
||||
{
|
||||
TCollection_AsciiString aFolder, aFileName;
|
||||
|
||||
// Test HTTPS path
|
||||
OSD_Path::FolderAndFileFromPath("https://www.server.org/folder/file.gif", aFolder, aFileName);
|
||||
EXPECT_STREQ("https://www.server.org/folder/", aFolder.ToCString());
|
||||
EXPECT_STREQ("file.gif", aFileName.ToCString());
|
||||
|
||||
// Test content protocol
|
||||
OSD_Path::FolderAndFileFromPath("content://path/file.jpg", aFolder, aFileName);
|
||||
EXPECT_STREQ("content://path/", aFolder.ToCString());
|
||||
EXPECT_STREQ("file.jpg", aFileName.ToCString());
|
||||
}
|
||||
|
||||
TEST_F(OSD_PathTest, EdgeCases)
|
||||
{
|
||||
TCollection_AsciiString aFolder, aFileName;
|
||||
|
||||
// Test empty path
|
||||
OSD_Path::FolderAndFileFromPath("", aFolder, aFileName);
|
||||
EXPECT_STREQ("", aFolder.ToCString());
|
||||
EXPECT_STREQ("", aFileName.ToCString());
|
||||
|
||||
// Test just separator
|
||||
OSD_Path::FolderAndFileFromPath("/", aFolder, aFileName);
|
||||
EXPECT_STREQ("/", aFolder.ToCString());
|
||||
EXPECT_STREQ("", aFileName.ToCString());
|
||||
|
||||
OSD_Path::FolderAndFileFromPath("\\", aFolder, aFileName);
|
||||
EXPECT_STREQ("\\", aFolder.ToCString());
|
||||
EXPECT_STREQ("", aFileName.ToCString());
|
||||
|
||||
// Test path with no file extension
|
||||
OSD_Path::FolderAndFileFromPath("/home/username/foldername", aFolder, aFileName);
|
||||
EXPECT_STREQ("/home/username/", aFolder.ToCString());
|
||||
EXPECT_STREQ("foldername", aFileName.ToCString());
|
||||
}
|
||||
|
||||
TEST_F(OSD_PathTest, MixedSeparators)
|
||||
{
|
||||
TCollection_AsciiString aFolder, aFileName;
|
||||
|
||||
// Test mixed separators (this might happen in cross-platform scenarios)
|
||||
OSD_Path::FolderAndFileFromPath("C:/Users/John\\Documents/file.txt", aFolder, aFileName);
|
||||
// The exact behavior might depend on implementation, but it should handle this gracefully
|
||||
EXPECT_FALSE(aFolder.IsEmpty() || aFileName.IsEmpty());
|
||||
}
|
@@ -1,354 +0,0 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <Standard_ArrayStreamBuffer.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
TEST(Standard_ArrayStreamBufferTest, ConstructorAndBasicUsage)
|
||||
{
|
||||
const char* aTestData = "Hello, World!";
|
||||
const size_t aDataSize = strlen(aTestData);
|
||||
|
||||
Standard_ArrayStreamBuffer aBuffer(aTestData, aDataSize);
|
||||
std::istream aStream(&aBuffer);
|
||||
|
||||
std::string aResult;
|
||||
aStream >> aResult;
|
||||
|
||||
EXPECT_EQ("Hello,", aResult);
|
||||
}
|
||||
|
||||
TEST(Standard_ArrayStreamBufferTest, InitMethod)
|
||||
{
|
||||
const char* aTestData1 = "First data";
|
||||
const char* aTestData2 = "Second data";
|
||||
const size_t aDataSize1 = strlen(aTestData1);
|
||||
const size_t aDataSize2 = strlen(aTestData2);
|
||||
|
||||
Standard_ArrayStreamBuffer aBuffer(aTestData1, aDataSize1);
|
||||
std::istream aStream(&aBuffer);
|
||||
|
||||
std::string aResult1;
|
||||
aStream >> aResult1;
|
||||
EXPECT_EQ("First", aResult1);
|
||||
|
||||
aBuffer.Init(aTestData2, aDataSize2);
|
||||
aStream.clear();
|
||||
aStream.seekg(0);
|
||||
|
||||
std::string aResult2;
|
||||
aStream >> aResult2;
|
||||
EXPECT_EQ("Second", aResult2);
|
||||
}
|
||||
|
||||
TEST(Standard_ArrayStreamBufferTest, ReadFullContent)
|
||||
{
|
||||
const char* aTestData = "Hello World";
|
||||
const size_t aDataSize = strlen(aTestData);
|
||||
|
||||
Standard_ArrayStreamBuffer aBuffer(aTestData, aDataSize);
|
||||
std::istream aStream(&aBuffer);
|
||||
|
||||
std::string aResult;
|
||||
std::getline(aStream, aResult);
|
||||
|
||||
EXPECT_EQ("Hello World", aResult);
|
||||
}
|
||||
|
||||
TEST(Standard_ArrayStreamBufferTest, CharacterByCharacterRead)
|
||||
{
|
||||
const char* aTestData = "ABC";
|
||||
const size_t aDataSize = strlen(aTestData);
|
||||
|
||||
Standard_ArrayStreamBuffer aBuffer(aTestData, aDataSize);
|
||||
std::istream aStream(&aBuffer);
|
||||
|
||||
char aCh1, aCh2, aCh3, aCh4;
|
||||
aStream >> aCh1 >> aCh2 >> aCh3;
|
||||
|
||||
EXPECT_EQ('A', aCh1);
|
||||
EXPECT_EQ('B', aCh2);
|
||||
EXPECT_EQ('C', aCh3);
|
||||
|
||||
EXPECT_TRUE(aStream.good());
|
||||
|
||||
aStream >> aCh4;
|
||||
EXPECT_TRUE(aStream.eof());
|
||||
}
|
||||
|
||||
TEST(Standard_ArrayStreamBufferTest, SeekFromBeginning)
|
||||
{
|
||||
const char* aTestData = "0123456789";
|
||||
const size_t aDataSize = strlen(aTestData);
|
||||
|
||||
Standard_ArrayStreamBuffer aBuffer(aTestData, aDataSize);
|
||||
std::istream aStream(&aBuffer);
|
||||
|
||||
aStream.seekg(5, std::ios::beg);
|
||||
char aCh;
|
||||
aStream >> aCh;
|
||||
|
||||
EXPECT_EQ('5', aCh);
|
||||
}
|
||||
|
||||
TEST(Standard_ArrayStreamBufferTest, SeekFromEnd)
|
||||
{
|
||||
const char* aTestData = "0123456789";
|
||||
const size_t aDataSize = strlen(aTestData);
|
||||
|
||||
Standard_ArrayStreamBuffer aBuffer(aTestData, aDataSize);
|
||||
std::istream aStream(&aBuffer);
|
||||
|
||||
// Position to 3 characters before the end
|
||||
// String: "0123456789" (length 10)
|
||||
// Position 7 should give us character '7'
|
||||
aStream.seekg(7, std::ios::beg);
|
||||
char aCh;
|
||||
aStream >> aCh;
|
||||
|
||||
EXPECT_EQ('7', aCh);
|
||||
}
|
||||
|
||||
TEST(Standard_ArrayStreamBufferTest, SeekFromCurrent)
|
||||
{
|
||||
const char* aTestData = "0123456789";
|
||||
const size_t aDataSize = strlen(aTestData);
|
||||
|
||||
Standard_ArrayStreamBuffer aBuffer(aTestData, aDataSize);
|
||||
std::istream aStream(&aBuffer);
|
||||
|
||||
aStream.seekg(2, std::ios::beg);
|
||||
aStream.seekg(3, std::ios::cur);
|
||||
|
||||
char aCh;
|
||||
aStream >> aCh;
|
||||
|
||||
EXPECT_EQ('5', aCh);
|
||||
}
|
||||
|
||||
TEST(Standard_ArrayStreamBufferTest, TellPosition)
|
||||
{
|
||||
const char* aTestData = "0123456789";
|
||||
const size_t aDataSize = strlen(aTestData);
|
||||
|
||||
Standard_ArrayStreamBuffer aBuffer(aTestData, aDataSize);
|
||||
std::istream aStream(&aBuffer);
|
||||
|
||||
EXPECT_EQ(0, aStream.tellg());
|
||||
|
||||
aStream.seekg(5);
|
||||
EXPECT_EQ(5, aStream.tellg());
|
||||
|
||||
char aCh;
|
||||
aStream >> aCh;
|
||||
EXPECT_EQ(6, aStream.tellg());
|
||||
}
|
||||
|
||||
TEST(Standard_ArrayStreamBufferTest, ReadBeyondBuffer)
|
||||
{
|
||||
const char* aTestData = "ABC";
|
||||
const size_t aDataSize = strlen(aTestData);
|
||||
|
||||
Standard_ArrayStreamBuffer aBuffer(aTestData, aDataSize);
|
||||
std::istream aStream(&aBuffer);
|
||||
|
||||
aStream.seekg(10);
|
||||
|
||||
char aCh;
|
||||
aStream >> aCh;
|
||||
|
||||
EXPECT_TRUE(aStream.eof());
|
||||
}
|
||||
|
||||
TEST(Standard_ArrayStreamBufferTest, EmptyBuffer)
|
||||
{
|
||||
const char* aTestData = "";
|
||||
const size_t aDataSize = 0;
|
||||
|
||||
Standard_ArrayStreamBuffer aBuffer(aTestData, aDataSize);
|
||||
std::istream aStream(&aBuffer);
|
||||
|
||||
char aCh;
|
||||
aStream >> aCh;
|
||||
|
||||
EXPECT_TRUE(aStream.eof());
|
||||
}
|
||||
|
||||
TEST(Standard_ArrayStreamBufferTest, NullPointerBuffer)
|
||||
{
|
||||
Standard_ArrayStreamBuffer aBuffer(nullptr, 0);
|
||||
std::istream aStream(&aBuffer);
|
||||
|
||||
char aCh;
|
||||
aStream >> aCh;
|
||||
|
||||
EXPECT_TRUE(aStream.eof());
|
||||
}
|
||||
|
||||
TEST(Standard_ArrayStreamBufferTest, BinaryData)
|
||||
{
|
||||
const char aBinaryData[] = {0x01, 0x02, 0x03, 0x00, 0x04, 0x05};
|
||||
const size_t aDataSize = sizeof(aBinaryData);
|
||||
|
||||
Standard_ArrayStreamBuffer aBuffer(aBinaryData, aDataSize);
|
||||
std::istream aStream(&aBuffer);
|
||||
|
||||
char aByte1, aByte2, aByte3, aByte4, aByte5, aByte6;
|
||||
aStream.read(&aByte1, 1);
|
||||
aStream.read(&aByte2, 1);
|
||||
aStream.read(&aByte3, 1);
|
||||
aStream.read(&aByte4, 1);
|
||||
aStream.read(&aByte5, 1);
|
||||
aStream.read(&aByte6, 1);
|
||||
|
||||
EXPECT_EQ(0x01, static_cast<unsigned char>(aByte1));
|
||||
EXPECT_EQ(0x02, static_cast<unsigned char>(aByte2));
|
||||
EXPECT_EQ(0x03, static_cast<unsigned char>(aByte3));
|
||||
EXPECT_EQ(0x00, static_cast<unsigned char>(aByte4));
|
||||
EXPECT_EQ(0x04, static_cast<unsigned char>(aByte5));
|
||||
EXPECT_EQ(0x05, static_cast<unsigned char>(aByte6));
|
||||
}
|
||||
|
||||
TEST(Standard_ArrayStreamBufferTest, LargeBuffer)
|
||||
{
|
||||
const size_t aLargeSize = 10000;
|
||||
std::string aLargeData(aLargeSize, 'X');
|
||||
|
||||
Standard_ArrayStreamBuffer aBuffer(aLargeData.c_str(), aLargeData.size());
|
||||
std::istream aStream(&aBuffer);
|
||||
|
||||
aStream.seekg(aLargeSize / 2);
|
||||
char aCh;
|
||||
aStream >> aCh;
|
||||
|
||||
EXPECT_EQ('X', aCh);
|
||||
EXPECT_EQ((aLargeSize / 2) + 1, static_cast<size_t>(aStream.tellg()));
|
||||
}
|
||||
|
||||
TEST(Standard_ArrayStreamBufferTest, MultipleReads)
|
||||
{
|
||||
const char* aTestData = "Line1\nLine2\nLine3";
|
||||
const size_t aDataSize = strlen(aTestData);
|
||||
|
||||
Standard_ArrayStreamBuffer aBuffer(aTestData, aDataSize);
|
||||
std::istream aStream(&aBuffer);
|
||||
|
||||
std::string aLine1, aLine2, aLine3;
|
||||
std::getline(aStream, aLine1);
|
||||
std::getline(aStream, aLine2);
|
||||
std::getline(aStream, aLine3);
|
||||
|
||||
EXPECT_EQ("Line1", aLine1);
|
||||
EXPECT_EQ("Line2", aLine2);
|
||||
EXPECT_EQ("Line3", aLine3);
|
||||
}
|
||||
|
||||
TEST(Standard_ArrayStreamBufferTest, SeekToSpecificPosition)
|
||||
{
|
||||
const char* aTestData = "0123456789";
|
||||
const size_t aDataSize = strlen(aTestData);
|
||||
|
||||
Standard_ArrayStreamBuffer aBuffer(aTestData, aDataSize);
|
||||
std::istream aStream(&aBuffer);
|
||||
|
||||
aStream.seekg(7);
|
||||
char aCh;
|
||||
aStream >> aCh;
|
||||
|
||||
EXPECT_EQ('7', aCh);
|
||||
EXPECT_EQ(8, aStream.tellg());
|
||||
}
|
||||
|
||||
TEST(Standard_ArrayStreamBufferTest, ReadAfterSeekToEnd)
|
||||
{
|
||||
const char* aTestData = "Hello";
|
||||
const size_t aDataSize = strlen(aTestData);
|
||||
|
||||
Standard_ArrayStreamBuffer aBuffer(aTestData, aDataSize);
|
||||
std::istream aStream(&aBuffer);
|
||||
|
||||
aStream.seekg(0, std::ios::end);
|
||||
|
||||
char aCh;
|
||||
aStream >> aCh;
|
||||
|
||||
EXPECT_TRUE(aStream.eof());
|
||||
}
|
||||
|
||||
TEST(Standard_ArrayStreamBufferTest, BackwardSeek)
|
||||
{
|
||||
const char* aTestData = "0123456789";
|
||||
const size_t aDataSize = strlen(aTestData);
|
||||
|
||||
Standard_ArrayStreamBuffer aBuffer(aTestData, aDataSize);
|
||||
std::istream aStream(&aBuffer);
|
||||
|
||||
aStream.seekg(0, std::ios::end);
|
||||
aStream.seekg(-5, std::ios::cur);
|
||||
|
||||
char aCh;
|
||||
aStream >> aCh;
|
||||
|
||||
EXPECT_EQ('5', aCh);
|
||||
}
|
||||
|
||||
TEST(Standard_ArrayStreamBufferTest, MultilineContent)
|
||||
{
|
||||
const char* aTestData = "First line\nSecond line\nThird line";
|
||||
const size_t aDataSize = strlen(aTestData);
|
||||
|
||||
Standard_ArrayStreamBuffer aBuffer(aTestData, aDataSize);
|
||||
std::istream aStream(&aBuffer);
|
||||
|
||||
std::string aContent;
|
||||
std::getline(aStream, aContent, '\0');
|
||||
|
||||
EXPECT_EQ("First line\nSecond line\nThird line", aContent);
|
||||
}
|
||||
|
||||
TEST(Standard_ArrayStreamBufferTest, ReadBlock)
|
||||
{
|
||||
const char* aTestData = "ABCDEFGHIJ";
|
||||
const size_t aDataSize = strlen(aTestData);
|
||||
|
||||
Standard_ArrayStreamBuffer aBuffer(aTestData, aDataSize);
|
||||
std::istream aStream(&aBuffer);
|
||||
|
||||
char aBlock[5];
|
||||
aStream.read(aBlock, 4);
|
||||
aBlock[4] = '\0';
|
||||
|
||||
EXPECT_EQ(std::string("ABCD"), std::string(aBlock));
|
||||
EXPECT_EQ(4, aStream.gcount());
|
||||
}
|
||||
|
||||
TEST(Standard_ArrayStreamBufferTest, AvailableCharacters)
|
||||
{
|
||||
const char* aTestData = "Testing";
|
||||
const size_t aDataSize = strlen(aTestData);
|
||||
|
||||
Standard_ArrayStreamBuffer aBuffer(aTestData, aDataSize);
|
||||
std::istream aStream(&aBuffer);
|
||||
|
||||
std::streamsize anAvailable = aBuffer.in_avail();
|
||||
EXPECT_EQ(static_cast<std::streamsize>(aDataSize), anAvailable);
|
||||
|
||||
char aCh;
|
||||
aStream >> aCh;
|
||||
|
||||
anAvailable = aBuffer.in_avail();
|
||||
EXPECT_EQ(static_cast<std::streamsize>(aDataSize - 1), anAvailable);
|
||||
}
|
@@ -50,6 +50,8 @@ set(OCCT_OSD_FILES
|
||||
OSD_LocalFileSystem.cxx
|
||||
OSD_LocalFileSystem.hxx
|
||||
OSD_LockType.hxx
|
||||
OSD_MAllocHook.cxx
|
||||
OSD_MAllocHook.hxx
|
||||
OSD_MemInfo.cxx
|
||||
OSD_MemInfo.hxx
|
||||
OSD_OEMType.hxx
|
||||
|
545
src/FoundationClasses/TKernel/OSD/OSD_MAllocHook.cxx
Normal file
545
src/FoundationClasses/TKernel/OSD/OSD_MAllocHook.cxx
Normal file
@@ -0,0 +1,545 @@
|
||||
// Created on: 2011-02-04
|
||||
// Created by: Mikhail SAZONOV
|
||||
// Copyright (c) 2011-2014 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <OSD_MAllocHook.hxx>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#if !defined __STDC_LIMIT_MACROS
|
||||
#define __STDC_LIMIT_MACROS
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
#define SIZE_MAX UINT_MAX
|
||||
#endif
|
||||
|
||||
#define MAX_STR 80
|
||||
|
||||
static OSD_MAllocHook::Callback* MypCurrentCallback = NULL;
|
||||
|
||||
namespace
|
||||
{
|
||||
// dummy function to call at place where break point might be needed
|
||||
static unsigned debug_counter = 0;
|
||||
|
||||
inline void place_for_breakpoint()
|
||||
{
|
||||
// this statement is just to have any instruction in object code,
|
||||
// otherwise compiler does not leave a place for break point
|
||||
debug_counter++;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
OSD_MAllocHook::Callback* OSD_MAllocHook::GetCallback()
|
||||
{
|
||||
return MypCurrentCallback;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
OSD_MAllocHook::LogFileHandler* OSD_MAllocHook::GetLogFileHandler()
|
||||
{
|
||||
static LogFileHandler MyHandler;
|
||||
return &MyHandler;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
OSD_MAllocHook::CollectBySize* OSD_MAllocHook::GetCollectBySize()
|
||||
{
|
||||
static CollectBySize MyHandler;
|
||||
return &MyHandler;
|
||||
}
|
||||
|
||||
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// Platform-dependent methods
|
||||
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <crtdbg.h>
|
||||
|
||||
#if _MSC_VER >= 1500 /* VS 2008 */
|
||||
|
||||
static long getRequestNum(void* pvData, long lRequest, size_t& theSize)
|
||||
{
|
||||
#ifdef _DEBUG /* protect against invalid pointer; in Release, _CrtIsValidHeapPointer is always \
|
||||
1 */
|
||||
if (!_CrtIsValidHeapPointer(pvData))
|
||||
return lRequest;
|
||||
#else
|
||||
(void)lRequest; // avoid compiler warning on unused arg
|
||||
#endif
|
||||
|
||||
#define nNoMansLandSize 4
|
||||
|
||||
// the header struct is taken from crt/src/dbgint.h
|
||||
struct _CrtMemBlockHeader
|
||||
{
|
||||
#ifdef _WIN64
|
||||
int nBlockUse;
|
||||
size_t nDataSize;
|
||||
#else
|
||||
size_t nDataSize;
|
||||
int nBlockUse;
|
||||
#endif
|
||||
long lRequest;
|
||||
unsigned char gap[nNoMansLandSize];
|
||||
};
|
||||
|
||||
_CrtMemBlockHeader* aHeader = ((_CrtMemBlockHeader*)pvData) - 1;
|
||||
theSize = aHeader->nDataSize;
|
||||
return aHeader->lRequest;
|
||||
}
|
||||
|
||||
#else /* _MSC_VER < 1500 */
|
||||
|
||||
static long getRequestNum(void* /*pvData*/, long lRequest, size_t& /*theSize*/)
|
||||
{
|
||||
return lRequest;
|
||||
}
|
||||
|
||||
#endif /* _MSC_VER == 1500 */
|
||||
|
||||
int __cdecl MyAllocHook(int nAllocType,
|
||||
void* pvData,
|
||||
size_t nSize,
|
||||
int nBlockUse,
|
||||
long lRequest,
|
||||
const unsigned char* /*szFileName*/,
|
||||
int /*nLine*/)
|
||||
{
|
||||
if (nBlockUse == _CRT_BLOCK || // Ignore internal C runtime library allocations
|
||||
MypCurrentCallback == NULL)
|
||||
return (1);
|
||||
|
||||
if (nAllocType == _HOOK_ALLOC)
|
||||
MypCurrentCallback->AllocEvent(nSize, lRequest);
|
||||
else if (nAllocType == _HOOK_FREE)
|
||||
{
|
||||
// for free hook, lRequest is not defined,
|
||||
// but we can take it from the CRT mem block header
|
||||
size_t aSize = 0;
|
||||
lRequest = getRequestNum(pvData, lRequest, aSize);
|
||||
MypCurrentCallback->FreeEvent(pvData, aSize, lRequest);
|
||||
}
|
||||
else // _HOOK_REALLOC
|
||||
{
|
||||
// for realloc hook, lRequest shows the new request,
|
||||
// and we should get request number for old block
|
||||
size_t anOldSize = 0;
|
||||
long anOldRequest = getRequestNum(pvData, 0, anOldSize);
|
||||
MypCurrentCallback->FreeEvent(pvData, anOldSize, anOldRequest);
|
||||
MypCurrentCallback->AllocEvent(nSize, lRequest);
|
||||
}
|
||||
|
||||
return (1); // Allow the memory operation to proceed
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void OSD_MAllocHook::SetCallback(Callback* theCB)
|
||||
{
|
||||
MypCurrentCallback = theCB;
|
||||
if (theCB == NULL)
|
||||
_CrtSetAllocHook(NULL);
|
||||
else
|
||||
_CrtSetAllocHook(MyAllocHook);
|
||||
}
|
||||
|
||||
#else // ! _MSC_VER
|
||||
|
||||
// Not yet implemented for non-WNT platform
|
||||
|
||||
void OSD_MAllocHook::SetCallback(Callback* theCB)
|
||||
{
|
||||
MypCurrentCallback = theCB;
|
||||
}
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// LogFileHandler handler methods
|
||||
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
OSD_MAllocHook::LogFileHandler::LogFileHandler()
|
||||
: myBreakSize(0)
|
||||
{
|
||||
myLogFile.imbue(std::locale("C"));
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
OSD_MAllocHook::LogFileHandler::~LogFileHandler()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
Standard_Boolean OSD_MAllocHook::LogFileHandler::Open(const char* theFileName)
|
||||
{
|
||||
Close();
|
||||
myLogFile.open(theFileName);
|
||||
if (!myLogFile.is_open())
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
myLogFile << "Operation type; Request Number; Block Size\n"
|
||||
"------------------------------------------\n";
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void OSD_MAllocHook::LogFileHandler::Close()
|
||||
{
|
||||
if (myLogFile.is_open())
|
||||
{
|
||||
myLogFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
namespace
|
||||
{
|
||||
struct StorageInfo
|
||||
{
|
||||
Standard_Size size;
|
||||
Standard_Integer nbAlloc;
|
||||
Standard_Integer nbFree;
|
||||
Standard_Integer nbLeftPeak;
|
||||
std::set<unsigned long> alive;
|
||||
|
||||
StorageInfo(Standard_Size theSize = 0)
|
||||
: size(theSize),
|
||||
nbAlloc(0),
|
||||
nbFree(0),
|
||||
nbLeftPeak(0),
|
||||
alive()
|
||||
{
|
||||
}
|
||||
|
||||
bool operator<(const StorageInfo& theOther) const { return size < theOther.size; }
|
||||
};
|
||||
} // namespace
|
||||
|
||||
Standard_Boolean OSD_MAllocHook::LogFileHandler::MakeReport(const char* theLogFile,
|
||||
const char* theOutFile,
|
||||
const Standard_Boolean theIncludeAlive)
|
||||
{
|
||||
// open log file
|
||||
FILE* aLogFile = fopen(theLogFile, "r");
|
||||
if (aLogFile == NULL)
|
||||
return Standard_False;
|
||||
|
||||
// skip 2 header lines
|
||||
char aStr[MAX_STR];
|
||||
if (fgets(aStr, MAX_STR - 1, aLogFile) == NULL)
|
||||
{
|
||||
fclose(aLogFile);
|
||||
return Standard_False;
|
||||
}
|
||||
if (fgets(aStr, MAX_STR - 1, aLogFile) == NULL)
|
||||
{
|
||||
fclose(aLogFile);
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
// scan the log file
|
||||
size_t aTotalLeftSize = 0;
|
||||
size_t aTotalPeakSize = 0;
|
||||
std::set<StorageInfo> aStMap;
|
||||
while (fgets(aStr, MAX_STR - 1, aLogFile) != NULL)
|
||||
{
|
||||
// detect operation type, request number and block size
|
||||
unsigned long aReqNum, aSize;
|
||||
char* aType = aStr;
|
||||
char* pStr = aStr;
|
||||
// sscanf(aStr, "%5s %lu %lu", aType, &aReqNum, &aSize);
|
||||
while (*pStr != ' ' && *pStr)
|
||||
pStr++;
|
||||
*pStr++ = '\0';
|
||||
while (*pStr == ' ' && *pStr)
|
||||
pStr++;
|
||||
aReqNum = atol(pStr);
|
||||
while (*pStr != ' ' && *pStr)
|
||||
pStr++;
|
||||
while (*pStr == ' ' && *pStr)
|
||||
pStr++;
|
||||
aSize = atol(pStr);
|
||||
Standard_Boolean isAlloc = Standard_False;
|
||||
if (strcmp(aType, "alloc") == 0)
|
||||
{
|
||||
isAlloc = Standard_True;
|
||||
}
|
||||
else if (strcmp(aType, "free") != 0)
|
||||
continue;
|
||||
|
||||
// collect statistics by storage size
|
||||
StorageInfo aSuchInfo(aSize);
|
||||
std::set<StorageInfo>::iterator aFound = aStMap.find(aSuchInfo);
|
||||
if (aFound == aStMap.end())
|
||||
aFound = aStMap.insert(aSuchInfo).first;
|
||||
StorageInfo& aInfo = const_cast<StorageInfo&>(*aFound);
|
||||
if (isAlloc)
|
||||
{
|
||||
if (aInfo.nbAlloc + 1 > 0)
|
||||
aInfo.nbAlloc++;
|
||||
aTotalLeftSize += aSize;
|
||||
if (aTotalLeftSize > aTotalPeakSize)
|
||||
aTotalPeakSize = aTotalLeftSize;
|
||||
int nbLeft = aInfo.nbAlloc - aInfo.nbFree;
|
||||
if (nbLeft > aInfo.nbLeftPeak)
|
||||
aInfo.nbLeftPeak = nbLeft;
|
||||
aInfo.alive.insert(aReqNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::set<unsigned long>::iterator aFoundReqNum = aInfo.alive.find(aReqNum);
|
||||
if (aFoundReqNum == aInfo.alive.end())
|
||||
// freeing non-registered block, skip it
|
||||
continue;
|
||||
aTotalLeftSize -= aSize;
|
||||
aInfo.alive.erase(aFoundReqNum);
|
||||
if (aInfo.nbAlloc + 1 > 0)
|
||||
aInfo.nbFree++;
|
||||
}
|
||||
}
|
||||
fclose(aLogFile);
|
||||
|
||||
// print the report
|
||||
std::ofstream aRepFile(theOutFile);
|
||||
if (!aRepFile.is_open())
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
aRepFile.imbue(std::locale("C"));
|
||||
|
||||
aRepFile << std::setw(20) << "BlockSize " << std::setw(10) << "NbAlloc " << std::setw(10)
|
||||
<< "NbLeft " << std::setw(10) << "NbLeftPeak " << std::setw(20) << "AllocSize "
|
||||
<< std::setw(20) << "LeftSize " << std::setw(20) << "PeakSize " << std::endl;
|
||||
|
||||
Standard_Size aTotAlloc = 0;
|
||||
for (std::set<StorageInfo>::const_iterator it = aStMap.begin(); it != aStMap.end(); ++it)
|
||||
{
|
||||
const StorageInfo& aInfo = *it;
|
||||
Standard_Integer nbLeft = aInfo.nbAlloc - aInfo.nbFree;
|
||||
Standard_Size aSizeAlloc = aInfo.nbAlloc * aInfo.size;
|
||||
Standard_Size aSizeLeft = nbLeft * aInfo.size;
|
||||
Standard_Size aSizePeak = aInfo.nbLeftPeak * aInfo.size;
|
||||
|
||||
aRepFile << std::setw(20) << aInfo.size << ' ' << std::setw(10) << aInfo.nbAlloc << ' '
|
||||
<< std::setw(10) << nbLeft << ' ' << std::setw(10) << aInfo.nbLeftPeak << ' '
|
||||
<< std::setw(20) << aSizeAlloc << ' ' << std::setw(20) << aSizeLeft << ' '
|
||||
<< std::setw(20) << aSizePeak << std::endl;
|
||||
|
||||
if (aTotAlloc + aSizeAlloc < aTotAlloc) // overflow ?
|
||||
aTotAlloc = SIZE_MAX;
|
||||
else
|
||||
aTotAlloc += aSizeAlloc;
|
||||
if (theIncludeAlive && !aInfo.alive.empty())
|
||||
{
|
||||
for (std::set<unsigned long>::const_iterator it1 = aInfo.alive.begin();
|
||||
it1 != aInfo.alive.end();
|
||||
++it1)
|
||||
aRepFile << std::setw(10) << *it1;
|
||||
}
|
||||
}
|
||||
aRepFile << std::setw(20) << "Total:" << std::setw(10) << "" << ' ' << std::setw(10) << "" << ' '
|
||||
<< std::setw(10) << "" << ' ' << (aTotAlloc == SIZE_MAX ? '>' : ' ') << std::setw(20)
|
||||
<< aTotAlloc << ' ' << std::setw(20) << aTotalLeftSize << ' ' << std::setw(20)
|
||||
<< aTotalPeakSize << std::endl;
|
||||
|
||||
aRepFile.close();
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void OSD_MAllocHook::LogFileHandler::AllocEvent(size_t theSize, long theRequestNum)
|
||||
{
|
||||
if (myLogFile.is_open())
|
||||
{
|
||||
myMutex.Lock();
|
||||
myLogFile << "alloc " << std::setw(10) << theRequestNum << std::setw(20) << theSize
|
||||
<< std::endl;
|
||||
if (myBreakSize == theSize)
|
||||
place_for_breakpoint();
|
||||
myMutex.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void OSD_MAllocHook::LogFileHandler::FreeEvent(void* /*theData*/,
|
||||
size_t theSize,
|
||||
long theRequestNum)
|
||||
{
|
||||
if (myLogFile.is_open())
|
||||
{
|
||||
myMutex.Lock();
|
||||
myLogFile << "free " << std::setw(20) << theRequestNum << std::setw(20) << theSize << std::endl;
|
||||
myMutex.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// CollectBySize handler methods
|
||||
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
OSD_MAllocHook::CollectBySize::CollectBySize()
|
||||
: myArray(NULL),
|
||||
myTotalLeftSize(0),
|
||||
myTotalPeakSize(0),
|
||||
myBreakSize(0),
|
||||
myBreakPeak(0)
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
OSD_MAllocHook::CollectBySize::~CollectBySize()
|
||||
{
|
||||
if (myArray != NULL)
|
||||
delete[] myArray;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
#define MAX_ALLOC_SIZE 2000000
|
||||
const size_t OSD_MAllocHook::CollectBySize::myMaxAllocSize = MAX_ALLOC_SIZE;
|
||||
|
||||
void OSD_MAllocHook::CollectBySize::Reset()
|
||||
{
|
||||
myMutex.Lock();
|
||||
if (myArray == NULL)
|
||||
myArray = new Numbers[MAX_ALLOC_SIZE];
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < MAX_ALLOC_SIZE; i++)
|
||||
myArray[i] = Numbers();
|
||||
}
|
||||
myTotalLeftSize = 0;
|
||||
myTotalPeakSize = 0;
|
||||
myMutex.Unlock();
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
Standard_Boolean OSD_MAllocHook::CollectBySize::MakeReport(const char* theOutFile)
|
||||
{
|
||||
// print the report
|
||||
std::ofstream aRepFile(theOutFile);
|
||||
if (!aRepFile.is_open())
|
||||
return Standard_False;
|
||||
std::locale aCLoc("C");
|
||||
aRepFile.imbue(aCLoc);
|
||||
|
||||
aRepFile << std::setw(10) << "BlockSize " << std::setw(10) << "NbAlloc " << std::setw(10)
|
||||
<< "NbLeft " << std::setw(10) << "NbLeftPeak " << std::setw(20) << "AllocSize "
|
||||
<< std::setw(20) << "LeftSize " << std::setw(20) << "PeakSize " << std::endl;
|
||||
|
||||
Standard_Size aTotAlloc = 0;
|
||||
for (int i = 0; i < MAX_ALLOC_SIZE; i++)
|
||||
{
|
||||
if (myArray[i].nbAlloc > 0 || myArray[i].nbFree > 0)
|
||||
{
|
||||
Standard_Integer nbLeft = myArray[i].nbAlloc - myArray[i].nbFree;
|
||||
int aSize = i + 1;
|
||||
Standard_Size aSizeAlloc = myArray[i].nbAlloc * aSize;
|
||||
ptrdiff_t aSizeLeft = nbLeft * aSize;
|
||||
Standard_Size aSizePeak = myArray[i].nbLeftPeak * aSize;
|
||||
|
||||
aRepFile << std::setw(10) << aSize << ' ' << std::setw(10) << myArray[i].nbAlloc << ' '
|
||||
<< std::setw(10) << nbLeft << ' ' << std::setw(10) << myArray[i].nbLeftPeak << ' '
|
||||
<< std::setw(20) << aSizeAlloc << ' ' << std::setw(20) << aSizeLeft << ' '
|
||||
<< std::setw(20) << aSizePeak << std::endl;
|
||||
|
||||
if (aTotAlloc + aSizeAlloc < aTotAlloc) // overflow ?
|
||||
aTotAlloc = SIZE_MAX;
|
||||
else
|
||||
aTotAlloc += aSizeAlloc;
|
||||
}
|
||||
}
|
||||
aRepFile << std::setw(10) << "Total:" << ' ' << std::setw(10) << "" << ' ' << std::setw(10) << ""
|
||||
<< ' ' << std::setw(10) << "" << ' ' << (aTotAlloc == SIZE_MAX ? '>' : ' ')
|
||||
<< std::setw(20) << aTotAlloc << ' ' << std::setw(20) << myTotalLeftSize << ' '
|
||||
<< std::setw(20) << myTotalPeakSize << std::endl;
|
||||
aRepFile.close();
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void OSD_MAllocHook::CollectBySize::AllocEvent(size_t theSize, long /*theRequestNum*/)
|
||||
{
|
||||
if (myBreakSize == theSize)
|
||||
place_for_breakpoint();
|
||||
if (theSize > 0)
|
||||
{
|
||||
myMutex.Lock();
|
||||
int ind = (theSize > MAX_ALLOC_SIZE ? MAX_ALLOC_SIZE - 1 : (int)(theSize - 1));
|
||||
myArray[ind].nbAlloc++;
|
||||
myTotalLeftSize += theSize;
|
||||
int nbLeft = myArray[ind].nbAlloc - myArray[ind].nbFree;
|
||||
if (nbLeft > myArray[ind].nbLeftPeak)
|
||||
{
|
||||
myArray[ind].nbLeftPeak = nbLeft;
|
||||
if (myBreakPeak != 0 && (myBreakSize == theSize || myBreakSize == 0))
|
||||
{
|
||||
const Standard_Size aSizePeak = myArray[ind].nbLeftPeak * theSize;
|
||||
if (aSizePeak > myBreakPeak)
|
||||
{
|
||||
place_for_breakpoint();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (myTotalLeftSize > (ptrdiff_t)myTotalPeakSize)
|
||||
myTotalPeakSize = myTotalLeftSize;
|
||||
myMutex.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void OSD_MAllocHook::CollectBySize::FreeEvent(void* /*theData*/,
|
||||
size_t theSize,
|
||||
long /*theRequestNum*/)
|
||||
{
|
||||
if (theSize > 0)
|
||||
{
|
||||
myMutex.Lock();
|
||||
int ind = (theSize > MAX_ALLOC_SIZE ? MAX_ALLOC_SIZE - 1 : (int)(theSize - 1));
|
||||
myArray[ind].nbFree++;
|
||||
myTotalLeftSize -= theSize;
|
||||
myMutex.Unlock();
|
||||
}
|
||||
}
|
170
src/FoundationClasses/TKernel/OSD/OSD_MAllocHook.hxx
Normal file
170
src/FoundationClasses/TKernel/OSD/OSD_MAllocHook.hxx
Normal file
@@ -0,0 +1,170 @@
|
||||
// Created on: 2011-02-03
|
||||
// Created by: Mikhail SAZONOV
|
||||
// Copyright (c) 2011-2014 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _OSD_MAllocHook_HeaderFile
|
||||
#define _OSD_MAllocHook_HeaderFile
|
||||
|
||||
#include <Standard_Mutex.hxx>
|
||||
#include <fstream>
|
||||
|
||||
/**
|
||||
* This class provides the possibility to set callback for memory
|
||||
* allocation/deallocation.
|
||||
* On MS Windows, it works only in Debug builds. It relies on the
|
||||
* debug CRT function _CrtSetAllocHook (see MSDN for help).
|
||||
*/
|
||||
class OSD_MAllocHook
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Interface of a class that should handle allocation/deallocation events
|
||||
*/
|
||||
class Callback
|
||||
{
|
||||
public:
|
||||
//! Allocation event handler
|
||||
/**
|
||||
* It is called when allocation is done
|
||||
* @param theSize
|
||||
* the size of the memory block in bytes
|
||||
* @param theRequestNum
|
||||
* the allocation order number of the memory block
|
||||
*/
|
||||
virtual void AllocEvent(size_t theSize, long theRequestNum) = 0;
|
||||
|
||||
//! Freeing event handler
|
||||
/**
|
||||
* It is called when the block is freed
|
||||
* @param theData
|
||||
* the pointer to the user data section of the memory block
|
||||
* @param theSize
|
||||
* the size of the memory block in bytes
|
||||
* @param theRequestNum
|
||||
* the allocation order number of the memory block
|
||||
*/
|
||||
virtual void FreeEvent(void* theData, size_t theSize, long theRequestNum) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of the handler that collects all events
|
||||
* to the log file. It contains the method to generate the report
|
||||
* from the log file.
|
||||
*/
|
||||
class LogFileHandler : public Callback
|
||||
{
|
||||
public:
|
||||
//! Constructor
|
||||
Standard_EXPORT LogFileHandler();
|
||||
|
||||
//! Destructor
|
||||
Standard_EXPORT ~LogFileHandler();
|
||||
|
||||
//! Create the file and start collecting events.
|
||||
//! Return false if the file with the given name cannot be created.
|
||||
Standard_EXPORT Standard_Boolean Open(const char* theFileName);
|
||||
|
||||
//! Close the file and stop collecting events
|
||||
Standard_EXPORT void Close();
|
||||
|
||||
//! Make synthesized report on the given log file.
|
||||
/**
|
||||
* Generate an easy to use report in the
|
||||
* new file with the given name, taking the given log file as input.
|
||||
* If theIncludeAlive is true then
|
||||
* include into the report the alive allocation numbers.
|
||||
*/
|
||||
Standard_EXPORT static Standard_Boolean MakeReport(
|
||||
const char* theLogFile,
|
||||
const char* theOutFile,
|
||||
const Standard_Boolean theIncludeAlive = Standard_False);
|
||||
|
||||
Standard_EXPORT virtual void AllocEvent(size_t, long);
|
||||
Standard_EXPORT virtual void FreeEvent(void*, size_t, long);
|
||||
|
||||
private:
|
||||
std::ofstream myLogFile;
|
||||
Standard_Mutex myMutex;
|
||||
size_t myBreakSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of the handler that collects numbers of
|
||||
* allocations/deallocations for each block size directly in the memory.
|
||||
*/
|
||||
class CollectBySize : public Callback
|
||||
{
|
||||
public:
|
||||
//! Constructor
|
||||
Standard_EXPORT CollectBySize();
|
||||
|
||||
//! Destructor
|
||||
Standard_EXPORT ~CollectBySize();
|
||||
|
||||
//! Reset the buffer and start collecting events.
|
||||
Standard_EXPORT void Reset();
|
||||
|
||||
//! Write report in the given file.
|
||||
Standard_EXPORT Standard_Boolean MakeReport(const char* theOutFile);
|
||||
|
||||
Standard_EXPORT virtual void AllocEvent(size_t, long);
|
||||
Standard_EXPORT virtual void FreeEvent(void*, size_t, long);
|
||||
|
||||
public:
|
||||
struct Numbers
|
||||
{
|
||||
int nbAlloc;
|
||||
int nbFree;
|
||||
int nbLeftPeak;
|
||||
|
||||
Numbers()
|
||||
: nbAlloc(0),
|
||||
nbFree(0),
|
||||
nbLeftPeak(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static const size_t myMaxAllocSize; //!< maximum tracked size
|
||||
|
||||
Standard_Mutex myMutex; //!< used for thread-safe access
|
||||
Numbers* myArray; //!< indexed from 0 to myMaxAllocSize-1
|
||||
ptrdiff_t myTotalLeftSize; //!< currently remained allocated size
|
||||
size_t myTotalPeakSize; //!< maximum cumulative allocated size
|
||||
// clang-format off
|
||||
size_t myBreakSize; //!< user defined allocation size to debug (see place_for_breakpoint())
|
||||
// clang-format on
|
||||
size_t myBreakPeak; //!< user defined peak size limit to debug
|
||||
};
|
||||
|
||||
//! Set handler of allocation/deallocation events
|
||||
/**
|
||||
* You can pass here any implementation. For easy start, you can try
|
||||
* with the predefined handler LogFileHandler, which static instance
|
||||
* is returned by GetLogFileHandler().
|
||||
* To clear the handler, pass NULL here.
|
||||
*/
|
||||
Standard_EXPORT static void SetCallback(Callback* theCB);
|
||||
|
||||
//! Get current handler of allocation/deallocation events
|
||||
Standard_EXPORT static Callback* GetCallback();
|
||||
|
||||
//! Get static instance of LogFileHandler handler
|
||||
Standard_EXPORT static LogFileHandler* GetLogFileHandler();
|
||||
|
||||
//! Get static instance of CollectBySize handler
|
||||
Standard_EXPORT static CollectBySize* GetCollectBySize();
|
||||
};
|
||||
|
||||
#endif /* _OSD_MAllocHook_HeaderFile */
|
@@ -1687,12 +1687,6 @@ Standard_Boolean ShapeFix_Face::FixMissingSeam()
|
||||
Handle(Geom_ToroidalSurface) aTorSurf = Handle(Geom_ToroidalSurface)::DownCast(mySurf->Surface());
|
||||
Standard_Boolean anIsDegeneratedTor =
|
||||
(aTorSurf.IsNull() ? Standard_False : aTorSurf->MajorRadius() < aTorSurf->MinorRadius());
|
||||
// if the second wire is not null, we don't need mark the torus as degenerated
|
||||
// and should process it as a regular one.
|
||||
if (anIsDegeneratedTor && !w2.IsNull())
|
||||
{
|
||||
anIsDegeneratedTor = Standard_False;
|
||||
}
|
||||
|
||||
if (w1.IsNull())
|
||||
return Standard_False;
|
||||
|
@@ -2,5 +2,4 @@
|
||||
set(OCCT_TKGeomBase_GTests_FILES_LOCATION "${CMAKE_CURRENT_LIST_DIR}")
|
||||
|
||||
set(OCCT_TKGeomBase_GTests_FILES
|
||||
IntAna_IntQuadQuad_Test.cxx
|
||||
)
|
||||
|
@@ -1,206 +0,0 @@
|
||||
// Copyright (c) 2025 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <IntAna_IntQuadQuad.hxx>
|
||||
#include <IntAna_Quadric.hxx>
|
||||
#include <gp_Sphere.hxx>
|
||||
#include <gp_Cylinder.hxx>
|
||||
#include <gp_Cone.hxx>
|
||||
#include <gp_Pln.hxx>
|
||||
#include <gp_Ax3.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
class IntAna_IntQuadQuad_Test : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
// Set up common geometric objects for tests
|
||||
gp_Pnt anOrigin(0, 0, 0);
|
||||
gp_Dir aZDir(0, 0, 1);
|
||||
gp_Dir anXDir(1, 0, 0);
|
||||
gp_Ax3 anAxis(anOrigin, aZDir, anXDir);
|
||||
|
||||
// Create sphere at origin with radius 5
|
||||
mySphere1 = gp_Sphere(anAxis, 5.0);
|
||||
|
||||
// Create cylinder with axis along Z, radius 3
|
||||
myCylinder1 = gp_Cylinder(anAxis, 3.0);
|
||||
|
||||
// Create cone with semi-angle 30 degrees
|
||||
myCone1 = gp_Cone(anAxis, M_PI / 6, 2.0);
|
||||
|
||||
// Create plane at Z = 2
|
||||
gp_Pnt aPlaneOrigin(0, 0, 2);
|
||||
myPlane1 = gp_Pln(aPlaneOrigin, aZDir);
|
||||
}
|
||||
|
||||
gp_Sphere mySphere1;
|
||||
gp_Cylinder myCylinder1;
|
||||
gp_Cone myCone1;
|
||||
gp_Pln myPlane1;
|
||||
};
|
||||
|
||||
// Test basic intersection functionality - Cylinder vs Quadric (sphere)
|
||||
TEST_F(IntAna_IntQuadQuad_Test, CylinderVsSphereIntersection)
|
||||
{
|
||||
IntAna_Quadric aSphereQuad(mySphere1);
|
||||
|
||||
IntAna_IntQuadQuad anIntersector(myCylinder1, aSphereQuad, 1e-7);
|
||||
|
||||
// Should have intersection curves
|
||||
EXPECT_TRUE(anIntersector.IsDone());
|
||||
EXPECT_FALSE(anIntersector.IdenticalElements());
|
||||
|
||||
// Should have intersection curves for cylinder-sphere case
|
||||
EXPECT_GT(anIntersector.NbCurve(), 0);
|
||||
|
||||
// Test that we can access all curves without exceptions
|
||||
for (Standard_Integer i = 1; i <= anIntersector.NbCurve(); i++)
|
||||
{
|
||||
// This should not throw any exceptions - just verify we can access the curve
|
||||
EXPECT_NO_THROW(anIntersector.Curve(i));
|
||||
}
|
||||
}
|
||||
|
||||
// Test NextCurve functionality - the main test for our bug fix
|
||||
TEST_F(IntAna_IntQuadQuad_Test, NextCurveMethodCorrectness)
|
||||
{
|
||||
IntAna_Quadric aSphereQuad(mySphere1);
|
||||
|
||||
IntAna_IntQuadQuad anIntersector(myCylinder1, aSphereQuad, 1e-7);
|
||||
|
||||
EXPECT_TRUE(anIntersector.IsDone());
|
||||
|
||||
// Test HasNextCurve and NextCurve for valid indices
|
||||
for (Standard_Integer i = 1; i <= anIntersector.NbCurve(); i++)
|
||||
{
|
||||
// These methods should not crash and should return consistent results
|
||||
Standard_Boolean aHasNext = anIntersector.HasNextCurve(i);
|
||||
|
||||
if (aHasNext) // Only test NextCurve when HasNextCurve is true
|
||||
{
|
||||
Standard_Boolean anOpposite;
|
||||
Standard_Integer aNextIdx = anIntersector.NextCurve(i, anOpposite);
|
||||
|
||||
// Next curve index should be valid
|
||||
EXPECT_GT(aNextIdx, 0);
|
||||
EXPECT_LE(aNextIdx, anIntersector.NbCurve());
|
||||
EXPECT_NE(aNextIdx, i); // Should not point to itself
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test edge cases and boundary conditions
|
||||
TEST_F(IntAna_IntQuadQuad_Test, NextCurveBoundaryConditions)
|
||||
{
|
||||
IntAna_Quadric aSphereQuad(mySphere1);
|
||||
|
||||
IntAna_IntQuadQuad anIntersector(myCylinder1, aSphereQuad, 1e-7);
|
||||
|
||||
EXPECT_TRUE(anIntersector.IsDone());
|
||||
|
||||
// Test with invalid indices (should throw exceptions)
|
||||
EXPECT_THROW(anIntersector.HasNextCurve(0), Standard_OutOfRange);
|
||||
EXPECT_THROW(anIntersector.HasNextCurve(anIntersector.NbCurve() + 1), Standard_OutOfRange);
|
||||
|
||||
// Test NextCurve on curves that don't have next curves
|
||||
for (Standard_Integer i = 1; i <= anIntersector.NbCurve(); i++)
|
||||
{
|
||||
if (!anIntersector.HasNextCurve(i)) // Only test exception when HasNextCurve is false
|
||||
{
|
||||
Standard_Boolean anOpposite;
|
||||
EXPECT_THROW(anIntersector.NextCurve(i, anOpposite), Standard_DomainError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test specific geometric configuration that creates connected curves
|
||||
TEST_F(IntAna_IntQuadQuad_Test, ConnectedCurvesScenario)
|
||||
{
|
||||
// Create two spheres that intersect in a circle
|
||||
gp_Pnt aCenter1(0, 0, 0);
|
||||
gp_Pnt aCenter2(3, 0, 0); // Overlapping spheres
|
||||
gp_Dir aZDir(0, 0, 1);
|
||||
gp_Dir anXDir(1, 0, 0);
|
||||
gp_Ax3 anAxis1(aCenter1, aZDir, anXDir);
|
||||
gp_Ax3 anAxis2(aCenter2, aZDir, anXDir);
|
||||
|
||||
gp_Sphere aSphere1(anAxis1, 2.0);
|
||||
gp_Sphere aSphere2(anAxis2, 2.0);
|
||||
|
||||
IntAna_Quadric aSphere2Quad(aSphere2);
|
||||
|
||||
IntAna_IntQuadQuad anIntersector;
|
||||
anIntersector.Perform(gp_Cylinder(anAxis1, 2.0), aSphere2Quad, 1e-7);
|
||||
|
||||
EXPECT_TRUE(anIntersector.IsDone());
|
||||
|
||||
EXPECT_FALSE(anIntersector.IdenticalElements());
|
||||
|
||||
// Verify that NextCurve method works correctly for each curve
|
||||
for (Standard_Integer i = 1; i <= anIntersector.NbCurve(); i++)
|
||||
{
|
||||
if (anIntersector.HasNextCurve(i)) // Only test NextCurve when HasNextCurve is true
|
||||
{
|
||||
Standard_Boolean anOpposite;
|
||||
Standard_Integer aNextIdx = anIntersector.NextCurve(i, anOpposite);
|
||||
|
||||
// Validate the result
|
||||
EXPECT_GT(aNextIdx, 0);
|
||||
EXPECT_LE(aNextIdx, anIntersector.NbCurve());
|
||||
|
||||
// Test consistency: if curve i connects to j, then j should connect back
|
||||
// (though possibly with different opposite flag)
|
||||
if (anIntersector.HasNextCurve(aNextIdx))
|
||||
{
|
||||
Standard_Boolean aReverseOpposite;
|
||||
Standard_Integer aReverseNext = anIntersector.NextCurve(aNextIdx, aReverseOpposite);
|
||||
// This creates a circular reference which is geometrically possible
|
||||
EXPECT_GT(aReverseNext, 0);
|
||||
EXPECT_LE(aReverseNext, anIntersector.NbCurve());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test the fix specifically - ensure we don't access out-of-bounds memory
|
||||
TEST_F(IntAna_IntQuadQuad_Test, IndexingConsistencyTest)
|
||||
{
|
||||
// This test specifically validates that HasNextCurve and NextCurve
|
||||
// use consistent indexing (both should use I-1 for 0-based arrays)
|
||||
|
||||
IntAna_Quadric aSphereQuad(mySphere1); // Cylinder vs sphere intersection
|
||||
|
||||
IntAna_IntQuadQuad anIntersector(myCylinder1, aSphereQuad, 1e-7);
|
||||
|
||||
EXPECT_TRUE(anIntersector.IsDone());
|
||||
|
||||
// Test all valid curve indices
|
||||
for (Standard_Integer i = 1; i <= anIntersector.NbCurve(); i++)
|
||||
{
|
||||
// These calls should be consistent and not crash
|
||||
Standard_Boolean aHasNext = anIntersector.HasNextCurve(i);
|
||||
|
||||
if (aHasNext) // Only test NextCurve when HasNextCurve is true
|
||||
{
|
||||
Standard_Boolean anOpposite;
|
||||
// This should not crash or return invalid values
|
||||
Standard_Integer aNextIdx = anIntersector.NextCurve(i, anOpposite);
|
||||
|
||||
EXPECT_GT(aNextIdx, 0);
|
||||
EXPECT_LE(aNextIdx, anIntersector.NbCurve());
|
||||
}
|
||||
}
|
||||
}
|
@@ -1576,8 +1576,16 @@ Standard_Integer IntAna_IntQuadQuad::NextCurve(const Standard_Integer I,
|
||||
{
|
||||
if (HasNextCurve(I))
|
||||
{
|
||||
theOpposite = nextcurve[I - 1] < 0;
|
||||
return Abs(nextcurve[I - 1]);
|
||||
if (nextcurve[I] > 0)
|
||||
{
|
||||
theOpposite = Standard_False;
|
||||
return (nextcurve[I - 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
theOpposite = Standard_True;
|
||||
return (-nextcurve[I - 1]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -44,6 +44,7 @@
|
||||
#include <Message.hxx>
|
||||
#include <Message_Messenger.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Standard_ArrayStreamBuffer.hxx>
|
||||
#include <TCollection_AsciiString.hxx>
|
||||
#include <TCollection_ExtendedString.hxx>
|
||||
#include <OSD_OpenFile.hxx>
|
||||
|
@@ -1788,17 +1788,8 @@ void AIS_ViewController::handleViewRotation(const Handle(V3d_View)& theView,
|
||||
}
|
||||
if (myGL.ViewRotation.ToStart)
|
||||
{
|
||||
|
||||
gp_Dir aCamDirection = aCam->Direction();
|
||||
if (aCam->OrthogonalizedUp().IsParallel (gp::DY(), Precision::Angular()))
|
||||
{
|
||||
aCamDirection = aCamDirection.Dot (gp::DZ()) > 0
|
||||
? gp::DZ()
|
||||
: gp::DZ().Reversed();
|
||||
}
|
||||
|
||||
gp_Trsf aTrsf;
|
||||
aTrsf.SetTransformation(gp_Ax3(gp::Origin(), aCam->OrthogonalizedUp(), aCamDirection),
|
||||
aTrsf.SetTransformation(gp_Ax3(gp::Origin(), aCam->OrthogonalizedUp(), aCam->Direction()),
|
||||
gp_Ax3(gp::Origin(), gp::DZ(), gp::DX()));
|
||||
const gp_Quaternion aRot = aTrsf.GetRotation();
|
||||
double aRollDummy = 0.0;
|
||||
@@ -1806,12 +1797,6 @@ void AIS_ViewController::handleViewRotation(const Handle(V3d_View)& theView,
|
||||
myRotateStartYawPitchRoll[0],
|
||||
myRotateStartYawPitchRoll[1],
|
||||
aRollDummy);
|
||||
if (aCamDirection.IsParallel (gp::DZ(), Precision::Angular()))
|
||||
{
|
||||
myRotateStartYawPitchRoll[0] = aCamDirection.IsEqual (gp::DZ(), Precision::Angular())
|
||||
? aRollDummy
|
||||
: -aRollDummy;
|
||||
}
|
||||
}
|
||||
if (toRotateAnyway)
|
||||
{
|
||||
|
@@ -993,7 +993,7 @@ public:
|
||||
const Graphic3d_BufferType& theBufferType = Graphic3d_BT_RGB,
|
||||
const Standard_Boolean theToAdjustAspect = Standard_True,
|
||||
const Graphic3d_ZLayerId theTargetZLayerId = Graphic3d_ZLayerId_BotOSD,
|
||||
const Standard_Boolean theIsSingleLayer = Standard_False,
|
||||
const Standard_Integer theIsSingleLayer = Standard_False,
|
||||
const V3d_StereoDumpOptions theStereoOptions = V3d_SDO_MONO,
|
||||
const Standard_CString theLightName = "")
|
||||
{
|
||||
|
11
tests/bugs/fclasses/bug23569_1
Executable file
11
tests/bugs/fclasses/bug23569_1
Executable file
@@ -0,0 +1,11 @@
|
||||
puts "======="
|
||||
puts "OCC23569"
|
||||
puts "======="
|
||||
puts ""
|
||||
###########################################################################
|
||||
## Adding NCollection_StdAllocator
|
||||
###########################################################################
|
||||
|
||||
pload QAcommands
|
||||
|
||||
QANColStdAllocator1
|
11
tests/bugs/fclasses/bug23569_2
Executable file
11
tests/bugs/fclasses/bug23569_2
Executable file
@@ -0,0 +1,11 @@
|
||||
puts "======="
|
||||
puts "OCC23569"
|
||||
puts "======="
|
||||
puts ""
|
||||
###########################################################################
|
||||
## Adding NCollection_StdAllocator
|
||||
###########################################################################
|
||||
|
||||
pload QAcommands
|
||||
|
||||
QANColStdAllocator2
|
5
tests/bugs/fclasses/bug24831
Normal file
5
tests/bugs/fclasses/bug24831
Normal file
@@ -0,0 +1,5 @@
|
||||
puts "TODO ?CR33225 Windows: Failed class "
|
||||
|
||||
pload QAcommands
|
||||
|
||||
QANTestStlIterators
|
@@ -1,8 +0,0 @@
|
||||
puts "================================================"
|
||||
puts "Revolved shape in STEP file is imported inverted"
|
||||
puts "================================================"
|
||||
puts ""
|
||||
|
||||
stepread [locate_data_file gh_bug378.stp] a *
|
||||
checkprops a_1 -v 10504.9
|
||||
|
15
tests/bugs/xde/bug28887_1
Normal file
15
tests/bugs/xde/bug28887_1
Normal file
@@ -0,0 +1,15 @@
|
||||
puts "=========="
|
||||
puts "OCC28887 Test case for Standard_ArrayStreamBuffer class - streaming interface for reading from allocated memory block"
|
||||
puts "=========="
|
||||
puts ""
|
||||
|
||||
pload QAcommands VISUALIZATION
|
||||
OCC28887 [locate_data_file face.brep] f
|
||||
|
||||
vclear
|
||||
vclose ALL
|
||||
vinit View1
|
||||
vaxo
|
||||
vdisplay -dispMode 1 f
|
||||
vfit
|
||||
vdump $::imagedir/${::casename}.png
|
16
tests/bugs/xde/bug28887_2
Normal file
16
tests/bugs/xde/bug28887_2
Normal file
@@ -0,0 +1,16 @@
|
||||
puts "=========="
|
||||
puts "OCC28887 Test case for Standard_ArrayStreamBuffer class - streaming interface for reading from allocated memory block"
|
||||
puts "=========="
|
||||
puts ""
|
||||
|
||||
pload QAcommands VISUALIZATION DCAF
|
||||
Close Doc -silent
|
||||
OCC28887 [locate_data_file bug23384-doc_subshapes.xbf] doc
|
||||
|
||||
vclear
|
||||
vclose ALL
|
||||
XShow doc
|
||||
vaxo
|
||||
vfit
|
||||
vsetdispmode 1
|
||||
vdump $::imagedir/${::casename}.png
|
1
tests/collections/grids.list
Executable file
1
tests/collections/grids.list
Executable file
@@ -0,0 +1 @@
|
||||
001 n
|
3
tests/collections/n/array1
Normal file
3
tests/collections/n/array1
Normal file
@@ -0,0 +1,3 @@
|
||||
puts "Check NCollection_Array1 functionality"
|
||||
|
||||
QANColTestArray1 1 10
|
3
tests/collections/n/array2
Normal file
3
tests/collections/n/array2
Normal file
@@ -0,0 +1,3 @@
|
||||
puts "Check NCollection_Array2 functionality"
|
||||
|
||||
QANColTestArray2 1 5 1 3
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user