Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/tools/Tools.tests.cpp
blob: 90e9b129f7a6dea85c81bb0dd9ca1bde0ce0ec98 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Copyright (c) 2026 Progmasoft.
// SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-2.0

#include <Progmasoft/Catch3/Matchers/String.hpp>
#include <Progmasoft/Catch3/TestMacros.hpp>
#include <string>

#include "tools/Amalgamation.hpp"
#include "tools/Repository.hpp"
#include "tools/RepositoryReport.hpp"
#include "tools/Versions.hpp"

using namespace Progmasoft::Catch3::Tools;
using Catch::Matchers::ContainsSubstring;

TEST_CASE("Versions have three or four numbers", "[tools]")
{
    CHECK(ParseVersion("0.3.0") == Version{ 0, 3, 0, 0 });
    CHECK(ParseVersion("0.3.0.2") == Version{ 0, 3, 0, 2 });
    for (const char *wrong :
         { "0.3", "0.3.0.2.1", "01.3.0", "0.3.0.", "a.3.0", "", "0.3.0-rc" })
    {
        INFO(wrong);
        CHECK_FALSE(ParseVersion(wrong));
    }
}

TEST_CASE("The next version counts releases", "[tools]")
{
    const auto next = [](const char *version) {
        return FormatVersion(NextVersion(*ParseVersion(version)));
    };
    CHECK(next("0.3.0") == "0.3.0.1");
    CHECK(next("0.4.0.8") == "0.4.0.9");
    CHECK(next("0.4.0.9") == "0.4.1.0");
    CHECK(next("0.4.9.9") == "0.5.0.0");
    CHECK(next("0.19.9.9") == "1.0.0.0");
}

TEST_CASE("A version site is read and written in place", "[tools]")
{
    const VersionSite site{ "file", "version: '", "'" };
    const std::string text = "name\n  version: '1.2.3',\n  version: '9'\n";
    CHECK(ReadVersionSite(text, site) == "1.2.3");
    CHECK(WriteVersionSite(text, site, "1.2.3.4")
          == "name\n  version: '1.2.3.4',\n  version: '9'\n");
    CHECK_FALSE(ReadVersionSite("name", site));
    CHECK_FALSE(WriteVersionSite("name", site, "1"));
}

TEST_CASE("Release notes are found by their heading", "[tools]")
{
    const std::string notes = "# Release notes\n\n## 0.2\n\nNew.\n\n"
                              "### Part\n\n* One.\n\n\n## 0.1\n\nOld.\n";
    CHECK(ReleaseNotesOf(notes, "0.2") == "New.\n\n### Part\n\n* One.\n");
    CHECK(ReleaseNotesOf(notes, "0.1") == "Old.\n");
    CHECK_FALSE(ReleaseNotesOf(notes, "0.3"));
}

TEST_CASE("A release with D = 0 may be headed by three numbers", "[tools]")
{
    const std::string notes = "# Notes\n\n## 0.4.0\n\nThree.\n";
    CHECK(ReleaseNotesOf(notes, "0.4.0") == "Three.\n");
    CHECK(ReleaseNotesOf(notes, "0.4.0.0") == "Three.\n");
    CHECK_FALSE(ReleaseNotesOf(notes, "0.4.0.1"));
}

TEST_CASE("Git that could not say is not a clean checkout", "[tools]")
{
    RepositoryReport report;
    report.GitError = "unreadable";
    CHECK_THAT(ReportToJson(report), ContainsSubstring("\"dirty\": null"));
    CHECK_THAT(FormatReport(report),
               ContainsSubstring("Tracked changes: unknown"));
    report.Dirty = false;
    CHECK_THAT(ReportToJson(report), ContainsSubstring("\"dirty\": false"));
}

TEST_CASE("Includes are read as they are written", "[tools]")
{
    const auto angled = ParseInclude("  #include <a/b.hpp> // why\n");
    REQUIRE(angled);
    CHECK(angled->Name == "a/b.hpp");
    CHECK(angled->Angled);
    const auto quoted = ParseInclude("#include \"b.hpp\"\n");
    REQUIRE(quoted);
    CHECK_FALSE(quoted->Angled);
    CHECK_FALSE(ParseInclude("#  include <a.hpp>\n"));
    CHECK_FALSE(ParseInclude("// #include <a.hpp>\n"));
    CHECK_FALSE(ParseInclude("#include MACRO\n"));
}

TEST_CASE("The engine version comes from its declaration", "[tools]")
{
    CHECK(ParseEngineVersion("  static Version version( 3, 16, 1, \"\", 0 );")
          == "3.16.1");
    CHECK(ParseEngineVersion("static Version version( 3, 17, 0, \"rc\", 2 );")
          == "3.17.0-rc.2");
    CHECK_FALSE(ParseEngineVersion("nothing here"));
}

TEST_CASE("A report becomes JSON", "[tools]")
{
    RepositoryReport report;
    report.Root = "C:\\repos\\catch3";
    report.Os = "windows";
    report.Branch = "devel";
    report.Dirty = true;
    report.Tools.push_back({ "git", "/usr/bin/git", true });
    report.Tools.push_back({ "ninja", "", false });
    CHECK(ReportToJson(report) == R"({
  "root": "C:\\repos\\catch3",
  "os": "windows",
  "branch": "devel",
  "dirty": true,
  "tools": [
    {
      "name": "git",
      "path": "/usr/bin/git",
      "available": true
    },
    {
      "name": "ninja",
      "available": false
    }
  ]
}
)");
}

TEST_CASE("Text helpers keep line ends", "[tools]")
{
    CHECK(SplitLines("a\nb") == std::vector<std::string>{ "a\n", "b" });
    CHECK(SplitLines("").empty());
    CHECK(Trimmed("  a b\r\n") == "a b");
    CHECK(Trimmed(" \n").empty());
}