ic_http_certification/tree/
certification_tree_entry.rs1use super::certification_tree_path::{HttpCertificationPath, InnerTreePath};
2use crate::HttpCertification;
3use std::borrow::Cow;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct HttpCertificationTreeEntry<'a> {
20 pub path: Cow<'a, HttpCertificationPath<'a>>,
24
25 pub certification: Cow<'a, HttpCertification>,
27}
28
29impl<'a> HttpCertificationTreeEntry<'a> {
30 pub fn new(
34 path: impl Into<Cow<'a, HttpCertificationPath<'a>>>,
35 certification: impl Into<Cow<'a, HttpCertification>>,
36 ) -> Self {
37 Self {
38 path: path.into(),
39 certification: certification.into(),
40 }
41 }
42
43 pub(super) fn to_tree_path(&self) -> InnerTreePath {
44 let mut tree_path = vec![];
45 tree_path.append(&mut self.path.to_tree_path());
46 tree_path.append(&mut self.certification.to_tree_path());
47
48 tree_path
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55 use crate::{
56 request_hash, response_hash, DefaultCelBuilder, DefaultResponseCertification, HttpRequest,
57 HttpResponse, StatusCode, CERTIFICATE_EXPRESSION_HEADER_NAME,
58 };
59 use ic_representation_independent_hash::hash;
60 use rstest::*;
61 use rstest_reuse::*;
62
63 #[template]
64 #[rstest]
65 #[case(HttpCertificationPath::exact("/foo/bar"), vec!["foo", "bar", "<$>"])]
66 #[case(HttpCertificationPath::wildcard("/foo/bar"), vec!["foo", "bar", "<*>"])]
67 fn certification_paths(
68 #[case] path: HttpCertificationPath<'static>,
69 #[case] expected: Vec<&str>,
70 ) {
71 }
72
73 #[apply(certification_paths)]
74 fn skip_certification_path(
75 #[case] path: HttpCertificationPath<'static>,
76 #[case] expected: Vec<&str>,
77 ) {
78 let cel_expr = DefaultCelBuilder::skip_certification().to_string();
79 let cel_expr_hash = hash(cel_expr.as_bytes());
80
81 let certification = HttpCertification::skip();
82 let entry = HttpCertificationTreeEntry::new(&path, certification);
83
84 let result = entry.to_tree_path();
85
86 let path_segments: Vec<_> = expected
87 .into_iter()
88 .map(|segment| segment.as_bytes().to_vec())
89 .collect();
90 let expected = vec![cel_expr_hash.to_vec().to_owned()];
91
92 let expected: Vec<_> = path_segments
93 .into_iter()
94 .chain(expected.into_iter())
95 .collect();
96
97 assert_eq!(result, expected);
98 }
99
100 #[apply(certification_paths)]
101 fn response_only_certification_path(
102 #[case] path: HttpCertificationPath<'static>,
103 #[case] expected: Vec<&str>,
104 ) {
105 let cel_expr = DefaultCelBuilder::response_only_certification()
106 .with_response_certification(DefaultResponseCertification::certified_response_headers(
107 vec![],
108 ))
109 .build();
110 let cel_expr_hash = hash(cel_expr.to_string().as_bytes());
111 let response = HttpResponse::builder()
112 .with_status_code(StatusCode::OK)
113 .with_headers(vec![(
114 CERTIFICATE_EXPRESSION_HEADER_NAME.to_string(),
115 cel_expr.to_string(),
116 )])
117 .build();
118 let expected_response_hash = response_hash(&response, &cel_expr.response, None);
119
120 let certification = HttpCertification::response_only(&cel_expr, &response, None).unwrap();
121 let entry = HttpCertificationTreeEntry::new(&path, certification);
122
123 let result = entry.to_tree_path();
124
125 let path_segments: Vec<_> = expected
126 .into_iter()
127 .map(|segment| segment.as_bytes().to_vec())
128 .collect();
129 let expected = vec![
130 cel_expr_hash.to_vec().to_owned(),
131 "".as_bytes().to_vec(),
132 expected_response_hash.to_vec(),
133 ];
134
135 let expected: Vec<_> = path_segments
136 .into_iter()
137 .chain(expected.into_iter())
138 .collect();
139
140 assert_eq!(result, expected);
141 }
142
143 #[apply(certification_paths)]
144 fn full_certification_path(
145 #[case] path: HttpCertificationPath<'static>,
146 #[case] expected: Vec<&str>,
147 ) {
148 let cel_expr = DefaultCelBuilder::full_certification().build();
149 let cel_expr_hash = hash(cel_expr.to_string().as_bytes());
150
151 let request = HttpRequest::get("/index.html").build();
152 let expected_request_hash = request_hash(&request, &cel_expr.request).unwrap();
153
154 let response = HttpResponse::builder()
155 .with_status_code(StatusCode::OK)
156 .with_headers(vec![(
157 CERTIFICATE_EXPRESSION_HEADER_NAME.to_string(),
158 cel_expr.to_string(),
159 )])
160 .build();
161 let expected_response_hash = response_hash(&response, &cel_expr.response, None);
162
163 let certification = HttpCertification::full(&cel_expr, &request, &response, None).unwrap();
164 let entry = HttpCertificationTreeEntry::new(&path, certification);
165
166 let result = entry.to_tree_path();
167
168 let path_segments: Vec<_> = expected
169 .into_iter()
170 .map(|segment| segment.as_bytes().to_vec())
171 .collect();
172 let expected = vec![
173 cel_expr_hash.to_vec().to_owned(),
174 expected_request_hash.to_vec(),
175 expected_response_hash.to_vec(),
176 ];
177
178 let expected: Vec<_> = path_segments
179 .into_iter()
180 .chain(expected.into_iter())
181 .collect();
182
183 assert_eq!(result, expected);
184 }
185}