diff options
Diffstat (limited to 'tests')
6 files changed, 186 insertions, 68 deletions
diff --git a/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp b/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp index 07f8ddfc8e..2b30b0486b 100644 --- a/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp +++ b/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp @@ -69,9 +69,18 @@ int main(int argc, char *argv[]) // An option with a longer description, to test wrapping QCommandLineOption noImplicitIncludesOption(QStringList() << QStringLiteral("n") << QStringLiteral("no-implicit-includes")); - noImplicitIncludesOption.setDescription(QStringLiteral("Disable automatic generation of implicit #include-directives.")); + noImplicitIncludesOption.setDescription(QStringLiteral("Disable magic generation of implicit #include-directives.")); parser.addOption(noImplicitIncludesOption); + QCommandLineOption newlineOption(QStringList() << QStringLiteral("newline")); + newlineOption.setDescription(QString::fromLatin1("This is an option with a rather long\n" + "description using explicit newline characters " + "(but testing automatic wrapping too). In addition, " + "here, we test breaking after a comma. Testing -option. " + "Long URL: http://qt-project.org/wiki/How_to_create_a_library_with_Qt_and_use_it_in_an_application " + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz")); + parser.addOption(newlineOption); + // This program supports different options depending on the "command" (first argument). // Call parse() to find out the positional arguments. parser.parse(QCoreApplication::arguments()); diff --git a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp index d8965dee5d..f37e192ad3 100644 --- a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp +++ b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp @@ -459,27 +459,40 @@ void tst_QCommandLineParser::testVersionOption() #endif // !QT_NO_PROCESS } +static const char expectedOptionsHelp[] = + "Options:\n" + " -h, --help Displays this help.\n" + " -v, --version Displays version information.\n" + " --load <url> Load file from URL.\n" + " -o, --output <file> Set output file.\n" + " -D <key=value> Define macro.\n" + " -n, --no-implicit-includes Disable magic generation of implicit\n" + " #include-directives.\n" + " --newline This is an option with a rather long\n" + " description using explicit newline characters (but\n" + " testing automatic wrapping too). In addition,\n" + " here, we test breaking after a comma. Testing\n" + " -option. Long URL:\n" + " http://qt-project.org/wiki/How_to_create_a_library\n" + " _with_Qt_and_use_it_in_an_application\n" + " abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx\n" + " yzabcdefghijklmnopqrstuvwxyz\n"; + void tst_QCommandLineParser::testHelpOption_data() { QTest::addColumn<QCommandLineParser::SingleDashWordOptionMode>("parsingMode"); QTest::addColumn<QString>("expectedHelpOutput"); - QString expectedOutput = + QString expectedOutput = QString::fromLatin1( "Usage: testhelper/qcommandlineparser_test_helper [options] parsingMode command\n" "Test helper\n" - "\n" - "Options:\n" - " -h, --help Displays this help.\n" - " -v, --version Displays version information.\n" - " --load <url> Load file from URL.\n" - " -o, --output <file> Set output file.\n" - " -D <key=value> Define macro.\n" - " -n, --no-implicit-includes Disable automatic generation of implicit #include\n" - " -directives.\n" + "\n") + + QString::fromLatin1(expectedOptionsHelp) + + QString::fromLatin1( "\n" "Arguments:\n" " parsingMode The parsing mode to test.\n" - " command The command to execute.\n"; + " command The command to execute.\n"); #ifdef Q_OS_WIN expectedOutput.replace(" -h, --help Displays this help.\n", " -?, -h, --help Displays this help.\n"); @@ -510,6 +523,7 @@ void tst_QCommandLineParser::testHelpOption() #ifdef Q_OS_WIN output.replace(QStringLiteral("\r\n"), QStringLiteral("\n")); #endif + QCOMPARE(output.split('\n'), expectedHelpOutput.split('\n')); // easier to debug than the next line, on failure QCOMPARE(output, expectedHelpOutput); process.start("testhelper/qcommandlineparser_test_helper", QStringList() << "0" << "resize" << "--help"); @@ -519,18 +533,11 @@ void tst_QCommandLineParser::testHelpOption() #ifdef Q_OS_WIN output.replace(QStringLiteral("\r\n"), QStringLiteral("\n")); #endif - QByteArray expectedResizeHelp = + QByteArray expectedResizeHelp = QByteArrayLiteral( "Usage: testhelper/qcommandlineparser_test_helper [options] resize [resize_options]\n" "Test helper\n" - "\n" - "Options:\n" - " -h, --help Displays this help.\n" - " -v, --version Displays version information.\n" - " --load <url> Load file from URL.\n" - " -o, --output <file> Set output file.\n" - " -D <key=value> Define macro.\n" - " -n, --no-implicit-includes Disable automatic generation of implicit #include\n" - " -directives.\n" + "\n") + + expectedOptionsHelp + " --size <size> New size.\n" "\n" "Arguments:\n" diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp index 0c6d369254..36bf76564f 100644 --- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp +++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp @@ -58,17 +58,8 @@ #include <qscrollbar.h> #include <qboxlayout.h> #include <qlineedit.h> - -// Will try to wait for the condition while allowing event processing -// for a maximum of 5 seconds. -#define TRY_COMPARE(expr, expected) \ - do { \ - const int step = 50; \ - for (int q = 0; q < 5000 && ((expr) != (expected)); q+=step) { \ - QTest::qWait(step); \ - } \ - QCOMPARE(expr, expected); \ - } while(0) +#include <qscreen.h> +#include <qscopedpointer.h> static inline void setFrameless(QWidget *w) { @@ -78,6 +69,22 @@ static inline void setFrameless(QWidget *w) w->setWindowFlags(flags); } +static inline void centerOnScreen(QWidget *w) +{ + const QPoint offset = QPoint(w->width() / 2, w->height() / 2); + w->move(QGuiApplication::primaryScreen()->availableGeometry().center() - offset); +} + +// Move cursor out of widget area to avoid undesired interaction on Mac. +static inline void moveCursorAway(const QWidget *topLevel) +{ +#ifndef QT_NO_CURSOR + QCursor::setPos(topLevel->geometry().topRight() + QPoint(100, 0)); +#else + Q_UNUSED(topLevel) +#endif +} + class TestView : public QAbstractItemView { Q_OBJECT @@ -374,25 +381,27 @@ void tst_QAbstractItemView::emptyModels() { QFETCH(QString, viewType); - TestView *view = 0; + QScopedPointer<QAbstractItemView> view; if (viewType == "QListView") - view = reinterpret_cast<TestView*>(new QListView()); + view.reset(new QListView()); else if (viewType == "QTableView") - view = reinterpret_cast<TestView*>(new QTableView()); + view.reset(new QTableView()); else if (viewType == "QTreeView") - view = reinterpret_cast<TestView*>(new QTreeView()); + view.reset(new QTreeView()); else if (viewType == "QHeaderView") - view = reinterpret_cast<TestView*>(new QHeaderView(Qt::Vertical)); + view.reset(new QHeaderView(Qt::Vertical)); else QVERIFY(0); + centerOnScreen(view.data()); + moveCursorAway(view.data()); view->show(); + QVERIFY(QTest::qWaitForWindowExposed(view.data())); QVERIFY(!view->model()); QVERIFY(!view->selectionModel()); //QVERIFY(view->itemDelegate() != 0); - basic_tests(view); - delete view; + basic_tests(reinterpret_cast<TestView*>(view.data())); } void tst_QAbstractItemView::setModel_data() @@ -408,24 +417,28 @@ void tst_QAbstractItemView::setModel_data() void tst_QAbstractItemView::setModel() { QFETCH(QString, viewType); - TestView *view = 0; + + QScopedPointer<QAbstractItemView> view; + if (viewType == "QListView") - view = reinterpret_cast<TestView*>(new QListView()); + view.reset(new QListView()); else if (viewType == "QTableView") - view = reinterpret_cast<TestView*>(new QTableView()); + view.reset(new QTableView()); else if (viewType == "QTreeView") - view = reinterpret_cast<TestView*>(new QTreeView()); + view.reset(new QTreeView()); else if (viewType == "QHeaderView") - view = reinterpret_cast<TestView*>(new QHeaderView(Qt::Vertical)); + view.reset(new QHeaderView(Qt::Vertical)); else QVERIFY(0); + centerOnScreen(view.data()); + moveCursorAway(view.data()); view->show(); + QVERIFY(QTest::qWaitForWindowExposed(view.data())); QStandardItemModel model(20,20); view->setModel(0); view->setModel(&model); - basic_tests(view); - delete view; + basic_tests(reinterpret_cast<TestView*>(view.data())); } void tst_QAbstractItemView::basic_tests(TestView *view) @@ -636,7 +649,10 @@ void tst_QAbstractItemView::noModel() view.setModel(&model); // Make the viewport smaller than the contents, so that we can scroll view.resize(100,100); + centerOnScreen(&view); + moveCursorAway(&view); view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); // make sure that the scrollbars are not at value 0 view.scrollTo(view.model()->index(10,10)); @@ -656,7 +672,10 @@ void tst_QAbstractItemView::dragSelect() QTableView view; view.setModel(&model); + centerOnScreen(&view); + moveCursorAway(&view); view.setVisible(true); + QVERIFY(QTest::qWaitForWindowExposed(&view)); const int delay = 2; for (int i = 0; i < 2; ++i) { @@ -677,7 +696,10 @@ void tst_QAbstractItemView::rowDelegate() QTableView view; view.setModel(&model); view.setItemDelegateForRow(3, &delegate); + centerOnScreen(&view); + moveCursorAway(&view); view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); QModelIndex index = model.index(3, 0); view.openPersistentEditor(index); @@ -694,7 +716,10 @@ void tst_QAbstractItemView::columnDelegate() QTableView view; view.setModel(&model); view.setItemDelegateForColumn(3, &delegate); + centerOnScreen(&view); + moveCursorAway(&view); view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); QModelIndex index = model.index(0, 3); view.openPersistentEditor(index); @@ -747,11 +772,13 @@ void tst_QAbstractItemView::persistentEditorFocus() view.setCurrentIndex(model.index(0, 0)); QCOMPARE(view.currentIndex(), model.index(0, 0)); + centerOnScreen(&view); + moveCursorAway(&view); view.show(); - QTRY_VERIFY(view.isVisible()); + QVERIFY(QTest::qWaitForWindowExposed(&view)); for (int i = 0; i < list.count(); ++i) { - TRY_COMPARE(list.at(i)->isVisible(), true); + QTRY_VERIFY(list.at(i)->isVisible()); QPoint p = QPoint(5, 5); QMouseEvent mouseEvent(QEvent::MouseButtonPress, p, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); @@ -1045,6 +1072,8 @@ void tst_QAbstractItemView::setItemDelegate() } } } + centerOnScreen(&v); + moveCursorAway(&v); v.show(); #ifdef Q_WS_X11 QCursor::setPos(v.geometry().center()); @@ -1056,7 +1085,7 @@ void tst_QAbstractItemView::setItemDelegate() v.edit(index); // This will close the editor - TRY_COMPARE(QApplication::focusWidget() == 0, false); + QTRY_VERIFY(QApplication::focusWidget()); QWidget *editor = QApplication::focusWidget(); QVERIFY(editor); editor->hide(); @@ -1122,20 +1151,25 @@ void tst_QAbstractItemView::setCurrentIndex() QFETCH(int, itemFlags); QFETCH(bool, result); - TestView *view = 0; + QScopedPointer<QAbstractItemView> view; + if (viewType == "QListView") - view = reinterpret_cast<TestView*>(new QListView()); + view.reset(new QListView()); else if (viewType == "QTableView") - view = reinterpret_cast<TestView*>(new QTableView()); + view.reset(new QTableView()); else if (viewType == "QTreeView") - view = reinterpret_cast<TestView*>(new QTreeView()); + view.reset(new QTreeView()); else if (viewType == "QHeaderView") - view = reinterpret_cast<TestView*>(new QHeaderView(Qt::Vertical)); + view.reset(new QHeaderView(Qt::Vertical)); else QVERIFY(0); + + centerOnScreen(view.data()); + moveCursorAway(view.data()); view->show(); + QVERIFY(QTest::qWaitForWindowExposed(view.data())); - QStandardItemModel *model = new QStandardItemModel(view); + QStandardItemModel *model = new QStandardItemModel(view.data()); QStandardItem *item = new QStandardItem("first item"); item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); model->appendRow(item); @@ -1150,8 +1184,6 @@ void tst_QAbstractItemView::setCurrentIndex() QVERIFY(view->currentIndex() == model->index(0,0)); view->setCurrentIndex(model->index(1,0)); QVERIFY(view->currentIndex() == model->index(result ? 1 : 0,0)); - - delete view; } void tst_QAbstractItemView::task221955_selectedEditor() @@ -1170,11 +1202,13 @@ void tst_QAbstractItemView::task221955_selectedEditor() tree.setItemWidget(dummy, 0, button = new QPushButton("More...")); button->setAutoFillBackground(true); // as recommended in doc + centerOnScreen(&tree); + moveCursorAway(&tree); tree.show(); tree.setFocus(); tree.setCurrentIndex(tree.model()->index(1,0)); - QTest::qWait(100); QApplication::setActiveWindow(&tree); + QVERIFY(QTest::qWaitForWindowActive(&tree)); QVERIFY(! tree.selectionModel()->selectedIndexes().contains(tree.model()->index(3,0))); @@ -1218,9 +1252,11 @@ void tst_QAbstractItemView::task250754_fontChange() } tree.setModel(m); + w.resize(160, 240); // Minimum width for windows with frame on Windows 8 + centerOnScreen(&w); + moveCursorAway(&w); w.show(); - w.resize(150,240); - QTest::qWait(30); + QVERIFY(QTest::qWaitForWindowExposed(&w)); QFont font = tree.font(); font.setPixelSize(10); tree.setFont(font); @@ -1244,8 +1280,10 @@ void tst_QAbstractItemView::task200665_itemEntered() QStandardItemModel model(1000,1); QListView view; view.setModel(&model); + centerOnScreen(&view); + moveCursorAway(&view); view.show(); - QTest::qWait(200); + QVERIFY(QTest::qWaitForWindowExposed(&view)); QRect rect = view.visualRect(model.index(0,0)); QCursor::setPos( view.viewport()->mapToGlobal(rect.center()) ); QSignalSpy spy(&view, SIGNAL(entered(QModelIndex))); @@ -1267,7 +1305,10 @@ void tst_QAbstractItemView::task257481_emptyEditor() QTreeView treeView; treeView.setRootIsDecorated(false); treeView.setModel(&model); + centerOnScreen(&treeView); + moveCursorAway(&treeView); treeView.show(); + QVERIFY(QTest::qWaitForWindowExposed(&treeView)); treeView.edit(model.index(0,0)); QList<QLineEdit *> lineEditors = treeView.viewport()->findChildren<QLineEdit *>(); @@ -1298,14 +1339,16 @@ void tst_QAbstractItemView::shiftArrowSelectionAfterScrolling() } QListView view; - view.setFixedSize(150, 250); + view.setFixedSize(160, 250); // Minimum width for windows with frame on Windows 8 view.setFlow(QListView::LeftToRight); view.setGridSize(QSize(100, 100)); view.setSelectionMode(QListView::ExtendedSelection); view.setViewMode(QListView::IconMode); view.setModel(&model); + centerOnScreen(&view); + moveCursorAway(&view); view.show(); - QTest::qWait(30); + QVERIFY(QTest::qWaitForWindowExposed(&view)); QModelIndex index0 = model.index(0, 0); QModelIndex index1 = model.index(1, 0); @@ -1333,14 +1376,16 @@ void tst_QAbstractItemView::shiftSelectionAfterRubberbandSelection() } QListView view; - view.setFixedSize(150, 450); + view.setFixedSize(160, 450); // Minimum width for windows with frame on Windows 8 view.setFlow(QListView::LeftToRight); view.setGridSize(QSize(100, 100)); view.setSelectionMode(QListView::ExtendedSelection); view.setViewMode(QListView::IconMode); view.setModel(&model); + centerOnScreen(&view); + moveCursorAway(&view); view.show(); - QTest::qWait(30); + QVERIFY(QTest::qWaitForWindowExposed(&view)); QModelIndex index0 = model.index(0, 0); QModelIndex index1 = model.index(1, 0); @@ -1408,14 +1453,16 @@ void tst_QAbstractItemView::ctrlRubberbandSelection() } QListView view; - view.setFixedSize(150, 450); + view.setFixedSize(160, 450); // Minimum width for windows with frame on Windows 8 view.setFlow(QListView::LeftToRight); view.setGridSize(QSize(100, 100)); view.setSelectionMode(QListView::ExtendedSelection); view.setViewMode(QListView::IconMode); view.setModel(&model); + centerOnScreen(&view); + moveCursorAway(&view); view.show(); - QTest::qWait(30); + QVERIFY(QTest::qWaitForWindowExposed(&view)); QModelIndex index1 = model.index(1, 0); QModelIndex index2 = model.index(2, 0); @@ -1454,6 +1501,8 @@ void tst_QAbstractItemView::QTBUG6407_extendedSelection() font.setPixelSize(10); view.setFont(font); view.resize(200,240); + centerOnScreen(&view); + moveCursorAway(&view); view.show(); QApplication::setActiveWindow(&view); @@ -1493,7 +1542,11 @@ void tst_QAbstractItemView::QTBUG6753_selectOnSelection() for (int j = 0; j < table.columnCount(); ++j) table.setItem(i, j, new QTableWidgetItem("choo-be-doo-wah")); + centerOnScreen(&table); + moveCursorAway(&table); table.show(); + QVERIFY(QTest::qWaitForWindowExposed(&table)); + table.setSelectionMode(QAbstractItemView::ExtendedSelection); table.selectAll(); QVERIFY(QTest::qWaitForWindowExposed(&table)); @@ -1523,6 +1576,8 @@ void tst_QAbstractItemView::testClickedSignal() { QTableWidget view(5, 5); + centerOnScreen(&view); + moveCursorAway(&view); view.show(); QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); @@ -1591,6 +1646,8 @@ void tst_QAbstractItemView::testChangeEditorState() view.setEditTriggers(QAbstractItemView::CurrentChanged); view.setItemDelegate(new StateChangeDelegate); view.setModel(&model); + centerOnScreen(&view); + moveCursorAway(&view); view.show(); QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); @@ -1607,7 +1664,10 @@ void tst_QAbstractItemView::deselectInSingleSelection() s.setRowCount(10); s.setColumnCount(10); view.setModel(&s); + centerOnScreen(&view); + moveCursorAway(&view); view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); view.setSelectionMode(QAbstractItemView::SingleSelection); view.setEditTriggers(QAbstractItemView::NoEditTriggers); QApplication::setActiveWindow(&view); @@ -1650,6 +1710,8 @@ void tst_QAbstractItemView::testNoActivateOnDisabledItem() model.setItem(0, 0, item); item->setFlags(Qt::NoItemFlags); treeView.setModel(&model); + centerOnScreen(&treeView); + moveCursorAway(&treeView); treeView.show(); QApplication::setActiveWindow(&treeView); diff --git a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp index 398b1b4d98..3e6df0f136 100644 --- a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp +++ b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp @@ -368,6 +368,8 @@ void tst_QHeaderView::getSetCheck() QCOMPARE(0, obj1.minimumSectionSize()); obj1.setMinimumSectionSize(99999); QCOMPARE(99999, obj1.minimumSectionSize()); + obj1.setMinimumSectionSize(-1); + QVERIFY(obj1.minimumSectionSize() < 100); // int QHeaderView::offset() // void QHeaderView::setOffset(int) diff --git a/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp b/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp index 135605f185..d04b812878 100644 --- a/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp +++ b/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp @@ -47,6 +47,7 @@ #include <qproxystyle.h> #include <qsizepolicy.h> +#include <QtWidgets/QCheckBox> #include <QtWidgets/QLabel> #include <QtWidgets/QLineEdit> #include <QtWidgets/QPushButton> @@ -347,6 +348,19 @@ void tst_QFormLayout::spacing() style->hspacing = 20; //QCOMPARE(fl->spacing(), 20); + + + // Do not assert if spacings are negative (QTBUG-34731) + style->vspacing = -1; + style->hspacing = -1; + QLabel *label = new QLabel(tr("Asserts")); + QCheckBox *checkBox = new QCheckBox(tr("Yes")); + fl->setWidget(0, QFormLayout::LabelRole, label); + fl->setWidget(1, QFormLayout::FieldRole, checkBox); + w->resize(200, 100); + w->show(); + QVERIFY(QTest::qWaitForWindowExposed(w)); + delete w; delete style; } diff --git a/tests/auto/widgets/widgets/qkeysequenceedit/tst_qkeysequenceedit.cpp b/tests/auto/widgets/widgets/qkeysequenceedit/tst_qkeysequenceedit.cpp index 8c010abfe6..1434d98e59 100644 --- a/tests/auto/widgets/widgets/qkeysequenceedit/tst_qkeysequenceedit.cpp +++ b/tests/auto/widgets/widgets/qkeysequenceedit/tst_qkeysequenceedit.cpp @@ -43,6 +43,8 @@ #include <QtTest/QtTest> #include <QKeySequenceEdit> +#include <QLineEdit> +#include <QString> Q_DECLARE_METATYPE(Qt::Key) Q_DECLARE_METATYPE(Qt::KeyboardModifiers) @@ -55,6 +57,7 @@ private slots: void testSetters(); void testKeys_data(); void testKeys(); + void testLineEditContents(); }; void tst_QKeySequenceEdit::testSetters() @@ -100,5 +103,26 @@ void tst_QKeySequenceEdit::testKeys() QTRY_COMPARE(spy.count(), 1); } +void tst_QKeySequenceEdit::testLineEditContents() +{ + QKeySequenceEdit edit; + QLineEdit *le = edit.findChild<QLineEdit*>(); + QVERIFY(le); + + QCOMPARE(le->text(), QString()); + + edit.setKeySequence(QKeySequence::New); + QCOMPARE(edit.keySequence(), QKeySequence(QKeySequence::New)); + + edit.clear(); + QCOMPARE(le->text(), QString()); + + edit.setKeySequence(QKeySequence::New); + QVERIFY(le->text() != QString()); + + edit.setKeySequence(QKeySequence()); + QCOMPARE(le->text(), QString()); +} + QTEST_MAIN(tst_QKeySequenceEdit) #include "tst_qkeysequenceedit.moc" |