Skip to content

Commit 59f4306

Browse files
authored
SIP51 Allow empty or nonexistent event files (#52)
* Allows empty and nonexistent event files, updates tests * Updates with PR feedback
1 parent bb8835a commit 59f4306

File tree

7 files changed

+158
-130
lines changed

7 files changed

+158
-130
lines changed

compile_flags.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
-Isrc
2+
-Itests

src/sipnet/events.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <stdio.h>
2828
#include <string.h>
2929
#include <stdlib.h>
30+
#include <unistd.h> // for access()
3031
#include "exitCodes.h"
3132
#include "common/util.h"
3233

@@ -159,17 +160,26 @@ EventNode **readEventData(char *eventFile, int numLocs) {
159160
char line[EVENT_LINE_SIZE];
160161
EventNode *curr, *next;
161162

162-
printf("Begin reading event data from file %s\n", eventFile);
163-
164163
EventNode **events =
165164
(EventNode **)calloc(sizeof(EventNode *), numLocs * sizeof(EventNode *));
166-
// status of the read
165+
166+
// Check for a non-empty file
167+
if (access(eventFile, F_OK) != 0) {
168+
// no file found, which is fine; we're done, a vector of NULL is what we
169+
// want for events
170+
printf("No event file found, assuming no events");
171+
return events;
172+
}
173+
174+
printf("Begin reading event data from file %s\n", eventFile);
175+
167176
FILE *in = openFile(eventFile, "r");
168177

169178
if (fgets(line, EVENT_LINE_SIZE, in) == NULL) {
170-
printf("Error reading event file: no event data in %s\n", eventFile);
171-
exit(1);
179+
// Again, this is fine - just return the empty events array
180+
return events;
172181
}
182+
173183
int numRead = sscanf(line, "%d %d %d %s %n", &loc, &year, &day, eventTypeStr,
174184
&numBytes);
175185
if (numRead != NUM_EVENT_CORE_PARAMS) {

src/sipnet/sipnet.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2517,7 +2517,7 @@ void updateTrackers(double oldSoilWater) {
25172517
//
25182518
// Process events for current location/year/day
25192519
#if EVENT_HANDLER
2520-
void processEvents() {
2520+
void processEvents(void) {
25212521
// If locEvent starts off NULL, this function will just fall through, as it
25222522
// should.
25232523
const int year = climate->year;
@@ -2532,7 +2532,7 @@ void processEvents() {
25322532
printf("Agronomic event found for loc: %d year: %d day: %d that does not "
25332533
"have a corresponding record in the climate file\n",
25342534
locEvent->year, locEvent->year, locEvent->day);
2535-
exit(1);
2535+
exit(EXIT_CODE_INPUT_FILE_ERROR);
25362536
}
25372537
switch (locEvent->type) {
25382538
// Implementation TBD, as we enable the various event types

tests/.clang-tidy

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Allow inclusion of *.c files in tests, and ease off of free() and NULL dereference checks
2+
Checks: '-bugprone-suspicious-include,
3+
-clang-analyzer-unix.Malloc,
4+
-clang-analyzer-core.NullDereference'

tests/sipnet/test_events_infrastructure/infra_events_empty_file.in

Whitespace-only changes.

tests/sipnet/test_events_infrastructure/testEventInfra.c

Lines changed: 103 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@
66
#include "utils/tUtils.h"
77
#include "sipnet/events.c"
88

9-
int checkEvent(EventNode* event, int loc, int year, int day, enum EventType type) {
10-
int success =
11-
event->loc == loc &&
12-
event->year == year &&
13-
event->day == day &&
14-
event->type == type;
9+
int checkEvent(EventNode *event, int loc, int year, int day,
10+
enum EventType type) {
11+
if (!event) {
12+
return 1;
13+
}
14+
int success = event->loc == loc && event->year == year && event->day == day &&
15+
event->type == type;
1516
if (!success) {
1617
printf("Error checking event\n");
1718
printEvent(event);
@@ -20,111 +21,95 @@ int checkEvent(EventNode* event, int loc, int year, int day, enum EventType type
2021
return 0;
2122
}
2223

23-
int checkHarvestParams(
24-
HarvestParams *params, double fracRemAbove,
25-
double fracRemBelow,
26-
double fracTransAbove,
27-
double fracTransBelow
28-
) {
29-
return !(
30-
compareDoubles(params->fractionRemovedAbove, fracRemAbove) &&
31-
compareDoubles(params->fractionRemovedBelow, fracRemBelow) &&
32-
compareDoubles(params->fractionTransferredAbove, fracTransAbove) &&
33-
compareDoubles(params->fractionTransferredBelow, fracTransBelow)
34-
);
24+
int checkHarvestParams(HarvestParams *params, double fracRemAbove,
25+
double fracRemBelow, double fracTransAbove,
26+
double fracTransBelow) {
27+
return !(compareDoubles(params->fractionRemovedAbove, fracRemAbove) &&
28+
compareDoubles(params->fractionRemovedBelow, fracRemBelow) &&
29+
compareDoubles(params->fractionTransferredAbove, fracTransAbove) &&
30+
compareDoubles(params->fractionTransferredBelow, fracTransBelow));
3531
}
3632

37-
int checkIrrigationParams(
38-
IrrigationParams *params,
39-
double amountAdded,
40-
int method
41-
) {
42-
return !(
43-
compareDoubles(params->amountAdded, amountAdded) &&
44-
params->method == method
45-
);
33+
int checkIrrigationParams(IrrigationParams *params, double amountAdded,
34+
int method) {
35+
return !(compareDoubles(params->amountAdded, amountAdded) &&
36+
params->method == method);
4637
}
4738

48-
int checkFertilizationParams(
49-
FertilizationParams *params,
50-
double orgN,
51-
double orgC,
52-
double minN
53-
) {
54-
return !(
55-
compareDoubles(params->orgN, orgN) &&
56-
compareDoubles(params->orgC, orgC) &&
57-
compareDoubles(params->minN, minN)
58-
);
39+
int checkFertilizationParams(FertilizationParams *params, double orgN,
40+
double orgC, double minN) {
41+
return !(compareDoubles(params->orgN, orgN) &&
42+
compareDoubles(params->orgC, orgC) &&
43+
compareDoubles(params->minN, minN));
5944
}
6045

61-
int checkPlantingParams(
62-
PlantingParams *params, int emergenceLag, double addedC, double addedN
63-
) {
64-
return !(
65-
params->emergenceLag == emergenceLag &&
66-
compareDoubles(params->addedC, addedC) &&
67-
compareDoubles(params->addedN, addedN)
68-
);
46+
int checkPlantingParams(PlantingParams *params, int emergenceLag, double addedC,
47+
double addedN) {
48+
return !(params->emergenceLag == emergenceLag &&
49+
compareDoubles(params->addedC, addedC) &&
50+
compareDoubles(params->addedN, addedN));
6951
}
7052

71-
int checkTillageParams(
72-
TillageParams *params,
73-
double fracLitterTransferred,
74-
double somDecompModifier,
75-
double litterDecompModifier
76-
) {
77-
return !(
78-
compareDoubles(params->fractionLitterTransferred, fracLitterTransferred) &&
79-
compareDoubles(params->somDecompModifier, somDecompModifier) &&
80-
compareDoubles(params->litterDecompModifier, litterDecompModifier)
81-
);
53+
int checkTillageParams(TillageParams *params, double fracLitterTransferred,
54+
double somDecompModifier, double litterDecompModifier) {
55+
return !(compareDoubles(params->fractionLitterTransferred,
56+
fracLitterTransferred) &&
57+
compareDoubles(params->somDecompModifier, somDecompModifier) &&
58+
compareDoubles(params->litterDecompModifier, litterDecompModifier));
8259
}
8360

84-
int init() {
85-
// char * filename = "infra_events_simple.in";
86-
// if (access(filename, F_OK) == -1) {
87-
// return 1;
88-
// }
89-
//
90-
// return copyFile(filename, "events.in");
91-
return 0;
61+
int init(void) { return 0; }
62+
63+
int runTestEmpty(void) {
64+
int numLocs = 2;
65+
int status = 0;
66+
// Should return empty for no file
67+
EventNode **output = readEventData("infra_events_no_file.in", numLocs);
68+
status |= !((output[0] == NULL) && (output[1] == NULL));
69+
output = readEventData("infra_events_empty_file.in", numLocs);
70+
status |= !((output[0] == NULL) && (output[1] == NULL));
71+
72+
return status;
9273
}
9374

94-
int runTestSimple() {
75+
int runTestSimple(void) {
9576
// Simple test with one loc, one event per type
9677
int numLocs = 1;
97-
EventNode** output = readEventData("infra_events_simple.in", numLocs);
78+
EventNode **output = readEventData("infra_events_simple.in", numLocs);
9879

99-
if (!output) {
80+
if (!output || !output[0]) {
10081
return 1;
10182
}
10283

10384
// check output is correct
10485
int status = 0;
10586
EventNode *event = output[0];
10687
status |= checkEvent(event, 0, 2022, 40, IRRIGATION);
107-
status |= checkIrrigationParams((IrrigationParams*)event->eventParams, 5, 0);
88+
status |= checkIrrigationParams((IrrigationParams *)event->eventParams, 5, 0);
10889
event = event->nextEvent;
10990
status |= checkEvent(event, 0, 2022, 40, FERTILIZATION);
110-
status |= checkFertilizationParams((FertilizationParams*)event->eventParams, 15, 5,10);
91+
status |= checkFertilizationParams((FertilizationParams *)event->eventParams,
92+
15, 5, 10);
11193
event = event->nextEvent;
11294
status |= checkEvent(event, 0, 2022, 45, TILLAGE);
113-
status |= checkTillageParams((TillageParams*)event->eventParams, 0.1, 0.2, 0.3);
95+
status |=
96+
checkTillageParams((TillageParams *)event->eventParams, 0.1, 0.2, 0.3);
11497
event = event->nextEvent;
11598
status |= checkEvent(event, 0, 2022, 46, PLANTING);
116-
status |= checkPlantingParams((PlantingParams*)event->eventParams, 10, 10, 1);
99+
status |=
100+
checkPlantingParams((PlantingParams *)event->eventParams, 10, 10, 1);
117101
event = event->nextEvent;
118102
status |= checkEvent(event, 0, 2022, 250, HARVEST);
119-
status |= checkHarvestParams((HarvestParams*)event->eventParams, 0.4, 0.1, 0.2, 0.3);
103+
status |= checkHarvestParams((HarvestParams *)event->eventParams, 0.4, 0.1,
104+
0.2, 0.3);
120105

121106
return status;
122107
}
123108

124-
int runTestMulti() {
109+
int runTestMulti(void) {
125110
// More complex test; multiple locations
126111
int numLocs = 1;
127-
EventNode** output = readEventData("infra_events_multi.in", numLocs);
112+
EventNode **output = readEventData("infra_events_multi.in", numLocs);
128113

129114
if (!output) {
130115
return 1;
@@ -135,61 +120,78 @@ int runTestMulti() {
135120
int loc = 0;
136121
EventNode *event = output[loc];
137122
status |= checkEvent(event, loc, 2024, 60, TILLAGE);
138-
status |= checkTillageParams((TillageParams*)event->eventParams, 0.1, 0.2, 0.3);
123+
status |=
124+
checkTillageParams((TillageParams *)event->eventParams, 0.1, 0.2, 0.3);
139125
event = event->nextEvent;
140126
status |= checkEvent(event, loc, 2024, 65, PLANTING);
141-
status |= checkPlantingParams((PlantingParams*)event->eventParams, 15, 20, 5);
127+
status |=
128+
checkPlantingParams((PlantingParams *)event->eventParams, 15, 20, 5);
142129
event = event->nextEvent;
143130
status |= checkEvent(event, loc, 2024, 70, IRRIGATION);
144-
status |= checkIrrigationParams((IrrigationParams*)event->eventParams, 5, 1);
131+
status |= checkIrrigationParams((IrrigationParams *)event->eventParams, 5, 1);
145132
event = event->nextEvent;
146133
status |= checkEvent(event, loc, 2024, 75, FERTILIZATION);
147-
status |= checkFertilizationParams((FertilizationParams*)event->eventParams, 15, 10,5);
134+
status |= checkFertilizationParams((FertilizationParams *)event->eventParams,
135+
15, 10, 5);
148136
event = event->nextEvent;
149137
status |= checkEvent(event, loc, 2024, 250, HARVEST);
150-
status |= checkHarvestParams((HarvestParams*)event->eventParams, 0.1, 0.2, 0.3, 0.4);
138+
status |= checkHarvestParams((HarvestParams *)event->eventParams, 0.1, 0.2,
139+
0.3, 0.4);
151140

152141
loc++;
153142
event = output[loc];
154143
status |= checkEvent(event, loc, 2024, 59, TILLAGE);
155-
status |= checkTillageParams((TillageParams*)event->eventParams, 0.2, 0.3, 0.1);
144+
status |=
145+
checkTillageParams((TillageParams *)event->eventParams, 0.2, 0.3, 0.1);
156146
event = event->nextEvent;
157147
status |= checkEvent(event, loc, 2024, 64, PLANTING);
158-
status |= checkPlantingParams((PlantingParams*)event->eventParams, 15, 20, 5);
148+
status |=
149+
checkPlantingParams((PlantingParams *)event->eventParams, 15, 20, 5);
159150
event = event->nextEvent;
160151
status |= checkEvent(event, loc, 2024, 69, IRRIGATION);
161-
status |= checkIrrigationParams((IrrigationParams*)event->eventParams, 5, 0);
152+
status |= checkIrrigationParams((IrrigationParams *)event->eventParams, 5, 0);
162153
event = event->nextEvent;
163154
status |= checkEvent(event, loc, 2024, 74, FERTILIZATION);
164-
status |= checkFertilizationParams((FertilizationParams*)event->eventParams, 5, 15,10);
155+
status |= checkFertilizationParams((FertilizationParams *)event->eventParams,
156+
5, 15, 10);
165157
event = event->nextEvent;
166158
status |= checkEvent(event, loc, 2024, 249, HARVEST);
167-
status |= checkHarvestParams((HarvestParams*)event->eventParams, 0.2, 0.3, 0.4, 0.1);
159+
status |= checkHarvestParams((HarvestParams *)event->eventParams, 0.2, 0.3,
160+
0.4, 0.1);
168161

169162
loc++;
170163
event = output[loc];
171164
status |= checkEvent(event, loc, 2024, 58, TILLAGE);
172-
status |= checkTillageParams((TillageParams*)event->eventParams, 0.3, 0.1, 0.2);
165+
status |=
166+
checkTillageParams((TillageParams *)event->eventParams, 0.3, 0.1, 0.2);
173167
event = event->nextEvent;
174168
status |= checkEvent(event, loc, 2024, 63, PLANTING);
175-
status |= checkPlantingParams((PlantingParams*)event->eventParams, 15, 20, 5);
169+
status |=
170+
checkPlantingParams((PlantingParams *)event->eventParams, 15, 20, 5);
176171
event = event->nextEvent;
177172
status |= checkEvent(event, loc, 2024, 68, IRRIGATION);
178-
status |= checkIrrigationParams((IrrigationParams*)event->eventParams, 6, 1);
173+
status |= checkIrrigationParams((IrrigationParams *)event->eventParams, 6, 1);
179174
event = event->nextEvent;
180175
status |= checkEvent(event, loc, 2024, 73, FERTILIZATION);
181-
status |= checkFertilizationParams((FertilizationParams*)event->eventParams, 5, 10,15);
176+
status |= checkFertilizationParams((FertilizationParams *)event->eventParams,
177+
5, 10, 15);
182178
event = event->nextEvent;
183179
status |= checkEvent(event, loc, 2024, 248, HARVEST);
184-
status |= checkHarvestParams((HarvestParams*)event->eventParams, 0.3, 0.4, 0.1, 0.2);
180+
status |= checkHarvestParams((HarvestParams *)event->eventParams, 0.3, 0.4,
181+
0.1, 0.2);
185182

186183
return status;
187184
}
188185

189-
int run() {
186+
int run(void) {
190187

191188
int status;
192189

190+
status = runTestEmpty();
191+
if (status) {
192+
return 1;
193+
}
194+
193195
status = runTestSimple();
194196
if (status) {
195197
return 1;
@@ -203,20 +205,20 @@ int run() {
203205
return 0;
204206
}
205207

206-
void cleanup() {
208+
void cleanup(void) {
207209
// Perform any cleanup as needed
208210
// None needed here, we can leave the copied file
209211
}
210212

211-
int main() {
213+
int main(void) {
212214
int status;
213-
status = init();
214-
if (status) {
215-
printf("Test initialization failed with status %d\n", status);
216-
exit(status);
217-
} else {
218-
printf("Test initialized\n");
219-
}
215+
// status = init();
216+
// if (status) {
217+
// printf("Test initialization failed with status %d\n", status);
218+
// exit(status);
219+
// } else {
220+
printf("Test initialized\n");
221+
// }
220222

221223
printf("Starting run()\n");
222224
status = run();
@@ -228,4 +230,4 @@ int main() {
228230
printf("testEventInfra PASSED\n");
229231

230232
cleanup();
231-
}
233+
}

0 commit comments

Comments
 (0)