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

geo-engine / geoengine / 13809415963

12 Mar 2025 10:42AM UTC coverage: 90.026% (-0.05%) from 90.076%
13809415963

Pull #1013

github

web-flow
Merge b51e2554c into c96026921
Pull Request #1013: Update-utoipa

787 of 935 new or added lines in 41 files covered. (84.17%)

28 existing lines in 10 files now uncovered.

125995 of 139954 relevant lines covered (90.03%)

57510.86 hits per line

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

85.71
/services/src/util/openapi_visitor.rs
1
use utoipa::openapi::{
2
    path::Operation,
3
    schema::{AdditionalProperties, ArrayItems},
4
    Components, HttpMethod, OpenApi, PathItem, Ref, RefOr, Response, Schema,
5
};
6

7
pub trait OpenapiVisitor {
8
    fn resolve_failed(&mut self, _ref_location: &str) {}
×
9

10
    fn visit_schema_component(
3,886✔
11
        &mut self,
3,886✔
12
        _name: &str,
3,886✔
13
        _schema: &RefOr<Schema>,
3,886✔
14
        _source_location: &str,
3,886✔
15
    ) {
3,886✔
16
    }
3,886✔
17
}
18

19
/// Recursively walks through the given schema object and calls corresponding events on the visitor.
20
///
21
/// # Panics
22
///
23
/// Panics if a schema has an unknown type.
24
pub fn visit_schema<T: OpenapiVisitor>(
13,378✔
25
    schema: &RefOr<Schema>,
13,378✔
26
    components: &Components,
13,378✔
27
    visitor: &mut T,
13,378✔
28
    source_location: &str,
13,378✔
29
) {
13,378✔
30
    match schema {
13,378✔
31
        RefOr::Ref(reference) => {
3,898✔
32
            visit_reference(reference, components, visitor, source_location);
3,898✔
33
        }
3,898✔
34
        RefOr::T(concrete) => match concrete {
9,480✔
35
            Schema::Array(arr) => {
1,725✔
36
                if let ArrayItems::RefOrSchema(schema) = &arr.items {
1,725✔
37
                    visit_schema(schema, components, visitor, source_location);
1,725✔
38
                }
1,725✔
39
            }
40
            Schema::Object(obj) => {
6,992✔
41
                for property in obj.properties.values() {
6,992✔
42
                    visit_schema(property, components, visitor, source_location);
5,562✔
43
                }
5,562✔
44
                if let Some(additional_properties) = &obj.additional_properties {
6,992✔
45
                    if let AdditionalProperties::RefOr(ref properties_schema) =
160✔
46
                        additional_properties.as_ref()
160✔
47
                    {
160✔
48
                        visit_schema(properties_schema, components, visitor, source_location);
160✔
49
                    }
160✔
50
                }
6,832✔
51
            }
52
            Schema::OneOf(oo) => {
537✔
53
                for item in &oo.items {
1,830✔
54
                    visit_schema(item, components, visitor, source_location);
1,293✔
55
                }
1,293✔
56
            }
57
            Schema::AllOf(ao) => {
226✔
58
                for item in &ao.items {
672✔
59
                    visit_schema(item, components, visitor, source_location);
446✔
60
                }
446✔
61
            }
62
            _ => panic!("Unknown schema type"),
×
63
        },
64
    }
65
}
13,378✔
66

67
/// Recursively walks through the given response object and calls corresponding events on the visitor.
68
///
69
/// # Panics
70
///
71
/// Panics if a schema has an unknown type.
72
fn visit_response<T: OpenapiVisitor>(
25✔
73
    response: &RefOr<Response>,
25✔
74
    components: &Components,
25✔
75
    visitor: &mut T,
25✔
76
    source_location: &str,
25✔
77
) {
25✔
78
    match response {
25✔
79
        RefOr::Ref(reference) => {
×
80
            visit_reference(reference, components, visitor, source_location);
×
81
        }
×
82
        RefOr::T(concrete) => {
25✔
83
            for content in concrete.content.values() {
25✔
84
                let Some(content_schema) = &content.schema else {
25✔
NEW
85
                    continue;
×
86
                };
87
                visit_schema(content_schema, components, visitor, source_location);
25✔
88
            }
89
        }
90
    }
91
}
25✔
92

