Skip to content

Commit e43775d

Browse files
jnthntatumcopybara-github
authored andcommitted
Add codelab exercise and example defining an opaque (abstract) type.
PiperOrigin-RevId: 846895863
1 parent eba8e2a commit e43775d

10 files changed

Lines changed: 1619 additions & 6 deletions

File tree

codelab/BUILD

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,3 +203,100 @@ cc_test(
203203
"@com_google_protobuf//:struct_cc_proto",
204204
],
205205
)
206+
207+
cc_library(
208+
name = "network_functions",
209+
srcs = ["network_functions.cc"],
210+
hdrs = ["network_functions.h"],
211+
deps = [
212+
"//checker:type_checker_builder",
213+
"//common:decl",
214+
"//common:native_type",
215+
"//common:type",
216+
"//common:typeinfo",
217+
"//common:value",
218+
"//compiler",
219+
"//internal:status_macros",
220+
"//runtime:function_adapter",
221+
"//runtime:function_registry",
222+
"//runtime:runtime_options",
223+
"//runtime:type_registry",
224+
"@com_google_absl//absl/base:no_destructor",
225+
"@com_google_absl//absl/base:nullability",
226+
"@com_google_absl//absl/log:absl_check",
227+
"@com_google_absl//absl/status",
228+
"@com_google_absl//absl/status:statusor",
229+
"@com_google_absl//absl/strings",
230+
"@com_google_absl//absl/strings:string_view",
231+
"@com_google_absl//absl/types:optional",
232+
"@com_google_absl//absl/types:span",
233+
"@com_google_protobuf//:protobuf",
234+
],
235+
)
236+
237+
cc_test(
238+
name = "network_functions_test",
239+
srcs = ["network_functions_test.cc"],
240+
deps = [
241+
":network_functions",
242+
"//common:decl",
243+
"//common:minimal_descriptor_pool",
244+
"//common:type",
245+
"//common:value",
246+
"//compiler",
247+
"//compiler:compiler_factory",
248+
"//compiler:standard_library",
249+
"//internal:benchmark",
250+
"//internal:status_macros",
251+
"//internal:testing",
252+
"//runtime",
253+
"//runtime:activation",
254+
"//runtime:constant_folding",
255+
"//runtime:runtime_options",
256+
"//runtime:standard_runtime_builder_factory",
257+
"@com_google_absl//absl/log:absl_check",
258+
"@com_google_absl//absl/status",
259+
"@com_google_absl//absl/status:status_matchers",
260+
"@com_google_absl//absl/status:statusor",
261+
"@com_google_absl//absl/strings:string_view",
262+
"@com_google_protobuf//:protobuf",
263+
],
264+
)
265+
266+
cc_library(
267+
name = "exercise10",
268+
srcs = ["exercise10.cc"],
269+
hdrs = ["exercise10.h"],
270+
deps = [
271+
":network_functions",
272+
"//checker:validation_result",
273+
"//common:decl",
274+
"//common:minimal_descriptor_pool",
275+
"//common:type",
276+
"//common:value",
277+
"//compiler",
278+
"//compiler:compiler_factory",
279+
"//compiler:standard_library",
280+
"//runtime",
281+
"//runtime:activation",
282+
"//runtime:runtime_builder",
283+
"//runtime:runtime_options",
284+
"//runtime:standard_runtime_builder_factory",
285+
"@com_google_absl//absl/status",
286+
"@com_google_absl//absl/status:statusor",
287+
"@com_google_absl//absl/strings",
288+
"@com_google_protobuf//:protobuf",
289+
],
290+
)
291+
292+
cc_test(
293+
name = "exercise10_test",
294+
srcs = ["exercise10_test.cc"],
295+
tags = EXERCISE_TEST_TAGS,
296+
deps = [
297+
":exercise10",
298+
"//internal:testing",
299+
"@com_google_absl//absl/status",
300+
"@com_google_absl//absl/status:status_matchers",
301+
],
302+
)

codelab/exercise10.cc

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "codelab/exercise10.h"
16+
17+
#include <memory>
18+
#include <utility>
19+
20+
#include "absl/status/status.h"
21+
#include "absl/status/statusor.h"
22+
#include "absl/strings/str_cat.h"
23+
#include "absl/strings/string_view.h"
24+
#include "checker/validation_result.h"
25+
#include "codelab/network_functions.h"
26+
#include "common/decl.h"
27+
#include "common/minimal_descriptor_pool.h"
28+
#include "common/type.h"
29+
#include "common/value.h"
30+
#include "compiler/compiler.h"
31+
#include "compiler/compiler_factory.h"
32+
#include "compiler/standard_library.h"
33+
#include "runtime/activation.h"
34+
#include "runtime/runtime.h"
35+
#include "runtime/runtime_builder.h"
36+
#include "runtime/runtime_options.h"
37+
#include "runtime/standard_runtime_builder_factory.h"
38+
#include "google/protobuf/arena.h"
39+
40+
namespace cel_codelab {
41+
42+
namespace {
43+
44+
absl::StatusOr<std::unique_ptr<cel::Compiler>> ConfigureCompiler() {
45+
absl::StatusOr<std::unique_ptr<cel::CompilerBuilder>> compiler_builder =
46+
cel::NewCompilerBuilder(cel::GetMinimalDescriptorPool());
47+
if (!compiler_builder.ok()) {
48+
return std::move(compiler_builder).status();
49+
}
50+
absl::Status s =
51+
(*compiler_builder)->AddLibrary(cel::StandardCompilerLibrary());
52+
// ===========================================================================
53+
// Codelab: Update compiler builder with functions from network_functions.h
54+
// and add a varible for the input IP.
55+
// ===========================================================================
56+
if (!s.ok()) return s;
57+
58+
return (*compiler_builder)->Build();
59+
}
60+
61+
absl::StatusOr<std::unique_ptr<cel::Runtime>> ConfigureRuntime() {
62+
cel::RuntimeOptions runtime_options;
63+
// Note: this is needed to resolve net.Address as a `type` constant.
64+
runtime_options.enable_qualified_type_identifiers = true;
65+
absl::StatusOr<cel::RuntimeBuilder> runtime_builder =
66+
cel::CreateStandardRuntimeBuilder(cel::GetMinimalDescriptorPool(),
67+
runtime_options);
68+
// ===========================================================================
69+
// Codelab: Update runtime builder with functions from network_functions.h
70+
// ===========================================================================
71+
return std::move(runtime_builder).value().Build();
72+
}
73+
74+
} // namespace
75+
76+
absl::StatusOr<bool> CompileAndEvaluateExercise10(absl::string_view expression,
77+
absl::string_view ip) {
78+
absl::StatusOr<std::unique_ptr<cel::Compiler>> compiler = ConfigureCompiler();
79+
if (!compiler.ok()) {
80+
return std::move(compiler).status();
81+
}
82+
83+
absl::StatusOr<std::unique_ptr<cel::Runtime>> runtime = ConfigureRuntime();
84+
if (!runtime.ok()) {
85+
return std::move(runtime).status();
86+
}
87+
88+
absl::StatusOr<cel::ValidationResult> checked =
89+
(*compiler)->Compile(expression);
90+
if (!checked.ok()) {
91+
return std::move(checked).status();
92+
}
93+
94+
if (!checked->IsValid() || checked->GetAst() == nullptr) {
95+
return absl::InvalidArgumentError(checked->FormatError());
96+
}
97+
98+
absl::StatusOr<std::unique_ptr<cel::Program>> program =
99+
(*runtime)->CreateProgram(checked->ReleaseAst().value());
100+
101+
if (!program.ok()) {
102+
return std::move(program).status();
103+
}
104+
105+
cel::Activation activation;
106+
google::protobuf::Arena arena;
107+
activation.InsertOrAssignValue("ip", cel::StringValue::From(ip, &arena));
108+
absl::StatusOr<cel::Value> result = (*program)->Evaluate(&arena, activation);
109+
110+
if (!result.ok()) {
111+
return std::move(result).status();
112+
}
113+
114+
if (result->IsBool()) {
115+
return result->GetBool();
116+
}
117+
118+
if (result->IsError()) {
119+
return result->GetError().ToStatus();
120+
}
121+
122+
return absl::InvalidArgumentError(
123+
absl::StrCat("unexpected result type: ", result->DebugString()));
124+
}
125+
126+
} // namespace cel_codelab

codelab/exercise10.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef THIRD_PARTY_CEL_CPP_CODELAB_EXERCISE10_H_
16+
#define THIRD_PARTY_CEL_CPP_CODELAB_EXERCISE10_H_
17+
18+
#include "absl/status/statusor.h"
19+
#include "absl/strings/string_view.h"
20+
21+
namespace cel_codelab {
22+
23+
// Exercise10 -- extension types.
24+
//
25+
// This function compiles an expression then evaluates, expecting a bool
26+
// return type.
27+
//
28+
// Example:
29+
// net.ParseAddressMatcher("8.8.0.0-8.8.255.255")
30+
// .containsAddress(
31+
// net.parseAddress(ip)
32+
// )
33+
//
34+
// Variables:
35+
// ip - string
36+
//
37+
// Functions:
38+
// net.ParseAddress(string) -> net.Address
39+
// net.ParseAddressMatcher(string) -> net.AddressMatcher
40+
// (net.AddressMatcher).
41+
absl::StatusOr<bool> CompileAndEvaluateExercise10(absl::string_view expression,
42+
absl::string_view ip);
43+
44+
} // namespace cel_codelab
45+
46+
#endif // THIRD_PARTY_CEL_CPP_CODELAB_EXERCISE10_H_

codelab/exercise10_test.cc

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "codelab/exercise10.h"
16+
17+
#include "absl/status/status.h"
18+
#include "absl/status/status_matchers.h"
19+
#include "internal/testing.h"
20+
21+
namespace cel_codelab {
22+
namespace {
23+
24+
using ::absl_testing::IsOkAndHolds;
25+
using ::absl_testing::StatusIs;
26+
using ::testing::HasSubstr;
27+
28+
TEST(Exercise10, IpInRange) {
29+
EXPECT_THAT(CompileAndEvaluateExercise10(
30+
R"cel(
31+
net.parseAddressMatcher("8.8.4.0-8.8.4.255")
32+
.containsAddress(
33+
net.parseAddress(ip)
34+
)
35+
)cel",
36+
"8.8.4.4"),
37+
IsOkAndHolds(true));
38+
}
39+
40+
TEST(Exercise10, IpNotInRange) {
41+
EXPECT_THAT(CompileAndEvaluateExercise10(
42+
R"cel(
43+
net.parseAddressMatcher("8.8.4.0-8.8.4.255")
44+
.containsAddress(
45+
net.parseAddress(ip)
46+
)
47+
)cel",
48+
"8.8.8.8"),
49+
IsOkAndHolds(false));
50+
}
51+
52+
TEST(Exercise10, IpEqual) {
53+
EXPECT_THAT(CompileAndEvaluateExercise10(
54+
R"cel(
55+
net.parseAddress("8.8.4.4") == net.parseAddress(ip)
56+
)cel",
57+
"8.8.4.4"),
58+
IsOkAndHolds(true));
59+
}
60+
61+
TEST(Exercise10, IpInequal) {
62+
EXPECT_THAT(CompileAndEvaluateExercise10(
63+
R"cel(
64+
net.parseAddress("8.8.4.4") == net.parseAddress(ip)
65+
)cel",
66+
"8.8.8.8"),
67+
IsOkAndHolds(false));
68+
}
69+
70+
TEST(Exercise10, IpInvalid) {
71+
EXPECT_THAT(CompileAndEvaluateExercise10(
72+
R"cel(
73+
net.parseAddress("8.8.4.4") == net.parseAddress(ip)
74+
)cel",
75+
"8.8"),
76+
StatusIs(absl::StatusCode::kInvalidArgument,
77+
HasSubstr("invalid address")));
78+
}
79+
80+
} // namespace
81+
} // namespace cel_codelab

0 commit comments

Comments
 (0)