// 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 #include #include #include #include #include #include #include #include #include #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; }