93
/// Resolves the given reference, recursively walks through the target and
94
/// calls corresponding events on the visitor.
95
///
96
/// # Panics
97
///
98
/// Panics if a schema has an unknown type.
99
fn visit_reference<T: OpenapiVisitor>(
3,923✔
100
    reference: &Ref,
3,923✔
101
    components: &Components,
3,923✔
102
    visitor: &mut T,
3,923✔
103
    source_location: &str,
3,923✔
104
) {
3,923✔
105
    const SCHEMA_REF_PREFIX: &str = "#/components/schemas/";
106
    const RESPONSE_REF_PREFIX: &str = "#/components/responses/";
107

108
    let ref_location = reference.ref_location.as_str();
3,923✔
109

110
    if let Some(schema_name) = ref_location.strip_prefix(SCHEMA_REF_PREFIX) {
3,923✔
111
        match components.schemas.get(schema_name) {
3,898✔
112
            None => visitor.resolve_failed(ref_location),
8✔
113
            Some(resolved) => {
3,890✔
114
                visitor.visit_schema_component(schema_name, resolved, source_location);
3,890✔
115
                visit_schema(resolved, components, visitor, ref_location);
3,890✔
116
            }
3,890✔
117
        }
118
    } else if let Some(response_name) = ref_location.strip_prefix(RESPONSE_REF_PREFIX) {
25✔
119
        match components.responses.get(response_name) {
25✔
120
            None => visitor.resolve_failed(ref_location),
×
121
            Some(resolved) => visit_response(resolved, components, visitor, ref_location),
25✔
122
        }
123
    } else {
×
124
        visitor.resolve_failed(ref_location);
×
125
    }
×
126
}
3,923✔
127

128
/// Recursively walks through all registered HTTP handlers and the referenced schemas
129
/// (inside of request bodies, parameters or responses) and calls corresponding events
130
/// on the visitor.
131
///
132
/// # Panics
133
///
134
/// Panics if a schema has an unknown type.
135
pub fn visit_api<T: OpenapiVisitor>(api: &OpenApi, visitor: &mut T) {
5✔
136
    let Some(components) = api.components.as_ref() else {
5✔
137
        debug_assert!(api.components.as_ref().is_some());
×
138
        return;
×
139
    };
140

141
    for (source_location, path_item) in &api.paths.paths {
85✔
142
        if let Some(parameters) = &path_item.parameters {
80✔
UNCOV
143
            for parameter in parameters {
×
UNCOV
144
                if let Some(schema) = parameter.schema.as_ref() {
×
UNCOV
145
                    visit_schema(schema, components, visitor, source_location);
×
UNCOV
146
                }
×
147
            }
148
        }
80✔
149

150
        for (_, operation) in operations_from_path(path_item) {
93✔
151
            if let Some(request_body) = operation.request_body.as_ref() {
93✔
152
                for content in request_body.content.values() {
26✔
153
                    let Some(content_schema) = &content.schema else {
26✔
NEW
154
                        continue;
×
155
                    };
156
                    visit_schema(content_schema, components, visitor, source_location);
26✔
157
                }
158
            }
67✔
159

160
            if let Some(parameters) = operation.parameters.as_ref() {
93✔
161
                for parameter in parameters {
254✔
162
                    if let Some(schema) = parameter.schema.as_ref() {
184✔
163
                        visit_schema(schema, components, visitor, source_location);
184✔
164
                    }
184✔
165
                }
166
            }
23✔
167

168
            for response in operation.responses.responses.values() {
112✔
169
                match response {
112✔
170
                    RefOr::Ref(ref reference) => {
25✔
171
                        visit_reference(reference, components, visitor, source_location);
25✔
172
                    }
25✔
173
                    RefOr::T(concrete) => {
87✔
174
                        for content in concrete.content.values() {
87✔
175
                            let Some(content_schema) = &content.schema else {
61✔
NEW
176
                                continue;
×
177
                            };
178
                            visit_schema(content_schema, components, visitor, source_location);
61✔
179
                        }
180
                    }
181
                }
182
            }
183
        }
184
    }
185
}
5✔
186

187
pub fn operations_from_path(
158✔
188
    path_item: &PathItem,
158✔
189
) -> impl Iterator<Item = (&HttpMethod, &Operation)> {
158✔
190
    let mut path_methods = Vec::<(&HttpMethod, &Operation)>::new();
158✔
191
    if let Some(operation) = &path_item.get {
158✔
192
        path_methods.push((&HttpMethod::Get, operation));
96✔
193
    }
96✔
194
    if let Some(operation) = &path_item.put {
158✔
195
        path_methods.push((&HttpMethod::Put, operation));
14✔
196
    }
144✔
197
    if let Some(operation) = &path_item.post {
158✔
198
        path_methods.push((&HttpMethod::Post, operation));
52✔
199
    }
106✔
200
    if let Some(operation) = &path_item.delete {
158✔
201
        path_methods.push((&HttpMethod::Delete, operation));
20✔
202
    }
138✔
203
    if let Some(operation) = &path_item.options {
158✔
NEW
204
        path_methods.push((&HttpMethod::Options, operation));
×
205
    }
158✔
206
    if let Some(operation) = &path_item.head {
158✔
NEW
207
        path_methods.push((&HttpMethod::Head, operation));
×
208
    }
158✔
209
    if let Some(operation) = &path_item.patch {
158✔
210
        path_methods.push((&HttpMethod::Patch, operation));
2✔
211
    }
156✔
212
    if let Some(operation) = &path_item.trace {
158✔
NEW
213
        path_methods.push((&HttpMethod::Trace, operation));
×
214
    }
158✔
215

216
    path_methods.into_iter()
158✔
217
}
158✔
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

© 2025 Coveralls, Inc