Update bindings to include newer APIs (#250)

- c, cpp
- csharp
- ffi
- go
- Java
- Python
- WASM

`arc` feature is turned on for all bindings
Use pretty string instead of colored string.

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
Anand Krishnamoorthi
2024-05-25 13:24:06 -04:00
committed by GitHub
parent 33fe9d5039
commit d09c445add
41 changed files with 1175 additions and 565 deletions

View File

@@ -46,21 +46,21 @@ int main() {
free(buffer);
if (r.status != RegorusStatusOk)
goto error;
printf("Loaded policy %s\n", r.output);
printf("Loaded package %s\n", r.output);
regorus_result_drop(r);
r = regorus_engine_add_policy(engine, "api.rego", (buffer = file_to_string("../../../tests/aci/api.rego")));
free(buffer);
if (r.status != RegorusStatusOk)
goto error;
printf("Loaded policy %s\n", r.output);
printf("Loaded package %s\n", r.output);
regorus_result_drop(r);
r = regorus_engine_add_policy(engine, "policy.rego", (buffer = file_to_string("../../../tests/aci/policy.rego")));
free(buffer);
if (r.status != RegorusStatusOk)
goto error;
printf("Loaded policy %s\n", r.output);
printf("Loaded package %s\n", r.output);
regorus_result_drop(r);
// Add data
@@ -77,8 +77,8 @@ int main() {
goto error;
regorus_result_drop(r);
// Eval query
r = regorus_engine_eval_query(engine, "data.framework.mount_overlay=x");
// Eval rule.
r = regorus_engine_eval_rule(engine, "data.framework.mount_overlay");
if (r.status != RegorusStatusOk)
goto error;

View File

@@ -25,7 +25,7 @@ corrosion_import_crate(
FEATURES "regorus/semver"
# Link statically
CRATE_TYPES "staticlib"
CRATE_TYPES "cdylib"
)
add_executable(regorus_test main.c)

View File

@@ -10,19 +10,19 @@ int main() {
r = regorus_engine_add_policy_from_file(engine, "../../../tests/aci/framework.rego");
if (r.status != RegorusStatusOk)
goto error;
printf("Loaded policy %s\n", r.output);
printf("Loaded package %s\n", r.output);
regorus_result_drop(r);
r = regorus_engine_add_policy_from_file(engine, "../../../tests/aci/api.rego");
if (r.status != RegorusStatusOk)
goto error;
printf("Loaded policy %s\n", r.output);
printf("Loaded package %s\n", r.output);
regorus_result_drop(r);
r = regorus_engine_add_policy_from_file(engine, "../../../tests/aci/policy.rego");
if (r.status != RegorusStatusOk)
goto error;
printf("Loaded policy %s\n", r.output);
printf("Loaded package %s\n", r.output);
regorus_result_drop(r);
// Add data
@@ -37,22 +37,61 @@ int main() {
goto error;
regorus_result_drop(r);
// Eval query
r = regorus_engine_eval_query(engine, "data.framework.mount_overlay=x");
// Eval rule.
r = regorus_engine_eval_query(engine, "data.framework.mount_overlay");
if (r.status != RegorusStatusOk)
goto error;
// Print output
printf("%s", r.output);
printf("%s\n", r.output);
regorus_result_drop(r);
// Free the engine.
regorus_engine_drop(engine);
// Create another engine.
engine = regorus_engine_new();
r = regorus_engine_add_policy(
engine,
"test.rego",
"package test\n"
"x = 1\n"
"message = `Hello`"
);
// Evaluate rule.
if (r.status != RegorusStatusOk)
goto error;
r = regorus_engine_set_enable_coverage(engine, true);
regorus_result_drop(r);
r = regorus_engine_eval_query(engine, "data.test.message");
if (r.status != RegorusStatusOk)
goto error;
// Print output
printf("%s\n", r.output);
regorus_result_drop(r);
// Print pretty coverage report.
r = regorus_engine_get_coverage_report_pretty(engine);
if (r.status != RegorusStatusOk)
goto error;
printf("%s\n", r.output);
regorus_result_drop(r);
// Free the engine.
regorus_engine_drop(engine);
return 0;
error:
printf("%s", r.error_message);
regorus_result_drop(r);
regorus_engine_drop(engine);
return 1;
}

View File

@@ -26,7 +26,7 @@ corrosion_import_crate(
FEATURES "regorus/semver"
# Link statically
CRATE_TYPES "staticlib")
CRATE_TYPES "cdylib")
add_executable(regorus_test main.cpp)
# Add path to <regorus-source-folder>/bindings/ffi

View File

@@ -6,6 +6,8 @@ void example()
// Create engine
regorus::Engine engine;
engine.set_enable_coverage(true);
// Add policies.
engine.add_policy("objects.rego",R"(package objects
@@ -67,6 +69,14 @@ f := e["dev"])");
} else {
std::cerr<<result.error()<<std::endl;
}
// Print coverage report
auto result1 = engine.get_coverage_report_pretty();
if (result1) {
std::cout<<result1.output()<<std::endl;
} else {
std::cerr<<result1.error()<<std::endl;
}
}
int main() {
@@ -89,7 +99,7 @@ int main() {
std::cerr<<result.error()<<std::endl;
return -1;
}
std::cout<<"Loaded policy "<<result.output()<< std::endl;
std::cout<<"Loaded package "<<result.output()<< std::endl;
}
{
auto result = engine.add_data_from_json_file("../../../tests/aci/data.json");
@@ -99,7 +109,7 @@ int main() {
}
}
// Set input and eval query.
// Set input and eval rule.
{
auto result = engine.set_input_from_json_file("../../../tests/aci/input.json");
if (!result) {
@@ -107,13 +117,13 @@ int main() {
return -1;
}
}
auto result = engine.eval_query("data.framework.mount_overlay = x");
auto result = engine.eval_rule("data.framework.mount_overlay");
if (!result) {
std::cerr<<result.error()<<std::endl;
return -1;
}
std::cout<<result.output()<<std::endl;
example();
}

View File

@@ -83,6 +83,26 @@ namespace regorus {
return Result(regorus_engine_eval_query(engine, query));
}
Result eval_rule(const char* rule) {
return Result(regorus_engine_eval_rule(engine, rule));
}
Result set_enable_coverage(bool enable) {
return Result(regorus_engine_set_enable_coverage(engine, enable));
}
Result clear_coverage_data() {
return Result(regorus_engine_clear_coverage_data(engine));
}
Result get_coverage_report() {
return Result(regorus_engine_get_coverage_report(engine));
}
Result get_coverage_report_pretty() {
return Result(regorus_engine_get_coverage_report_pretty(engine));
}
~Engine() {
regorus_engine_drop(engine);
}

View File

@@ -33,19 +33,26 @@ var loadPoliciesTicks = w.ElapsedTicks;
w.Restart();
// Set input and eval query.
// Set input and eval rule.
engine.SetInputFromJsonFile("../../tests/aci/input.json");
var results = engine.EvalQuery("data.framework.mount_overlay = x");
var resultsDoc = System.Text.Json.JsonDocument.Parse(results);
var value = engine.EvalQuery("data.framework.mount_overlay");
var valueDoc = System.Text.Json.JsonDocument.Parse(value);
w.Stop();
var evalTicks = w.ElapsedTicks;
Console.WriteLine("{0}", results);
Console.WriteLine("{0}", valueDoc);
Console.WriteLine("Engine creation took {0} msecs", (newEngineTicks*nanosecPerTick)/(1000.0*1000.0));
Console.WriteLine("Load policies and data took {0} msecs", (loadPoliciesTicks*nanosecPerTick)/(1000.0*1000.0));
Console.WriteLine("EvalQuery took {0} msecs", (evalTicks*nanosecPerTick)/(1000.0*1000.0));
engine = new Regorus.Engine();
engine.AddPolicy(
"test.rego",
"package test\nx = 1\nmessage = `Hello`");
engine.SetEnableCoverage(true);
Console.WriteLine("{0}", engine.EvalRule("data.test.message"));
Console.WriteLine("{0}", engine.GetCoverageReportPretty());

View File

@@ -29,117 +29,159 @@ namespace Regorus
}
public void AddPolicy(string path, string rego)
public string AddPolicy(string path, string rego)
{
var pathBytes = Encoding.UTF8.GetBytes(path);
var regoBytes = Encoding.UTF8.GetBytes(rego);
unsafe
{
fixed (byte* pathPtr = pathBytes)
{
fixed(byte* regoPtr = regoBytes)
{
CheckAndDropResult(RegorusFFI.API.regorus_engine_add_policy(E, pathPtr, regoPtr));
return CheckAndDropResult(RegorusFFI.API.regorus_engine_add_policy(E, pathPtr, regoPtr));
}
}
}
}
}
public void AddPolicyFromFile(string path)
public string AddPolicyFromFile(string path)
{
var pathBytes = Encoding.UTF8.GetBytes(path);
unsafe
{
fixed (byte* pathPtr = pathBytes)
{
CheckAndDropResult(RegorusFFI.API.regorus_engine_add_policy_from_file(E, pathPtr));
}
return CheckAndDropResult(RegorusFFI.API.regorus_engine_add_policy_from_file(E, pathPtr));
}
}
}
public void AddDataJson(string data)
{
var dataBytes = Encoding.UTF8.GetBytes(data);
unsafe
{
fixed (byte* dataPtr = dataBytes)
{
CheckAndDropResult(RegorusFFI.API.regorus_engine_add_data_json(E, dataPtr));
}
}
}
}
public void AddDataFromJsonFile(string path)
{
var pathBytes = Encoding.UTF8.GetBytes(path);
unsafe
{
fixed (byte* pathPtr = pathBytes)
{
CheckAndDropResult(RegorusFFI.API.regorus_engine_add_data_from_json_file(E, pathPtr));
}
}
}
}
public void SetInputJson(string input)
{
var inputBytes = Encoding.UTF8.GetBytes(input);
unsafe
{
fixed (byte* inputPtr = inputBytes)
{
CheckAndDropResult(RegorusFFI.API.regorus_engine_set_input_json(E, inputPtr));
}
}
}
}
public void SetInputFromJsonFile(string path)
{
var pathBytes = Encoding.UTF8.GetBytes(path);
unsafe
{
fixed (byte* pathPtr = pathBytes)
{
CheckAndDropResult(RegorusFFI.API.regorus_engine_set_input_from_json_file(E, pathPtr));
}
}
}
}
public string EvalQuery(string query)
{
var queryBytes = Encoding.UTF8.GetBytes(query);
var resultJson = "";
unsafe
{
fixed (byte* queryPtr = queryBytes)
{
var result = RegorusFFI.API.regorus_engine_eval_query(E, queryPtr);
if (result.status == RegorusFFI.RegorusStatus.RegorusStatusOk) {
if (result.output is not null) {
resultJson = System.Runtime.InteropServices.Marshal.PtrToStringUTF8((IntPtr)result.output);
}
RegorusFFI.API.regorus_result_drop(result);
} else {
CheckAndDropResult(result);
}
}
return CheckAndDropResult(RegorusFFI.API.regorus_engine_eval_query(E, queryPtr));
}
}
if (resultJson is not null) {
return resultJson;
} else {
return "";
}
public string EvalRule(string rule)
{
var ruleBytes = Encoding.UTF8.GetBytes(rule);
unsafe
{
fixed (byte* rulePtr = ruleBytes)
{
return CheckAndDropResult(RegorusFFI.API.regorus_engine_eval_query(E, rulePtr));
}
}
}
public void SetEnableCoverage(bool enable)
{
unsafe
{
CheckAndDropResult(RegorusFFI.API.regorus_engine_set_enable_coverage(E, enable));
}
}
public void ClearCoverageData()
{
unsafe
{
CheckAndDropResult(RegorusFFI.API.regorus_engine_clear_coverage_data(E));
}
}
public string GetCoverageReport()
{
unsafe
{
return CheckAndDropResult(RegorusFFI.API.regorus_engine_get_coverage_report(E));
}
}
public string GetCoverageReportPretty()
{
unsafe
{
return CheckAndDropResult(RegorusFFI.API.regorus_engine_get_coverage_report_pretty(E));
}
}
public void SetGatherPrints(bool enable)
{
unsafe
{
CheckAndDropResult(RegorusFFI.API.regorus_engine_set_gather_prints(E, enable));
}
}
public string TakePrints()
{
unsafe
{
return CheckAndDropResult(RegorusFFI.API.regorus_engine_take_prints(E));
}
}
@@ -151,8 +193,8 @@ namespace Regorus
}
}
void CheckAndDropResult(RegorusFFI.RegorusResult result)
string CheckAndDropResult(RegorusFFI.RegorusResult result)
{
if (result.status != RegorusFFI.RegorusStatus.RegorusStatusOk) {
unsafe {
@@ -162,7 +204,16 @@ namespace Regorus
throw ex;
}
}
RegorusFFI.API.regorus_result_drop(result);
var resultString = "";
unsafe
{
if (result.output is not null) {
resultString = System.Runtime.InteropServices.Marshal.PtrToStringUTF8((IntPtr)result.output);
}
RegorusFFI.API.regorus_result_drop(result);
}
return resultString;
}
}

View File

@@ -13,8 +13,9 @@ regorus = { path = "../..", default-features = false }
serde_json = "1.0.113"
[features]
default = ["std", "regorus/full-opa"]
default = ["std", "coverage", "regorus/arc", "regorus/full-opa"]
std = ["regorus/std"]
coverage = ["regorus/coverage"]
custom_allocator = []
[build-dependencies]

View File

@@ -1,87 +0,0 @@
// <auto-generated>
// This code is generated by csbindgen.
// DON'T CHANGE THIS DIRECTLY.
// </auto-generated>
#pragma warning disable CS8500
#pragma warning disable CS8981
using System;
using System.Runtime.InteropServices;
namespace RegorusFFI
{
internal static unsafe partial class API
{
const string __DllName = "regorus_ffi";
/// <summary>Drop a `RegorusResult`. `output` and `error_message` strings are not valid after drop.</summary>
[DllImport(__DllName, EntryPoint = "regorus_result_drop", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void regorus_result_drop(RegorusResult r);
/// <summary>Construct a new Engine See https://docs.rs/regorus/latest/regorus/struct.Engine.html</summary>
[DllImport(__DllName, EntryPoint = "regorus_engine_new", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern RegorusEngine* regorus_engine_new();
/// <summary>Clone a [`RegorusEngine`] To avoid having to parse same policy again, the engine can be cloned after policies and data have been added.</summary>
[DllImport(__DllName, EntryPoint = "regorus_engine_clone", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern RegorusEngine* regorus_engine_clone(RegorusEngine* engine);
[DllImport(__DllName, EntryPoint = "regorus_engine_drop", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern void regorus_engine_drop(RegorusEngine* engine);
/// <summary>Add a policy The policy is parsed into AST. See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.add_policy * `path`: A filename to be associated with the policy. * `rego`: Rego policy.</summary>
[DllImport(__DllName, EntryPoint = "regorus_engine_add_policy", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern RegorusResult regorus_engine_add_policy(RegorusEngine* engine, byte* path, byte* rego);
[DllImport(__DllName, EntryPoint = "regorus_engine_add_policy_from_file", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern RegorusResult regorus_engine_add_policy_from_file(RegorusEngine* engine, byte* path);
/// <summary>Add policy data. See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.add_data * `data`: JSON encoded value to be used as policy data.</summary>
[DllImport(__DllName, EntryPoint = "regorus_engine_add_data_json", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern RegorusResult regorus_engine_add_data_json(RegorusEngine* engine, byte* data);
[DllImport(__DllName, EntryPoint = "regorus_engine_add_data_from_json_file", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern RegorusResult regorus_engine_add_data_from_json_file(RegorusEngine* engine, byte* path);
/// <summary>Clear policy data. See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.clear_data</summary>
[DllImport(__DllName, EntryPoint = "regorus_engine_clear_data", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern RegorusResult regorus_engine_clear_data(RegorusEngine* engine);
/// <summary>Set input. See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.set_input * `input`: JSON encoded value to be used as input to query.</summary>
[DllImport(__DllName, EntryPoint = "regorus_engine_set_input_json", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern RegorusResult regorus_engine_set_input_json(RegorusEngine* engine, byte* input);
[DllImport(__DllName, EntryPoint = "regorus_engine_set_input_from_json_file", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern RegorusResult regorus_engine_set_input_from_json_file(RegorusEngine* engine, byte* path);
/// <summary>Evaluate query. See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.eval_query * `query`: Rego expression to be evaluate.</summary>
[DllImport(__DllName, EntryPoint = "regorus_engine_eval_query", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern RegorusResult regorus_engine_eval_query(RegorusEngine* engine, byte* query);
}
[StructLayout(LayoutKind.Sequential)]
internal unsafe partial struct RegorusResult
{
public RegorusStatus status;
public byte* output;
public byte* error_message;
}
[StructLayout(LayoutKind.Sequential)]
internal unsafe partial struct RegorusEngine
{
}
internal enum RegorusStatus : uint
{
RegorusStatusOk,
RegorusStatusError,
}
}

View File

@@ -1,99 +0,0 @@
#ifndef REGORUS_FFI_HPP
#define REGORUS_FFI_HPP
#include <cstdarg>
#include <cstdint>
#include <cstdlib>
#include <ostream>
#include <new>
/// Status of a call on `RegorusEngine`.
enum class RegorusStatus {
/// The operation was successful.
RegorusStatusOk,
/// The operation was unsuccessful.
RegorusStatusError,
};
/// Wrapper for `regorus::Engine`.
struct RegorusEngine;
/// Result of a call on `RegorusEngine`.
///
/// Must be freed using `regorus_result_drop`.
struct RegorusResult {
/// Status
RegorusStatus status;
/// Output produced by the call.
/// Owned by Rust.
char *output;
/// Errors produced by the call.
/// Owned by Rust.
char *error_message;
};
extern "C" {
/// Drop a `RegorusResult`.
///
/// `output` and `error_message` strings are not valid after drop.
void regorus_result_drop(RegorusResult r);
/// Construct a new Engine
///
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html
RegorusEngine *regorus_engine_new();
/// Clone a [`RegorusEngine`]
///
/// To avoid having to parse same policy again, the engine can be cloned
/// after policies and data have been added.
RegorusEngine *regorus_engine_clone(RegorusEngine *engine);
void regorus_engine_drop(RegorusEngine *engine);
/// Add a policy
///
/// The policy is parsed into AST.
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.add_policy
///
/// * `path`: A filename to be associated with the policy.
/// * `rego`: Rego policy.
RegorusResult regorus_engine_add_policy(RegorusEngine *engine, const char *path, const char *rego);
RegorusResult regorus_engine_add_policy_from_file(RegorusEngine *engine, const char *path);
/// Add policy data.
///
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.add_data
/// * `data`: JSON encoded value to be used as policy data.
RegorusResult regorus_engine_add_data_json(RegorusEngine *engine, const char *data);
RegorusResult regorus_engine_add_data_from_json_file(RegorusEngine *engine, const char *path);
/// Clear policy data.
///
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.clear_data
RegorusResult regorus_engine_clear_data(RegorusEngine *engine);
/// Set input.
///
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.set_input
/// * `input`: JSON encoded value to be used as input to query.
RegorusResult regorus_engine_set_input_json(RegorusEngine *engine, const char *input);
RegorusResult regorus_engine_set_input_from_json_file(RegorusEngine *engine, const char *path);
/// Evaluate query.
///
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.eval_query
/// * `query`: Rego expression to be evaluate.
RegorusResult regorus_engine_eval_query(RegorusEngine *engine, const char *query);
extern uint8_t *regorus_aligned_alloc(uintptr_t alignment, uintptr_t size);
extern void regorus_free(uint8_t *ptr);
} // extern "C"
#endif // REGORUS_FFI_HPP

View File

@@ -1,131 +0,0 @@
#ifndef REGORUS_H
#define REGORUS_H
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
/**
* Status of a call on `RegorusEngine`.
*/
typedef enum RegorusStatus {
/**
* The operation was successful.
*/
RegorusStatusOk,
/**
* The operation was unsuccessful.
*/
RegorusStatusError,
} RegorusStatus;
/**
* Wrapper for `regorus::Engine`.
*/
typedef struct RegorusEngine RegorusEngine;
/**
* Result of a call on `RegorusEngine`.
*
* Must be freed using `regorus_result_drop`.
*/
typedef struct RegorusResult {
/**
* Status
*/
enum RegorusStatus status;
/**
* Output produced by the call.
* Owned by Rust.
*/
char *output;
/**
* Errors produced by the call.
* Owned by Rust.
*/
char *error_message;
} RegorusResult;
/**
* Drop a `RegorusResult`.
*
* `output` and `error_message` strings are not valid after drop.
*/
void regorus_result_drop(struct RegorusResult r);
/**
* Construct a new Engine
*
* See https://docs.rs/regorus/latest/regorus/struct.Engine.html
*/
struct RegorusEngine *regorus_engine_new(void);
/**
* Clone a [`RegorusEngine`]
*
* To avoid having to parse same policy again, the engine can be cloned
* after policies and data have been added.
*/
struct RegorusEngine *regorus_engine_clone(struct RegorusEngine *engine);
void regorus_engine_drop(struct RegorusEngine *engine);
/**
* Add a policy
*
* The policy is parsed into AST.
* See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.add_policy
*
* * `path`: A filename to be associated with the policy.
* * `rego`: Rego policy.
*/
struct RegorusResult regorus_engine_add_policy(struct RegorusEngine *engine,
const char *path,
const char *rego);
struct RegorusResult regorus_engine_add_policy_from_file(struct RegorusEngine *engine,
const char *path);
/**
* Add policy data.
*
* See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.add_data
* * `data`: JSON encoded value to be used as policy data.
*/
struct RegorusResult regorus_engine_add_data_json(struct RegorusEngine *engine, const char *data);
struct RegorusResult regorus_engine_add_data_from_json_file(struct RegorusEngine *engine,
const char *path);
/**
* Clear policy data.
*
* See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.clear_data
*/
struct RegorusResult regorus_engine_clear_data(struct RegorusEngine *engine);
/**
* Set input.
*
* See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.set_input
* * `input`: JSON encoded value to be used as input to query.
*/
struct RegorusResult regorus_engine_set_input_json(struct RegorusEngine *engine, const char *input);
struct RegorusResult regorus_engine_set_input_from_json_file(struct RegorusEngine *engine,
const char *path);
/**
* Evaluate query.
*
* See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.eval_query
* * `query`: Rego expression to be evaluate.
*/
struct RegorusResult regorus_engine_eval_query(struct RegorusEngine *engine, const char *query);
extern uint8_t *regorus_aligned_alloc(uintptr_t alignment, uintptr_t size);
extern void regorus_free(uint8_t *ptr);
#endif /* REGORUS_H */

View File

@@ -119,21 +119,20 @@ pub extern "C" fn regorus_engine_new() -> *mut RegorusEngine {
///
/// To avoid having to parse same policy again, the engine can be cloned
/// after policies and data have been added.
///
#[no_mangle]
pub extern "C" fn regorus_engine_clone(engine: *mut RegorusEngine) -> *mut RegorusEngine {
unsafe {
if engine.is_null() {
return std::ptr::null_mut();
}
Box::into_raw(Box::new((*engine).clone()))
match to_ref(&engine) {
Ok(e) => Box::into_raw(Box::new(e.clone())),
_ => std::ptr::null_mut(),
}
}
#[no_mangle]
pub extern "C" fn regorus_engine_drop(engine: *mut RegorusEngine) {
if !engine.is_null() {
if let Ok(e) = to_ref(&engine) {
unsafe {
let _ = Box::from_raw(engine);
let _ = Box::from_raw(std::ptr::from_mut(e));
}
}
}
@@ -187,6 +186,18 @@ pub extern "C" fn regorus_engine_add_data_json(
}())
}
/// Get list of loaded Rego packages as JSON.
///
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.get_packages
/// * `data`: JSON encoded value to be used as policy data.
#[no_mangle]
pub extern "C" fn regorus_engine_get_packages(engine: *mut RegorusEngine) -> RegorusResult {
to_regorus_string_result(|| -> Result<String> {
serde_json::to_string_pretty(&to_ref(&engine)?.engine.get_packages()?)
.map_err(anyhow::Error::msg)
}())
}
#[cfg(feature = "std")]
#[no_mangle]
pub extern "C" fn regorus_engine_add_data_from_json_file(
@@ -196,7 +207,7 @@ pub extern "C" fn regorus_engine_add_data_from_json_file(
to_regorus_result(|| -> Result<()> {
to_ref(&engine)?
.engine
.add_data(regorus::Value::from_json_file(&from_c_str("path", path)?)?)
.add_data(regorus::Value::from_json_file(from_c_str("path", path)?)?)
}())
}
@@ -237,7 +248,7 @@ pub extern "C" fn regorus_engine_set_input_from_json_file(
to_regorus_result(|| -> Result<()> {
to_ref(&engine)?
.engine
.set_input(regorus::Value::from_json_file(&from_c_str("path", path)?)?);
.set_input(regorus::Value::from_json_file(from_c_str("path", path)?)?);
Ok(())
}())
}
@@ -267,6 +278,139 @@ pub extern "C" fn regorus_engine_eval_query(
}
}
/// Evaluate specified rule.
///
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.eval_rule
/// * `rule`: Path to the rule.
#[no_mangle]
pub extern "C" fn regorus_engine_eval_rule(
engine: *mut RegorusEngine,
rule: *const c_char,
) -> RegorusResult {
let output = || -> Result<String> {
to_ref(&engine)?
.engine
.eval_rule(from_c_str("rule", rule)?)?
.to_json_str()
}();
match output {
Ok(out) => RegorusResult {
status: RegorusStatus::RegorusStatusOk,
output: to_c_str(out),
error_message: std::ptr::null_mut(),
},
Err(e) => to_regorus_result(Err(e)),
}
}
/// Enable/disable coverage.
///
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.set_enable_coverage
/// * `enable`: Whether to enable or disable coverage.
#[no_mangle]
#[cfg(feature = "coverage")]
pub extern "C" fn regorus_engine_set_enable_coverage(
engine: *mut RegorusEngine,
enable: bool,
) -> RegorusResult {
to_regorus_result(|| -> Result<()> {
to_ref(&engine)?.engine.set_enable_coverage(enable);
Ok(())
}())
}
/// Get coverage report.
///
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.get_coverage_report
#[no_mangle]
#[cfg(feature = "coverage")]
pub extern "C" fn regorus_engine_get_coverage_report(engine: *mut RegorusEngine) -> RegorusResult {
let output = || -> Result<String> {
Ok(serde_json::to_string_pretty(
&to_ref(&engine)?.engine.get_coverage_report()?,
)?)
}();
match output {
Ok(out) => RegorusResult {
status: RegorusStatus::RegorusStatusOk,
output: to_c_str(out),
error_message: std::ptr::null_mut(),
},
Err(e) => to_regorus_result(Err(e)),
}
}
/// Get pretty printed coverage report.
///
/// See https://docs.rs/regorus/latest/regorus/coverage/struct.Report.html#method.to_string_pretty
#[no_mangle]
#[cfg(feature = "coverage")]
pub extern "C" fn regorus_engine_get_coverage_report_pretty(
engine: *mut RegorusEngine,
) -> RegorusResult {
let output = || -> Result<String> {
to_ref(&engine)?
.engine
.get_coverage_report()?
.to_string_pretty()
}();
match output {
Ok(out) => RegorusResult {
status: RegorusStatus::RegorusStatusOk,
output: to_c_str(out),
error_message: std::ptr::null_mut(),
},
Err(e) => to_regorus_result(Err(e)),
}
}
/// Clear coverage data.
///
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.clear_coverage_data
#[no_mangle]
#[cfg(feature = "coverage")]
pub extern "C" fn regorus_engine_clear_coverage_data(engine: *mut RegorusEngine) -> RegorusResult {
to_regorus_result(|| -> Result<()> {
to_ref(&engine)?.engine.clear_coverage_data();
Ok(())
}())
}
/// Whether to gather output of print statements.
///
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.set_gather_prints
/// * `enable`: Whether to enable or disable gathering print statements.
#[no_mangle]
pub extern "C" fn regorus_engine_set_gather_prints(
engine: *mut RegorusEngine,
enable: bool,
) -> RegorusResult {
to_regorus_result(|| -> Result<()> {
to_ref(&engine)?.engine.set_gather_prints(enable);
Ok(())
}())
}
/// Take all the gathered print statements.
///
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.take_prints
#[no_mangle]
pub extern "C" fn regorus_engine_take_prints(engine: *mut RegorusEngine) -> RegorusResult {
let output = || -> Result<String> {
Ok(serde_json::to_string_pretty(
&to_ref(&engine)?.engine.take_prints()?,
)?)
}();
match output {
Ok(out) => RegorusResult {
status: RegorusStatus::RegorusStatusOk,
output: to_c_str(out),
error_message: std::ptr::null_mut(),
},
Err(e) => to_regorus_result(Err(e)),
}
}
#[cfg(feature = "custom_allocator")]
extern "C" {
fn regorus_aligned_alloc(alignment: usize, size: usize) -> *mut u8;

View File

@@ -12,7 +12,7 @@ func main() {
var err error
t := time.Now();
// Create new engine
engine := regorus.NewEngine()
defer engine.Close()
@@ -26,10 +26,12 @@ func main() {
"../../tests/aci/policy.rego",
}
for _, policy := range policies {
if err := engine.AddPolicyFromFile(policy); err != nil {
var pkg string
if pkg, err = engine.AddPolicyFromFile(policy); err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
fmt.Printf("Loaded package %s\n", pkg);
}
if err = engine.AddDataFromJsonFile("../../tests/aci/data.json"); err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
@@ -38,21 +40,48 @@ func main() {
elapsed2 := time.Since(t)
t = time.Now()
// Set input and eval query.
// Set input.
if err = engine.SetInputFromJsonFile("../../tests/aci/input.json"); err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
if output, err = engine.EvalQuery("data.framework.mount_overlay = x"); err != nil {
// Eval Rule
if output, err = engine.EvalRule("data.framework.mount_overlay"); err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
elapsed3 := time.Since(t)
fmt.Println("{%s}", output)
fmt.Printf("%s\n", output)
fmt.Printf("NewEngine took %v\n", elapsed1)
fmt.Printf("Add policies and data took %v\n", elapsed2)
fmt.Printf("Set input and eval query took %v\n", elapsed3)
// Create new engine.
engine1 := regorus.NewEngine()
defer engine1.Close()
// Enable coverage
engine1.SetEnableCoverage(true)
var pkg string
pkg, err = engine1.AddPolicy("test.rego", "package test\nx = 1\nmessage = `Hello`")
fmt.Printf("Loaded package %s\n", pkg)
// Eval Rule
if output, err = engine1.EvalRule("data.test.message"); err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
fmt.Printf("%s\n", output)
// Print pretty coverage report.
if output, err = engine1.GetCoverageReportPretty(); err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
fmt.Printf("%s\n", output)
}

View File

@@ -28,7 +28,7 @@ func (e *Engine) Clone() *Engine {
return c
}
func (e *Engine) AddPolicy(path string, rego string) error {
func (e *Engine) AddPolicy(path string, rego string) (string, error) {
path_c := C.CString(path)
defer C.free(unsafe.Pointer(path_c))
@@ -38,21 +38,21 @@ func (e *Engine) AddPolicy(path string, rego string) error {
result := C.regorus_engine_add_policy(e.e, path_c, rego_c)
defer C.regorus_result_drop(result)
if result.status != C.RegorusStatusOk {
return fmt.Errorf("%s", C.GoString(result.error_message))
return "", fmt.Errorf("%s", C.GoString(result.error_message))
}
return nil
return C.GoString(result.output), nil
}
func (e *Engine) AddPolicyFromFile(path string) error {
func (e *Engine) AddPolicyFromFile(path string) (string, error) {
path_c := C.CString(path)
defer C.free(unsafe.Pointer(path_c))
result := C.regorus_engine_add_policy_from_file(e.e, path_c)
defer C.regorus_result_drop(result)
if result.status != C.RegorusStatusOk {
return fmt.Errorf("%s", C.GoString(result.error_message))
return "", fmt.Errorf("%s", C.GoString(result.error_message))
}
return nil
return C.GoString(result.output), nil
}
func (e *Engine) AddDataJson(data string) error {
@@ -115,3 +115,73 @@ func (e *Engine) EvalQuery(query string) (string, error) {
return C.GoString(result.output), nil
}
func (e *Engine) EvalRule(rule string) (string, error) {
rule_c := C.CString(rule)
defer C.free(unsafe.Pointer(rule_c))
result := C.regorus_engine_eval_rule(e.e, rule_c)
defer C.regorus_result_drop(result)
if result.status != C.RegorusStatusOk {
return "", fmt.Errorf("%s", C.GoString(result.error_message))
}
return C.GoString(result.output), nil
}
func (e *Engine) SetEnableCoverage(enable bool) error {
result := C.regorus_engine_set_enable_coverage(e.e, C.bool(enable))
defer C.regorus_result_drop(result)
if result.status != C.RegorusStatusOk {
return fmt.Errorf("%s", C.GoString(result.error_message))
}
return nil
}
func (e *Engine) ClearCoverageData() error {
result := C.regorus_engine_clear_coverage_data(e.e)
defer C.regorus_result_drop(result)
if result.status != C.RegorusStatusOk {
return fmt.Errorf("%s", C.GoString(result.error_message))
}
return nil
}
func (e *Engine) GetCoverageReport() (string, error) {
result := C.regorus_engine_get_coverage_report(e.e)
defer C.regorus_result_drop(result)
if result.status != C.RegorusStatusOk {
return "", fmt.Errorf("%s", C.GoString(result.error_message))
}
return C.GoString(result.output), nil
}
func (e *Engine) GetCoverageReportPretty() (string, error) {
result := C.regorus_engine_get_coverage_report_pretty(e.e)
defer C.regorus_result_drop(result)
if result.status != C.RegorusStatusOk {
return "", fmt.Errorf("%s", C.GoString(result.error_message))
}
return C.GoString(result.output), nil
}
func (e *Engine) SetGatherPrints(b bool) error {
result := C.regorus_engine_set_gather_prints(e.e, C.bool(b))
defer C.regorus_result_drop(result)
if result.status != C.RegorusStatusOk {
return fmt.Errorf("%s", C.GoString(result.error_message))
}
return nil
}
func (e *Engine) TakePrints() (string, error) {
result := C.regorus_engine_take_prints(e.e)
defer C.regorus_result_drop(result)
if result.status != C.RegorusStatusOk {
return "", fmt.Errorf("%s", C.GoString(result.error_message))
}
return C.GoString(result.output), nil
}

View File

@@ -10,8 +10,11 @@ keywords = ["interpreter", "opa", "policy-as-code", "rego"]
[lib]
crate-type = ["cdylib"]
[features]
default = ["regorus/std", "regorus/full-opa"]
[dependencies]
anyhow = "1.0"
serde_json = "1.0.112"
jni = "0.21.1"
regorus = { path = "../.." }
regorus = { path = "../..", default-features = false, features = ["arc"] }

View File

@@ -6,15 +6,31 @@ import com.microsoft.regorus.Engine;
public class Test {
public static void main(String[] args) {
try (Engine engine = new Engine()) {
engine.addPolicy(
String pkg = engine.addPolicy(
"hello.rego",
"package test\nmessage = concat(\", \", [input.message, data.message])"
"package test\nx=1\nmessage = concat(\", \", [input.message, data.message])"
);
System.out.println("Loaded package " + pkg);
engine.addDataJson("{\"message\":\"World!\"}");
engine.setInputJson("{\"message\":\"Hello\"}");
String resJson = engine.evalQuery("data.test.message");
// Evaluate query.
String resJson = engine.evalQuery("data.test.message");
System.out.println(resJson);
// Enable coverage.
engine.setEnableCoverage(true);
// Evaluate rule.
String valueJson = engine.evalRule("data.test.message");
System.out.println(valueJson);
String coverageJson = engine.getCoverageReport();
System.out.println(coverageJson);
System.out.println(engine.getCoverageReportPretty());
}
}
}

View File

@@ -17,18 +17,26 @@ JNIEXPORT jlong JNICALL Java_com_microsoft_regorus_Engine_nativeNewEngine
/*
* Class: com_microsoft_regorus_Engine
* Method: nativeAddPolicy
* Signature: (JLjava/lang/String;Ljava/lang/String;)V
* Method: nativeClone
* Signature: (J)J
*/
JNIEXPORT void JNICALL Java_com_microsoft_regorus_Engine_nativeAddPolicy
JNIEXPORT jlong JNICALL Java_com_microsoft_regorus_Engine_nativeClone
(JNIEnv *, jclass, jlong);
/*
* Class: com_microsoft_regorus_Engine
* Method: nativeAddPolicy
* Signature: (JLjava/lang/String;Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_microsoft_regorus_Engine_nativeAddPolicy
(JNIEnv *, jclass, jlong, jstring, jstring);
/*
* Class: com_microsoft_regorus_Engine
* Method: nativeAddPolicyFromFile
* Signature: (JLjava/lang/String;)V
* Signature: (JLjava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT void JNICALL Java_com_microsoft_regorus_Engine_nativeAddPolicyFromFile
JNIEXPORT jstring JNICALL Java_com_microsoft_regorus_Engine_nativeAddPolicyFromFile
(JNIEnv *, jclass, jlong, jstring);
/*
@@ -79,6 +87,62 @@ JNIEXPORT void JNICALL Java_com_microsoft_regorus_Engine_nativeSetInputJsonFromF
JNIEXPORT jstring JNICALL Java_com_microsoft_regorus_Engine_nativeEvalQuery
(JNIEnv *, jclass, jlong, jstring);
/*
* Class: com_microsoft_regorus_Engine
* Method: nativeEvalRule
* Signature: (JLjava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_microsoft_regorus_Engine_nativeEvalRule
(JNIEnv *, jclass, jlong, jstring);
/*
* Class: com_microsoft_regorus_Engine
* Method: nativeSetEnableCoverage
* Signature: (JZ)V
*/
JNIEXPORT void JNICALL Java_com_microsoft_regorus_Engine_nativeSetEnableCoverage
(JNIEnv *, jclass, jlong, jboolean);
/*
* Class: com_microsoft_regorus_Engine
* Method: nativeGetCoverageReport
* Signature: (J)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_microsoft_regorus_Engine_nativeGetCoverageReport
(JNIEnv *, jclass, jlong);
/*
* Class: com_microsoft_regorus_Engine
* Method: nativeGetCoverageReportAsColoredString
* Signature: (J)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_microsoft_regorus_Engine_nativeGetCoverageReportAsColoredString
(JNIEnv *, jclass, jlong);
/*
* Class: com_microsoft_regorus_Engine
* Method: nativeClearCoverageData
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_com_microsoft_regorus_Engine_nativeClearCoverageData
(JNIEnv *, jclass, jlong);
/*
* Class: com_microsoft_regorus_Engine
* Method: nativeSetGatherPrints
* Signature: (JZ)V
*/
JNIEXPORT void JNICALL Java_com_microsoft_regorus_Engine_nativeSetGatherPrints
(JNIEnv *, jclass, jlong, jboolean);
/*
* Class: com_microsoft_regorus_Engine
* Method: nativeTakePrints
* Signature: (J)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_microsoft_regorus_Engine_nativeTakePrints
(JNIEnv *, jclass, jlong);
/*
* Class: com_microsoft_regorus_Engine
* Method: nativeDestroyEngine

View File

@@ -17,6 +17,17 @@ pub extern "system" fn Java_com_microsoft_regorus_Engine_nativeNewEngine(
Box::into_raw(Box::new(engine)) as jlong
}
#[no_mangle]
pub extern "system" fn Java_com_microsoft_regorus_Engine_nativeClone(
_env: JNIEnv,
_class: JClass,
engine_ptr: jlong,
) -> jlong {
let engine = unsafe { &mut *(engine_ptr as *mut Engine) };
let c = engine.clone();
Box::into_raw(Box::new(c)) as jlong
}
#[no_mangle]
pub extern "system" fn Java_com_microsoft_regorus_Engine_nativeAddPolicy(
env: JNIEnv,
@@ -24,14 +35,19 @@ pub extern "system" fn Java_com_microsoft_regorus_Engine_nativeAddPolicy(
engine_ptr: jlong,
path: JString,
rego: JString,
) {
let _ = throw_err(env, |env| {
) -> jstring {
let res = throw_err(env, |env| {
let engine = unsafe { &mut *(engine_ptr as *mut Engine) };
let path: String = env.get_string(&path)?.into();
let rego: String = env.get_string(&rego)?.into();
engine.add_policy(path, rego)?;
Ok(())
let pkg = env.new_string(engine.add_policy(path, rego)?)?;
Ok(pkg.into_raw())
});
match res {
Ok(val) => val,
Err(_) => JObject::null().into_raw(),
}
}
#[no_mangle]
@@ -40,13 +56,37 @@ pub extern "system" fn Java_com_microsoft_regorus_Engine_nativeAddPolicyFromFile
_class: JClass,
engine_ptr: jlong,
path: JString,
) {
let _ = throw_err(env, |env| {
) -> jstring {
let res = throw_err(env, |env| {
let engine = unsafe { &mut *(engine_ptr as *mut Engine) };
let path: String = env.get_string(&path)?.into();
engine.add_policy_from_file(path)?;
Ok(())
let pkg = env.new_string(engine.add_policy_from_file(path)?)?;
Ok(pkg.into_raw())
});
match res {
Ok(val) => val,
Err(_) => JObject::null().into_raw(),
}
}
#[no_mangle]
pub extern "system" fn Java_com_microsoft_regorus_Engine_nativeGetPackages(
env: JNIEnv,
_class: JClass,
engine_ptr: jlong,
) -> jstring {
let res = throw_err(env, |env| {
let engine = unsafe { &mut *(engine_ptr as *mut Engine) };
let packages = engine.get_packages()?;
let packages_json = env.new_string(serde_json::to_string_pretty(&packages)?)?;
Ok(packages_json.into_raw())
});
match res {
Ok(val) => val,
Err(_) => JObject::null().into_raw(),
}
}
#[no_mangle]
@@ -117,7 +157,7 @@ pub extern "system" fn Java_com_microsoft_regorus_Engine_nativeSetInputJsonFromF
let _ = throw_err(env, |env| {
let engine = unsafe { &mut *(engine_ptr as *mut Engine) };
let path: String = env.get_string(&path)?.into();
engine.set_input(Value::from_json_file(&path)?);
engine.set_input(Value::from_json_file(path)?);
Ok(())
});
}
@@ -144,12 +184,133 @@ pub extern "system" fn Java_com_microsoft_regorus_Engine_nativeEvalQuery(
}
#[no_mangle]
pub unsafe extern "system" fn Java_com_microsoft_regorus_Engine_nativeDestroyEngine(
pub extern "system" fn Java_com_microsoft_regorus_Engine_nativeEvalRule(
env: JNIEnv,
_class: JClass,
engine_ptr: jlong,
rule: JString,
) -> jstring {
let res = throw_err(env, |env| {
let engine = unsafe { &mut *(engine_ptr as *mut Engine) };
let rule: String = env.get_string(&rule)?.into();
let value = engine.eval_rule(rule)?;
let output = env.new_string(value.to_json_str()?)?;
Ok(output.into_raw())
});
match res {
Ok(val) => val,
Err(_) => JObject::null().into_raw(),
}
}
#[no_mangle]
pub extern "system" fn Java_com_microsoft_regorus_Engine_nativeSetEnableCoverage(
env: JNIEnv,
_class: JClass,
engine_ptr: jlong,
enable: bool,
) {
let _ = throw_err(env, |_| {
let engine = unsafe { &mut *(engine_ptr as *mut Engine) };
engine.set_enable_coverage(enable);
Ok(())
});
}
#[no_mangle]
pub extern "system" fn Java_com_microsoft_regorus_Engine_nativeGetCoverageReport(
env: JNIEnv,
_class: JClass,
engine_ptr: jlong,
) -> jstring {
let res = throw_err(env, |env| {
let engine = unsafe { &mut *(engine_ptr as *mut Engine) };
let report = engine.get_coverage_report()?;
let output = env.new_string(serde_json::to_string_pretty(&report)?)?;
Ok(output.into_raw())
});
match res {
Ok(val) => val,
Err(_) => JObject::null().into_raw(),
}
}
#[no_mangle]
pub extern "system" fn Java_com_microsoft_regorus_Engine_nativeGetCoverageReportPretty(
env: JNIEnv,
_class: JClass,
engine_ptr: jlong,
) -> jstring {
let res = throw_err(env, |env| {
let engine = unsafe { &mut *(engine_ptr as *mut Engine) };
let report = engine.get_coverage_report()?.to_string_pretty()?;
let output = env.new_string(&report)?;
Ok(output.into_raw())
});
match res {
Ok(val) => val,
Err(_) => JObject::null().into_raw(),
}
}
#[no_mangle]
pub extern "system" fn Java_com_microsoft_regorus_Engine_nativeClearCoverageData(
env: JNIEnv,
_class: JClass,
engine_ptr: jlong,
) {
let _ = throw_err(env, |_| {
let engine = unsafe { &mut *(engine_ptr as *mut Engine) };
engine.clear_coverage_data();
Ok(())
});
}
#[no_mangle]
pub extern "system" fn Java_com_microsoft_regorus_Engine_nativeSetGatherPrints(
env: JNIEnv,
_class: JClass,
engine_ptr: jlong,
b: bool,
) {
let _ = throw_err(env, |_| {
let engine = unsafe { &mut *(engine_ptr as *mut Engine) };
engine.set_gather_prints(b);
Ok(())
});
}
#[no_mangle]
pub extern "system" fn Java_com_microsoft_regorus_Engine_nativeTakePrints(
env: JNIEnv,
_class: JClass,
engine_ptr: jlong,
) -> jstring {
let res = throw_err(env, |env| {
let engine = unsafe { &mut *(engine_ptr as *mut Engine) };
let prints = engine.take_prints()?;
let output = env.new_string(serde_json::to_string_pretty(&prints)?)?;
Ok(output.into_raw())
});
match res {
Ok(val) => val,
Err(_) => JObject::null().into_raw(),
}
}
#[no_mangle]
pub extern "system" fn Java_com_microsoft_regorus_Engine_nativeDestroyEngine(
_env: JNIEnv,
_class: JClass,
engine_ptr: jlong,
) {
let _engine = Box::from_raw(engine_ptr as *mut Engine);
unsafe {
let _engine = Box::from_raw(engine_ptr as *mut Engine);
}
}
fn throw_err<T>(mut env: JNIEnv, mut f: impl FnMut(&mut JNIEnv) -> Result<T>) -> Result<T> {

View File

@@ -16,20 +16,29 @@ import java.util.concurrent.atomic.AtomicReference;
/**
* Regorus Engine.
*/
public class Engine implements AutoCloseable {
public class Engine implements AutoCloseable, Cloneable {
// Methods exposed from Rust side, you can run
// `javac -h . src/main/java/com/microsoft/regorus/Engine.java` to update
// expected native header at `bindings/java/com_microsoft_regorus_Engine.h`
// if you update the native API.
private static native long nativeNewEngine();
private static native void nativeAddPolicy(long enginePtr, String path, String rego);
private static native void nativeAddPolicyFromFile(long enginePtr, String path);
private static native long nativeClone(long enginePtr);
private static native String nativeAddPolicy(long enginePtr, String path, String rego);
private static native String nativeAddPolicyFromFile(long enginePtr, String path);
private static native String nativeGetPackages(long enginePtr);
private static native void nativeClearData(long enginePtr);
private static native void nativeAddDataJson(long enginePtr, String data);
private static native void nativeAddDataJsonFromFile(long enginePtr, String path);
private static native void nativeSetInputJson(long enginePtr, String input);
private static native void nativeSetInputJsonFromFile(long enginePtr, String path);
private static native String nativeEvalQuery(long enginePtr, String query);
private static native String nativeEvalRule(long enginePtr, String qrule);
private static native void nativeSetEnableCoverage(long enginePtr, boolean enable);
private static native String nativeGetCoverageReport(long enginePtr);
private static native String nativeGetCoverageReportPretty(long enginePtr);
private static native void nativeClearCoverageData(long enginePtr);
private static native void nativeSetGatherPrints(long enginePtr, boolean b);
private static native String nativeTakePrints(long enginePtr);
private static native void nativeDestroyEngine(long enginePtr);
// Pointer to Engine allocated on Rust's heap, all native methods works on
@@ -43,25 +52,50 @@ public class Engine implements AutoCloseable {
enginePtr = nativeNewEngine();
}
Engine(long ptr) {
enginePtr = ptr;
}
/**
* Efficiently clones an Engine.
*/
public Engine Clone() {
return new Engine(nativeClone(enginePtr));
}
/**
* Adds an inline Rego policy.
*
* @param filename Filename of this Rego policy.
* @param rego Rego policy.
*
* @return Rego package defined in the policy.
*/
public void addPolicy(String filename, String rego) {
nativeAddPolicy(enginePtr, filename, rego);
public String addPolicy(String filename, String rego) {
return nativeAddPolicy(enginePtr, filename, rego);
}
/**
* Adds a Rego policy from given path.
*
* @param path Path of the Rego policy.
*
* @return Rego package defined in the policy.
*/
public void addPolicyFromFile(String path) {
nativeAddPolicyFromFile(enginePtr, path);
public String addPolicyFromFile(String path) {
return nativeAddPolicyFromFile(enginePtr, path);
}
/**
* Get list of loaded Rego packages.
*
* @return List of Rego packages as a JSON array of strings.
*/
public String getPackages() {
return nativeGetPackages(enginePtr);
}
/**
* Clears the data document.
*/
@@ -137,6 +171,70 @@ public class Engine implements AutoCloseable {
return nativeEvalQuery(enginePtr, query);
}
/**
* Evaluates given Rego rule and returns a JSON string as a result.
*
* @param rule Path of the Rego rule.
*
* @return Value of the rule as a JSON string.
*/
public String evalRule(String rule) {
return nativeEvalRule(enginePtr, rule);
}
/**
* Enable/disable coverage.
*
* @param enable Whether to enable coverage or not.
*
*/
public void setEnableCoverage(boolean enable) {
nativeSetEnableCoverage(enginePtr, enable);
}
/**
* Clear coverage data.
*
*/
public void clearCoverageData() {
nativeClearCoverageData(enginePtr);
}
/**
* Get coverage report as json string.
*
*/
public String getCoverageReport() {
return nativeGetCoverageReport(enginePtr);
}
/**
* Get coverage report as ANSI color coded string.
*
*/
public String getCoverageReportPretty() {
return nativeGetCoverageReportPretty(enginePtr);
}
/**
* Enable/disable gathering prints.
*
* @param b Whether to gather prints or not.
*
*/
public void setGatherPrints(boolean b) {
nativeSetGatherPrints(enginePtr, b);
}
/**
* Take gathered prints.
*
*/
public String takePrints() {
return nativeTakePrints(enginePtr);
}
@Override
public void close() {
nativeDestroyEngine(enginePtr);

View File

@@ -11,10 +11,13 @@ keywords = ["interpreter", "opa", "policy-as-code", "rego"]
[lib]
crate-type = ["cdylib"]
[features]
default = ["regorus/std", "regorus/full-opa"]
[dependencies]
anyhow = "1.0"
ordered-float = "4.2.0"
pyo3 = {version = "0.21.0", features = ["anyhow", "extension-module"] }
regorus = { path = "../.." }
regorus = { path = "../..", default-features = false, features = ["arc"] }
serde_json = "1.0.112"

View File

@@ -10,7 +10,7 @@ Regorus can be used in Python via `regorus` package. (It is not yet available in
See [Repository](https://github.com/microsoft/regorus).
To build this binding, see [building](https://github.com/microsoft/regorus/bindings/python/building.md)
To build this binding, see [building](https://github.com/microsoft/regorus/blob/main/bindings/python/building.md)
## Usage
```Python
@@ -54,14 +54,11 @@ input = {
}
engine.set_input(input)
# Eval query
results = engine.eval_query('data.framework.mount_overlay=x')
# Eval rule
value = engine.eval_rule('data.framework.mount_overlay')
# Print results
print(results['result'][0])
# Print value
print(value)
# Eval query as json
results_json = engine.eval_query_as_json('data.framework.mount_overlay=x')
print(results_json)
```

View File

@@ -21,19 +21,7 @@ impl Default for Engine {
}
}
impl Clone for Engine {
/// Clone a [`Engine`]
///
/// To avoid having to parse same policy again, the engine can be cloned
/// after policies and data have been added.
fn clone(&self) -> Self {
Self {
engine: self.engine.clone(),
}
}
}
fn from<'source>(ob: &Bound<'_, PyAny>) -> Result<Value, PyErr> {
fn from(ob: &Bound<'_, PyAny>) -> Result<Value, PyErr> {
// dicts
Ok(if let Ok(dict) = ob.downcast::<PyDict>() {
let mut map = BTreeMap::new();
@@ -141,7 +129,7 @@ fn to(mut v: Value, py: Python<'_>) -> Result<PyObject> {
Value::Array(_) => {
let list = PyList::empty_bound(py);
for v in std::mem::replace(v.as_array_mut()?, Vec::new()) {
for v in std::mem::take(v.as_array_mut()?) {
list.append(to(v, py)?)?;
}
list.into()
@@ -149,7 +137,7 @@ fn to(mut v: Value, py: Python<'_>) -> Result<PyObject> {
Value::Set(_) => {
let set = PySet::empty_bound(py)?;
for v in std::mem::replace(v.as_set_mut()?, BTreeSet::new()) {
for v in std::mem::take(v.as_set_mut()?) {
set.add(to(v, py)?)?;
}
set.into()
@@ -157,7 +145,7 @@ fn to(mut v: Value, py: Python<'_>) -> Result<PyObject> {
Value::Object(_) => {
let dict = PyDict::new_bound(py);
for (k, v) in std::mem::replace(v.as_object_mut()?, BTreeMap::new()) {
for (k, v) in std::mem::take(v.as_object_mut()?) {
dict.set_item(to(k, py)?, to(v, py)?)?;
}
dict.into()
@@ -221,7 +209,7 @@ impl Engine {
///
/// * `path`: Path to JSON policy data.
pub fn add_data_from_json_file(&mut self, path: String) -> Result<()> {
let data = Value::from_json_file(&path)?;
let data = Value::from_json_file(path)?;
self.engine.add_data(data)
}
@@ -254,7 +242,7 @@ impl Engine {
///
/// * `path`: Path to JSON input data.
pub fn set_input_from_json_file(&mut self, path: String) -> Result<()> {
let input = Value::from_json_file(&path)?;
let input = Value::from_json_file(path)?;
self.engine.set_input(input);
Ok(())
}
@@ -299,6 +287,69 @@ impl Engine {
let results = self.engine.eval_query(query, false)?;
serde_json::to_string_pretty(&results).map_err(|e| anyhow!("{e}"))
}
/// Evaluate rule.
///
/// * `rule`: Full path to the rule.
pub fn eval_rule(&mut self, rule: String, py: Python<'_>) -> Result<PyObject> {
to(self.engine.eval_rule(rule)?, py)
}
/// Evaluate rule and return value as json.
///
/// * `rule`: Full path to the rule.
pub fn eval_rule_as_json(&mut self, rule: String) -> Result<String> {
let v = self.engine.eval_rule(rule)?;
v.to_json_str()
}
/// Enable code coverage
///
/// * `enable`: Whether to enable coverage or not.
pub fn set_enable_coverage(&mut self, enable: bool) {
self.engine.set_enable_coverage(enable)
}
/// Get coverage report as json.
///
pub fn get_coverage_report_as_json(&self) -> Result<String> {
let report = self.engine.get_coverage_report()?;
serde_json::to_string_pretty(&report).map_err(|e| anyhow!("{e}"))
}
/// Get coverage report as pretty printable string.
///
pub fn get_coverage_report_pretty(&self) -> Result<String> {
self.engine.get_coverage_report()?.to_string_pretty()
}
/// Clear coverage data.
///
pub fn clear_coverage_data(&mut self) {
self.engine.clear_coverage_data();
}
/// Gather print statements instead of printing to stderr.
///
pub fn set_gather_prints(&mut self, b: bool) {
self.engine.set_gather_prints(b)
}
/// Take gathered prints.
///
pub fn take_prints(&mut self) -> Result<Vec<String>> {
self.engine.take_prints()
}
/// Clone a [`Engine`]
///
/// To avoid having to parse same policy again, the engine can be cloned
/// after policies and data have been added.
fn clone(&self) -> Self {
Self {
engine: self.engine.clone(),
}
}
}
#[pymodule]

View File

@@ -8,13 +8,13 @@ engine = regorus.Engine()
# Load policies
pkg = engine.add_policy_from_file('../../tests/aci/framework.rego')
print(' Loaded Policy %s' % pkg)
print(' Loaded package %s' % pkg)
pkg = engine.add_policy_from_file('../../tests/aci/api.rego')
print(' Loaded Policy %s' % pkg)
print(' Loaded package %s' % pkg)
pkg = engine.add_policy_from_file('../../tests/aci/policy.rego')
print(' Loaded Policy %s' % pkg)
print(' Loaded package %s' % pkg)
# Add policy data
data = {
@@ -55,3 +55,40 @@ print(results['result'][0])
# Eval query as json
results_json = engine.eval_query_as_json('data.framework.mount_overlay=x')
print(results_json)
# Eval rule
v = engine.eval_rule('data.framework.mount_overlay')
print(v)
# Eval rule as json
v = engine.eval_rule_as_json('data.framework.mount_overlay')
print(v)
# Enable coverage
engine.set_enable_coverage(True)
engine.eval_rule('data.framework.mount_overlay')
# Print coverage
report_json = engine.get_coverage_report_as_json()
print(report_json)
# Pretty coverage report
report = engine.get_coverage_report_pretty()
print(report)
# Clone engine
engine1 = engine.clone()
# Clear coverage data
engine.clear_coverage_data();
print(engine1.get_coverage_report_pretty())
# Enable gathering prints
engine1.set_gather_prints(True)
# Gather prints
engine1.eval_query('print("Hello")')
ps = engine1.take_prints()
print(ps)

View File

@@ -9,8 +9,11 @@ publish = false
crate-type = ["cdylib"]
path = "src/lib.rs"
[features]
default = ["regorus/std", "regorus/full-opa"]
[dependencies]
magnus = { version = "0.6.4" }
regorus = { git = "https://github.com/microsoft/regorus" }
regorus = { git = "https://github.com/microsoft/regorus", default-features = false, features = ["arc"] }
serde_json = "1.0.117"
serde_magnus = "0.8.1"

View File

@@ -72,7 +72,7 @@ impl Engine {
}
fn add_data_from_json_file(&self, path: String) -> Result<(), Error> {
let json_data = regorus::Value::from_json_file(&path).map_err(|e| {
let json_data = regorus::Value::from_json_file(path).map_err(|e| {
Error::new(
runtime_error(),
format!("Failed to parse JSON data file: {}", e),
@@ -112,7 +112,7 @@ impl Engine {
}
fn add_input_from_json_file(&self, path: String) -> Result<(), Error> {
let json_data = regorus::Value::from_json_file(&path).map_err(|e| {
let json_data = regorus::Value::from_json_file(path).map_err(|e| {
Error::new(
runtime_error(),
format!("Failed to parse JSON input file: {}", e),
@@ -193,7 +193,8 @@ impl Engine {
}
fn set_enable_coverage(&self, enable: bool) -> Result<(), Error> {
Ok(self.engine.borrow_mut().set_enable_coverage(enable))
self.engine.borrow_mut().set_enable_coverage(enable);
Ok(())
}
fn get_coverage_report_as_json(&self) -> Result<String, Error> {
@@ -237,12 +238,14 @@ impl Engine {
}
fn clear_coverage_data(&self) -> Result<(), Error> {
Ok(self.engine.borrow_mut().clear_coverage_data())
self.engine.borrow_mut().clear_coverage_data();
Ok(())
}
// Print statements can be gathered async instead of printing to stderr
fn set_gather_prints(&self, enable: bool) -> Result<(), Error> {
Ok(self.engine.borrow_mut().set_gather_prints(enable))
self.engine.borrow_mut().set_gather_prints(enable);
Ok(())
}
fn take_prints(&self) -> Result<Vec<String>, Error> {

View File

@@ -10,8 +10,11 @@ keywords = ["interpreter", "opa", "policy-as-code", "rego"]
[lib]
crate-type = ["cdylib"]
[features]
default = ["regorus/std", "regorus/full-opa"]
[dependencies]
regorus = { path = "../.." }
regorus = { path = "../..", default-features = false, features = ["arc"] }
serde_json = "1.0.111"
wasm-bindgen = "0.2.90"

View File

@@ -10,72 +10,10 @@
See [Repository](https://github.com/microsoft/regorus).
To build this binding, see [building](https://github.com/microsoft/regorus/bindings/wasm/building.md)
To build this binding, see [building.md](https://github.com/microsoft/regorus/blob/main/bindings/wasm/building.md)
## Usage
```javascript
var regorus = require('regorusjs')
// Create an engine.
var engine = new regorus.Engine();
// Add Rego policy.
engine.add_policy(
// Associate this file name with policy
'hello.rego',
// Rego policy
`
package test
# Join messages
message = concat(", ", [input.message, data.message])
`)
// Set policy data
engine.add_data_json(`
{
"message" : "World!"
}
`)
// Set policy input
engine.set_input_json(`
{
"message" : "Hello"
}
`)
// Eval query
results = engine.eval_query('data.test.message')
// Display
console.log(results)
// {
// "result": [
// {
// "expressions": [
// {
// "value": "Hello, World!",
// "text": "data.test.message",
// "location": {
// "row": 1,
// "col": 1
// }
// }
// ]
// }
// ]
// }
// Convert results to object
results = JSON.parse(results)
// Process result
console.log(results.result[0].expressions[0].value)
// Hello, World!
```
See [test.js](https://github.com/microsoft/regorus/blob/main/bindings/wasm/test.js) for example usage.

View File

@@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#![allow(non_snake_case)]
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
@@ -50,7 +52,7 @@ impl Engine {
///
/// * `path`: A filename to be associated with the policy.
/// * `rego`: Rego policy.
pub fn add_policy(&mut self, path: String, rego: String) -> Result<String, JsValue> {
pub fn addPolicy(&mut self, path: String, rego: String) -> Result<String, JsValue> {
self.engine.add_policy(path, rego).map_err(error_to_jsvalue)
}
@@ -58,15 +60,22 @@ impl Engine {
///
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.add_data
/// * `data`: JSON encoded value to be used as policy data.
pub fn add_data_json(&mut self, data: String) -> Result<(), JsValue> {
pub fn addDataJson(&mut self, data: String) -> Result<(), JsValue> {
let data = regorus::Value::from_json_str(&data).map_err(error_to_jsvalue)?;
self.engine.add_data(data).map_err(error_to_jsvalue)
}
/// Get the list of packages defined by loaded policies.
///
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.get_packages
pub fn getPackages(&self) -> Result<Vec<String>, JsValue> {
self.engine.get_packages().map_err(error_to_jsvalue)
}
/// Clear policy data.
///
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.clear_data
pub fn clear_data(&mut self) -> Result<(), JsValue> {
pub fn clearData(&mut self) -> Result<(), JsValue> {
self.engine.clear_data();
Ok(())
}
@@ -75,7 +84,7 @@ impl Engine {
///
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.set_input
/// * `input`: JSON encoded value to be used as input to query.
pub fn set_input_json(&mut self, input: String) -> Result<(), JsValue> {
pub fn setInputJson(&mut self, input: String) -> Result<(), JsValue> {
let input = regorus::Value::from_json_str(&input).map_err(error_to_jsvalue)?;
self.engine.set_input(input);
Ok(())
@@ -85,13 +94,75 @@ impl Engine {
///
/// See https://docs.rs/regorus/0.1.0-alpha.2/regorus/struct.Engine.html#method.eval_query
/// * `query`: Rego expression to be evaluate.
pub fn eval_query(&mut self, query: String) -> Result<String, JsValue> {
pub fn evalQuery(&mut self, query: String) -> Result<String, JsValue> {
let results = self
.engine
.eval_query(query, false)
.map_err(error_to_jsvalue)?;
serde_json::to_string_pretty(&results).map_err(error_to_jsvalue)
}
/// Evaluate rule(s) at given path.
///
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.eval_rule
///
/// * `path`: The full path to the rule(s).
pub fn evalRule(&mut self, path: String) -> Result<String, JsValue> {
let v = self.engine.eval_rule(path).map_err(error_to_jsvalue)?;
v.to_json_str().map_err(error_to_jsvalue)
}
/// Gather output from print statements instead of emiting to stderr.
///
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.set_gather_prints
/// * `b`: Whether to enable gathering prints or not.
pub fn setGatherPrints(&mut self, b: bool) {
self.engine.set_gather_prints(b)
}
/// Take the gathered output of print statements.
///
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.take_prints
pub fn takePrints(&mut self) -> Result<Vec<String>, JsValue> {
self.engine.take_prints().map_err(error_to_jsvalue)
}
/// Enable/disable policy coverage.
///
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.set_enable_coverage
/// * `b`: Whether to enable gathering coverage or not.
pub fn setEnableCoverage(&mut self, enable: bool) {
self.engine.set_enable_coverage(enable)
}
/// Get the coverage report as json.
///
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.get_coverage_report
pub fn getCoverageReport(&self) -> Result<String, JsValue> {
let report = self
.engine
.get_coverage_report()
.map_err(error_to_jsvalue)?;
serde_json::to_string_pretty(&report).map_err(error_to_jsvalue)
}
/// Clear gathered coverage data.
///
/// See https://docs.rs/regorus/latest/regorus/struct.Engine.html#method.clear_coverage_data
pub fn clearCoverageData(&mut self) {
self.engine.clear_coverage_data()
}
/// Get ANSI color coded coverage report.
///
/// See https://docs.rs/regorus/latest/regorus/coverage/struct.Report.html#method.to_string_pretty
pub fn getCoverageReportPretty(&self) -> Result<String, JsValue> {
let report = self
.engine
.get_coverage_report()
.map_err(error_to_jsvalue)?;
report.to_string_pretty().map_err(error_to_jsvalue)
}
}
#[cfg(test)]
@@ -102,9 +173,10 @@ mod tests {
#[wasm_bindgen_test]
pub fn basic() -> Result<(), JsValue> {
let mut engine = crate::Engine::new();
engine.setEnableCoverage(true);
// Exercise all APIs.
engine.add_data_json(
engine.addDataJson(
r#"
{
"foo" : "bar"
@@ -113,7 +185,7 @@ mod tests {
.to_string(),
)?;
engine.set_input_json(
engine.setInputJson(
r#"
{
"message" : "Hello"
@@ -122,15 +194,16 @@ mod tests {
.to_string(),
)?;
engine.add_policy(
let pkg = engine.addPolicy(
"hello.rego".to_string(),
r#"
package test
message = input.message"#
.to_string(),
)?;
assert_eq!(pkg, "data.test");
let results = engine.eval_query("data".to_string())?;
let results = engine.evalQuery("data".to_string())?;
let r = regorus::Value::from_json_str(&results).map_err(crate::error_to_jsvalue)?;
let v = &r["result"][0]["expressions"][0]["value"];
@@ -141,6 +214,38 @@ mod tests {
// Test that data was set.
assert_eq!(v["foo"], regorus::Value::from("bar"));
// Use eval_rule to perform same query.
let v = engine.evalRule("data.test.message".to_owned())?;
let v = regorus::Value::from_json_str(&v).map_err(crate::error_to_jsvalue)?;
// Ensure that input and policy were evaluated.
assert_eq!(v, regorus::Value::from("Hello"));
let pkgs = engine.getPackages()?;
assert_eq!(pkgs, vec!["data.test"]);
engine.setGatherPrints(true);
let _ = engine.evalQuery("print(\"Hello\")".to_owned());
let prints = engine.takePrints()?;
assert_eq!(prints, vec!["<query.rego>:1: Hello"]);
// Test clone.
let mut engine1 = engine.clone();
// Test code coverage.
let report = engine1.getCoverageReport()?;
let r = regorus::Value::from_json_str(&report).map_err(crate::error_to_jsvalue)?;
assert_eq!(
r["files"][0]["covered"]
.as_array()
.map_err(crate::error_to_jsvalue)?,
&vec![regorus::Value::from(3)]
);
println!("{}", engine1.getCoverageReportPretty()?);
engine1.clearCoverageData();
Ok(())
}
}

View File

@@ -1,48 +1,87 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
var regorus = require('./pkg/regorusjs')
var regorus = require('./pkg/regorusjs');
// Create an engine.
var engine = new regorus.Engine();
// Enable code coverage
engine.setEnableCoverage(true);
// Add Rego policy.
var pkg = engine.add_policy(
var pkg = engine.addPolicy(
// Associate this file name with policy
'hello.rego',
// Rego policy
`
package test
x = 10
# Join messages
message = concat(", ", [input.message, data.message])
`)
console.log("Loaded policy " + pkg)
`);
console.log(pkg);
// data.test
// Set policy data
engine.add_data_json(`
engine.addDataJson(`
{
"message" : "World!"
}
`)
`);
// Set policy input
engine.set_input_json(`
engine.setInputJson(`
{
"message" : "Hello"
}
`)
`);
// Eval rule as json
var value = engine.evalRule('data.test.message');
value = JSON.parse(value);
// Display value
console.log(value);
// Hello, World!
// Eval query
var results = engine.eval_query('data.test.message')
results = engine.evalQuery('data.test.message');
// Display
console.log(results)
console.log(results);
// {
// "result": [
// {
// "expressions": [
// {
// "value": "Hello, World!",
// "text": "data.test.message",
// "location": {
// "row": 1,
// "col": 1
// }
// }
// ]
// }
// ]
// }
// Convert results to object
results = JSON.parse(results)
results = JSON.parse(results);
// Process result
console.log(results.result[0].expressions[0].value)
console.log(results.result[0].expressions[0].value);
// Hello, World!
// Print coverage report
report = engine.getCoverageReport();
console.log(report);
// Print pretty report.
report = engine.getCoverageReportPretty();
console.log(report);