From 89a5b9dbe8aa56452dfa1a9241c194eeb9c06a28 Mon Sep 17 00:00:00 2001 From: Benjamin C Meyer Date: Mon, 24 Feb 2014 19:31:06 -0500 Subject: [PATCH 12/23] Create autotest for BookmarkNode class BookmarkNode was causing Arora to crash on exit because of the way it was deleting its children. --- autotests/autotests.pro | 1 + autotests/bookmarknode/.gitignore | 1 + autotests/bookmarknode/bookmarknode.pro | 14 + autotests/bookmarknode/tst_bookmarknode.cpp | 272 ++++++++++++++++++++ src/bookmarks/bookmarknode.cpp | 13 +- src/bookmarks/bookmarknode.h | 4 +- 6 files changed, 300 insertions(+), 5 deletions(-) create mode 100644 autotests/bookmarknode/.gitignore create mode 100644 autotests/bookmarknode/bookmarknode.pro create mode 100644 autotests/bookmarknode/tst_bookmarknode.cpp diff --git autotests/autotests.pro autotests/autotests.pro index 5e31e94..fdd3290 100644 --- autotests/autotests.pro +++ autotests/autotests.pro @@ -3,6 +3,7 @@ SUBDIRS = \ adblock \ addbookmarkdialog \ autosaver \ + bookmarknode \ cookiejar \ historyfiltermodel \ historymanager \ diff --git autotests/bookmarknode/.gitignore autotests/bookmarknode/.gitignore new file mode 100644 index 0000000..e2f5b4a --- /dev/null +++ autotests/bookmarknode/.gitignore @@ -0,0 +1 @@ +bookmarknode diff --git autotests/bookmarknode/bookmarknode.pro autotests/bookmarknode/bookmarknode.pro new file mode 100644 index 0000000..b796c01 --- /dev/null +++ autotests/bookmarknode/bookmarknode.pro @@ -0,0 +1,14 @@ +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . ../ + +include(../autotests.pri) + +QT = core + +# Input +SOURCES = bookmarknode.cpp tst_bookmarknode.cpp +HEADERS = bookmarknode.h +FORMS = +RESOURCE = diff --git autotests/bookmarknode/tst_bookmarknode.cpp autotests/bookmarknode/tst_bookmarknode.cpp new file mode 100644 index 0000000..a8307e7 --- /dev/null +++ autotests/bookmarknode/tst_bookmarknode.cpp @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2014 Benjamin C. Meyer + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Benjamin Meyer nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +class tst_BookmarkNode : public QObject +{ + Q_OBJECT + +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + +private slots: + void bookmarknode_data(); + void bookmarknode(); + + void add_duplicate(); + void add_to_bookmark(); + void add_move(); + void add_data(); + void add(); + void equal(); + void remove(); + void deleteNode(); + void deleteChildren(); + void type_data(); + void type(); +}; + +// This will be called before the first test function is executed. +// It is only called once. +void tst_BookmarkNode::initTestCase() +{ +} + +// This will be called after the last test function is executed. +// It is only called once. +void tst_BookmarkNode::cleanupTestCase() +{ +} + +// This will be called before each test function is executed. +void tst_BookmarkNode::init() +{ +} + +// This will be called after every test function. +void tst_BookmarkNode::cleanup() +{ +} + +void tst_BookmarkNode::bookmarknode_data() +{ +} + +void tst_BookmarkNode::bookmarknode() +{ + BookmarkNode node; + QCOMPARE(node.children(), QList()); + QCOMPARE(node.parent(), (BookmarkNode*)0); + QCOMPARE(node.type(), BookmarkNode::Root); + node.add((BookmarkNode*)0, -1); + node.remove((BookmarkNode*)0); +} + +void tst_BookmarkNode::add_to_bookmark() +{ + BookmarkNode node(BookmarkNode::Bookmark); + BookmarkNode *child = new BookmarkNode(BookmarkNode::Bookmark); + node.add(child); + // qWarning()? + QCOMPARE(node.children().count(), 0); + QCOMPARE(child->parent(), (BookmarkNode*)0); + delete child; +} + +void tst_BookmarkNode::add_duplicate() +{ + BookmarkNode node; + BookmarkNode *child = new BookmarkNode(BookmarkNode::Bookmark); + node.add(child); + node.add(child); + QCOMPARE(node.children().count(), 1); +} + +void tst_BookmarkNode::add_move() +{ + BookmarkNode node1; + BookmarkNode *child = new BookmarkNode(BookmarkNode::Bookmark); + node1.add(child); + + BookmarkNode node2; + node2.add(child); + + QCOMPARE(child->parent(), &node2); + QVERIFY(node2.children().contains(child)); + QVERIFY(!node1.children().contains(child)); +} + +void tst_BookmarkNode::add_data() +{ + QTest::addColumn("startcount"); + QTest::addColumn("insertoffset"); + QTest::addColumn("resultingoffset"); + QTest::newRow("0,-1,0") << 0 << -1 << 0; + QTest::newRow("0,0,0") << 0 << 0 << 0; + QTest::newRow("0,1,0") << 0 << 1 << 0; + QTest::newRow("1,-1,1") << 1 << -1 << 1; + QTest::newRow("1,0,0") << 1 << 0 << 0; + QTest::newRow("1,1,0") << 1 << 1 << 1; +} + +// public void add(BookmarkNode *child, int offset = -1) +void tst_BookmarkNode::add() +{ + QFETCH(int, startcount); + QFETCH(int, insertoffset); + QFETCH(int, resultingoffset); + + BookmarkNode node; + + for (int i = 0; i < startcount; ++i) { + BookmarkNode *child = new BookmarkNode(BookmarkNode::Bookmark); + node.add(child, -1); + } + + BookmarkNode *child = new BookmarkNode(BookmarkNode::Bookmark); + node.add(child, insertoffset); + + QCOMPARE(child->parent(), &node); + QList children = node.children(); + QVERIFY(children.contains(child)); + QCOMPARE(children.at(resultingoffset), child); +} + +Q_DECLARE_METATYPE(BookmarkNode) +// public bool equal(BookmarkNode const &other) +void tst_BookmarkNode::equal() +{ + BookmarkNode null1; + BookmarkNode null2; + QCOMPARE(null1, null2); + + BookmarkNode b1(BookmarkNode::Bookmark); + BookmarkNode b2(BookmarkNode::Bookmark); + QCOMPARE(b1, b2); + + b1.title = "title"; + QVERIFY(!(b1 == b2)); + b2.title = "title"; + QCOMPARE(b1, b2); + + b1.url = "url"; + QVERIFY(!(b1 == b2)); + b2.url = "url"; + QCOMPARE(b1, b2); + + b1.desc = "description"; + QVERIFY(!(b1 == b2)); + b2.desc = "description"; + QCOMPARE(b1, b2); + + BookmarkNode f1(BookmarkNode::Folder); + BookmarkNode f2(BookmarkNode::Folder); + QCOMPARE(f1, f2); + + f1.expanded = true; + QVERIFY(!(f1 == f2)); + f2.expanded = true; + QCOMPARE(f1, f2); + + BookmarkNode *child1 = new BookmarkNode(BookmarkNode::Bookmark); + child1->title = "title"; + f1.add(child1); + QVERIFY(!(f1 == f2)); + + BookmarkNode *child2 = new BookmarkNode(BookmarkNode::Bookmark); + child2->title = "title"; + f2.add(child2); + QCOMPARE(f1, f2); +} + +// public void remove(BookmarkNode *child) +void tst_BookmarkNode::remove() +{ + BookmarkNode node; + BookmarkNode *child = new BookmarkNode(BookmarkNode::Bookmark); + node.add(child); + node.remove(child); + QCOMPARE(node.children().count(), 0); + QCOMPARE(child->parent(), (BookmarkNode*)0); + delete child; +} + +void tst_BookmarkNode::deleteNode() +{ + BookmarkNode node; + BookmarkNode *child = new BookmarkNode(BookmarkNode::Bookmark); + node.add(child); + + delete child; + + QCOMPARE(node.children().count(), 0); + QCOMPARE(child->parent(), (BookmarkNode*)0); +} + +void tst_BookmarkNode::deleteChildren() +{ + BookmarkNode *node = new BookmarkNode(); + for (int i = 0; i < 10; ++i) { + BookmarkNode *child = new BookmarkNode(BookmarkNode::Bookmark); + node->add(child, -1); + } + delete node; + // This shouldn't segfualt :) +} + +Q_DECLARE_METATYPE(BookmarkNode::Type) +void tst_BookmarkNode::type_data() +{ + QTest::addColumn("type"); + QTest::newRow("root") << BookmarkNode::Root; + QTest::newRow("folder") << BookmarkNode::Folder; + QTest::newRow("sep") << BookmarkNode::Separator; + QTest::newRow("bookmark") << BookmarkNode::Bookmark; +} + +// public BookmarkNode::Type type() const +void tst_BookmarkNode::type() +{ + QFETCH(BookmarkNode::Type, type); + + BookmarkNode node(type); + + QCOMPARE(node.type(), type); + if (node.type() == BookmarkNode::Root) + QVERIFY(!node.parent()); + if (node.type() == BookmarkNode::Bookmark) + QVERIFY(node.children().isEmpty()); +} + +QTEST_MAIN(tst_BookmarkNode) +#include "tst_bookmarknode.moc" diff --git src/bookmarks/bookmarknode.cpp src/bookmarks/bookmarknode.cpp index ce6d742..a05e239 100644 --- src/bookmarks/bookmarknode.cpp +++ src/bookmarks/bookmarknode.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2008-2009 Benjamin C. Meyer + * Copyright 2008-2014 Benjamin C. Meyer * * 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 @@ -75,12 +75,13 @@ BookmarkNode::~BookmarkNode() { if (m_parent) m_parent->remove(this); - qDeleteAll(m_children); + for (int i = m_children.count() -1; i >= 0; --i) + delete m_children[i]; m_parent = 0; m_type = BookmarkNode::Root; } -bool BookmarkNode::operator==(const BookmarkNode &other) +bool BookmarkNode::operator==(const BookmarkNode &other) const { if (url != other.url || title != other.title @@ -118,6 +119,10 @@ BookmarkNode *BookmarkNode::parent() const void BookmarkNode::add(BookmarkNode *child, int offset) { + if (!child) + return; + if (m_type == BookmarkNode::Bookmark) + return; Q_ASSERT(child->m_type != Root); if (child->m_parent) child->m_parent->remove(child); @@ -129,6 +134,8 @@ void BookmarkNode::add(BookmarkNode *child, int offset) void BookmarkNode::remove(BookmarkNode *child) { + if (!child) + return; child->m_parent = 0; m_children.removeAll(child); } diff --git src/bookmarks/bookmarknode.h src/bookmarks/bookmarknode.h index b817c28..69c05d2 100644 --- src/bookmarks/bookmarknode.h +++ src/bookmarks/bookmarknode.h @@ -1,5 +1,5 @@ /* - * Copyright 2008-2009 Benjamin C. Meyer + * Copyright 2008-2014 Benjamin C. Meyer * * 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 @@ -78,7 +78,7 @@ public: BookmarkNode(Type type = Root, BookmarkNode *parent = 0); ~BookmarkNode(); - bool operator==(const BookmarkNode &other); + bool operator==(const BookmarkNode &other) const; Type type() const; void setType(Type type); -- 2.44.0