• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

MapServer / MapServer / 25968262348

16 May 2026 05:24PM UTC coverage: 42.534% (+0.1%) from 42.439%
25968262348

Pull #7507

github

web-flow
Merge 4053aab2f into 9e1ae01f6
Pull Request #7507: Implementation for MS RFC 142 (scalebar geodesic measurement)

178 of 199 new or added lines in 4 files covered. (89.45%)

25425 existing lines in 4 files now uncovered.

64905 of 152594 relevant lines covered (42.53%)

27351.34 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.3
/tests/unit/test.cpp
1
#include "../../src/mapserver.h"
2
#include "../../src/maperror.h"
3

4
#include <cmath>
5

6
extern "C" void freeScalebar(scalebarObj *scalebar);
7
extern "C" int msCopyScalebar(scalebarObj *dst, const scalebarObj *src);
8

9
/* ----------------------------------------------------------------------- */
10

11
int gTestRetCode = 0;
12

13
// Poor man GoogleTest like framework
14

15
static void EXPECT_STREQ_func(const char *got, const char *expected,
28✔
16
                              const char *function, int line) {
17
  if (strcmp(got, expected) != 0) {
28✔
18
    fprintf(stderr, "EXPECT_STREQ(\"%s\", \"%s\") failed at %s:%d\n", got,
×
19
            expected, function, line);
20
    gTestRetCode = 1;
×
21
  }
22
}
28✔
23

24
#define EXPECT_STREQ(got, expected)                                            \
25
  EXPECT_STREQ_func(got, expected, __func__, __LINE__)
26

27
static void EXPECT_TRUE_FUNC(bool cond, const char *condstr,
28
                             const char *function, int line) {
29
  if (!cond) {
30✔
30
    fprintf(stderr, "EXPECT_TRUE(\"%s\") failed at %s:%d\n", condstr, function,
×
31
            line);
32
    gTestRetCode = 1;
×
33
  }
34
}
35

36
#define EXPECT_TRUE(cond) EXPECT_TRUE_FUNC(cond, #cond, __func__, __LINE__)
37

38
static void EXPECT_NEAR_FUNC(double got, double expected, double tolerance,
8✔
39
                             const char *gotstr, const char *expectedstr,
40
                             const char *function, int line) {
41
  if (std::fabs(got - expected) > tolerance) {
8✔
NEW
42
    fprintf(stderr,
×
43
            "EXPECT_NEAR(\"%s\", \"%s\") failed at %s:%d: got %.15g, "
44
            "expected %.15g, tolerance %.15g\n",
45
            gotstr, expectedstr, function, line, got, expected, tolerance);
NEW
46
    gTestRetCode = 1;
×
47
  }
48
}
8✔
49

50
#define EXPECT_NEAR(got, expected, tolerance)                                  \
51
  EXPECT_NEAR_FUNC(got, expected, tolerance, #got, #expected, __func__,        \
52
                   __LINE__)
53

54
/* ----------------------------------------------------------------------- */
55

56
static void testRedactCredentials() {
2✔
57
  {
58
    std::string s("foo");
2✔
59
    msRedactCredentials(&s[0]);
2✔
60
    EXPECT_STREQ(s.data(), "foo");
2✔
61
  }
62
  {
63
    std::string s("password=");
2✔
64
    msRedactCredentials(&s[0]);
2✔
65
    EXPECT_STREQ(s.data(), "password=");
2✔
66
  }
67
  {
68
    std::string s("PG:dbname=foo password=mypassword");
2✔
69
    msRedactCredentials(&s[0]);
2✔
70
    EXPECT_STREQ(s.data(), "PG:dbname=foo password=*");
2✔
71
  }
72
  {
73
    std::string s("PG:dbname=foo password=mypassword\n");
2✔
74
    msRedactCredentials(&s[0]);
2✔
75
    EXPECT_STREQ(s.data(), "PG:dbname=foo password=*\n");
2✔
76
  }
77
  {
78
    std::string s("PG:dbname=foo password=mypassword something=else\n");
2✔
79
    msRedactCredentials(&s[0]);
2✔
80
    EXPECT_STREQ(s.data(), "PG:dbname=foo password=* something=else\n");
2✔
81
  }
82
  {
83
    std::string s(
84
        "PG:dbname=foo password='mypassword with\"\\'space' something=else\n");
2✔
85
    msRedactCredentials(&s[0]);
2✔
86
    EXPECT_STREQ(s.data(), "PG:dbname=foo password='*' something=else\n");
2✔
87
  }
88
  {
89
    std::string s("\\SQL2019;DATABASE=msautotest;pwd=Password12!;uid=sa;\n");
2✔
90
    msRedactCredentials(&s[0]);
2✔
91
    EXPECT_STREQ(s.data(), "\\SQL2019;DATABASE=msautotest;pwd=*;uid=sa;\n");
2✔
92
  }
93
  {
94
    std::string s(
95
        "\\SQL2019;DATABASE=msautotest;pwd={Password12!;foo};uid=sa;\n");
2✔
96
    msRedactCredentials(&s[0]);
2✔
97
    EXPECT_STREQ(s.data(), "\\SQL2019;DATABASE=msautotest;pwd={*};uid=sa;\n");
2✔
98
  }
99
}
2✔
100

101
/* ----------------------------------------------------------------------- */
102

103
static void testToString() {
2✔
104
  {
105
    char *ret = msToString("x%f %%y", 1.5);
2✔
106
    EXPECT_STREQ(ret, "x1.500000 %y");
2✔
107
    msFree(ret);
2✔
108
  }
109
  {
110
    char *ret = msToString("%+f", 1.5);
2✔
111
    EXPECT_STREQ(ret, "+1.500000");
2✔
112
    msFree(ret);
2✔
113
  }
114
  {
115
    char *ret = msToString("%5.2f", 1.5);
2✔
116
    EXPECT_STREQ(ret, " 1.50");
2✔
117
    msFree(ret);
2✔
118
  }
119
  {
120
    char *ret = msToString("%f", 1e308);
2✔
121
    EXPECT_STREQ(
2✔
122
        ret, "10000000000000000109790636294404554174049230967731184633681068290"
123
             "31575854049114915371633289784946888990612496697211725156115902837"
124
             "43140088328307009198146046031271664502933027185697489699588559043"
125
             "33838446616500117842689762621294517762809119578670745812278397017"
126
             "1784415105291802893207873272974885715430223118336.000000");
127
    msFree(ret);
2✔
128
  }
129
  {
130
    char *ret = msToString("%1f", 1e308);
2✔
131
    EXPECT_STREQ(
2✔
132
        ret, "10000000000000000109790636294404554174049230967731184633681068290"
133
             "31575854049114915371633289784946888990612496697211725156115902837"
134
             "43140088328307009198146046031271664502933027185697489699588559043"
135
             "33838446616500117842689762621294517762809119578670745812278397017"
136
             "1784415105291802893207873272974885715430223118336.000000");
137
    msFree(ret);
2✔
138
  }
139
  {
140
    char *ret = msToString("%320f", 1e308);
2✔
141
    EXPECT_STREQ(
2✔
142
        ret, "    "
143
             "10000000000000000109790636294404554174049230967731184633681068290"
144
             "31575854049114915371633289784946888990612496697211725156115902837"
145
             "43140088328307009198146046031271664502933027185697489699588559043"
146
             "33838446616500117842689762621294517762809119578670745812278397017"
147
             "1784415105291802893207873272974885715430223118336.000000");
148
    msFree(ret);
2✔
149
  }
150
  {
151
    char *ret = msToString("%f%f", 1);
2✔
152
    EXPECT_TRUE(ret == nullptr);
153
    msFree(ret);
2✔
154
  }
155
  {
156
    char *ret = msToString("%s", 1);
2✔
157
    EXPECT_TRUE(ret == nullptr);
158
    msFree(ret);
2✔
159
  }
160
  {
161
    char *ret = msToString("%100000f", 1);
2✔
162
    EXPECT_TRUE(ret == nullptr);
163
    msFree(ret);
2✔
164
  }
165
}
2✔
166

167
/* ----------------------------------------------------------------------- */
168

