diff options
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | dive.c | 14 | ||||
-rw-r--r-- | dive.h | 1 | ||||
-rw-r--r-- | planner.c | 1 | ||||
-rw-r--r-- | planner.h | 1 | ||||
-rw-r--r-- | tests/testplan.cpp | 119 | ||||
-rw-r--r-- | tests/testplan.h | 13 |
7 files changed, 148 insertions, 2 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 534e8e2b6..5f6d1fb24 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -520,6 +520,7 @@ if(NOT NO_TESTS) TEST(TestProfile testprofile.cpp) TEST(TestGpsCoords testgpscoords.cpp) TEST(TestParse testparse.cpp) + TEST(TestPlan testplan.cpp) endif() # install a few things so that one can run Subsurface from the build @@ -3119,3 +3119,17 @@ void delete_current_divecomputer(void) if (dc_number == count_divecomputers()) dc_number--; } + +/* helper function to make it easier to work with our structures + * we don't interpolate here, just use the value from the last sample up to that time */ +int get_depth_at_time(struct divecomputer *dc, int time) +{ + int depth = 0; + if (dc && dc->sample) + for (int i = 0; i < dc->samples; i++) { + if (dc->sample[i].time.seconds > time) + break; + depth = dc->sample[i].depth.mm; + } + return depth; +} @@ -393,6 +393,7 @@ extern timestamp_t picture_get_timestamp(char *filename); extern void dive_set_geodata_from_picture(struct dive *d, struct picture *pic); extern int explicit_first_cylinder(struct dive *dive, struct divecomputer *dc); +extern int get_depth_at_time(struct divecomputer *dc, int time); static inline int get_surface_pressure_in_mbar(const struct dive *dive, bool non_null) { @@ -857,7 +857,6 @@ bool plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool int bottom_depth; int bottom_gi; int bottom_stopidx; - bool is_final_plan = true; int deco_time; int previous_deco_time; @@ -11,7 +11,6 @@ extern "C" { extern int validate_gas(const char *text, struct gasmix *gas); extern int validate_po2(const char *text, int *mbar_po2); extern timestamp_t current_time_notz(void); -extern void show_planned_dive(char **error_string_p); extern void set_last_stop(bool last_stop_6m); extern void set_verbatim(bool verbatim); extern void set_display_runtime(bool display); diff --git a/tests/testplan.cpp b/tests/testplan.cpp new file mode 100644 index 000000000..f08cfdeeb --- /dev/null +++ b/tests/testplan.cpp @@ -0,0 +1,119 @@ +#include "dive.h" +#include "testplan.h" +#include "planner.h" +#include "units.h" +#include <QDebug> + +// testing the dive plan algorithm +extern bool plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool show_disclaimer); + +void setupPrefs() +{ + prefs = default_prefs; + prefs.ascrate50 = feet_to_mm(30) / 60; + prefs.ascrate75 = prefs.ascrate50; + prefs.ascratestops = prefs.ascrate50; + prefs.ascratelast6m = feet_to_mm(10) / 60; + prefs.last_stop = true; + +} + +void setupPlan(struct diveplan *dp) +{ + dp->salinity = 10030; + dp->surface_pressure = 1013; + dp->gfhigh = 100; + dp->gflow = 100; + dp->bottomsac = 0; + dp->decosac = 0; + + struct gasmix bottomgas = { {150}, {450} }; + struct gasmix ean36 = { {360}, {0} }; + struct gasmix oxygen = { {1000}, {0} }; + pressure_t po2 = { 1600 }; + displayed_dive.cylinder[0].gasmix = bottomgas; + displayed_dive.cylinder[1].gasmix = ean36; + displayed_dive.cylinder[2].gasmix = oxygen; + reset_cylinders(&displayed_dive, true); + free_dps(dp); + + int droptime = M_OR_FT(79, 260) * 60 / M_OR_FT(23, 75); + plan_add_segment(dp, droptime, M_OR_FT(79, 260), bottomgas, 0, 1); + plan_add_segment(dp, 30*60 - droptime, M_OR_FT(79, 260), bottomgas, 0, 1); + plan_add_segment(dp, 0, gas_mod(&ean36, po2, M_OR_FT(3,10)).mm, ean36, 0, 1); + plan_add_segment(dp, 0, gas_mod(&oxygen, po2, M_OR_FT(3,10)).mm, oxygen, 0, 1); +} + +void TestPlan::testMetric() +{ + char *cache = NULL; + + setupPrefs(); + prefs.unit_system = METRIC; + prefs.units.length = units::METERS; + prefs.deco_mode = BUEHLMANN; + + struct diveplan testPlan = { 0 }; + setupPlan(&testPlan); + + plan(&testPlan, &cache, 1, 0); + +#if DEBUG + free(displayed_dive.notes); + displayed_dive.notes = NULL; + save_dive(stdout, &displayed_dive); +#endif + + // check first gas change to EAN36 at 33m + struct event *ev = displayed_dive.dc.events; + QVERIFY(ev != NULL); + QCOMPARE(ev->gas.index, 1); + QCOMPARE(ev->value, 36); + QCOMPARE(get_depth_at_time(&displayed_dive.dc, ev->time.seconds), 33000); + // check second gas change to Oxygen at 6m + ev = ev->next; + QVERIFY(ev != NULL); + QCOMPARE(ev->gas.index, 2); + QCOMPARE(ev->value, 100); + QCOMPARE(get_depth_at_time(&displayed_dive.dc, ev->time.seconds), 6000); + // check expected run time of 105 minutes + QCOMPARE(displayed_dive.dc.duration.seconds, 104u * 60u); +} + +void TestPlan::testImperial() +{ + char *cache = NULL; + + setupPrefs(); + prefs.unit_system = IMPERIAL; + prefs.units.length = units::FEET; + prefs.deco_mode = BUEHLMANN; + + struct diveplan testPlan = { 0 }; + setupPlan(&testPlan); + + plan(&testPlan, &cache, 1, 0); + +#if DEBUG + free(displayed_dive.notes); + displayed_dive.notes = NULL; + save_dive(stdout, &displayed_dive); +#endif + + // check first gas change to EAN36 at 33m + struct event *ev = displayed_dive.dc.events; + QVERIFY(ev != NULL); + QCOMPARE(ev->gas.index, 1); + QCOMPARE(ev->value, 36); + QCOMPARE(get_depth_at_time(&displayed_dive.dc, ev->time.seconds), 33528); + // check second gas change to Oxygen at 6m + ev = ev->next; + QVERIFY(ev != NULL); + QCOMPARE(ev->gas.index, 2); + QCOMPARE(ev->value, 100); + QCOMPARE(get_depth_at_time(&displayed_dive.dc, ev->time.seconds), 6096); + // check expected run time of 105 minutes + QCOMPARE(displayed_dive.dc.duration.seconds, 105u * 60u); +} + +QTEST_MAIN(TestPlan) diff --git a/tests/testplan.h b/tests/testplan.h new file mode 100644 index 000000000..b35cd75c6 --- /dev/null +++ b/tests/testplan.h @@ -0,0 +1,13 @@ +#ifndef TESTPLAN_H +#define TESTPLAN_H + +#include <QTest> + +class TestPlan : public QObject { + Q_OBJECT +private slots: + void testImperial(); + void testMetric(); +}; + +#endif // TESTPLAN_H |