tests/interface: Add a (currently crashing) BMenu "concurrency" test.
Adds/removes items as rapidly as possible from the menu from the main thread while the menu is open. That part works. Then it deletes all of the BMenuItems and then closes the menu, which crashes, as the BMenuItems do not notify the BMenu they are being deleted. I tested this on BeOS and it seems that this model crashes there also (looking through the code comments, it seems there are a number of testcases found throughout the years like this.) Removing the items before deleting them indeed fixes the crashes on both BeOS and Haiku. Change-Id: I8624f966bdc17030ddca05b97aa57b518ab420c5 Reviewed-on: https://review.haiku-os.org/540 Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
parent
81d0a0e0a7
commit
4628b6de8e
@ -6,6 +6,7 @@
|
||||
#include "bbitmap/BitmapTest.h"
|
||||
#include "bdeskbar/DeskbarTest.h"
|
||||
#include "bpolygon/PolygonTest.h"
|
||||
#include "bmenu/MenuTest.h"
|
||||
#include "bregion/RegionTest.h"
|
||||
#include "btextcontrol/TextControlTest.h"
|
||||
#include "btextview/TextViewTest.h"
|
||||
@ -24,6 +25,7 @@ getTestSuite()
|
||||
suite->addTest("BBitmap", BitmapTestSuite());
|
||||
suite->addTest("BDeskbar", DeskbarTestSuite());
|
||||
suite->addTest("BOutlineListView", OutlineListViewTestSuite());
|
||||
suite->addTest("BMenu", MenuTestSuite());
|
||||
suite->addTest("BPolygon", PolygonTestSuite());
|
||||
suite->addTest("BRegion", RegionTestSuite());
|
||||
suite->addTest("BTextControl", TextControlTestSuite());
|
||||
|
@ -9,6 +9,7 @@ UsePrivateHeaders interface shared ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) balert ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) bbitmap ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) bdeskbar ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) bmenu ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) bpolygon ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) bregion ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) btextcontrol ] ;
|
||||
@ -42,6 +43,9 @@ UnitTestLib libinterfacetest.so
|
||||
CreatePolygonTest.cpp
|
||||
MapPolygonTest.cpp
|
||||
|
||||
# BMenu
|
||||
MenuTest.cpp
|
||||
|
||||
# BRegion
|
||||
RegionTest.cpp
|
||||
RegionTestcase.cpp
|
||||
|
84
src/tests/kits/interface/bmenu/MenuTest.cpp
Normal file
84
src/tests/kits/interface/bmenu/MenuTest.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2018, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Augustin Cavalier <waddlesplash>
|
||||
*/
|
||||
#include "../common.h"
|
||||
|
||||
|
||||
#include <Application.h>
|
||||
#include <String.h>
|
||||
#include <Menu.h>
|
||||
#include <MenuItem.h>
|
||||
#include <PopUpMenu.h>
|
||||
|
||||
|
||||
class MenuTestcase : public TestCase {
|
||||
public:
|
||||
void
|
||||
SizeTest()
|
||||
{
|
||||
CPPUNIT_ASSERT_EQUAL(312, sizeof(BMenu));
|
||||
CPPUNIT_ASSERT_EQUAL(128, sizeof(BMenuItem));
|
||||
}
|
||||
|
||||
void
|
||||
ConcurrencyAbuseTest()
|
||||
{
|
||||
BApplication app("application/x-vnd.Haiku-interfacekit-menutest");
|
||||
BPopUpMenu* menu = new BPopUpMenu("Test");
|
||||
menu->AddItem(new BMenuItem("One", NULL));
|
||||
menu->AddItem(new BMenuItem("Two", NULL));
|
||||
menu->AddSeparatorItem();
|
||||
|
||||
BMenuItem* items[10];
|
||||
for (int i = 0; i < 10; i++) {
|
||||
BString str;
|
||||
str.SetToFormat("%d", i);
|
||||
items[i] = new BMenuItem(str.String(), NULL);
|
||||
}
|
||||
|
||||
// Now for the actual abuse.
|
||||
menu->Go(BPoint(), false, true, true);
|
||||
snooze(50 * 1000 /* 50 ms */);
|
||||
for (int i = 0; i < 100; i++) {
|
||||
for (int j = 0; j < (i % 5); j++) {
|
||||
BMenuItem* item = items[(i + j) % 10];
|
||||
if (item->Menu() != NULL)
|
||||
continue;
|
||||
menu->AddItem(item);
|
||||
}
|
||||
if ((i % 3) == 0) {
|
||||
for (int j = 0; j < (i % 5); j++)
|
||||
menu->RemoveItem((int32)0);
|
||||
}
|
||||
}
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(6, menu->CountItems());
|
||||
|
||||
// Cleanup.
|
||||
for (int i = 0; i < 10; i++)
|
||||
delete items[i];
|
||||
|
||||
// Close the menu.
|
||||
char bytes[] = {B_ESCAPE};
|
||||
menu->KeyDown(bytes, 1);
|
||||
delete menu;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Test*
|
||||
MenuTestSuite()
|
||||
{
|
||||
TestSuite* testSuite = new TestSuite();
|
||||
|
||||
testSuite->addTest(new CppUnit::TestCaller<MenuTestcase>(
|
||||
"BMenu_Size", &MenuTestcase::SizeTest));
|
||||
testSuite->addTest(new CppUnit::TestCaller<MenuTestcase>(
|
||||
"BMenu_ConcurrencyAbuse", &MenuTestcase::ConcurrencyAbuseTest));
|
||||
|
||||
return testSuite;
|
||||
}
|
10
src/tests/kits/interface/bmenu/MenuTest.h
Normal file
10
src/tests/kits/interface/bmenu/MenuTest.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef _menu_test_h_
|
||||
#define _menu_test_h_
|
||||
|
||||
class CppUnit::Test;
|
||||
|
||||
CppUnit::Test* MenuTestSuite();
|
||||
|
||||
#endif // _menu_test_h_
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user