169
static void testScalebarMeasure() {
2✔
170
  {
171
    scalebarObj scalebar;
172
    initScalebar(&scalebar);
2✔
173
    EXPECT_TRUE(scalebar.measure == MS_SCALEBAR_MEASURE_CARTESIAN);
2✔
174
    freeScalebar(&scalebar);
2✔
175
  }
176
  {
177
    char snippet[] = "SCALEBAR\n  MEASURE GEODESIC\nEND\n";
2✔
178
    scalebarObj scalebar;
179
    initScalebar(&scalebar);
2✔
180
    EXPECT_TRUE(msUpdateScalebarFromString(&scalebar, snippet) == MS_SUCCESS);
2✔
181
    EXPECT_TRUE(scalebar.measure == MS_SCALEBAR_MEASURE_GEODESIC);
2✔
182

183
    char *serialized = msWriteScalebarToString(&scalebar);
2✔
184
    EXPECT_TRUE(strstr(serialized, "MEASURE GEODESIC") != nullptr);
185
    msFree(serialized);
2✔
186
    freeScalebar(&scalebar);
2✔
187
  }
188
  {
189
    char snippet[] = "SCALEBAR\n  MEASURE RHUMB\nEND\n";
2✔
190
    scalebarObj scalebar;
191
    initScalebar(&scalebar);
2✔
192
    EXPECT_TRUE(msUpdateScalebarFromString(&scalebar, snippet) == MS_FAILURE);
2✔
193
    freeScalebar(&scalebar);
2✔
194
  }
195
  {
196
    scalebarObj source;
197
    scalebarObj copy;
198
    initScalebar(&source);
2✔
199
    source.measure = MS_SCALEBAR_MEASURE_GEODESIC;
2✔
200
    EXPECT_TRUE(msCopyScalebar(&copy, &source) == MS_SUCCESS);
2✔
201
    EXPECT_TRUE(copy.measure == MS_SCALEBAR_MEASURE_GEODESIC);
2✔
202
    freeScalebar(&copy);
2✔
203
    freeScalebar(&source);
2✔
204
  }
205
}
2✔
206

207
/* ----------------------------------------------------------------------- */
208

209
static mapObj *createWebMercatorMap(double center_y) {
6✔
210
  mapObj *map = msNewMapObj();
6✔
211
  if (!map)
6✔
212
    return nullptr;
213

214
  map->width = 200;
6✔
215
  map->height = 100;
6✔
216
  map->units = MS_METERS;
6✔
217
  map->extent.minx = -1000000;
6✔
218
  map->extent.maxx = 1000000;
6✔
219
  map->extent.miny = center_y - 500000;
6✔
220
  map->extent.maxy = center_y + 500000;
6✔
221
  map->cellsize = msAdjustExtent(&map->extent, map->width, map->height);
6✔
222

223
  if (msLoadProjectionString(&map->projection, "init=epsg:3857") !=
6✔
224
      MS_SUCCESS) {
NEW
225
    msFreeMap(map);
×
NEW
226
    return nullptr;
×
227
  }
228

229
  map->scalebar.units = MS_KILOMETERS;
6✔
230
  return map;
6✔
231
}
232

233
static mapObj *createGeographicMap() {
2✔
234
  mapObj *map = msNewMapObj();
2✔
235
  if (!map)
2✔
236
    return nullptr;
237

238
  map->width = 200;
2✔
239
  map->height = 100;
2✔
240
  map->units = MS_DD;
2✔
241
  map->extent.minx = -5;
2✔
242
  map->extent.maxx = 5;
2✔
243
  map->extent.miny = -2.5;
2✔
244
  map->extent.maxy = 2.5;
2✔
245
  map->cellsize = msAdjustExtent(&map->extent, map->width, map->height);
2✔
246
  map->scalebar.units = MS_KILOMETERS;
2✔
247
  return map;
2✔
248
}
249

