From fd55ca84ccaf0d809359e09af55034ec58188b9d Mon Sep 17 00:00:00 2001 From: David Steele Date: Fri, 27 Apr 2018 11:24:22 +0100 Subject: [PATCH] Adding debug methods for Control internals Enables writing the Actor hierarchy, including control internals, as a JSON file. Extremely useful for validating test cases. Change-Id: I50559f3361c839ac7996581a0ba3ba902b3d2f81 --- .../src/dali-toolkit-internal/CMakeLists.txt | 2 +- .../dali-toolkit-test-utils/toolkit-text-utils.cpp | 5 +- .../utc-Dali-BidirectionalSupport.cpp | 9 +- .../utc-Dali-Control-internal.cpp | 26 +- .../utc-Dali-Text-MultiLanguage.cpp | 13 +- .../utc-Dali-Text-Segmentation.cpp | 16 +- .../devel-api/visual-factory/visual-base.cpp | 4 +- .../devel-api/visual-factory/visual-base.h | 4 +- .../internal/controls/control/control-debug.cpp | 353 +++++++++++++++++++++ .../internal/controls/control/control-debug.h | 67 ++++ dali-toolkit/internal/file.list | 1 + dali-toolkit/internal/visuals/visual-base-impl.cpp | 2 +- dali-toolkit/internal/visuals/visual-base-impl.h | 2 +- 13 files changed, 479 insertions(+), 25 deletions(-) create mode 100644 dali-toolkit/internal/controls/control/control-debug.cpp create mode 100644 dali-toolkit/internal/controls/control/control-debug.h diff --git a/automated-tests/src/dali-toolkit-internal/CMakeLists.txt b/automated-tests/src/dali-toolkit-internal/CMakeLists.txt index 902b00d..037fd71 100755 --- a/automated-tests/src/dali-toolkit-internal/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit-internal/CMakeLists.txt @@ -72,7 +72,7 @@ PKG_CHECK_MODULES(${CAPI_LIB} REQUIRED dali-toolkit ) -ADD_COMPILE_OPTIONS( -O0 -ggdb --coverage -Wall -Werror ) +ADD_COMPILE_OPTIONS( -O0 -ggdb --coverage -Wall -Werror -DDEBUG_ENABLED ) ADD_COMPILE_OPTIONS( ${${CAPI_LIB}_CFLAGS_OTHER} ) ADD_DEFINITIONS(-DTEST_RESOURCE_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}/../../resources\" ) diff --git a/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp b/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp index 7768344..b977ec3 100755 --- a/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp +++ b/automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -109,7 +109,8 @@ void CreateTextModel( const std::string& text, Vector& utf32Characters = logicalModel->mText; utf32Characters.Resize( text.size() ); - const uint32_t numberOfCharacters = Utf8ToUtf32( reinterpret_cast( text.c_str() ), + const uint32_t numberOfCharacters = ( text.size() == 0) ? 0 : + Utf8ToUtf32( reinterpret_cast( text.c_str() ), text.size(), &utf32Characters[0u] ); utf32Characters.Resize( numberOfCharacters ); diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-BidirectionalSupport.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-BidirectionalSupport.cpp index 37b5277..cb33f00 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-BidirectionalSupport.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-BidirectionalSupport.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -439,8 +439,11 @@ bool GetCharactersDirectionTest( const GetCharactersDirectionData& data ) // 2) Clear the direction info data. Vector& directions = logicalModel->mCharacterDirections; - directions.Erase( directions.Begin() + data.startIndex, - directions.Begin() + data.startIndex + data.numberOfCharacters ); + if( directions.Count() >= data.startIndex + data.numberOfCharacters ) + { + directions.Erase( directions.Begin() + data.startIndex, + directions.Begin() + data.startIndex + data.numberOfCharacters ); + } // 3) Call GetCharactersDirection() function. diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Control-internal.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Control-internal.cpp index 09e2873..c7e8c39 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Control-internal.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Control-internal.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,8 @@ #include #include <../dali-toolkit/dali-toolkit-test-utils/dummy-control.h> #include +#include + using namespace Dali; using namespace Toolkit; @@ -67,3 +69,25 @@ int UtcDaliControlActionOnVisual(void) END_TEST; } + +int UtcDaliControlDebugHierarchy(void) +{ + ToolkitTestApplication application; + tet_infoline( "Create a control hierarchy, and test that the debug produces output" ); + + auto tableView = Toolkit::TableView::New(1, 2); + tableView.AddChild( ImageView::New( TEST_RESOURCE_DIR "/gallery-small-1.jpg" ), TableView::CellPosition( 1, 1 ) ); + tableView.AddChild( TextLabel::New("Stuff"), TableView::CellPosition( 1, 2 ) ); + + Stage::GetCurrent().Add( tableView ); + + Property::Value v(Matrix3::IDENTITY); + tableView.RegisterProperty( "SomeMatrix3", v); + + std::ostringstream oss; + Dali::Toolkit::Internal::DumpControlHierarchy( oss, Stage::GetCurrent().GetRootLayer() ); + DALI_TEST_CHECK( oss.str().length() != 0 ); + tet_printf("Control hierarchy: \n%s\n", oss.str().c_str() ); + + END_TEST; +} diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-MultiLanguage.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-MultiLanguage.cpp index dbb0e94..94bb485 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-MultiLanguage.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-MultiLanguage.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -178,9 +178,11 @@ bool ScriptsTest( const ScriptsData& data ) Vector utf32; utf32.Resize( data.text.size() ); - const uint32_t numberOfCharacters = Utf8ToUtf32( reinterpret_cast( data.text.c_str() ), - data.text.size(), - &utf32[0u] ); + const uint32_t numberOfCharacters = ( data.text.size() == 0 ) ? 0 : + Utf8ToUtf32( reinterpret_cast( data.text.c_str() ), + data.text.size(), + &utf32[0u] ); + utf32.Resize( numberOfCharacters ); // 2) Set the script info. @@ -255,7 +257,8 @@ bool ValidateFontTest( const ValidateFontsData& data ) Vector utf32; utf32.Resize( data.text.size() ); - const uint32_t numberOfCharacters = Utf8ToUtf32( reinterpret_cast( data.text.c_str() ), + const uint32_t numberOfCharacters = (data.text.size() == 0 ) ? 0 : + Utf8ToUtf32( reinterpret_cast( data.text.c_str() ), data.text.size(), &utf32[0u] ); utf32.Resize( numberOfCharacters ); diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Segmentation.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Segmentation.cpp index 5366164..cfbf325 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Segmentation.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Segmentation.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -56,9 +56,10 @@ bool LineBreakInfoTest( const BreakInfoData& data ) Vector utf32; utf32.Resize( data.text.size() ); - const uint32_t numberOfCharacters = Utf8ToUtf32( reinterpret_cast( data.text.c_str() ), - data.text.size(), - &utf32[0u] ); + const uint32_t numberOfCharacters = ( data.text.size() == 0 ) ? 0 : + Utf8ToUtf32( reinterpret_cast( data.text.c_str() ), + data.text.size(), + &utf32[0u] ); utf32.Resize( numberOfCharacters ); @@ -113,9 +114,10 @@ bool WordBreakInfoTest( const BreakInfoData& data ) Vector utf32; utf32.Resize( data.text.size() ); - const uint32_t numberOfCharacters = Utf8ToUtf32( reinterpret_cast( data.text.c_str() ), - data.text.size(), - &utf32[0u] ); + const uint32_t numberOfCharacters = ( data.text.size() == 0 ) ? 0 : + Utf8ToUtf32( reinterpret_cast( data.text.c_str() ), + data.text.size(), + &utf32[0u] ); utf32.Resize( numberOfCharacters ); diff --git a/dali-toolkit/devel-api/visual-factory/visual-base.cpp b/dali-toolkit/devel-api/visual-factory/visual-base.cpp index 88cb626..7b20c60 100644 --- a/dali-toolkit/devel-api/visual-factory/visual-base.cpp +++ b/dali-toolkit/devel-api/visual-factory/visual-base.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -56,7 +56,7 @@ void Visual::Base::SetName( const std::string& name ) GetImplementation( *this ).SetName( name ); } -const std::string& Visual::Base::GetName() +const std::string& Visual::Base::GetName() const { return GetImplementation( *this ).GetName(); } diff --git a/dali-toolkit/devel-api/visual-factory/visual-base.h b/dali-toolkit/devel-api/visual-factory/visual-base.h index 54a0310..74af0cb 100644 --- a/dali-toolkit/devel-api/visual-factory/visual-base.h +++ b/dali-toolkit/devel-api/visual-factory/visual-base.h @@ -1,7 +1,7 @@ #ifndef DALI_TOOLKIT_VISUAL_BASE_H #define DALI_TOOLKIT_VISUAL_BASE_H /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -122,7 +122,7 @@ public: * Used by the styling system to animate properties * @return The name of the visual */ - const std::string& GetName(); + const std::string& GetName() const; /** * @brief Sets the transform and the control size diff --git a/dali-toolkit/internal/controls/control/control-debug.cpp b/dali-toolkit/internal/controls/control/control-debug.cpp new file mode 100644 index 0000000..a359dee --- /dev/null +++ b/dali-toolkit/internal/controls/control/control-debug.cpp @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(DEBUG_ENABLED) + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal +{ + +class JsonWriter +{ +public: + JsonWriter( Property::Value& value ) + : mValue(value) + { + } + + std::string ToString() + { + std::ostringstream stream; + ToStream( stream ); + return stream.str(); + } + + void ToStream( std::ostream& stream ) + { + switch( mValue.GetType() ) + { + case Dali::Property::BOOLEAN: + { + auto value = mValue.Get(); + stream << ((value)?"true":"false"); + break; + } + case Dali::Property::FLOAT: + { + stream << mValue.Get(); + break; + } + case Dali::Property::INTEGER: + { + stream << mValue.Get(); + break; + } + case Dali::Property::VECTOR2: + { + auto vector = mValue.Get(); + stream << "[" << vector.x << ", " << vector.y << "]"; + break; + } + case Dali::Property::VECTOR3: + { + auto vector = mValue.Get(); + stream << "[" << vector.x << ", " << vector.y << ", " << vector.z << "]"; + break; + } + case Dali::Property::VECTOR4: + { + auto vector = mValue.Get(); + stream << "[" << vector.x << ", " << vector.y << ", " << vector.z << ", " << vector.w << "]"; + break; + } + case Dali::Property::MATRIX3: + { + auto matrix = mValue.Get(); + stream << "["; + for( int i=0; i<9; ++i ) + { + if( i>0) + stream << ","; + stream << matrix.AsFloat()[i]; + } + stream << "]"; + break; + } + case Dali::Property::MATRIX: + { + auto matrix = mValue.Get(); + stream << "["; + for( int i=0; i<16; ++i ) + { + if( i>0) + stream << ","; + stream << matrix.AsFloat()[i]; + } + stream << "]"; + break; + } + case Dali::Property::RECTANGLE: + { + auto vector = mValue.Get >(); + stream << "[" << vector.x << ", " << vector.y << ", " << vector.width << ", " << vector.height << "]"; + break; + } + case Dali::Property::ROTATION: + { + auto angleAxis = mValue.Get(); + stream << "[ [ " << angleAxis.axis.x << ", " << angleAxis.axis.y << ", " << angleAxis.axis.z << "], " + << angleAxis.angle.radian << "]"; + break; + } + case Dali::Property::STRING: + { + stream << '"' << mValue.Get() << '"'; + break; + } + case Dali::Property::ARRAY: + { + auto array = mValue.GetArray(); + stream << "[ "; + if( array ) + { + for( Property::Array::SizeType i=0; iSize(); ++i) + { + if( i>0) + stream << ", "; + auto outValue = JsonWriter( array->GetElementAt(i) ); + stream << outValue.ToString(); + } + } + stream << "]"; + break; + } + case Dali::Property::MAP: + { + auto map = mValue.GetMap(); + stream << "{ "; + if( map ) + { + for( Property::Map::SizeType i=0; iCount(); ++i) + { + if( i>0) + stream << ", "; + auto key = map->GetKeyAt( i ); + auto outValue = JsonWriter( map->GetValue(i) ); + stream << '\"' << key << "\":"; + stream << outValue.ToString(); + } + } + stream << "}"; + break; + } + case Dali::Property::EXTENTS: + { + stream << mValue.Get(); + break; + } + case Dali::Property::NONE: + { + stream << "undefined type"; + break; + } + } + } + + Property::Value& mValue; +}; + +static std::ostream& operator<<( std::ostream& o, JsonWriter& value ) +{ + value.ToStream(o); + return o; +} + + +std::ostream& operator<<( std::ostream& o, const RegisteredVisual& registeredVisual ) +{ + o << "{\n" << "\"index\":" << registeredVisual.index << ",\n"; + o << "\"enabled\":" << (registeredVisual.enabled?"true":"false") << ",\n"; + o << "\"pending\":" << (registeredVisual.pending?"true":"false") << ",\n"; + + Property::Map map; + registeredVisual.visual.CreatePropertyMap( map ); + o << "\"visual\": {\n\"name\":\"" << registeredVisual.visual.GetName() << "\",\n"; + o << map << "}\n" << "\n}\n"; + return o; +} + +std::ostream& operator<<( std::ostream& o, const RegisteredVisualContainer& visualContainer ) +{ + o<<"[\n"; + + bool first=true; + for( auto&& elem : visualContainer ) + { + if(!first) + { + o << ","; + } + first = false; + + o<<*elem<<"\n"; + } + o<<"]\n"; + return o; +} + +std::ostream& DumpProperty( std::ostream& o, Property::Index index, Handle handle ) +{ + auto propertyValue = handle.GetProperty( index ); + auto jsonPropertyValue = JsonWriter(propertyValue); + + o << "{\n"; + o << "\"index\":" << index << ",\n"; + o << "\"name\":\"" << handle.GetPropertyName( index ) << "\",\n"; + o << "\"value\":" << jsonPropertyValue << "\n"; + o << "}"; + return o; +} + + +std::ostream& DumpPropertiesWithPredicate( std::ostream& o, Dali::Handle handle, + Property::IndexContainer& indices, std::function predicate) +{ + bool first = true; + for( auto index : indices ) + { + if( predicate( index ) ) + { + if( !first ) + { + o << ","; + } + o << std::endl; + first = false; + DumpProperty( o, index, handle ); + } + } + return o; +} + +std::ostream& DumpProperties( std::ostream& o, Handle handle ) +{ + Property::IndexContainer indices; + handle.GetPropertyIndices( indices ); + + auto childPropertiesP = [](int index) -> bool + { + return CHILD_PROPERTY_REGISTRATION_START_INDEX <= index && index <= CHILD_PROPERTY_REGISTRATION_MAX_INDEX; + }; + auto propertiesP = [](int index) -> bool + { + return !(CHILD_PROPERTY_REGISTRATION_START_INDEX <= index && index <= CHILD_PROPERTY_REGISTRATION_MAX_INDEX); + }; + + o << "\"childProperties\":[\n" ; + DumpPropertiesWithPredicate( o, handle, indices, childPropertiesP ); + o << std::endl << "]," << std::endl; + + o << "\"Properties\":[\n" ; + DumpPropertiesWithPredicate( o, handle, indices, propertiesP ); + o << std::endl << "]" << std::endl; + + return o; +} + +std::string DumpControl( const Internal::Control& control ) +{ + auto& controlData = Internal::Control::Impl::Get( control ); + + std::ostringstream oss; + oss << "{\n "; + const std::string& name = control.Self().GetName(); + if( ! name.empty() ) + { + oss << "\"name\":\"" << name << "\",\n"; + } + oss << "\"id\":\"" << control.Self().GetId() << "\",\n"; + oss << "\"registeredVisuals\":\n" << controlData.mVisuals << ",\n"; + oss << "\"removeVisuals\":\n" << controlData.mRemoveVisuals << ",\n"; + oss << "\"rendererCount\":" << control.Self().GetRendererCount() << ",\n"; + oss << "\"properties\":\n{\n"; + DumpProperties( oss, control.Self() ) << "}\n"; + oss << "}\n"; + return oss.str(); +} + +std::string DumpActor( Actor actor ) +{ + std::ostringstream oss; + oss << "{\n "; + const std::string& name = actor.GetName(); + if( ! name.empty() ) + { + oss << "\"name\":\"" << name << "\",\n"; + } + oss << "\"id\":\"" << actor.GetId() << "\",\n"; + oss << "\"rendererCount\":" << actor.GetRendererCount() << ",\n"; + oss << "\"properties\":\n{\n"; + Toolkit::Internal::DumpProperties( oss, actor ) << "}\n"; + oss << "}\n"; + return oss.str(); +} + +void DumpControlHierarchy( std::ostream& o, Actor actor ) +{ + auto control = Toolkit::Control::DownCast( actor ); + o << "{\n"; + if( control ) + { + o << "\"Control\":" << DumpControl( Toolkit::Internal::GetImplementation( control ) ); + } + else + { + o << "\"Actor\":" << DumpActor( actor ); + } + o << ",\n\"children\":[\n"; + bool first=true; + for( auto count=actor.GetChildCount(), i=0u; i +#include +#include +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal +{ + +/** + * Convert properties of handle into JSON output, separated into 'normal' and 'child' properties. + * @param[in] ouputStream the output stream to write to + * @param[in] handle The handle of the object from which to retrieve properties + * @return The output stream + */ +std::ostream& DumpProperties( std::ostream& outputStream, Handle handle ); + +/** + * Dumps control internals, visuals and properties to a string in JSON format + */ +std::string DumpControl( const Internal::Control& control ); + +/** + * Dumps actor internals and properties to a string in JSON format + */ +std::string DumpActor( Actor actor ); + +/** + * Dumps actor hierarchy from a given root, but expands Control output to encompass Control internals. + * Formats the output in JSON. + * @param[in] ouputStream the output stream to write to + * @param[in] root The root actor + */ +void DumpControlHierarchy( std::ostream& outputStream, Actor rootActor ); + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali + +#endif + +#endif //DALI_TOOLKIT_INTERNAL_CONTROL_DEBUG_H diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index a83612d..f32296b 100755 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -52,6 +52,7 @@ toolkit_src_files = \ $(toolkit_src_dir)/controls/buttons/radio-button-impl.cpp \ $(toolkit_src_dir)/controls/buttons/toggle-button-impl.cpp \ $(toolkit_src_dir)/controls/control/control-data-impl.cpp \ + $(toolkit_src_dir)/controls/control/control-debug.cpp \ $(toolkit_src_dir)/controls/effects-view/effects-view-impl.cpp \ $(toolkit_src_dir)/controls/flex-container/flex-container-impl.cpp \ $(toolkit_src_dir)/controls/gaussian-blur-view/gaussian-blur-view-impl.cpp \ diff --git a/dali-toolkit/internal/visuals/visual-base-impl.cpp b/dali-toolkit/internal/visuals/visual-base-impl.cpp index 05a318b..064b13d 100755 --- a/dali-toolkit/internal/visuals/visual-base-impl.cpp +++ b/dali-toolkit/internal/visuals/visual-base-impl.cpp @@ -214,7 +214,7 @@ void Visual::Base::SetName( const std::string& name ) mImpl->mName = name; } -const std::string& Visual::Base::GetName() +const std::string& Visual::Base::GetName() const { return mImpl->mName; } diff --git a/dali-toolkit/internal/visuals/visual-base-impl.h b/dali-toolkit/internal/visuals/visual-base-impl.h index 755409f..00c397d 100644 --- a/dali-toolkit/internal/visuals/visual-base-impl.h +++ b/dali-toolkit/internal/visuals/visual-base-impl.h @@ -89,7 +89,7 @@ public: /** * @copydoc Toolkit::Visual::Base::GetName */ - const std::string& GetName(); + const std::string& GetName() const; /** * @copydoc Toolkit::Visual::Base::SetSize -- 2.7.4