Browse Source
Add some QA tests
Add some QA tests
Created basic tests for: - Notification Manager - Clipboard - File history - Filename Resolver - Hotkey store - Collector - Reporterspull/18/head
8 changed files with 1611 additions and 9 deletions
-
7common/paths.cpp
-
8include/paths.h
-
8qa/tests/common/CMakeLists.txt
-
374qa/tests/common/test_clipboard.cpp
-
601qa/tests/common/test_collector.cpp
-
79qa/tests/common/test_hotkey_store.cpp
-
65qa/tests/common/test_notifications_manager.cpp
-
478qa/tests/common/test_reporting.cpp
@ -0,0 +1,374 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify it |
|||
* under the terms of the GNU General Public License as published by the |
|||
* Free Software Foundation, either version 3 of the License, or (at your |
|||
* option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, but |
|||
* WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
* General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License along |
|||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#include <boost/test/unit_test.hpp>
|
|||
#include <clipboard.h>
|
|||
#include <wx/clipbrd.h>
|
|||
#include <wx/image.h>
|
|||
#include <wx/string.h>
|
|||
#include <wx/filename.h>
|
|||
#include <wx/mstream.h>
|
|||
#include <vector>
|
|||
|
|||
BOOST_AUTO_TEST_SUITE( ClipboardTests ) |
|||
|
|||
BOOST_AUTO_TEST_CASE( SaveClipboard_BasicText ) |
|||
{ |
|||
std::string testText = "Basic clipboard test"; |
|||
bool result = SaveClipboard( testText ); |
|||
|
|||
if( result ) |
|||
{ |
|||
std::string retrieved = GetClipboardUTF8(); |
|||
BOOST_CHECK_EQUAL( retrieved, testText ); |
|||
} |
|||
// Note: Test may fail on headless systems where clipboard isn't available
|
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( SaveClipboard_EmptyString ) |
|||
{ |
|||
std::string emptyText = ""; |
|||
bool result = SaveClipboard( emptyText ); |
|||
|
|||
if( result ) |
|||
{ |
|||
std::string retrieved = GetClipboardUTF8(); |
|||
BOOST_CHECK_EQUAL( retrieved, emptyText ); |
|||
} |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( SaveClipboard_UTF8Characters ) |
|||
{ |
|||
std::string utf8Text = "Héllo Wörld! 你好 🚀"; |
|||
bool result = SaveClipboard( utf8Text ); |
|||
|
|||
if( result ) |
|||
{ |
|||
std::string retrieved = GetClipboardUTF8(); |
|||
BOOST_CHECK_EQUAL( retrieved, utf8Text ); |
|||
} |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( SaveClipboard_LargeText ) |
|||
{ |
|||
std::string largeText( 10000, 'A' ); |
|||
largeText += "END"; |
|||
bool result = SaveClipboard( largeText ); |
|||
|
|||
if( result ) |
|||
{ |
|||
std::string retrieved = GetClipboardUTF8(); |
|||
BOOST_CHECK_EQUAL( retrieved, largeText ); |
|||
} |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( SaveClipboard_SpecialCharacters ) |
|||
{ |
|||
std::string specialText = "Line1\nLine2\tTabbed\r\nWindows newline"; |
|||
bool result = SaveClipboard( specialText ); |
|||
|
|||
if( result ) |
|||
{ |
|||
std::string retrieved = GetClipboardUTF8(); |
|||
BOOST_CHECK_EQUAL( retrieved, specialText ); |
|||
} |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( GetClipboardUTF8_EmptyClipboard ) |
|||
{ |
|||
// Clear clipboard first
|
|||
if( wxTheClipboard->Open() ) |
|||
{ |
|||
wxTheClipboard->Clear(); |
|||
wxTheClipboard->Close(); |
|||
} |
|||
|
|||
std::string result = GetClipboardUTF8(); |
|||
BOOST_CHECK( result.empty() ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( GetClipboardUTF8_NonTextData ) |
|||
{ |
|||
// This test verifies behavior when clipboard contains non-text data
|
|||
// Implementation depends on system behavior - may return empty string
|
|||
std::string result = GetClipboardUTF8(); |
|||
// No specific assertion - just ensure it doesn't crash
|
|||
BOOST_CHECK( true ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( SaveTabularData_SimpleGrid ) |
|||
{ |
|||
std::vector<std::vector<wxString>> testData = { |
|||
{ wxS("A1"), wxS("B1"), wxS("C1") }, |
|||
{ wxS("A2"), wxS("B2"), wxS("C2") }, |
|||
{ wxS("A3"), wxS("B3"), wxS("C3") } |
|||
}; |
|||
|
|||
bool result = SaveTabularDataToClipboard( testData ); |
|||
|
|||
if( result ) |
|||
{ |
|||
std::vector<std::vector<wxString>> retrieved; |
|||
bool parseResult = GetTabularDataFromClipboard( retrieved ); |
|||
|
|||
if( parseResult ) |
|||
{ |
|||
BOOST_CHECK_EQUAL( retrieved.size(), testData.size() ); |
|||
for( size_t i = 0; i < testData.size() && i < retrieved.size(); ++i ) |
|||
{ |
|||
BOOST_CHECK_EQUAL( retrieved[i].size(), testData[i].size() ); |
|||
for( size_t j = 0; j < testData[i].size() && j < retrieved[i].size(); ++j ) |
|||
{ |
|||
BOOST_CHECK_EQUAL( retrieved[i][j], testData[i][j] ); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( SaveTabularData_EmptyGrid ) |
|||
{ |
|||
std::vector<std::vector<wxString>> emptyData; |
|||
bool result = SaveTabularDataToClipboard( emptyData ); |
|||
|
|||
if( result ) |
|||
{ |
|||
std::vector<std::vector<wxString>> retrieved; |
|||
bool parseResult = GetTabularDataFromClipboard( retrieved ); |
|||
|
|||
if( parseResult ) |
|||
{ |
|||
BOOST_CHECK( retrieved.empty() ); |
|||
} |
|||
} |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( SaveTabularData_SingleCell ) |
|||
{ |
|||
std::vector<std::vector<wxString>> singleCell = { |
|||
{ wxS("OnlyCell") } |
|||
}; |
|||
|
|||
bool result = SaveTabularDataToClipboard( singleCell ); |
|||
|
|||
if( result ) |
|||
{ |
|||
std::vector<std::vector<wxString>> retrieved; |
|||
bool parseResult = GetTabularDataFromClipboard( retrieved ); |
|||
|
|||
if( parseResult ) |
|||
{ |
|||
BOOST_CHECK_EQUAL( retrieved.size(), 1 ); |
|||
BOOST_CHECK_EQUAL( retrieved[0].size(), 1 ); |
|||
BOOST_CHECK_EQUAL( retrieved[0][0], wxS("OnlyCell") ); |
|||
} |
|||
} |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( SaveTabularData_WithCommas ) |
|||
{ |
|||
std::vector<std::vector<wxString>> dataWithCommas = { |
|||
{ wxS("Value, with comma"), wxS("Normal") }, |
|||
{ wxS("Another, comma"), wxS("Also normal") } |
|||
}; |
|||
|
|||
bool result = SaveTabularDataToClipboard( dataWithCommas ); |
|||
|
|||
if( result ) |
|||
{ |
|||
std::vector<std::vector<wxString>> retrieved; |
|||
bool parseResult = GetTabularDataFromClipboard( retrieved ); |
|||
|
|||
if( parseResult ) |
|||
{ |
|||
BOOST_CHECK_EQUAL( retrieved.size(), dataWithCommas.size() ); |
|||
for( size_t i = 0; i < dataWithCommas.size() && i < retrieved.size(); ++i ) |
|||
{ |
|||
BOOST_CHECK_EQUAL( retrieved[i].size(), dataWithCommas[i].size() ); |
|||
for( size_t j = 0; j < dataWithCommas[i].size() && j < retrieved[i].size(); ++j ) |
|||
{ |
|||
BOOST_CHECK_EQUAL( retrieved[i][j], dataWithCommas[i][j] ); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( SaveTabularData_WithQuotes ) |
|||
{ |
|||
std::vector<std::vector<wxString>> dataWithQuotes = { |
|||
{ wxS("\"Quoted value\""), wxS("Normal") }, |
|||
{ wxS("Value with \"inner\" quotes"), wxS("Plain") } |
|||
}; |
|||
|
|||
bool result = SaveTabularDataToClipboard( dataWithQuotes ); |
|||
|
|||
if( result ) |
|||
{ |
|||
std::vector<std::vector<wxString>> retrieved; |
|||
bool parseResult = GetTabularDataFromClipboard( retrieved ); |
|||
|
|||
if( parseResult ) |
|||
{ |
|||
BOOST_CHECK_EQUAL( retrieved.size(), dataWithQuotes.size() ); |
|||
// Note: Exact quote handling depends on CSV parser implementation
|
|||
} |
|||
} |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( SaveTabularData_WithNewlines ) |
|||
{ |
|||
std::vector<std::vector<wxString>> dataWithNewlines = { |
|||
{ wxS("Line1\nLine2"), wxS("Normal") }, |
|||
{ wxS("Single line"), wxS("Another\nmultiline") } |
|||
}; |
|||
|
|||
bool result = SaveTabularDataToClipboard( dataWithNewlines ); |
|||
|
|||
if( result ) |
|||
{ |
|||
std::vector<std::vector<wxString>> retrieved; |
|||
bool parseResult = GetTabularDataFromClipboard( retrieved ); |
|||
|
|||
if( parseResult ) |
|||
{ |
|||
BOOST_CHECK_EQUAL( retrieved.size(), dataWithNewlines.size() ); |
|||
// Note: Newline handling depends on CSV parser implementation
|
|||
} |
|||
} |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( SaveTabularData_IrregularGrid ) |
|||
{ |
|||
std::vector<std::vector<wxString>> irregularData = { |
|||
{ wxS("A1"), wxS("B1"), wxS("C1"), wxS("D1") }, |
|||
{ wxS("A2"), wxS("B2") }, |
|||
{ wxS("A3"), wxS("B3"), wxS("C3") } |
|||
}; |
|||
|
|||
bool result = SaveTabularDataToClipboard( irregularData ); |
|||
|
|||
if( result ) |
|||
{ |
|||
std::vector<std::vector<wxString>> retrieved; |
|||
bool parseResult = GetTabularDataFromClipboard( retrieved ); |
|||
|
|||
if( parseResult ) |
|||
{ |
|||
BOOST_CHECK_EQUAL( retrieved.size(), irregularData.size() ); |
|||
// Each row should maintain its individual size
|
|||
for( size_t i = 0; i < irregularData.size() && i < retrieved.size(); ++i ) |
|||
{ |
|||
for( size_t j = 0; j < irregularData[i].size() && j < retrieved[i].size(); ++j ) |
|||
{ |
|||
BOOST_CHECK_EQUAL( retrieved[i][j], irregularData[i][j] ); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( GetTabularDataFromClipboard_InvalidData ) |
|||
{ |
|||
// Save non-tabular text to clipboard
|
|||
std::string invalidText = "This is not tabular data\nJust some text"; |
|||
SaveClipboard( invalidText ); |
|||
|
|||
std::vector<std::vector<wxString>> retrieved; |
|||
bool result = GetTabularDataFromClipboard( retrieved ); |
|||
|
|||
// Should either parse as single-column data or return appropriate result
|
|||
// Exact behavior depends on AutoDecodeCSV implementation
|
|||
BOOST_CHECK( true ); // Test that it doesn't crash
|
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( GetImageFromClipboard_NoImage ) |
|||
{ |
|||
// Clear clipboard
|
|||
if( wxTheClipboard->Open() ) |
|||
{ |
|||
wxTheClipboard->Clear(); |
|||
wxTheClipboard->Close(); |
|||
} |
|||
|
|||
std::unique_ptr<wxImage> image = GetImageFromClipboard(); |
|||
BOOST_CHECK( !image || !image->IsOk() ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( GetImageFromClipboard_TextInClipboard ) |
|||
{ |
|||
// Put text in clipboard
|
|||
SaveClipboard( "This is text, not an image" ); |
|||
|
|||
std::unique_ptr<wxImage> image = GetImageFromClipboard(); |
|||
BOOST_CHECK( !image || !image->IsOk() ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( Clipboard_MultipleSaveOperations ) |
|||
{ |
|||
// Test multiple sequential save operations
|
|||
std::vector<std::string> testStrings = { |
|||
"First string", |
|||
"Second string with 特殊字符", |
|||
"Third string\nwith\nnewlines", |
|||
"" |
|||
}; |
|||
|
|||
for( const auto& testString : testStrings ) |
|||
{ |
|||
bool saved = SaveClipboard( testString ); |
|||
if( saved ) |
|||
{ |
|||
std::string retrieved = GetClipboardUTF8(); |
|||
BOOST_CHECK_EQUAL( retrieved, testString ); |
|||
} |
|||
} |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( Clipboard_ConcurrentAccess ) |
|||
{ |
|||
// Test that clipboard operations are properly synchronized
|
|||
std::string testText1 = "Concurrent test 1"; |
|||
std::string testText2 = "Concurrent test 2"; |
|||
|
|||
bool result1 = SaveClipboard( testText1 ); |
|||
bool result2 = SaveClipboard( testText2 ); |
|||
|
|||
if( result2 ) |
|||
{ |
|||
std::string retrieved = GetClipboardUTF8(); |
|||
BOOST_CHECK_EQUAL( retrieved, testText2 ); // Should have the last saved value
|
|||
} |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( Clipboard_FlushBehavior ) |
|||
{ |
|||
// Test that Flush() allows data to persist after the application
|
|||
std::string persistentText = "This should persist after flush"; |
|||
bool result = SaveClipboard( persistentText ); |
|||
|
|||
if( result ) |
|||
{ |
|||
// Data should still be available
|
|||
std::string retrieved = GetClipboardUTF8(); |
|||
BOOST_CHECK_EQUAL( retrieved, persistentText ); |
|||
} |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_SUITE_END() |
|||
@ -0,0 +1,601 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify it |
|||
* under the terms of the GNU General Public License as published by the |
|||
* Free Software Foundation, either version 3 of the License, or (at your |
|||
* option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, but |
|||
* WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
* General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License along |
|||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#include <boost/test/unit_test.hpp>
|
|||
#include <collector.h>
|
|||
#include <eda_item.h>
|
|||
#include <vector>
|
|||
#include <ostream>
|
|||
|
|||
// Mock EDA_ITEM for testing
|
|||
class TEST_EDA_ITEM : public EDA_ITEM |
|||
{ |
|||
public: |
|||
TEST_EDA_ITEM( KICAD_T aType ) : EDA_ITEM( aType ) {} |
|||
|
|||
wxString GetClass() const override { return wxT("TEST_EDA_ITEM"); } |
|||
|
|||
// Minimal required implementations for abstract methods
|
|||
EDA_ITEM* Clone() const override { return new TEST_EDA_ITEM( Type() ); } |
|||
}; |
|||
|
|||
// Test collector that implements Inspect
|
|||
class TEST_COLLECTOR : public COLLECTOR |
|||
{ |
|||
public: |
|||
TEST_COLLECTOR() : m_inspectCalls( 0 ), m_shouldCollect( true ) {} |
|||
|
|||
INSPECT_RESULT Inspect( EDA_ITEM* aTestItem, void* aTestData ) override |
|||
{ |
|||
m_inspectCalls++; |
|||
|
|||
if( m_shouldCollect && aTestItem ) |
|||
{ |
|||
// Only collect items of specified types if scan types are set
|
|||
if( !m_scanTypes.empty() ) |
|||
{ |
|||
for( KICAD_T type : m_scanTypes ) |
|||
{ |
|||
if( aTestItem->Type() == type ) |
|||
{ |
|||
Append( aTestItem ); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
Append( aTestItem ); |
|||
} |
|||
} |
|||
|
|||
return INSPECT_RESULT::CONTINUE; |
|||
} |
|||
|
|||
int GetInspectCalls() const { return m_inspectCalls; } |
|||
void SetShouldCollect( bool aShouldCollect ) { m_shouldCollect = aShouldCollect; } |
|||
|
|||
private: |
|||
int m_inspectCalls; |
|||
bool m_shouldCollect; |
|||
}; |
|||
|
|||
// Add this for Boost test output of INSPECT_RESULT
|
|||
std::ostream& operator<<( std::ostream& os, const INSPECT_RESULT& result ) |
|||
{ |
|||
switch( result ) |
|||
{ |
|||
case INSPECT_RESULT::CONTINUE: os << "CONTINUE"; break; |
|||
case INSPECT_RESULT::QUIT: os << "QUIT"; break; |
|||
default: os << "UNKNOWN"; break; |
|||
} |
|||
return os; |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_SUITE( CollectorTests ) |
|||
|
|||
BOOST_AUTO_TEST_CASE( Constructor_DefaultValues ) |
|||
{ |
|||
COLLECTOR collector; |
|||
|
|||
BOOST_CHECK_EQUAL( collector.GetCount(), 0 ); |
|||
BOOST_CHECK_EQUAL( collector.m_Threshold, 0 ); |
|||
BOOST_CHECK_EQUAL( collector.m_MenuCancelled, false ); |
|||
BOOST_CHECK( !collector.HasAdditionalItems() ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( Append_SingleItem ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item( PCB_T ); |
|||
|
|||
collector.Append( &item ); |
|||
|
|||
BOOST_CHECK_EQUAL( collector.GetCount(), 1 ); |
|||
BOOST_CHECK_EQUAL( collector[0], &item ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( Append_MultipleItems ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
TEST_EDA_ITEM item2( PCB_VIA_T ); |
|||
TEST_EDA_ITEM item3( PCB_TRACE_T ); |
|||
|
|||
collector.Append( &item1 ); |
|||
collector.Append( &item2 ); |
|||
collector.Append( &item3 ); |
|||
|
|||
BOOST_CHECK_EQUAL( collector.GetCount(), 3 ); |
|||
BOOST_CHECK_EQUAL( collector[0], &item1 ); |
|||
BOOST_CHECK_EQUAL( collector[1], &item2 ); |
|||
BOOST_CHECK_EQUAL( collector[2], &item3 ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( Append_NullItem ) |
|||
{ |
|||
COLLECTOR collector; |
|||
|
|||
collector.Append( nullptr ); |
|||
|
|||
BOOST_CHECK_EQUAL( collector.GetCount(), 1 ); |
|||
BOOST_CHECK_EQUAL( collector[0], nullptr ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( Empty_ClearsList ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
TEST_EDA_ITEM item2( PCB_VIA_T ); |
|||
|
|||
collector.Append( &item1 ); |
|||
collector.Append( &item2 ); |
|||
BOOST_CHECK_EQUAL( collector.GetCount(), 2 ); |
|||
|
|||
collector.Empty(); |
|||
|
|||
BOOST_CHECK_EQUAL( collector.GetCount(), 0 ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( Remove_ByIndex_ValidIndex ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
TEST_EDA_ITEM item2( PCB_VIA_T ); |
|||
TEST_EDA_ITEM item3( PCB_TRACE_T ); |
|||
|
|||
collector.Append( &item1 ); |
|||
collector.Append( &item2 ); |
|||
collector.Append( &item3 ); |
|||
|
|||
collector.Remove( 1 ); // Remove middle item
|
|||
|
|||
BOOST_CHECK_EQUAL( collector.GetCount(), 2 ); |
|||
BOOST_CHECK_EQUAL( collector[0], &item1 ); |
|||
BOOST_CHECK_EQUAL( collector[1], &item3 ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( Remove_ByIndex_FirstItem ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
TEST_EDA_ITEM item2( PCB_VIA_T ); |
|||
|
|||
collector.Append( &item1 ); |
|||
collector.Append( &item2 ); |
|||
|
|||
collector.Remove( 0 ); |
|||
|
|||
BOOST_CHECK_EQUAL( collector.GetCount(), 1 ); |
|||
BOOST_CHECK_EQUAL( collector[0], &item2 ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( Remove_ByIndex_LastItem ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
TEST_EDA_ITEM item2( PCB_VIA_T ); |
|||
|
|||
collector.Append( &item1 ); |
|||
collector.Append( &item2 ); |
|||
|
|||
collector.Remove( 1 ); |
|||
|
|||
BOOST_CHECK_EQUAL( collector.GetCount(), 1 ); |
|||
BOOST_CHECK_EQUAL( collector[0], &item1 ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( Remove_ByPointer_ExistingItem ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
TEST_EDA_ITEM item2( PCB_VIA_T ); |
|||
TEST_EDA_ITEM item3( PCB_TRACE_T ); |
|||
|
|||
collector.Append( &item1 ); |
|||
collector.Append( &item2 ); |
|||
collector.Append( &item3 ); |
|||
|
|||
collector.Remove( &item2 ); |
|||
|
|||
BOOST_CHECK_EQUAL( collector.GetCount(), 2 ); |
|||
BOOST_CHECK_EQUAL( collector[0], &item1 ); |
|||
BOOST_CHECK_EQUAL( collector[1], &item3 ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( Remove_ByPointer_NonExistingItem ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
TEST_EDA_ITEM item2( PCB_VIA_T ); |
|||
TEST_EDA_ITEM item3( PCB_TRACE_T ); |
|||
|
|||
collector.Append( &item1 ); |
|||
collector.Append( &item2 ); |
|||
|
|||
collector.Remove( &item3 ); // Not in collection
|
|||
|
|||
BOOST_CHECK_EQUAL( collector.GetCount(), 2 ); |
|||
BOOST_CHECK_EQUAL( collector[0], &item1 ); |
|||
BOOST_CHECK_EQUAL( collector[1], &item2 ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( Remove_ByPointer_DuplicateItems ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
|
|||
collector.Append( &item1 ); |
|||
collector.Append( &item1 ); |
|||
collector.Append( &item1 ); |
|||
|
|||
collector.Remove( &item1 ); |
|||
|
|||
BOOST_CHECK_EQUAL( collector.GetCount(), 0 ); // All instances should be removed
|
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( Transfer_ByIndex_ValidIndex ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
TEST_EDA_ITEM item2( PCB_VIA_T ); |
|||
TEST_EDA_ITEM item3( PCB_TRACE_T ); |
|||
|
|||
collector.Append( &item1 ); |
|||
collector.Append( &item2 ); |
|||
collector.Append( &item3 ); |
|||
|
|||
collector.Transfer( 1 ); |
|||
|
|||
BOOST_CHECK_EQUAL( collector.GetCount(), 2 ); |
|||
BOOST_CHECK_EQUAL( collector[0], &item1 ); |
|||
BOOST_CHECK_EQUAL( collector[1], &item3 ); |
|||
BOOST_CHECK( collector.HasAdditionalItems() ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( Transfer_ByPointer_ExistingItem ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
TEST_EDA_ITEM item2( PCB_VIA_T ); |
|||
TEST_EDA_ITEM item3( PCB_TRACE_T ); |
|||
|
|||
collector.Append( &item1 ); |
|||
collector.Append( &item2 ); |
|||
collector.Append( &item3 ); |
|||
|
|||
collector.Transfer( &item2 ); |
|||
|
|||
BOOST_CHECK_EQUAL( collector.GetCount(), 2 ); |
|||
BOOST_CHECK_EQUAL( collector[0], &item1 ); |
|||
BOOST_CHECK_EQUAL( collector[1], &item3 ); |
|||
BOOST_CHECK( collector.HasAdditionalItems() ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( Transfer_ByPointer_NonExistingItem ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
TEST_EDA_ITEM item2( PCB_VIA_T ); |
|||
TEST_EDA_ITEM item3( PCB_TRACE_T ); |
|||
|
|||
collector.Append( &item1 ); |
|||
collector.Append( &item2 ); |
|||
|
|||
collector.Transfer( &item3 ); // Not in collection
|
|||
|
|||
BOOST_CHECK_EQUAL( collector.GetCount(), 2 ); |
|||
BOOST_CHECK( !collector.HasAdditionalItems() ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( Combine_RestoresBackupItems ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
TEST_EDA_ITEM item2( PCB_VIA_T ); |
|||
TEST_EDA_ITEM item3( PCB_TRACE_T ); |
|||
|
|||
collector.Append( &item1 ); |
|||
collector.Append( &item2 ); |
|||
collector.Append( &item3 ); |
|||
|
|||
collector.Transfer( &item2 ); |
|||
collector.Transfer( &item3 ); |
|||
|
|||
BOOST_CHECK_EQUAL( collector.GetCount(), 1 ); |
|||
BOOST_CHECK( collector.HasAdditionalItems() ); |
|||
|
|||
collector.Combine(); |
|||
|
|||
BOOST_CHECK_EQUAL( collector.GetCount(), 3 ); |
|||
BOOST_CHECK( !collector.HasAdditionalItems() ); |
|||
BOOST_CHECK_EQUAL( collector[0], &item1 ); |
|||
BOOST_CHECK_EQUAL( collector[1], &item2 ); |
|||
BOOST_CHECK_EQUAL( collector[2], &item3 ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( Combine_EmptyBackupList ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
|
|||
collector.Append( &item1 ); |
|||
|
|||
BOOST_CHECK( !collector.HasAdditionalItems() ); |
|||
|
|||
collector.Combine(); |
|||
|
|||
BOOST_CHECK_EQUAL( collector.GetCount(), 1 ); |
|||
BOOST_CHECK( !collector.HasAdditionalItems() ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( OperatorBrackets_ValidIndex ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
TEST_EDA_ITEM item2( PCB_VIA_T ); |
|||
|
|||
collector.Append( &item1 ); |
|||
collector.Append( &item2 ); |
|||
|
|||
BOOST_CHECK_EQUAL( collector[0], &item1 ); |
|||
BOOST_CHECK_EQUAL( collector[1], &item2 ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( OperatorBrackets_InvalidIndex ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
|
|||
collector.Append( &item1 ); |
|||
|
|||
BOOST_CHECK_EQUAL( collector[1], nullptr ); // Out of bounds
|
|||
BOOST_CHECK_EQUAL( collector[-1], nullptr ); // Negative index
|
|||
BOOST_CHECK_EQUAL( collector[100], nullptr ); // Large index
|
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( OperatorBrackets_EmptyCollector ) |
|||
{ |
|||
COLLECTOR collector; |
|||
|
|||
BOOST_CHECK_EQUAL( collector[0], nullptr ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( HasItem_ExistingItem ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
TEST_EDA_ITEM item2( PCB_VIA_T ); |
|||
|
|||
collector.Append( &item1 ); |
|||
collector.Append( &item2 ); |
|||
|
|||
BOOST_CHECK( collector.HasItem( &item1 ) ); |
|||
BOOST_CHECK( collector.HasItem( &item2 ) ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( HasItem_NonExistingItem ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
TEST_EDA_ITEM item2( PCB_VIA_T ); |
|||
TEST_EDA_ITEM item3( PCB_TRACE_T ); |
|||
|
|||
collector.Append( &item1 ); |
|||
collector.Append( &item2 ); |
|||
|
|||
BOOST_CHECK( !collector.HasItem( &item3 ) ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( HasItem_NullItem ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
|
|||
collector.Append( &item1 ); |
|||
collector.Append( nullptr ); |
|||
|
|||
BOOST_CHECK( collector.HasItem( nullptr ) ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( HasItem_EmptyCollector ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
|
|||
BOOST_CHECK( !collector.HasItem( &item1 ) ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( CountType_SingleType ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
TEST_EDA_ITEM item2( PCB_T ); |
|||
TEST_EDA_ITEM item3( PCB_VIA_T ); |
|||
|
|||
collector.Append( &item1 ); |
|||
collector.Append( &item2 ); |
|||
collector.Append( &item3 ); |
|||
|
|||
BOOST_CHECK_EQUAL( collector.CountType( PCB_T ), 2 ); |
|||
BOOST_CHECK_EQUAL( collector.CountType( PCB_VIA_T ), 1 ); |
|||
BOOST_CHECK_EQUAL( collector.CountType( PCB_TRACE_T ), 0 ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( CountType_EmptyCollector ) |
|||
{ |
|||
COLLECTOR collector; |
|||
|
|||
BOOST_CHECK_EQUAL( collector.CountType( PCB_T ), 0 ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( SetScanTypes_Basic ) |
|||
{ |
|||
COLLECTOR collector; |
|||
std::vector<KICAD_T> types = { PCB_T, PCB_VIA_T }; |
|||
|
|||
collector.SetScanTypes( types ); |
|||
|
|||
// No direct way to test this, but it should not crash
|
|||
BOOST_CHECK( true ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( SetRefPos_Basic ) |
|||
{ |
|||
COLLECTOR collector; |
|||
VECTOR2I refPos( 100, 200 ); |
|||
|
|||
collector.SetRefPos( refPos ); |
|||
|
|||
// No direct way to test this, but it should not crash
|
|||
BOOST_CHECK( true ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( Iterator_BeginEnd ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
TEST_EDA_ITEM item2( PCB_VIA_T ); |
|||
TEST_EDA_ITEM item3( PCB_TRACE_T ); |
|||
|
|||
collector.Append( &item1 ); |
|||
collector.Append( &item2 ); |
|||
collector.Append( &item3 ); |
|||
|
|||
std::vector<EDA_ITEM*> items; |
|||
for( auto iter = collector.begin(); iter != collector.end(); ++iter ) |
|||
{ |
|||
items.push_back( *iter ); |
|||
} |
|||
|
|||
BOOST_CHECK_EQUAL( items.size(), 3 ); |
|||
BOOST_CHECK_EQUAL( items[0], &item1 ); |
|||
BOOST_CHECK_EQUAL( items[1], &item2 ); |
|||
BOOST_CHECK_EQUAL( items[2], &item3 ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( Iterator_RangeBasedFor ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
TEST_EDA_ITEM item2( PCB_VIA_T ); |
|||
|
|||
collector.Append( &item1 ); |
|||
collector.Append( &item2 ); |
|||
|
|||
std::vector<EDA_ITEM*> items; |
|||
for( EDA_ITEM* item : collector ) |
|||
{ |
|||
items.push_back( item ); |
|||
} |
|||
|
|||
BOOST_CHECK_EQUAL( items.size(), 2 ); |
|||
BOOST_CHECK_EQUAL( items[0], &item1 ); |
|||
BOOST_CHECK_EQUAL( items[1], &item2 ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( Iterator_ConstIterator ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
|
|||
collector.Append( &item1 ); |
|||
|
|||
const COLLECTOR& constCollector = collector; |
|||
std::vector<const EDA_ITEM*> items; |
|||
|
|||
for( auto iter = constCollector.begin(); iter != constCollector.end(); ++iter ) |
|||
{ |
|||
items.push_back( *iter ); |
|||
} |
|||
|
|||
BOOST_CHECK_EQUAL( items.size(), 1 ); |
|||
BOOST_CHECK_EQUAL( items[0], &item1 ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( Inspect_BasicFunctionality ) |
|||
{ |
|||
TEST_COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
|
|||
INSPECT_RESULT result = collector.Inspect( &item1, nullptr ); |
|||
|
|||
BOOST_CHECK_EQUAL( result, INSPECT_RESULT::CONTINUE ); |
|||
BOOST_CHECK_EQUAL( collector.GetInspectCalls(), 1 ); |
|||
BOOST_CHECK_EQUAL( collector.GetCount(), 1 ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( Inspect_WithScanTypes ) |
|||
{ |
|||
TEST_COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
TEST_EDA_ITEM item2( PCB_VIA_T ); |
|||
TEST_EDA_ITEM item3( PCB_TRACE_T ); |
|||
|
|||
std::vector<KICAD_T> scanTypes = { PCB_T, PCB_VIA_T }; |
|||
collector.SetScanTypes( scanTypes ); |
|||
|
|||
collector.Inspect( &item1, nullptr ); // Should be collected
|
|||
collector.Inspect( &item2, nullptr ); // Should be collected
|
|||
collector.Inspect( &item3, nullptr ); // Should NOT be collected
|
|||
|
|||
BOOST_CHECK_EQUAL( collector.GetCount(), 2 ); |
|||
BOOST_CHECK( collector.HasItem( &item1 ) ); |
|||
BOOST_CHECK( collector.HasItem( &item2 ) ); |
|||
BOOST_CHECK( !collector.HasItem( &item3 ) ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( ComplexWorkflow_TransferAndCombine ) |
|||
{ |
|||
COLLECTOR collector; |
|||
TEST_EDA_ITEM item1( PCB_T ); |
|||
TEST_EDA_ITEM item2( PCB_VIA_T ); |
|||
TEST_EDA_ITEM item3( PCB_TRACE_T ); |
|||
TEST_EDA_ITEM item4( PCB_PAD_T ); |
|||
|
|||
// Add items
|
|||
collector.Append( &item1 ); |
|||
collector.Append( &item2 ); |
|||
collector.Append( &item3 ); |
|||
collector.Append( &item4 ); |
|||
BOOST_CHECK_EQUAL( collector.GetCount(), 4 ); |
|||
|
|||
// Transfer some items
|
|||
collector.Transfer( &item2 ); |
|||
collector.Transfer( &item4 ); |
|||
BOOST_CHECK_EQUAL( collector.GetCount(), 2 ); |
|||
BOOST_CHECK( collector.HasAdditionalItems() ); |
|||
|
|||
// Remove one remaining item
|
|||
collector.Remove( &item1 ); |
|||
BOOST_CHECK_EQUAL( collector.GetCount(), 1 ); |
|||
|
|||
// Combine back
|
|||
collector.Combine(); |
|||
BOOST_CHECK_EQUAL( collector.GetCount(), 3 ); |
|||
BOOST_CHECK( !collector.HasAdditionalItems() ); |
|||
|
|||
// Check final state
|
|||
BOOST_CHECK( !collector.HasItem( &item1 ) ); // Was removed
|
|||
BOOST_CHECK( collector.HasItem( &item2 ) ); // Was transferred back
|
|||
BOOST_CHECK( collector.HasItem( &item3 ) ); // Was never moved
|
|||
BOOST_CHECK( collector.HasItem( &item4 ) ); // Was transferred back
|
|||
} |
|||
|
|||
BOOST_AUTO_TEST_SUITE_END() |
|||
@ -0,0 +1,79 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify it |
|||
* under the terms of the GNU General Public License as published by the |
|||
* Free Software Foundation, either version 3 of the License, or (at your |
|||
* option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, but |
|||
* WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
* General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License along |
|||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#include <boost/test/unit_test.hpp>
|
|||
|
|||
#include <hotkey_store.h>
|
|||
#include <hotkeys_basic.h>
|
|||
#include <tool/tool_action.h>
|
|||
#include <tool/tool_event.h>
|
|||
|
|||
BOOST_AUTO_TEST_SUITE( HotkeyStore ) |
|||
|
|||
BOOST_AUTO_TEST_CASE( PersistenceAndDefaults ) |
|||
{ |
|||
TOOL_ACTION action1( TOOL_ACTION_ARGS().Name( "common.test1" ).FriendlyName( "Test1" ) |
|||
.Scope( AS_GLOBAL ).DefaultHotkey( 'A' ) ); |
|||
TOOL_ACTION action2( TOOL_ACTION_ARGS().Name( "common.test2" ).FriendlyName( "Test2" ) |
|||
.Scope( AS_GLOBAL ).DefaultHotkey( 'B' ) ); |
|||
|
|||
HOTKEY_STORE store; |
|||
store.Init( { &action1, &action2 }, false ); |
|||
|
|||
auto& sections = store.GetSections(); |
|||
BOOST_REQUIRE( !sections.empty() ); |
|||
|
|||
HOTKEY& hk = sections[0].m_HotKeys[0]; |
|||
hk.m_EditKeycode = 'C'; |
|||
store.SaveAllHotkeys(); |
|||
BOOST_CHECK_EQUAL( action1.GetHotKey(), 'C' ); |
|||
|
|||
store.ResetAllHotkeysToDefault(); |
|||
BOOST_CHECK_EQUAL( sections[0].m_HotKeys[0].m_EditKeycode, action1.GetDefaultHotKey() ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( DuplicateRegistration ) |
|||
{ |
|||
TOOL_ACTION action1( TOOL_ACTION_ARGS().Name( "common.test1" ).FriendlyName( "Test1" ) |
|||
.Scope( AS_GLOBAL ).DefaultHotkey( 'A' ) ); |
|||
TOOL_ACTION action2( TOOL_ACTION_ARGS().Name( "common.test2" ).FriendlyName( "Test2" ) |
|||
.Scope( AS_GLOBAL ).DefaultHotkey( 'B' ) ); |
|||
|
|||
HOTKEY_STORE store; |
|||
store.Init( { &action1, &action2 }, false ); |
|||
|
|||
HOTKEY* conflict = nullptr; |
|||
bool has = store.CheckKeyConflicts( &action1, action2.GetHotKey(), &conflict ); |
|||
BOOST_CHECK( has ); |
|||
BOOST_CHECK( conflict != nullptr ); |
|||
|
|||
has = store.CheckKeyConflicts( &action1, 'Z', &conflict ); |
|||
BOOST_CHECK( !has ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( KeycodeSerialization ) |
|||
{ |
|||
int code = MD_CTRL + 'M'; |
|||
wxString name = KeyNameFromKeyCode( code ); |
|||
int round = KeyCodeFromKeyName( name ); |
|||
BOOST_CHECK_EQUAL( code, round ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_SUITE_END() |
|||
|
|||
@ -0,0 +1,65 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify it |
|||
* under the terms of the GNU General Public License as published by the |
|||
* Free Software Foundation, either version 3 of the License, or (at your |
|||
* option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, but |
|||
* WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
* General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License along |
|||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#include <boost/test/unit_test.hpp>
|
|||
|
|||
#include <ui_events.h>
|
|||
#include <build_version.h>
|
|||
#include <paths.h>
|
|||
#include <wx/filename.h>
|
|||
#include <wx/string.h>
|
|||
|
|||
#include <notifications_manager.h>
|
|||
|
|||
BOOST_AUTO_TEST_SUITE( Notifications ) |
|||
|
|||
BOOST_AUTO_TEST_CASE( CreateAndPersist ) |
|||
{ |
|||
wxFileName tmpDir( wxFileName::GetTempDir(), "" ); |
|||
wxString envPath = tmpDir.GetFullPath(); |
|||
|
|||
wxSetEnv( wxS("KICAD_CACHE_HOME"), envPath ); |
|||
wxFileName::Mkdir( tmpDir.GetFullPath(), wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ); |
|||
|
|||
NOTIFICATIONS_MANAGER mgr; |
|||
mgr.CreateOrUpdate( wxS("key"), wxS("Title"), wxS("Desc") ); |
|||
mgr.Save(); |
|||
|
|||
wxFileName fn( PATHS::GetUserCachePath(), wxS("notifications.json") ); |
|||
BOOST_CHECK( fn.FileExists() ); |
|||
} |
|||
|
|||
class TEST_HANDLER : public wxEvtHandler |
|||
{ |
|||
public: |
|||
bool triggered = false; |
|||
void OnEvent( wxCommandEvent& ) { triggered = true; } |
|||
}; |
|||
|
|||
BOOST_AUTO_TEST_CASE( EventDispatch ) |
|||
{ |
|||
TEST_HANDLER handler; |
|||
handler.Bind( EDA_EVT_UNITS_CHANGED, &TEST_HANDLER::OnEvent, &handler ); |
|||
wxCommandEvent evt( EDA_EVT_UNITS_CHANGED ); |
|||
handler.ProcessEvent( evt ); |
|||
BOOST_CHECK( handler.triggered ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_SUITE_END() |
|||
|
|||
@ -0,0 +1,478 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify it |
|||
* under the terms of the GNU General Public License as published by the |
|||
* Free Software Foundation, either version 3 of the License, or (at your |
|||
* option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, but |
|||
* WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
* General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License along |
|||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#include <boost/test/unit_test.hpp>
|
|||
#include <reporter.h>
|
|||
#include <wx/string.h>
|
|||
#include <wx/textctrl.h>
|
|||
#include <wx/statusbr.h>
|
|||
#include <wx/log.h>
|
|||
#include <vector>
|
|||
#include <sstream>
|
|||
|
|||
// Mock TEST_REPORTER to test base REPORTER functionality
|
|||
class TEST_REPORTER : public REPORTER |
|||
{ |
|||
public: |
|||
TEST_REPORTER() : m_hasMessage( false ), m_messageCount( 0 ) {} |
|||
|
|||
REPORTER& Report( const wxString& aText, SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED ) override |
|||
{ |
|||
REPORTER::Report( aText, aSeverity ); // Call base to update severity mask
|
|||
m_messages.push_back( std::make_pair( aText, aSeverity ) ); |
|||
m_hasMessage = true; |
|||
m_messageCount++; |
|||
return *this; |
|||
} |
|||
|
|||
bool HasMessage() const override |
|||
{ |
|||
return m_hasMessage; |
|||
} |
|||
|
|||
void Clear() override |
|||
{ |
|||
REPORTER::Clear(); |
|||
m_messages.clear(); |
|||
m_hasMessage = false; |
|||
m_messageCount = 0; |
|||
} |
|||
|
|||
const std::vector<std::pair<wxString, SEVERITY>>& GetMessages() const { return m_messages; } |
|||
int GetMessageCount() const { return m_messageCount; } |
|||
|
|||
private: |
|||
std::vector<std::pair<wxString, SEVERITY>> m_messages; |
|||
bool m_hasMessage; |
|||
int m_messageCount; |
|||
}; |
|||
|
|||
// Mock wxTextCtrl for testing
|
|||
class MockTextCtrl |
|||
{ |
|||
public: |
|||
MockTextCtrl() {} |
|||
void AppendText( const wxString& text ) { m_content += text; } |
|||
void SetValue( const wxString& text ) { m_content = text; } |
|||
wxString GetValue() const { return m_content; } |
|||
bool IsEmpty() const { return m_content.IsEmpty(); } |
|||
void Clear() { m_content.Clear(); } |
|||
|
|||
private: |
|||
wxString m_content; |
|||
}; |
|||
|
|||
// Mock wxStatusBar for testing
|
|||
class MockStatusBar |
|||
{ |
|||
public: |
|||
MockStatusBar() { m_fields.resize( 3 ); } // Default 3 fields
|
|||
void SetStatusText( const wxString& text, int field = 0 ) |
|||
{ |
|||
if( field >= 0 && field < (int)m_fields.size() ) |
|||
m_fields[field] = text; |
|||
} |
|||
wxString GetStatusText( int field = 0 ) const |
|||
{ |
|||
if( field >= 0 && field < (int)m_fields.size() ) |
|||
return m_fields[field]; |
|||
return wxEmptyString; |
|||
} |
|||
|
|||
private: |
|||
std::vector<wxString> m_fields; |
|||
}; |
|||
|
|||
BOOST_AUTO_TEST_SUITE( ReporterTests ) |
|||
|
|||
BOOST_AUTO_TEST_CASE( BaseReporter_Constructor ) |
|||
{ |
|||
TEST_REPORTER reporter; |
|||
|
|||
BOOST_CHECK( !reporter.HasMessage() ); |
|||
BOOST_CHECK( reporter.GetUnits() == EDA_UNITS::MM ); |
|||
BOOST_CHECK( !reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( BaseReporter_SingleReport ) |
|||
{ |
|||
TEST_REPORTER reporter; |
|||
|
|||
reporter.Report( wxT("Test message"), RPT_SEVERITY_INFO ); |
|||
|
|||
BOOST_CHECK( reporter.HasMessage() ); |
|||
BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 1 ); |
|||
BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) ); |
|||
|
|||
const auto& messages = reporter.GetMessages(); |
|||
BOOST_CHECK_EQUAL( messages.size(), 1 ); |
|||
BOOST_CHECK_EQUAL( messages[0].first, wxString("Test message") ); |
|||
BOOST_CHECK_EQUAL( messages[0].second, RPT_SEVERITY_INFO ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( BaseReporter_MultipleReports ) |
|||
{ |
|||
TEST_REPORTER reporter; |
|||
|
|||
reporter.Report( wxT("Info message"), RPT_SEVERITY_INFO ); |
|||
reporter.Report( wxT("Warning message"), RPT_SEVERITY_WARNING ); |
|||
reporter.Report( wxT("Error message"), RPT_SEVERITY_ERROR ); |
|||
|
|||
BOOST_CHECK( reporter.HasMessage() ); |
|||
BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 3 ); |
|||
|
|||
BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) ); |
|||
BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) ); |
|||
BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_ERROR ) ); |
|||
BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO | RPT_SEVERITY_WARNING ) ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( BaseReporter_ReportTail ) |
|||
{ |
|||
TEST_REPORTER reporter; |
|||
|
|||
reporter.ReportTail( wxT("Tail message"), RPT_SEVERITY_INFO ); |
|||
|
|||
BOOST_CHECK( reporter.HasMessage() ); |
|||
BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 1 ); |
|||
|
|||
const auto& messages = reporter.GetMessages(); |
|||
BOOST_CHECK_EQUAL( messages[0].first, wxString("Tail message") ); |
|||
BOOST_CHECK_EQUAL( messages[0].second, RPT_SEVERITY_INFO ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( BaseReporter_ReportHead ) |
|||
{ |
|||
TEST_REPORTER reporter; |
|||
|
|||
reporter.ReportHead( wxT("Head message"), RPT_SEVERITY_WARNING ); |
|||
|
|||
BOOST_CHECK( reporter.HasMessage() ); |
|||
BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 1 ); |
|||
|
|||
const auto& messages = reporter.GetMessages(); |
|||
BOOST_CHECK_EQUAL( messages[0].first, wxString("Head message") ); |
|||
BOOST_CHECK_EQUAL( messages[0].second, RPT_SEVERITY_WARNING ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( BaseReporter_OperatorLeftShift ) |
|||
{ |
|||
TEST_REPORTER reporter; |
|||
|
|||
reporter << wxT("Stream message"); |
|||
|
|||
BOOST_CHECK( reporter.HasMessage() ); |
|||
BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 1 ); |
|||
|
|||
const auto& messages = reporter.GetMessages(); |
|||
BOOST_CHECK_EQUAL( messages[0].first, wxString("Stream message") ); |
|||
BOOST_CHECK_EQUAL( messages[0].second, RPT_SEVERITY_UNDEFINED ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( BaseReporter_CharPointerReport ) |
|||
{ |
|||
TEST_REPORTER reporter; |
|||
|
|||
reporter.Report( "C-style string", RPT_SEVERITY_ERROR ); |
|||
|
|||
BOOST_CHECK( reporter.HasMessage() ); |
|||
BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 1 ); |
|||
BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_ERROR ) ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( BaseReporter_Clear ) |
|||
{ |
|||
TEST_REPORTER reporter; |
|||
|
|||
reporter.Report( wxT("Message 1"), RPT_SEVERITY_INFO ); |
|||
reporter.Report( wxT("Message 2"), RPT_SEVERITY_WARNING ); |
|||
|
|||
BOOST_CHECK( reporter.HasMessage() ); |
|||
BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) ); |
|||
BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) ); |
|||
|
|||
reporter.Clear(); |
|||
|
|||
BOOST_CHECK( !reporter.HasMessage() ); |
|||
BOOST_CHECK( !reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) ); |
|||
BOOST_CHECK( !reporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) ); |
|||
BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 0 ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( BaseReporter_SeverityMask ) |
|||
{ |
|||
TEST_REPORTER reporter; |
|||
|
|||
// Test individual severities
|
|||
reporter.Report( wxT("Info"), RPT_SEVERITY_INFO ); |
|||
BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) ); |
|||
BOOST_CHECK( !reporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) ); |
|||
|
|||
reporter.Report( wxT("Warning"), RPT_SEVERITY_WARNING ); |
|||
BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) ); |
|||
BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) ); |
|||
BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO | RPT_SEVERITY_WARNING ) ); |
|||
|
|||
// Test combined mask
|
|||
BOOST_CHECK( !reporter.HasMessageOfSeverity( RPT_SEVERITY_ERROR ) ); |
|||
BOOST_CHECK( !reporter.HasMessageOfSeverity( RPT_SEVERITY_ACTION ) ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( BaseReporter_EmptyMessage ) |
|||
{ |
|||
TEST_REPORTER reporter; |
|||
|
|||
reporter.Report( wxT(""), RPT_SEVERITY_INFO ); |
|||
|
|||
BOOST_CHECK( reporter.HasMessage() ); |
|||
BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 1 ); |
|||
|
|||
const auto& messages = reporter.GetMessages(); |
|||
BOOST_CHECK_EQUAL( messages[0].first, wxString("") ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( BaseReporter_LongMessage ) |
|||
{ |
|||
TEST_REPORTER reporter; |
|||
wxString longMessage( 10000, 'A' ); |
|||
|
|||
reporter.Report( longMessage, RPT_SEVERITY_INFO ); |
|||
|
|||
BOOST_CHECK( reporter.HasMessage() ); |
|||
BOOST_CHECK_EQUAL( reporter.GetMessageCount(), 1 ); |
|||
|
|||
const auto& messages = reporter.GetMessages(); |
|||
BOOST_CHECK_EQUAL( messages[0].first, longMessage ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( WxStringReporter_BasicFunctionality ) |
|||
{ |
|||
WX_STRING_REPORTER reporter; |
|||
|
|||
BOOST_CHECK( !reporter.HasMessage() ); |
|||
|
|||
reporter.Report( wxT("Test message"), RPT_SEVERITY_INFO ); |
|||
|
|||
BOOST_CHECK( reporter.HasMessage() ); |
|||
BOOST_CHECK( !reporter.GetMessages().IsEmpty() ); |
|||
BOOST_CHECK( reporter.GetMessages().Contains( wxT("Test message") ) ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( WxStringReporter_MultipleMessages ) |
|||
{ |
|||
WX_STRING_REPORTER reporter; |
|||
|
|||
reporter.Report( wxT("Message 1"), RPT_SEVERITY_INFO ); |
|||
reporter.Report( wxT("Message 2"), RPT_SEVERITY_WARNING ); |
|||
|
|||
BOOST_CHECK( reporter.HasMessage() ); |
|||
|
|||
const wxString& messages = reporter.GetMessages(); |
|||
BOOST_CHECK( messages.Contains( wxT("Message 1") ) ); |
|||
BOOST_CHECK( messages.Contains( wxT("Message 2") ) ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( WxStringReporter_Clear ) |
|||
{ |
|||
WX_STRING_REPORTER reporter; |
|||
|
|||
reporter.Report( wxT("Test message"), RPT_SEVERITY_INFO ); |
|||
BOOST_CHECK( reporter.HasMessage() ); |
|||
|
|||
reporter.Clear(); |
|||
|
|||
BOOST_CHECK( !reporter.HasMessage() ); |
|||
BOOST_CHECK( reporter.GetMessages().IsEmpty() ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( WxStringReporter_SeverityMask ) |
|||
{ |
|||
WX_STRING_REPORTER reporter; |
|||
|
|||
reporter.Report( wxT("Info"), RPT_SEVERITY_INFO ); |
|||
reporter.Report( wxT("Warning"), RPT_SEVERITY_WARNING ); |
|||
|
|||
BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) ); |
|||
BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) ); |
|||
BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO | RPT_SEVERITY_WARNING ) ); |
|||
BOOST_CHECK( !reporter.HasMessageOfSeverity( RPT_SEVERITY_ERROR ) ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( WxStringReporter_OperatorChaining ) |
|||
{ |
|||
WX_STRING_REPORTER reporter; |
|||
|
|||
reporter.Report( wxT("First"), RPT_SEVERITY_INFO ) |
|||
.Report( wxT("Second"), RPT_SEVERITY_WARNING ) |
|||
<< wxT("Third"); |
|||
|
|||
BOOST_CHECK( reporter.HasMessage() ); |
|||
const wxString& messages = reporter.GetMessages(); |
|||
BOOST_CHECK( messages.Contains( wxT("First") ) ); |
|||
BOOST_CHECK( messages.Contains( wxT("Second") ) ); |
|||
BOOST_CHECK( messages.Contains( wxT("Third") ) ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( NullReporter_Singleton ) |
|||
{ |
|||
REPORTER& reporter1 = NULL_REPORTER::GetInstance(); |
|||
REPORTER& reporter2 = NULL_REPORTER::GetInstance(); |
|||
|
|||
BOOST_CHECK_EQUAL( &reporter1, &reporter2 ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( NullReporter_NoMessages ) |
|||
{ |
|||
REPORTER& reporter = NULL_REPORTER::GetInstance(); |
|||
|
|||
BOOST_CHECK( !reporter.HasMessage() ); |
|||
|
|||
reporter.Report( wxT("Test message"), RPT_SEVERITY_INFO ); |
|||
|
|||
BOOST_CHECK( !reporter.HasMessage() ); // Should still report no messages
|
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( NullReporter_SeverityMask ) |
|||
{ |
|||
REPORTER& reporter = NULL_REPORTER::GetInstance(); |
|||
|
|||
reporter.Report( wxT("Info"), RPT_SEVERITY_INFO ); |
|||
reporter.Report( wxT("Warning"), RPT_SEVERITY_WARNING ); |
|||
|
|||
// NULL_REPORTER should track severity mask even though it doesn't store messages
|
|||
BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_INFO ) ); |
|||
BOOST_CHECK( reporter.HasMessageOfSeverity( RPT_SEVERITY_WARNING ) ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( CliReporter_Singleton ) |
|||
{ |
|||
REPORTER& reporter1 = CLI_REPORTER::GetInstance(); |
|||
REPORTER& reporter2 = CLI_REPORTER::GetInstance(); |
|||
|
|||
BOOST_CHECK_EQUAL( &reporter1, &reporter2 ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( CliReporter_NoMessages ) |
|||
{ |
|||
REPORTER& reporter = CLI_REPORTER::GetInstance(); |
|||
|
|||
BOOST_CHECK( !reporter.HasMessage() ); |
|||
|
|||
reporter.Report( wxT("Test message"), RPT_SEVERITY_INFO ); |
|||
|
|||
BOOST_CHECK( !reporter.HasMessage() ); // Should not store messages
|
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( StdoutReporter_Singleton ) |
|||
{ |
|||
REPORTER& reporter1 = STDOUT_REPORTER::GetInstance(); |
|||
REPORTER& reporter2 = STDOUT_REPORTER::GetInstance(); |
|||
|
|||
BOOST_CHECK_EQUAL( &reporter1, &reporter2 ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( StdoutReporter_NoMessages ) |
|||
{ |
|||
REPORTER& reporter = STDOUT_REPORTER::GetInstance(); |
|||
|
|||
BOOST_CHECK( !reporter.HasMessage() ); |
|||
|
|||
reporter.Report( wxT("Test message"), RPT_SEVERITY_INFO ); |
|||
|
|||
BOOST_CHECK( !reporter.HasMessage() ); // Should not store messages
|
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( WxLogReporter_Singleton ) |
|||
{ |
|||
REPORTER& reporter1 = WXLOG_REPORTER::GetInstance(); |
|||
REPORTER& reporter2 = WXLOG_REPORTER::GetInstance(); |
|||
|
|||
BOOST_CHECK_EQUAL( &reporter1, &reporter2 ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( WxLogReporter_NoMessages ) |
|||
{ |
|||
REPORTER& reporter = WXLOG_REPORTER::GetInstance(); |
|||
|
|||
BOOST_CHECK( !reporter.HasMessage() ); |
|||
|
|||
reporter.Report( wxT("Test message"), RPT_SEVERITY_INFO ); |
|||
|
|||
BOOST_CHECK( !reporter.HasMessage() ); // Should not store messages
|
|||
} |
|||
|
|||
// Note: WX_TEXT_CTRL_REPORTER and STATUSBAR_REPORTER tests would require
|
|||
// actual wxWidgets objects or more sophisticated mocking
|
|||
|
|||
BOOST_AUTO_TEST_CASE( ReporterInterface_Polymorphism ) |
|||
{ |
|||
std::vector<std::unique_ptr<REPORTER>> reporters; |
|||
reporters.push_back( std::make_unique<WX_STRING_REPORTER>() ); |
|||
reporters.push_back( std::make_unique<TEST_REPORTER>() ); |
|||
|
|||
for( auto& reporter : reporters ) |
|||
{ |
|||
reporter->Report( wxT("Polymorphic test"), RPT_SEVERITY_INFO ); |
|||
|
|||
// WX_STRING_REPORTER and TEST_REPORTER should both store messages
|
|||
if( dynamic_cast<WX_STRING_REPORTER*>( reporter.get() ) || |
|||
dynamic_cast<TEST_REPORTER*>( reporter.get() ) ) |
|||
{ |
|||
BOOST_CHECK( reporter->HasMessage() ); |
|||
} |
|||
} |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( ReporterInterface_ChainedOperations ) |
|||
{ |
|||
WX_STRING_REPORTER reporter; |
|||
|
|||
// Test method chaining
|
|||
REPORTER& result = reporter.Report( wxT("First"), RPT_SEVERITY_INFO ) |
|||
.ReportHead( wxT("Head"), RPT_SEVERITY_WARNING ) |
|||
.ReportTail( wxT("Tail"), RPT_SEVERITY_ERROR ); |
|||
|
|||
BOOST_CHECK_EQUAL( &result, &reporter ); // Should return reference to self
|
|||
BOOST_CHECK( reporter.HasMessage() ); |
|||
|
|||
const wxString& messages = reporter.GetMessages(); |
|||
BOOST_CHECK( messages.Contains( wxT("First") ) ); |
|||
BOOST_CHECK( messages.Contains( wxT("Head") ) ); |
|||
BOOST_CHECK( messages.Contains( wxT("Tail") ) ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( ReporterInterface_DefaultSeverity ) |
|||
{ |
|||
TEST_REPORTER reporter; |
|||
|
|||
// Test default severity parameter
|
|||
reporter.Report( wxT("Default severity") ); |
|||
|
|||
const auto& messages = reporter.GetMessages(); |
|||
BOOST_CHECK_EQUAL( messages[0].second, RPT_SEVERITY_UNDEFINED ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_CASE( ReporterInterface_UnitsDefault ) |
|||
{ |
|||
TEST_REPORTER reporter; |
|||
|
|||
BOOST_CHECK( reporter.GetUnits() == EDA_UNITS::MM ); |
|||
} |
|||
|
|||
BOOST_AUTO_TEST_SUITE_END() |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue