testSystemTools.cxx 39.1 KB
Newer Older
1
2
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing#kwsys for details.  */
3
#include "kwsysPrivate.h"
4
5

#if defined(_MSC_VER)
6
#  pragma warning(disable : 4786)
7
8
#endif

9
#include KWSYS_HEADER(FStream.hxx)
10
11
#include KWSYS_HEADER(SystemTools.hxx)

12
13
14
// Work-around CMake dependency scanning limitation.  This must
// duplicate the above list of headers.
#if 0
15
16
#  include "FStream.hxx.in"
#  include "SystemTools.hxx.in"
17
18
#endif

19
20
21
// Include with <> instead of "" to avoid getting any in-source copy
// left on disk.
#include <testSystemTools.h>
22

23
24
#include <cstdlib> /* free */
#include <cstring> /* strcmp */
25
#include <iostream>
26
#include <sstream>
27
#if defined(_WIN32) && !defined(__CYGWIN__)
28
29
30
31
#  include <io.h> /* _umask (MSVC) / umask (Borland) */
#  ifdef _MSC_VER
#    define umask _umask // Note this is still umask on Borland
#  endif
32
33
34
#endif
#include <sys/stat.h> /* umask (POSIX), _S_I* constants (Windows) */
// Visual C++ does not define mode_t (note that Borland does, however).
35
#if defined(_MSC_VER)
36
37
typedef unsigned short mode_t;
#endif
38

39
40
41
static const char* toUnixPaths[][2] = {
  { "/usr/local/bin/passwd", "/usr/local/bin/passwd" },
  { "/usr/lo cal/bin/pa sswd", "/usr/lo cal/bin/pa sswd" },
42
  { "/usr/lo\\ cal/bin/pa\\ sswd", "/usr/lo/ cal/bin/pa/ sswd" },
43
44
  { "c:/usr/local/bin/passwd", "c:/usr/local/bin/passwd" },
  { "c:/usr/lo cal/bin/pa sswd", "c:/usr/lo cal/bin/pa sswd" },
45
  { "c:/usr/lo\\ cal/bin/pa\\ sswd", "c:/usr/lo/ cal/bin/pa/ sswd" },
46
47
  { "\\usr\\local\\bin\\passwd", "/usr/local/bin/passwd" },
  { "\\usr\\lo cal\\bin\\pa sswd", "/usr/lo cal/bin/pa sswd" },
48
  { "\\usr\\lo\\ cal\\bin\\pa\\ sswd", "/usr/lo/ cal/bin/pa/ sswd" },
49
50
  { "c:\\usr\\local\\bin\\passwd", "c:/usr/local/bin/passwd" },
  { "c:\\usr\\lo cal\\bin\\pa sswd", "c:/usr/lo cal/bin/pa sswd" },
51
  { "c:\\usr\\lo\\ cal\\bin\\pa\\ sswd", "c:/usr/lo/ cal/bin/pa/ sswd" },
52
53
  { "\\\\usr\\local\\bin\\passwd", "//usr/local/bin/passwd" },
  { "\\\\usr\\lo cal\\bin\\pa sswd", "//usr/lo cal/bin/pa sswd" },
54
  { "\\\\usr\\lo\\ cal\\bin\\pa\\ sswd", "//usr/lo/ cal/bin/pa/ sswd" },
55
  { nullptr, nullptr }
56
57
};

Daniel Pfeifer's avatar
Daniel Pfeifer committed
58
59
static bool CheckConvertToUnixSlashes(std::string const& input,
                                      std::string const& output)
60
{
Brad King's avatar
Brad King committed
61
  std::string result = input;
62
  kwsys::SystemTools::ConvertToUnixSlashes(result);
63
64
65
  if (result != output) {
    std::cerr << "Problem with ConvertToUnixSlashes - input: " << input
              << " output: " << result << " expected: " << output << std::endl;
66
    return false;
67
  }
68
69
70
  return true;
}

71
72
73
static const char* checkEscapeChars[][4] = {
  { "1 foo 2 bar 2", "12", "\\", "\\1 foo \\2 bar \\2" },
  { " {} ", "{}", "#", " #{#} " },
74
  { nullptr, nullptr, nullptr, nullptr }
75
};
76

Daniel Pfeifer's avatar
Daniel Pfeifer committed
77
78
79
static bool CheckEscapeChars(std::string const& input,
                             const char* chars_to_escape, char escape_char,
                             std::string const& output)
80
{
Brad King's avatar
Brad King committed
81
  std::string result = kwsys::SystemTools::EscapeChars(
82
    input.c_str(), chars_to_escape, escape_char);
83
84
85
  if (result != output) {
    std::cerr << "Problem with CheckEscapeChars - input: " << input
              << " output: " << result << " expected: " << output << std::endl;
86
    return false;
87
  }
88
89
90
  return true;
}

Sean McBride's avatar
Sean McBride committed
91
static bool CheckFileOperations()
92
93
{
  bool res = true;
Brad King's avatar
Brad King committed
94
  const std::string testNonExistingFile(TEST_SYSTEMTOOLS_SOURCE_DIR
95
96
                                        "/testSystemToolsNonExistingFile");
  const std::string testDotFile(TEST_SYSTEMTOOLS_SOURCE_DIR "/.");
Brad King's avatar
Brad King committed
97
  const std::string testBinFile(TEST_SYSTEMTOOLS_SOURCE_DIR
98
                                "/testSystemTools.bin");
Brad King's avatar
Brad King committed
99
  const std::string testTxtFile(TEST_SYSTEMTOOLS_SOURCE_DIR
100
                                "/testSystemTools.cxx");
Brad King's avatar
Brad King committed
101
  const std::string testNewDir(TEST_SYSTEMTOOLS_BINARY_DIR
102
                               "/testSystemToolsNewDir");
Brad King's avatar
Brad King committed
103
  const std::string testNewFile(testNewDir + "/testNewFile.txt");
104

105
  if (kwsys::SystemTools::DetectFileType(testNonExistingFile.c_str()) !=
106
107
108
      kwsys::SystemTools::FileTypeUnknown) {
    std::cerr << "Problem with DetectFileType - failed to detect type of: "
              << testNonExistingFile << std::endl;
109
    res = false;
110
  }
111

112
  if (kwsys::SystemTools::DetectFileType(testDotFile.c_str()) !=
113
114
115
      kwsys::SystemTools::FileTypeUnknown) {
    std::cerr << "Problem with DetectFileType - failed to detect type of: "
              << testDotFile << std::endl;
116
    res = false;
117
  }
118

119
  if (kwsys::SystemTools::DetectFileType(testBinFile.c_str()) !=
120
121
122
      kwsys::SystemTools::FileTypeBinary) {
    std::cerr << "Problem with DetectFileType - failed to detect type of: "
              << testBinFile << std::endl;
123
    res = false;
124
  }
125

126
  if (kwsys::SystemTools::DetectFileType(testTxtFile.c_str()) !=
127
128
129
      kwsys::SystemTools::FileTypeText) {
    std::cerr << "Problem with DetectFileType - failed to detect type of: "
              << testTxtFile << std::endl;
130
    res = false;
131
  }
132

133
134
135
  if (kwsys::SystemTools::FileLength(testBinFile) != 766) {
    std::cerr << "Problem with FileLength - incorrect length for: "
              << testBinFile << std::endl;
136
    res = false;
137
  }
138

139
140
141
142
143
144
145
146
147
148
149
150
151
  kwsys::SystemTools::Stat_t buf;
  if (kwsys::SystemTools::Stat(testTxtFile.c_str(), &buf) != 0) {
    std::cerr << "Problem with Stat - unable to stat text file: "
              << testTxtFile << std::endl;
    res = false;
  }

  if (kwsys::SystemTools::Stat(testBinFile, &buf) != 0) {
    std::cerr << "Problem with Stat - unable to stat bin file: " << testBinFile
              << std::endl;
    res = false;
  }

152
153
  if (!kwsys::SystemTools::MakeDirectory(testNewDir)) {
    std::cerr << "Problem with MakeDirectory for: " << testNewDir << std::endl;
154
    res = false;
155
  }
156
  // calling it again should just return true
157
158
159
  if (!kwsys::SystemTools::MakeDirectory(testNewDir)) {
    std::cerr << "Problem with second call to MakeDirectory for: "
              << testNewDir << std::endl;
160
    res = false;
161
  }
162
  // calling with 0 pointer should return false
163
  if (kwsys::SystemTools::MakeDirectory(nullptr)) {
164
    std::cerr << "Problem with MakeDirectory(0)" << std::endl;
165
    res = false;
166
  }
167
  // calling with an empty string should return false
168
169
  if (kwsys::SystemTools::MakeDirectory(std::string())) {
    std::cerr << "Problem with MakeDirectory(std::string())" << std::endl;
170
    res = false;
171
  }
172
  // check existence
173
174
175
  if (!kwsys::SystemTools::FileExists(testNewDir.c_str(), false)) {
    std::cerr << "Problem with FileExists as C string and not file for: "
              << testNewDir << std::endl;
176
    res = false;
177
  }
178
  // check existence
179
180
  if (!kwsys::SystemTools::PathExists(testNewDir)) {
    std::cerr << "Problem with PathExists for: " << testNewDir << std::endl;
181
    res = false;
182
  }
183
  // remove it
184
185
186
  if (!kwsys::SystemTools::RemoveADirectory(testNewDir)) {
    std::cerr << "Problem with RemoveADirectory for: " << testNewDir
              << std::endl;
187
    res = false;
188
  }
189
  // check existence
190
191
192
193
  if (kwsys::SystemTools::FileExists(testNewDir.c_str(), false)) {
    std::cerr << "After RemoveADirectory: "
              << "Problem with FileExists as C string and not file for: "
              << testNewDir << std::endl;
194
    res = false;
195
  }
196
  // check existence
197
198
199
  if (kwsys::SystemTools::PathExists(testNewDir)) {
    std::cerr << "After RemoveADirectory: "
              << "Problem with PathExists for: " << testNewDir << std::endl;
200
    res = false;
201
  }
202
  // create it using the char* version
203
204
205
  if (!kwsys::SystemTools::MakeDirectory(testNewDir.c_str())) {
    std::cerr << "Problem with second call to MakeDirectory as C string for: "
              << testNewDir << std::endl;
206
    res = false;
207
  }
208

209
  if (!kwsys::SystemTools::Touch(testNewFile, true)) {
210
    std::cerr << "Problem with Touch for: " << testNewFile << std::endl;
211
    res = false;
212
  }
213
  // calling MakeDirectory with something that is no file should fail
214
215
216
  if (kwsys::SystemTools::MakeDirectory(testNewFile)) {
    std::cerr << "Problem with to MakeDirectory for: " << testNewFile
              << std::endl;
217
    res = false;
218
  }
219

220
  // calling with 0 pointer should return false
221
  if (kwsys::SystemTools::FileExists(nullptr)) {
222
    std::cerr << "Problem with FileExists(0)" << std::endl;
223
    res = false;
224
  }
225
  if (kwsys::SystemTools::FileExists(nullptr, true)) {
226
    std::cerr << "Problem with FileExists(0) as file" << std::endl;
227
    res = false;
228
  }
229
  // calling with an empty string should return false
230
231
  if (kwsys::SystemTools::FileExists(std::string())) {
    std::cerr << "Problem with FileExists(std::string())" << std::endl;
232
    res = false;
233
  }
234
  // FileExists(x, true) should return false on a directory
235
236
237
  if (kwsys::SystemTools::FileExists(testNewDir, true)) {
    std::cerr << "Problem with FileExists as file for: " << testNewDir
              << std::endl;
238
    res = false;
239
240
241
242
  }
  if (kwsys::SystemTools::FileExists(testNewDir.c_str(), true)) {
    std::cerr << "Problem with FileExists as C string and file for: "
              << testNewDir << std::endl;
243
    res = false;
244
  }
245
  // FileExists(x, false) should return true even on a directory
246
247
248
  if (!kwsys::SystemTools::FileExists(testNewDir, false)) {
    std::cerr << "Problem with FileExists as not file for: " << testNewDir
              << std::endl;
249
    res = false;
250
251
252
253
  }
  if (!kwsys::SystemTools::FileExists(testNewDir.c_str(), false)) {
    std::cerr << "Problem with FileExists as C string and not file for: "
              << testNewDir << std::endl;
254
    res = false;
255
  }
256
  // should work, was created as new file before
257
  if (!kwsys::SystemTools::FileExists(testNewFile)) {
258
    std::cerr << "Problem with FileExists for: " << testNewFile << std::endl;
259
    res = false;
260
261
  }
  if (!kwsys::SystemTools::FileExists(testNewFile.c_str())) {
262
    std::cerr << "Problem with FileExists as C string for: " << testNewFile
263
              << std::endl;
264
    res = false;
265
266
  }
  if (!kwsys::SystemTools::FileExists(testNewFile, true)) {
267
    std::cerr << "Problem with FileExists as file for: " << testNewFile
268
              << std::endl;
269
    res = false;
270
271
272
  }
  if (!kwsys::SystemTools::FileExists(testNewFile.c_str(), true)) {
    std::cerr << "Problem with FileExists as C string and file for: "
273
              << testNewFile << std::endl;
274
    res = false;
275
  }
276

277
  // calling with an empty string should return false
278
279
  if (kwsys::SystemTools::PathExists(std::string())) {
    std::cerr << "Problem with PathExists(std::string())" << std::endl;
280
    res = false;
281
  }
282
  // PathExists(x) should return true on a directory
283
284
  if (!kwsys::SystemTools::PathExists(testNewDir)) {
    std::cerr << "Problem with PathExists for: " << testNewDir << std::endl;
285
    res = false;
286
  }
287
  // should work, was created as new file before
288
  if (!kwsys::SystemTools::PathExists(testNewFile)) {
289
    std::cerr << "Problem with PathExists for: " << testNewFile << std::endl;
290
    res = false;
291
  }
292

293
// Reset umask
294
295
296
297
298
299
300
301
302
303
304
#if defined(_WIN32) && !defined(__CYGWIN__)
  // NOTE:  Windows doesn't support toggling _S_IREAD.
  mode_t fullMask = _S_IWRITE;
#else
  // On a normal POSIX platform, we can toggle all permissions.
  mode_t fullMask = S_IRWXU | S_IRWXG | S_IRWXO;
#endif
  mode_t orig_umask = umask(fullMask);

  // Test file permissions without umask
  mode_t origPerm, thisPerm;
305
306
307
  if (!kwsys::SystemTools::GetPermissions(testNewFile, origPerm)) {
    std::cerr << "Problem with GetPermissions (1) for: " << testNewFile
              << std::endl;
308
    res = false;
309
  }
310

311
312
313
  if (!kwsys::SystemTools::SetPermissions(testNewFile, 0)) {
    std::cerr << "Problem with SetPermissions (1) for: " << testNewFile
              << std::endl;
314
    res = false;
315
  }
316

317
318
319
  if (!kwsys::SystemTools::GetPermissions(testNewFile, thisPerm)) {
    std::cerr << "Problem with GetPermissions (2) for: " << testNewFile
              << std::endl;
320
    res = false;
321
  }
322

323
324
325
326
  if ((thisPerm & fullMask) != 0) {
    std::cerr << "SetPermissions failed to set permissions (1) for: "
              << testNewFile << ": actual = " << thisPerm
              << "; expected = " << 0 << std::endl;
327
    res = false;
328
  }
329
330

  // While we're at it, check proper TestFileAccess functionality.
331
332
333
334
335
336
337
338
  bool do_write_test = true;
#if defined(__linux__)
  // If we are running as root on linux ignore this check, as
  // root can always write to files
  do_write_test = (getuid() != 0);
#endif
  if (do_write_test &&
      kwsys::SystemTools::TestFileAccess(testNewFile,
339
                                         kwsys::TEST_FILE_WRITE)) {
340
    std::cerr
341
      << "TestFileAccess incorrectly indicated that this is a writable file:"
342
      << testNewFile << std::endl;
343
    res = false;
344
  }
345

346
  if (!kwsys::SystemTools::TestFileAccess(testNewFile, kwsys::TEST_FILE_OK)) {
347
    std::cerr
348
      << "TestFileAccess incorrectly indicated that this file does not exist:"
349
      << testNewFile << std::endl;
350
    res = false;
351
  }
352
353

  // Test restoring/setting full permissions.
354
355
356
  if (!kwsys::SystemTools::SetPermissions(testNewFile, fullMask)) {
    std::cerr << "Problem with SetPermissions (2) for: " << testNewFile
              << std::endl;
357
    res = false;
358
  }
359

360
361
362
  if (!kwsys::SystemTools::GetPermissions(testNewFile, thisPerm)) {
    std::cerr << "Problem with GetPermissions (3) for: " << testNewFile
              << std::endl;
363
    res = false;
364
  }
365

366
367
368
369
  if ((thisPerm & fullMask) != fullMask) {
    std::cerr << "SetPermissions failed to set permissions (2) for: "
              << testNewFile << ": actual = " << thisPerm
              << "; expected = " << fullMask << std::endl;
370
    res = false;
371
  }
372
373

  // Test setting file permissions while honoring umask
374
375
376
  if (!kwsys::SystemTools::SetPermissions(testNewFile, fullMask, true)) {
    std::cerr << "Problem with SetPermissions (3) for: " << testNewFile
              << std::endl;
377
    res = false;
378
  }
379

380
381
382
  if (!kwsys::SystemTools::GetPermissions(testNewFile, thisPerm)) {
    std::cerr << "Problem with GetPermissions (4) for: " << testNewFile
              << std::endl;
383
    res = false;
384
  }
385

386
387
388
389
  if ((thisPerm & fullMask) != 0) {
    std::cerr << "SetPermissions failed to honor umask for: " << testNewFile
              << ": actual = " << thisPerm << "; expected = " << 0
              << std::endl;
390
    res = false;
391
  }
392
393
394
395
396

  // Restore umask
  umask(orig_umask);

  // Restore file permissions
397
398
399
  if (!kwsys::SystemTools::SetPermissions(testNewFile, origPerm)) {
    std::cerr << "Problem with SetPermissions (4) for: " << testNewFile
              << std::endl;
400
    res = false;
401
  }
402
403

  // Remove the test file
404
405
  if (!kwsys::SystemTools::RemoveFile(testNewFile)) {
    std::cerr << "Problem with RemoveFile: " << testNewFile << std::endl;
406
    res = false;
407
  }
408

Brad King's avatar
Brad King committed
409
  std::string const testFileMissing(testNewDir + "/testMissingFile.txt");
410
  if (!kwsys::SystemTools::RemoveFile(testFileMissing)) {
411
    std::string const& msg = kwsys::SystemTools::GetLastSystemError();
412
413
    std::cerr << "RemoveFile(\"" << testFileMissing << "\") failed: " << msg
              << "\n";
414
    res = false;
415
  }
416

Brad King's avatar
Brad King committed
417
  std::string const testFileMissingDir(testNewDir + "/missing/file.txt");
418
  if (!kwsys::SystemTools::RemoveFile(testFileMissingDir)) {
419
    std::string const& msg = kwsys::SystemTools::GetLastSystemError();
420
421
    std::cerr << "RemoveFile(\"" << testFileMissingDir << "\") failed: " << msg
              << "\n";
422
    res = false;
423
  }
424

425
  kwsys::SystemTools::Touch(testNewFile, true);
426
427
428
  if (!kwsys::SystemTools::RemoveADirectory(testNewDir)) {
    std::cerr << "Problem with RemoveADirectory for: " << testNewDir
              << std::endl;
429
    res = false;
430
  }
431
432
433
434
435

#ifdef KWSYS_TEST_SYSTEMTOOLS_LONG_PATHS
  // Perform the same file and directory creation and deletion tests but
  // with paths > 256 characters in length.

Brad King's avatar
Brad King committed
436
  const std::string testNewLongDir(
437
438
    TEST_SYSTEMTOOLS_BINARY_DIR
    "/"
439
440
441
442
443
    "012345678901234567890123456789012345678901234567890123456789"
    "012345678901234567890123456789012345678901234567890123456789"
    "012345678901234567890123456789012345678901234567890123456789"
    "012345678901234567890123456789012345678901234567890123456789"
    "01234567890123");
444
445
446
  const std::string testNewLongFile(
    testNewLongDir +
    "/"
447
448
449
450
451
452
    "012345678901234567890123456789012345678901234567890123456789"
    "012345678901234567890123456789012345678901234567890123456789"
    "012345678901234567890123456789012345678901234567890123456789"
    "012345678901234567890123456789012345678901234567890123456789"
    "0123456789.txt");

453
454
455
  if (!kwsys::SystemTools::MakeDirectory(testNewLongDir)) {
    std::cerr << "Problem with MakeDirectory for: " << testNewLongDir
              << std::endl;
456
    res = false;
457
  }
458

459
460
  if (!kwsys::SystemTools::Touch(testNewLongFile.c_str(), true)) {
    std::cerr << "Problem with Touch for: " << testNewLongFile << std::endl;
461
    res = false;
462
  }
463

464
465
  if (!kwsys::SystemTools::RemoveFile(testNewLongFile)) {
    std::cerr << "Problem with RemoveFile: " << testNewLongFile << std::endl;
466
    res = false;
467
  }
468
469

  kwsys::SystemTools::Touch(testNewLongFile.c_str(), true);
470
471
472
  if (!kwsys::SystemTools::RemoveADirectory(testNewLongDir)) {
    std::cerr << "Problem with RemoveADirectory for: " << testNewLongDir
              << std::endl;
473
    res = false;
474
  }
475
476
#endif

477
478
479
  return res;
}

Sean McBride's avatar
Sean McBride committed
480
static bool CheckStringOperations()
481
482
483
{
  bool res = true;

Brad King's avatar
Brad King committed
484
  std::string test = "mary had a little lamb.";
485
486
487
488
  if (kwsys::SystemTools::CapitalizedWords(test) !=
      "Mary Had A Little Lamb.") {
    std::cerr << "Problem with CapitalizedWords " << '"' << test << '"'
              << std::endl;
489
    res = false;
490
  }
491
492

  test = "Mary Had A Little Lamb.";
493
  if (kwsys::SystemTools::UnCapitalizedWords(test) !=
494
495
496
      "mary had a little lamb.") {
    std::cerr << "Problem with UnCapitalizedWords " << '"' << test << '"'
              << std::endl;
497
    res = false;
498
  }
499
500

  test = "MaryHadTheLittleLamb.";
501
  if (kwsys::SystemTools::AddSpaceBetweenCapitalizedWords(test) !=
502
503
504
      "Mary Had The Little Lamb.") {
    std::cerr << "Problem with AddSpaceBetweenCapitalizedWords " << '"' << test
              << '"' << std::endl;
505
    res = false;
506
  }
507

508
509
  char* cres =
    kwsys::SystemTools::AppendStrings("Mary Had A", " Little Lamb.");
510
  if (strcmp(cres, "Mary Had A Little Lamb.") != 0) {
511
512
    std::cerr << "Problem with AppendStrings "
              << "\"Mary Had A\" \" Little Lamb.\"" << std::endl;
513
    res = false;
514
515
  }
  delete[] cres;
516

517
  cres = kwsys::SystemTools::AppendStrings("Mary Had", " A ", "Little Lamb.");
518
  if (strcmp(cres, "Mary Had A Little Lamb.") != 0) {
519
520
    std::cerr << "Problem with AppendStrings "
              << "\"Mary Had\" \" A \" \"Little Lamb.\"" << std::endl;
521
    res = false;
522
523
  }
  delete[] cres;
524

525
526
527
  if (kwsys::SystemTools::CountChar("Mary Had A Little Lamb.", 'a') != 3) {
    std::cerr << "Problem with CountChar "
              << "\"Mary Had A Little Lamb.\"" << std::endl;
528
    res = false;
529
  }
530

531
  cres = kwsys::SystemTools::RemoveChars("Mary Had A Little Lamb.", "aeiou");
532
  if (strcmp(cres, "Mry Hd A Lttl Lmb.") != 0) {
533
534
    std::cerr << "Problem with RemoveChars "
              << "\"Mary Had A Little Lamb.\"" << std::endl;
535
    res = false;
536
537
  }
  delete[] cres;
538

539
  cres = kwsys::SystemTools::RemoveCharsButUpperHex("Mary Had A Little Lamb.");
540
  if (strcmp(cres, "A") != 0) {
541
542
    std::cerr << "Problem with RemoveCharsButUpperHex "
              << "\"Mary Had A Little Lamb.\"" << std::endl;
543
    res = false;
544
545
  }
  delete[] cres;
546

547
  char* cres2 = strdup("Mary Had A Little Lamb.");
548
  kwsys::SystemTools::ReplaceChars(cres2, "aeiou", 'X');
549
  if (strcmp(cres2, "MXry HXd A LXttlX LXmb.") != 0) {
550
551
    std::cerr << "Problem with ReplaceChars "
              << "\"Mary Had A Little Lamb.\"" << std::endl;
552
    res = false;
553
  }
554
  free(cres2);
555
556

  if (!kwsys::SystemTools::StringStartsWith("Mary Had A Little Lamb.",
557
558
559
                                            "Mary ")) {
    std::cerr << "Problem with StringStartsWith "
              << "\"Mary Had A Little Lamb.\"" << std::endl;
560
    res = false;
561
  }
562
563

  if (!kwsys::SystemTools::StringEndsWith("Mary Had A Little Lamb.",
564
565
566
                                          " Lamb.")) {
    std::cerr << "Problem with StringEndsWith "
              << "\"Mary Had A Little Lamb.\"" << std::endl;
567
    res = false;
568
  }
569
570

  cres = kwsys::SystemTools::DuplicateString("Mary Had A Little Lamb.");
571
  if (strcmp(cres, "Mary Had A Little Lamb.") != 0) {
572
573
    std::cerr << "Problem with DuplicateString "
              << "\"Mary Had A Little Lamb.\"" << std::endl;
574
    res = false;
575
576
  }
  delete[] cres;
577
578

  test = "Mary Had A Little Lamb.";
579
580
581
  if (kwsys::SystemTools::CropString(test, 13) != "Mary ...Lamb.") {
    std::cerr << "Problem with CropString "
              << "\"Mary Had A Little Lamb.\"" << std::endl;
582
    res = false;
583
  }
584

Brad King's avatar
Brad King committed
585
  std::vector<std::string> lines;
586
587
588
589
590
  kwsys::SystemTools::Split("Mary Had A Little Lamb.", lines, ' ');
  if (lines[0] != "Mary" || lines[1] != "Had" || lines[2] != "A" ||
      lines[3] != "Little" || lines[4] != "Lamb.") {
    std::cerr << "Problem with Split "
              << "\"Mary Had A Little Lamb.\"" << std::endl;
591
    res = false;
592
  }
Ken Martin's avatar
Ken Martin committed
593

594
595
596
597
598
  if (kwsys::SystemTools::ConvertToWindowsOutputPath(
        "L://Local Mojo/Hex Power Pack/Iffy Voodoo") !=
      "\"L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\"") {
    std::cerr << "Problem with ConvertToWindowsOutputPath "
              << "\"L://Local Mojo/Hex Power Pack/Iffy Voodoo\"" << std::endl;
599
    res = false;
600
  }
601

602
603
604
605
606
607
  if (kwsys::SystemTools::ConvertToWindowsOutputPath(
        "//grayson/Local Mojo/Hex Power Pack/Iffy Voodoo") !=
      "\"\\\\grayson\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\"") {
    std::cerr << "Problem with ConvertToWindowsOutputPath "
              << "\"//grayson/Local Mojo/Hex Power Pack/Iffy Voodoo\""
              << std::endl;
608
    res = false;
609
  }
Ken Martin's avatar
Ken Martin committed
610

611
612
613
614
615
  if (kwsys::SystemTools::ConvertToUnixOutputPath(
        "//Local Mojo/Hex Power Pack/Iffy Voodoo") !=
      "//Local\\ Mojo/Hex\\ Power\\ Pack/Iffy\\ Voodoo") {
    std::cerr << "Problem with ConvertToUnixOutputPath "
              << "\"//Local Mojo/Hex Power Pack/Iffy Voodoo\"" << std::endl;
616
    res = false;
617
  }
Ken Martin's avatar
Ken Martin committed
618

619
620
621
  return res;
}

622
623
static bool CheckPutEnv(const std::string& env, const char* name,
                        const char* value)
624
{
625
626
  if (!kwsys::SystemTools::PutEnv(env)) {
    std::cerr << "PutEnv(\"" << env << "\") failed!" << std::endl;
627
    return false;
628
  }
629
630
  std::string v = "(null)";
  kwsys::SystemTools::GetEnv(name, v);
631
632
633
  if (v != value) {
    std::cerr << "GetEnv(\"" << name << "\") returned \"" << v << "\", not \""
              << value << "\"!" << std::endl;
634
    return false;
635
  }
636
637
638
  return true;
}

Sean McBride's avatar
Sean McBride committed
639
static bool CheckUnPutEnv(const char* env, const char* name)
640
{
641
642
  if (!kwsys::SystemTools::UnPutEnv(env)) {
    std::cerr << "UnPutEnv(\"" << env << "\") failed!" << std::endl;
643
    return false;
644
  }
645
  std::string v;
646
647
648
  if (kwsys::SystemTools::GetEnv(name, v)) {
    std::cerr << "GetEnv(\"" << name << "\") returned \"" << v
              << "\", not (null)!" << std::endl;
649
    return false;
650
  }
651
652
653
  return true;
}

Sean McBride's avatar
Sean McBride committed
654
static bool CheckEnvironmentOperations()
655
656
657
658
659
660
661
662
663
664
665
666
667
{
  bool res = true;
  res &= CheckPutEnv("A=B", "A", "B");
  res &= CheckPutEnv("B=C", "B", "C");
  res &= CheckPutEnv("C=D", "C", "D");
  res &= CheckPutEnv("D=E", "D", "E");
  res &= CheckUnPutEnv("A", "A");
  res &= CheckUnPutEnv("B=", "B");
  res &= CheckUnPutEnv("C=D", "C");
  /* Leave "D=E" in environment so a memory checker can test for leaks.  */
  return res;
}

668
669
670
static bool CheckRelativePath(const std::string& local,
                              const std::string& remote,
                              const std::string& expected)
671
{
Brad King's avatar
Brad King committed
672
  std::string result = kwsys::SystemTools::RelativePath(local, remote);
673
674
675
  if (!kwsys::SystemTools::ComparePath(expected, result)) {
    std::cerr << "RelativePath(" << local << ", " << remote << ")  yielded "
              << result << " instead of " << expected << std::endl;
676
    return false;
677
  }
678
679
680
681
682
683
684
685
686
  return true;
}

static bool CheckRelativePaths()
{
  bool res = true;
  res &= CheckRelativePath("/usr/share", "/bin/bash", "../../bin/bash");
  res &= CheckRelativePath("/usr/./share/", "/bin/bash", "../../bin/bash");
  res &= CheckRelativePath("/usr//share/", "/bin/bash", "../../bin/bash");
687
688
  res &=
    CheckRelativePath("/usr/share/../bin/", "/bin/bash", "../../bin/bash");
689
690
691
692
  res &= CheckRelativePath("/usr/share", "/usr/share//bin", "bin");
  return res;
}

693
static bool CheckCollapsePath(const std::string& path,
694
695
                              const std::string& expected,
                              const char* base = nullptr)
696
{
697
  std::string result = kwsys::SystemTools::CollapseFullPath(path, base);
698
699
700
  if (!kwsys::SystemTools::ComparePath(expected, result)) {
    std::cerr << "CollapseFullPath(" << path << ")  yielded " << result
              << " instead of " << expected << std::endl;
701
    return false;
702
  }
703
704
705
706
707
708
709
710
  return true;
}

static bool CheckCollapsePath()
{
  bool res = true;
  res &= CheckCollapsePath("/usr/share/*", "/usr/share/*");
  res &= CheckCollapsePath("C:/Windows/*", "C:/Windows/*");
711
712
713
714
715
716
717
718
719
720
  res &= CheckCollapsePath("/usr/share/../lib", "/usr/lib");
  res &= CheckCollapsePath("/usr/share/./lib", "/usr/share/lib");
  res &= CheckCollapsePath("/usr/share/../../lib", "/lib");
  res &= CheckCollapsePath("/usr/share/.././../lib", "/lib");
  res &= CheckCollapsePath("/../lib", "/lib");
  res &= CheckCollapsePath("/../lib/", "/lib");
  res &= CheckCollapsePath("/", "/");
  res &= CheckCollapsePath("C:/", "C:/");
  res &= CheckCollapsePath("C:/../", "C:/");
  res &= CheckCollapsePath("C:/../../", "C:/");
721
722
723
  res &= CheckCollapsePath("../b", "../../b", "../");
  res &= CheckCollapsePath("../a/../b", "../b", "../rel");
  res &= CheckCollapsePath("a/../b", "../rel/b", "../rel");
724
725
726
  return res;
}

727
728
729
730
static std::string StringVectorToString(const std::vector<std::string>& vec)
{
  std::stringstream ss;
  ss << "vector(";
731
  for (auto i = vec.begin(); i != vec.end(); ++i) {
732
    if (i != vec.begin()) {
733
734
      ss << ", ";
    }
735
736
    ss << *i;
  }
737
738
739
740
741
742
743
744
745
746
747
748
749
750
  ss << ")";
  return ss.str();
}

static bool CheckGetPath()
{
  const char* envName = "S";
#ifdef _WIN32
  const char* envValue = "C:\\Somewhere\\something;D:\\Temp";
#else
  const char* envValue = "/Somewhere/something:/tmp";
#endif
  const char* registryPath = "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MyApp; MyKey]";

751
  std::vector<std::string> originalPaths;
752
  originalPaths.emplace_back(registryPath);
753

754
  std::vector<std::string> expectedPaths;
755
  expectedPaths.emplace_back(registryPath);
756
#ifdef _WIN32
757
758
  expectedPaths.push_back("C:/Somewhere/something");
  expectedPaths.push_back("D:/Temp");
759
#else
760
761
  expectedPaths.emplace_back("/Somewhere/something");
  expectedPaths.emplace_back("/tmp");
762
763
764
765
766
#endif

  bool res = true;
  res &= CheckPutEnv(std::string(envName) + "=" + envValue, envName, envValue);

767
768
  std::vector<std::string> paths = originalPaths;
  kwsys::SystemTools::GetPath(paths, envName);
769

770
771
772
773
  if (paths != expectedPaths) {
    std::cerr << "GetPath(" << StringVectorToString(originalPaths) << ", "
              << envName << ")  yielded " << StringVectorToString(paths)
              << " instead of " << StringVectorToString(expectedPaths)
774
              << std::endl;
775
    res = false;
776
  }
777
778
779
780
781

  res &= CheckUnPutEnv(envName, envName);
  return res;
}

