Goby3 3.7.0
2026.11.12
Loading...
Searching...
No Matches
validate.h
Go to the documentation of this file.
1// Copyright 2026:
2// GobySoft, LLC (2013-)
3// Community contributors (see AUTHORS file)
4// File authors:
5// Toby Schneider <toby@gobysoft.org>
6//
7//
8// This file is part of the Goby Underwater Autonomy Project Libraries
9// ("The Goby Libraries").
10//
11// The Goby Libraries are free software: you can redistribute them and/or modify
12// them under the terms of the GNU Lesser General Public License as published by
13// the Free Software Foundation, either version 2.1 of the License, or
14// (at your option) any later version.
15//
16// The Goby Libraries are distributed in the hope that they will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU Lesser General Public License for more details.
20//
21// You should have received a copy of the GNU Lesser General Public License
22// along with Goby. If not, see <http://www.gnu.org/licenses/>.
23
24#ifndef GOBY_MIDDLEWARE_TOOL_INTERFACE_VALIDATE_H
25#define GOBY_MIDDLEWARE_TOOL_INTERFACE_VALIDATE_H
26
27#include <map>
28#include <set>
29#include <string>
30#include <tuple>
31
33
34namespace goby
35{
36namespace middleware
37{
38namespace tool
39{
40namespace interface
41{
43{
44 // by default everything is checked, including the groups a diagram hides
45 ViewFilter::Params filter{"", "", true, true, true, false};
46 // report publications that nothing subscribes to (common, and usually fine, for libraries)
47 bool report_unused{false};
48 // count a dynamic publisher whose numeric is set at run time as reaching its subscribers
49 bool assume_dynamic{false};
50};
51
53{
54 int platforms{0};
57 int required{0};
59};
60
61namespace detail
62{
64{
66 s.platform = u.at.platform->name;
67 if (u.at.platform->has_modules())
68 s.module = u.at.module->name;
70 s.thread = u.entry.thread;
73 s.scheme = u.entry.scheme;
74 s.type = u.entry.type;
77 return s;
78}
79
80inline std::string describe(const PubSubEntry& e)
81{
82 return e.display_group() + " (" + e.scheme + " " + e.type + ")";
83}
84} // namespace detail
85
89inline ValidationSummary validate(const Deployment& deployment, const Resolution& resolution,
90 const ValidateParams& params, Issues& issues)
91{
92 ViewFilter filter(params.filter);
93 ValidationSummary summary;
94
95 for (const auto& platform : deployment.platforms)
96 {
97 ++summary.platforms;
98 for (const auto& module : platform.modules)
99 summary.applications += module.applications.size();
100 }
101
102 // subscription -> reached by a publisher whose group certainly matches
103 std::map<std::tuple<const Application*, PubSubEntry>, bool> reached;
104 for (const auto& c : resolution.connections)
105 {
106 if (!filter.is_included(c))
107 continue;
108 ++summary.connections;
109 auto it = reached.emplace(std::make_tuple(c.sub_at.application, c.sub), false).first;
110 it->second = it->second || !c.loose;
111 }
112
113 auto add = [&](Issue::Severity severity, const std::string& code, const std::string& message,
114 const Unmatched& u)
115 {
116 Issue issue;
117 issue.severity = severity;
118 issue.code = code;
119 issue.message = message;
120 issue.subject = detail::subject(u);
121 issues.push_back(issue);
122 };
123
124 std::vector<Unmatched> pubs, subs;
125 collect_entries(deployment, pubs, subs);
126
127 for (const auto& u : subs)
128 {
129 if (!filter.is_included(u) || u.entry.necessity == goby::middleware::Necessity::OPTIONAL)
130 continue;
131
132 bool required = u.entry.necessity == goby::middleware::Necessity::REQUIRED;
133 auto it = reached.find(std::make_tuple(u.at.application, u.entry));
134 bool met = it != reached.end() && (it->second || params.assume_dynamic);
135 if (required)
136 ++summary.required;
137 if (met)
138 {
139 if (required)
140 ++summary.required_met;
141 continue;
142 }
143
144 std::string message =
145 it == reached.end()
146 ? "no publisher for " + detail::describe(u.entry)
147 : "only a dynamic publisher with a numeric set at run time reaches " +
148 detail::describe(u.entry) + " (give its numeric with bind:, or use " +
149 "--assume_dynamic)";
150 if (u.entry.necessity_overridden)
151 message += " (necessity set by the deployment)";
152 if (required)
153 add(Issue::Severity::ERROR, "required-unmet", message, u);
154 else
155 add(Issue::Severity::WARNING, "recommended-unmet", message, u);
156 }
157
158 for (const auto* entries : {&pubs, &subs})
159 {
160 for (const auto& u : *entries)
161 {
162 if (!filter.is_included(u))
163 continue;
164 if (u.entry.unresolved())
165 add(Issue::Severity::INFO, "dynamic-unresolved",
166 "goby_clang_tool could not determine this dynamic group" +
167 (u.entry.expr.empty() ? std::string() : " (" + u.entry.expr + ")") +
168 "; a dynamic: bind can say what it stands for",
169 u);
170 else if (u.entry.unbound())
171 add(Issue::Severity::WARNING, "dynamic-unbound",
172 "the numeric part of " + u.entry.group +
173 " is set at run time; give it with bind: { group: " + u.entry.group +
174 ", numeric: ... }",
175 u);
176 }
177 }
178
179 if (params.report_unused)
180 {
181 for (const auto& u : resolution.unsubscribed)
182 {
183 if (u.entry.is_inner_pub || !filter.is_included(u))
184 continue;
185 add(Issue::Severity::INFO, "publisher-unused",
186 "no subscriber for " + detail::describe(u.entry), u);
187 }
188 }
189
190 return summary;
191}
192
193} // namespace interface
194} // namespace tool
195} // namespace middleware
196} // namespace goby
197
198#endif
Which groups and nodes a diagram (or a filtered check) shows.
Definition resolve.h:165
bool is_included(const Endpoint &at, const std::string &thread) const
Is every part of the path to this endpoint (and its thread) shown?
Definition resolve.h:248
detail namespace with internal helper functions
Definition json.hpp:263
std::string describe(const PubSubEntry &e)
Definition validate.h:80
Issue::Subject subject(const Unmatched &u)
Definition validate.h:63
std::string layer_name(Layer layer)
std::vector< Issue > Issues
Definition model.h:89
std::string necessity_name(goby::middleware::Necessity n)
void collect_entries(const Deployment &deployment, std::vector< Unmatched > &pubs, std::vector< Unmatched > &subs)
Every publication and subscription in a deployment, with where it is made.
Definition resolve.h:97
ValidationSummary validate(const Deployment &deployment, const Resolution &resolution, const ValidateParams &params, Issues &issues)
Check every required and recommended subscription in a resolved deployment.
Definition validate.h:89
The global namespace for the Goby project.
The publication or subscription an issue is about, when there is one.
Definition model.h:69
A problem found while loading or checking a deployment.
Definition model.h:59
One publication or subscription as written to (and read from) an interface file.
std::string display_group() const
The group as a deployment sees it, with any bound numeric values.
std::vector< Unmatched > unsubscribed
Definition resolve.h:74
std::vector< Connection > connections
Definition resolve.h:72