livello dati C++ (datastore JSON, 33 controlli) e schermate Home, scheda ordine e cover; .gitignore per gli artefatti
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
// Banco di prova del livello dati (fuori dal pacchetto RPM).
|
||||
// Compila con Qt 5.15 locale e gira con XDG_CONFIG_HOME su una cartella
|
||||
// temporanea, cosi' NON tocca la configurazione vera:
|
||||
// sh tests/cpp_test.sh
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QStandardPaths>
|
||||
#include <QVariantList>
|
||||
#include <QVariantMap>
|
||||
#include <QDebug>
|
||||
|
||||
#include "../../src/datastore.h"
|
||||
|
||||
static int failures = 0;
|
||||
|
||||
static void check(const QString &name, bool ok, const QString &detail = QString())
|
||||
{
|
||||
if (!ok)
|
||||
failures++;
|
||||
qInfo().noquote() << (ok ? "OK " : "FAIL") << name
|
||||
<< (ok || detail.isEmpty() ? QString() : "-> " + detail);
|
||||
}
|
||||
|
||||
static QVariantList makeBreeds()
|
||||
{
|
||||
QVariantList hens;
|
||||
QVariantMap m1;
|
||||
m1.insert("id", "m1");
|
||||
m1.insert("name", "Marta");
|
||||
m1.insert("birthDate", "2025-01-01T00:00:00.000");
|
||||
m1.insert("isLaying", true);
|
||||
hens.append(m1);
|
||||
|
||||
QVariantMap marans;
|
||||
marans.insert("breedId", "marans");
|
||||
marans.insert("hens", hens);
|
||||
return QVariantList() << marans;
|
||||
}
|
||||
|
||||
static QVariantList makeReservations()
|
||||
{
|
||||
QVariantMap r;
|
||||
r.insert("id", "r1");
|
||||
r.insert("customerName", "Cli1");
|
||||
r.insert("breedId", "araucana");
|
||||
r.insert("eggsRequested", 2);
|
||||
r.insert("createdAt", "2026-04-25T09:00:00.000");
|
||||
r.insert("deliveryDate", "2026-04-28");
|
||||
r.insert("isDelivered", false);
|
||||
return QVariantList() << r;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
app.setOrganizationName("harbour");
|
||||
app.setApplicationName("henflow");
|
||||
|
||||
qInfo().noquote() << "config dir:" << QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
|
||||
|
||||
// --- primo avvio: nessun file, stato vuoto -----------------------------
|
||||
{
|
||||
DataStore store;
|
||||
check("primo avvio: nessuna razza", store.breedSettings().isEmpty());
|
||||
check("primo avvio: nessuna prenotazione", store.reservations().isEmpty());
|
||||
check("primo avvio: magazzino vuoto", store.warehouseStock().isEmpty());
|
||||
check("primo avvio: nessuna data di aggiornamento", store.lastProductionUpdate().isEmpty());
|
||||
check("il file dati non esiste ancora", !QFile::exists(store.dataFilePath()));
|
||||
}
|
||||
|
||||
// --- scrittura e rilettura --------------------------------------------
|
||||
DataStore store;
|
||||
check("salvataggio razze", store.saveBreedSettings(makeBreeds()));
|
||||
check("salvataggio prenotazioni", store.saveReservations(makeReservations()));
|
||||
|
||||
QVariantMap customers;
|
||||
customers.insert("id", "c1");
|
||||
customers.insert("firstName", "Anna");
|
||||
customers.insert("lastName", "Rossi");
|
||||
customers.insert("phoneNumber", "+39 333 0000000");
|
||||
check("salvataggio clienti", store.saveCustomers(QVariantList() << customers));
|
||||
|
||||
QVariantMap stock;
|
||||
stock.insert("marans", 6.0);
|
||||
stock.insert("araucana", 1.5);
|
||||
check("salvataggio magazzino", store.saveWarehouseStock(stock));
|
||||
check("salvataggio data aggiornamento", store.saveLastProductionUpdate("2026-10-09"));
|
||||
|
||||
check("il file dati esiste", QFile::exists(store.dataFilePath()));
|
||||
|
||||
{
|
||||
DataStore reopened;
|
||||
check("rilettura razze", reopened.breedSettings().size() == 1);
|
||||
check("rilettura nidificata (galline)", reopened.breedSettings().at(0).toMap()
|
||||
.value("hens").toList().size() == 1);
|
||||
check("rilettura prenotazioni", reopened.reservations().size() == 1);
|
||||
check("rilettura quantita' uova", reopened.reservations().at(0).toMap()
|
||||
.value("eggsRequested").toInt() == 2);
|
||||
check("rilettura flag consegna (bool)", reopened.reservations().at(0).toMap()
|
||||
.value("isDelivered").toBool() == false);
|
||||
check("rilettura clienti", reopened.customers().size() == 1 &&
|
||||
reopened.customers().at(0).toMap().value("lastName").toString() == "Rossi");
|
||||
check("rilettura magazzino (numeri)", qFuzzyCompare(reopened.warehouseStock()
|
||||
.value("araucana").toDouble(), 1.5));
|
||||
check("rilettura data aggiornamento", reopened.lastProductionUpdate() == "2026-10-09");
|
||||
}
|
||||
|
||||
// --- contratto con le chiavi dell'app Flutter --------------------------
|
||||
{
|
||||
QFile f(store.dataFilePath());
|
||||
f.open(QIODevice::ReadOnly);
|
||||
const QJsonObject root = QJsonDocument::fromJson(f.readAll()).object();
|
||||
f.close();
|
||||
check("chiave breed_settings_v2 (compatibile con l'app Android)",
|
||||
root.contains("breed_settings_v2"));
|
||||
check("chiave reservations_v2", root.contains("reservations_v2"));
|
||||
check("chiave customers_v1", root.contains("customers_v1"));
|
||||
check("chiave warehouse_stock_v1", root.contains("warehouse_stock_v1"));
|
||||
check("chiave last_production_update_v1", root.contains("last_production_update_v1"));
|
||||
}
|
||||
|
||||
// --- backup / ripristino ----------------------------------------------
|
||||
{
|
||||
const QString backup = QDir(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation))
|
||||
.filePath("backup-test.json");
|
||||
check("export", store.exportTo(backup));
|
||||
check("clearAll", store.clearAll());
|
||||
check("dopo clearAll: vuoto", store.reservations().isEmpty() && store.customers().isEmpty());
|
||||
check("import", store.importFrom(backup));
|
||||
check("dopo import: prenotazioni ripristinate", store.reservations().size() == 1);
|
||||
check("dopo import: clienti ripristinati", store.customers().size() == 1);
|
||||
QFile::remove(backup);
|
||||
}
|
||||
|
||||
// --- file corrotto: non deve crashare e non deve perdere i dati ---------
|
||||
{
|
||||
QFile f(store.dataFilePath());
|
||||
f.open(QIODevice::WriteOnly | QIODevice::Truncate);
|
||||
f.write("{ questo non e' json");
|
||||
f.close();
|
||||
|
||||
DataStore broken;
|
||||
check("file corrotto: non crasha", true);
|
||||
check("file corrotto: stato vuoto", broken.reservations().isEmpty());
|
||||
|
||||
// il backup di un file corrotto viene rifiutato
|
||||
check("import di un file non valido rifiutato", !broken.importFrom(store.dataFilePath()));
|
||||
}
|
||||
|
||||
qInfo().noquote() << (failures == 0 ? "\ntutti i controlli superati"
|
||||
: QString("\n%1 controlli falliti").arg(failures));
|
||||
return failures == 0 ? 0 : 1;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
TEMPLATE = app
|
||||
TARGET = harness
|
||||
CONFIG += console c++11
|
||||
CONFIG -= app_bundle
|
||||
|
||||
# Solo QtCore: il livello dati non tocca la GUI, cosi' il banco di prova
|
||||
# compila su desktop senza QtQuick/Silica.
|
||||
QT += core
|
||||
QT -= gui
|
||||
|
||||
SOURCES += \
|
||||
harness.cpp \
|
||||
../../src/datastore.cpp
|
||||
|
||||
HEADERS += \
|
||||
../../src/datastore.h
|
||||
Reference in New Issue
Block a user