782
783
784
785
786
static bool CheckGetFilenameName()
{
  const char* windowsFilepath = "C:\\somewhere\\something";
  const char* unixFilepath = "/somewhere/something";

787
788
789
790
791
792
#if defined(_WIN32) || defined(KWSYS_SYSTEMTOOLS_SUPPORT_WINDOWS_SLASHES)
  std::string expectedWindowsFilename = "something";
#else
  std::string expectedWindowsFilename = "C:\\somewhere\\something";
#endif
  std::string expectedUnixFilename = "something";
793
794
795

  bool res = true;
  std::string filename = kwsys::SystemTools::GetFilenameName(windowsFilepath);
796
  if (filename != expectedWindowsFilename) {
797
    std::cerr << "GetFilenameName(" << windowsFilepath << ") yielded "
798
799
              << filename << " instead of " << expectedWindowsFilename
              << std::endl;
800
801
802
803
    res = false;
  }

  filename = kwsys::SystemTools::GetFilenameName(unixFilepath);
804
  if (filename != expectedUnixFilename) {
805
    std::cerr << "GetFilenameName(" << unixFilepath << ") yielded " << filename
806
              << " instead of " << expectedUnixFilename << std::endl;
807
808
809
810
811
    res = false;
  }
  return res;
}

812
813
814
815
static bool CheckFind()
{
  bool res = true;
  const std::string testFindFileName("testFindFile.txt");
816
817
  const std::string testFindFile(TEST_SYSTEMTOOLS_BINARY_DIR "/" +
                                 testFindFileName);
818

819
  if (!kwsys::SystemTools::Touch(testFindFile, true)) {
820
    std::cerr << "Problem with Touch for: " << testFindFile << std::endl;
821
822
    // abort here as the existence of the file only makes the test meaningful
    return false;
823
  }
824
825

  std::vector<std::string> searchPaths;
826
  searchPaths.emplace_back(TEST_SYSTEMTOOLS_BINARY_DIR);
827
828
829
830
  if (kwsys::SystemTools::FindFile(testFindFileName, searchPaths, true)
        .empty()) {
    std::cerr << "Problem with FindFile without system paths for: "
              << testFindFileName << std::endl;