250
static void testScalebarMeasurePixelSpan() {
2✔
251
  {
252
    mapObj *map = createWebMercatorMap(0);
2✔
253
    double cartesian_distance = 0;
2✔
254
    double geodesic_distance = 0;
2✔
255
    EXPECT_TRUE(map != nullptr);
256
    if (!map)
NEW
257
      return;
×
258

259
    const double expected_cartesian_distance =
260
        MS_CONVERT_UNIT(MS_METERS, MS_KILOMETERS, map->cellsize * 100);
2✔
261

262
    map->scalebar.position = MS_CC;
2✔
263
    map->scalebar.measure = MS_SCALEBAR_MEASURE_CARTESIAN;
2✔
264
    EXPECT_TRUE(msScalebarMeasurePixelSpan(map, &map->scalebar, 100,
2✔
265
                                           &cartesian_distance) == MS_SUCCESS);
266
    EXPECT_NEAR(cartesian_distance, expected_cartesian_distance, 0.001);
2✔
267

268
    map->scalebar.measure = MS_SCALEBAR_MEASURE_GEODESIC;
2✔
269
    EXPECT_TRUE(msScalebarMeasurePixelSpan(map, &map->scalebar, 100,
2✔
270
                                           &geodesic_distance) == MS_SUCCESS);
271
    EXPECT_NEAR(geodesic_distance, expected_cartesian_distance, 0.5);
2✔
272

273
    msFreeMap(map);
2✔
274
  }
275
  {
276
    mapObj *map = createWebMercatorMap(8399737.889818357);
2✔
277
    double cartesian_distance = 0;
2✔
278
    double geodesic_distance = 0;
2✔
279
    EXPECT_TRUE(map != nullptr);
280
    if (!map)
NEW
281
      return;
×
282

283
    const double expected_cartesian_distance =
284
        MS_CONVERT_UNIT(MS_METERS, MS_KILOMETERS, map->cellsize * 100);
2✔
285

286
    map->scalebar.position = MS_CC;
2✔
287
    map->scalebar.measure = MS_SCALEBAR_MEASURE_CARTESIAN;
2✔
288
    EXPECT_TRUE(msScalebarMeasurePixelSpan(map, &map->scalebar, 100,
2✔
289
                                           &cartesian_distance) == MS_SUCCESS);
290
    EXPECT_NEAR(cartesian_distance, expected_cartesian_distance, 0.001);
2✔
291

292
    map->scalebar.measure = MS_SCALEBAR_MEASURE_GEODESIC;
2✔
293
    EXPECT_TRUE(msScalebarMeasurePixelSpan(map, &map->scalebar, 100,
2✔
294
                                           &geodesic_distance) == MS_SUCCESS);
295
    EXPECT_TRUE(geodesic_distance < cartesian_distance * 0.55);
2✔
296
    EXPECT_TRUE(geodesic_distance > cartesian_distance * 0.45);
2✔
297

298
    msFreeMap(map);
2✔
299
  }
300
  {
301
    mapObj *map = createWebMercatorMap(8399737.889818357);
2✔
302
    double lower_distance = 0;
2✔
303
    double upper_distance = 0;
2✔
304
    double upper_offset_distance = 0;
2✔
305
    EXPECT_TRUE(map != nullptr);
306
    if (!map)
NEW
307
      return;
×
308

309
    map->scalebar.measure = MS_SCALEBAR_MEASURE_GEODESIC;
2✔
310

311
    map->scalebar.position = MS_LC;
2✔
312
    map->scalebar.offsety = 0;
2✔
313
    EXPECT_TRUE(msScalebarMeasurePixelSpan(map, &map->scalebar, 100,
2✔
314
                                           &lower_distance) == MS_SUCCESS);
315

316
    map->scalebar.position = MS_UC;
2✔
317
    map->scalebar.offsety = 0;
2✔
318
    EXPECT_TRUE(msScalebarMeasurePixelSpan(map, &map->scalebar, 100,
2✔
319
                                           &upper_distance) == MS_SUCCESS);
320

321
    map->scalebar.offsety = 20;
2✔
322
    EXPECT_TRUE(msScalebarMeasurePixelSpan(map, &map->scalebar, 100,
2✔
323
                                           &upper_offset_distance) ==
324
                MS_SUCCESS);
325

326
    EXPECT_TRUE(lower_distance > upper_distance);
2✔
327
    EXPECT_TRUE(upper_offset_distance > upper_distance);
2✔
328
    EXPECT_TRUE(upper_offset_distance < lower_distance);
2✔
329

330
    msFreeMap(map);
2✔
331
  }
332
  {
333
    mapObj *map = createGeographicMap();
2✔
334
    double geodesic_distance = 0;
2✔
335
    EXPECT_TRUE(map != nullptr);
336
    if (!map)
NEW
337
      return;
×
338

339
    EXPECT_TRUE(map->projection.proj == nullptr);
2✔
340

341
    const double expected_equator_distance =
2✔
342
        map->cellsize * 100 * 111.31949079327358;
2✔
343

344
    map->scalebar.position = MS_CC;
2✔
345
    map->scalebar.measure = MS_SCALEBAR_MEASURE_GEODESIC;
2✔
346
    EXPECT_TRUE(msScalebarMeasurePixelSpan(map, &map->scalebar, 100,
2✔
347
                                           &geodesic_distance) == MS_SUCCESS);
348
    EXPECT_NEAR(geodesic_distance, expected_equator_distance, 0.001);
2✔
349

350
    msFreeMap(map);
2✔
351
  }
352
}
353

354
/* ----------------------------------------------------------------------- */
355

356
int main() {
2✔
357
  testRedactCredentials();
2✔
358
  testToString();
2✔
359
  testScalebarMeasure();
2✔
360
  testScalebarMeasurePixelSpan();
2✔
361
  return gTestRetCode;
2✔
362
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc