mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-09-28 04:54:13 +02:00
c33f250910
MasterElement::isFull() decided whether a coil had room left with
connected_elements.size() >= max_slaves
which counts linked *elements*. A slave stands for as many contacts as
its "number" kind information declares, so a 4 pole contact consumed a
single contact from the coil's budget instead of four. 36 elements in
the standard collection declare a number between 2 and 4, so this is
reachable, not theoretical.
Add ContactUsage, a header-only tally holding the two rules that are
easy to get wrong:
- a slave counts once per contact it declares, not once per element
- a changeover is counted once, as sw, and never as one NO plus one
NC. CrossRefItem::NOElements() and NCElements() both return
changeovers, so a count built by adding those two lists together
reports one changeover as two contacts.
The upcoming per-type displays (the used count in the element's General
tab, and the per-type budget on the cross reference) need exactly this
count, so it lives in one place rather than being written out three
times, and isFull() now reads it too.
The header carries no graphics dependency, so the counting rules are
unit tested on their own in tests/qttest/tst_contactusage.cpp,
following the same pattern as diagramsortkeys.h.
Verified: all 9 unit tests pass, and both rules were mutation checked
(counting elements instead of contacts fails 2 tests, counting a
changeover as both NO and NC fails 3). The 23 example projects still
load and export without crash or hang, and qet-lint reports no
regressions against its baseline.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
124 lines
3.2 KiB
C++
124 lines
3.2 KiB
C++
/*
|
|
Copyright 2006-2026 The QElectroTech Team
|
|
This file is part of QElectroTech.
|
|
|
|
QElectroTech 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 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
#include <QtTest>
|
|
|
|
#include "contactusage.h"
|
|
|
|
class tst_contactusage : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
private slots:
|
|
// An empty master uses nothing.
|
|
void emptyUsesNothing()
|
|
{
|
|
ContactUsage usage;
|
|
|
|
QCOMPARE(usage.no, 0);
|
|
QCOMPARE(usage.nc, 0);
|
|
QCOMPARE(usage.sw, 0);
|
|
QCOMPARE(usage.other, 0);
|
|
QCOMPARE(usage.total(), 0);
|
|
}
|
|
|
|
// Each type accumulates into its own field only.
|
|
void countsEachTypeSeparately()
|
|
{
|
|
ContactUsage usage;
|
|
usage.addSlave(ContactUsage::NO, 1);
|
|
usage.addSlave(ContactUsage::NO, 1);
|
|
usage.addSlave(ContactUsage::NC, 1);
|
|
usage.addSlave(ContactUsage::SW, 1);
|
|
usage.addSlave(ContactUsage::Other, 1);
|
|
|
|
QCOMPARE(usage.no, 2);
|
|
QCOMPARE(usage.nc, 1);
|
|
QCOMPARE(usage.sw, 1);
|
|
QCOMPARE(usage.other, 1);
|
|
QCOMPARE(usage.total(), 5);
|
|
}
|
|
|
|
// A slave standing for several contacts counts once per contact.
|
|
// Counting elements rather than contacts made a 4 pole contact
|
|
// consume a single contact from the master's budget.
|
|
void countsContactsNotElements()
|
|
{
|
|
ContactUsage usage;
|
|
usage.addSlave(ContactUsage::NO, 4);
|
|
|
|
QCOMPARE(usage.no, 4);
|
|
QCOMPARE(usage.total(), 4);
|
|
}
|
|
|
|
// A changeover is one contact of its own kind, never one NO plus
|
|
// one NC. CrossRefItem::NOElements() and NCElements() both return
|
|
// changeovers, so a count built by adding those two lists would
|
|
// report a single changeover as two contacts.
|
|
void changeoverIsCountedOnce()
|
|
{
|
|
ContactUsage usage;
|
|
usage.addSlave(ContactUsage::SW, 1);
|
|
|
|
QCOMPARE(usage.sw, 1);
|
|
QCOMPARE(usage.no, 0);
|
|
QCOMPARE(usage.nc, 0);
|
|
QCOMPARE(usage.total(), 1);
|
|
}
|
|
|
|
// An element which declares no contact count, or a nonsensical one,
|
|
// is still a contact.
|
|
void missingContactCountIsOneContact_data()
|
|
{
|
|
QTest::addColumn<int>("declared");
|
|
|
|
QTest::newRow("zero") << 0;
|
|
QTest::newRow("negative") << -1;
|
|
}
|
|
|
|
void missingContactCountIsOneContact()
|
|
{
|
|
QFETCH(int, declared);
|
|
|
|
ContactUsage usage;
|
|
usage.addSlave(ContactUsage::NO, declared);
|
|
|
|
QCOMPARE(usage.no, 1);
|
|
QCOMPARE(usage.total(), 1);
|
|
}
|
|
|
|
// The mix a coil would actually carry: two single NO, one 4 pole NO,
|
|
// one NC and one changeover.
|
|
void tallysARealisticMix()
|
|
{
|
|
ContactUsage usage;
|
|
usage.addSlave(ContactUsage::NO, 1);
|
|
usage.addSlave(ContactUsage::NO, 1);
|
|
usage.addSlave(ContactUsage::NO, 4);
|
|
usage.addSlave(ContactUsage::NC, 1);
|
|
usage.addSlave(ContactUsage::SW, 1);
|
|
|
|
QCOMPARE(usage.no, 6);
|
|
QCOMPARE(usage.nc, 1);
|
|
QCOMPARE(usage.sw, 1);
|
|
QCOMPARE(usage.total(), 8);
|
|
}
|
|
};
|
|
|
|
QTEST_APPLESS_MAIN(tst_contactusage)
|
|
#include "tst_contactusage.moc"
|