more tests ready

This commit is contained in:
Katarzyna Miernikiewicz 2020-09-17 15:59:03 +00:00
parent 6dcac6de05
commit 9fec584455
14 changed files with 305 additions and 85 deletions

View File

@ -54,11 +54,11 @@ foreach(exe base multiple_files yaml_stream formatter)
endforeach() endforeach()
add_executable(jsonnet_base_transaction add_executable(jsonnet_base_transacted
jsonnet_base_transaction.cc jsonnet_base_transaction.cc
) )
target_link_libraries(jsonnet_base_transaction PRIVATE target_link_libraries(jsonnet_base_transacted PRIVATE
libjsonnet libjsonnet
jsonnet_helper jsonnet_helper
jsonnet_sapi jsonnet_sapi

View File

@ -0,0 +1,50 @@
/*
Copyright 2015 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
{
concat_array: [1, 2, 3] + [4],
concat_string: '123' + 4,
equality1: 1 == '1',
equality2: [{}, { x: 3 - 1 }]
== [{}, { x: 2 }],
ex1: 1 + 2 * 3 / (4 + 5),
// Bitwise operations first cast to int.
ex2: self.ex1 | 3,
// Modulo operator.
ex3: self.ex1 % 2,
// Boolean logic
ex4: (4 > 3) && (1 <= 3) || false,
// Mixing objects together
obj: { a: 1, b: 2 } + { b: 3, c: 4 },
// Test if a field is in an object
obj_member: 'foo' in { foo: 1 },
// String formatting
str1: 'The value of self.ex2 is '
+ self.ex2 + '.',
str2: 'The value of self.ex2 is %g.'
% self.ex2,
str3: 'ex1=%0.2f, ex2=%0.2f'
% [self.ex1, self.ex2],
// By passing self, we allow ex1 and ex2 to
// be extracted internally.
str4: 'ex1=%(ex1)0.2f, ex2=%(ex2)0.2f'
% self,
// Do textual templating of entire files:
str5: |||
ex1=%(ex1)0.2f
ex2=%(ex2)0.2f
||| % self,
}

View File

@ -0,0 +1,29 @@
/*
Copyright 2015 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
local utils = import 'utils.libsonnet';
{
Negroni: {
// Divide 3oz among the 3 ingredients.
ingredients: utils.equal_parts(3, [
'Farmers Gin',
'Sweet Red Vermouth',
'Campari',
]),
garnish: 'Orange Peel',
served: 'On The Rocks',
},
}

View File

@ -0,0 +1,26 @@
/*
Copyright 2015 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
{
equal_parts(size, ingredients)::
// Define a function-scoped variable.
local qty = size / std.length(ingredients);
// Return an array.
[
{ kind: i, qty: qty }
for i in ingredients
],
}

View File

@ -0,0 +1,26 @@
{
"concat_array": [
1,
2,
3,
4
],
"concat_string": "1234",
"equality1": false,
"equality2": true,
"ex1": 1.6666666666666665,
"ex2": 3,
"ex3": 1.6666666666666665,
"ex4": true,
"obj": {
"a": 1,
"b": 3,
"c": 4
},
"obj_member": true,
"str1": "The value of self.ex2 is 3.",
"str2": "The value of self.ex2 is 3.",
"str3": "ex1=1.67, ex2=3.00",
"str4": "ex1=1.67, ex2=3.00",
"str5": "ex1=1.67\nex2=3.00\n"
}

View File

@ -0,0 +1,20 @@
{
"Negroni": {
"garnish": "Orange Peel",
"ingredients": [
{
"kind": "Farmers Gin",
"qty": 1
},
{
"kind": "Sweet Red Vermouth",
"qty": 1
},
{
"kind": "Campari",
"qty": 1
}
],
"served": "On The Rocks"
}
}

View File

@ -104,7 +104,7 @@ int main(int argc, char* argv[]) {
sapi::v::ConstCStr out_file_var(out_file_in_sandboxee.c_str()); sapi::v::ConstCStr out_file_var(out_file_in_sandboxee.c_str());
sapi::v::RemotePtr output_pointer(output.value()); sapi::v::RemotePtr output_pointer(output.value());
sapi::StatusOr<bool> success = api.c_write_multi_output_files( sapi::StatusOr<bool> success = api.c_write_multi_output_files(
&output_pointer, out_file_var.PtrBefore()); &output_pointer, out_file_var.PtrBefore(), true);
CHECK(success.ok() && success.value()) CHECK(success.ok() && success.value())
<< "Writing to output file failed " << success.status() << " " << "Writing to output file failed " << success.status() << " "

View File

@ -1,6 +1,6 @@
--- jsonnet.cpp 2020-09-09 12:15:33.687539042 +0000 --- jsonnet.cpp 2020-09-09 12:15:33.687539042 +0000
+++ write_helper.cpp 2020-09-15 14:27:01.907774290 +0000 +++ write_helper.cpp 2020-09-17 15:35:02.684743876 +0000
@@ -14,559 +14,123 @@ @@ -14,559 +14,125 @@
limitations under the License. limitations under the License.
*/ */
@ -101,34 +101,7 @@
- : filenameIsCode(false), - : filenameIsCode(false),
- evalMulti(false), - evalMulti(false),
- evalStream(false) - evalStream(false)
+/** Writes output files for multiple file output */ - {
+bool write_multi_output_files(char *output, const std::string &output_dir) {
+ // If multiple file output is used, then iterate over each string from
+ // the sequence of strings returned by jsonnet_evaluate_snippet_multi,
+ // construct pairs of filename and content, and write each output file.
+ std::map<std::string, std::string> r;
+ for (const char *c = output; *c != '\0';) {
+ const char *filename = c;
+ const char *c2 = c;
+ while (*c2 != '\0') ++c2;
+ ++c2;
+ const char *json = c2;
+ while (*c2 != '\0') ++c2;
+ ++c2;
+ c = c2;
+ r[filename] = json;
+ }
+
+ std::ostream *o;
+ std::ofstream f;
+
+ o = &std::cout;
+
+ for (const auto &pair : r) {
+ const std::string &new_content = pair.second;
+ const std::string &filename = output_dir + pair.first;
+ (*o) << filename << std::endl;
{
- } - }
-}; -};
- -
@ -166,7 +139,35 @@
- // duplicate all the single quotes in @path to make a quoted string - // duplicate all the single quotes in @path to make a quoted string
- for (b = 0; (e = path.find("'", b)) != std::string::npos; b = e + 1) { - for (b = 0; (e = path.find("'", b)) != std::string::npos; b = e + 1) {
- val.append(path.substr(b, e - b + 1)).push_back('\''); - val.append(path.substr(b, e - b + 1)).push_back('\'');
- } +/** Writes output files for multiple file output */
+bool write_multi_output_files(char *output, const std::string &output_dir, bool show_output_file_names) {
+ // If multiple file output is used, then iterate over each string from
+ // the sequence of strings returned by jsonnet_evaluate_snippet_multi,
+ // construct pairs of filename and content, and write each output file.
+ std::map<std::string, std::string> r;
+ for (const char *c = output; *c != '\0';) {
+ const char *filename = c;
+ const char *c2 = c;
+ while (*c2 != '\0') ++c2;
+ ++c2;
+ const char *json = c2;
+ while (*c2 != '\0') ++c2;
+ ++c2;
+ c = c2;
+ r[filename] = json;
+ }
+
+ std::ostream *o;
+ std::ofstream f;
+
+ o = &std::cout;
+
+ for (const auto &pair : r) {
+ const std::string &new_content = pair.second;
+ const std::string &filename = output_dir + pair.first;
+ if (show_output_file_names) {
+ (*o) << filename << std::endl;
}
- val.append(path.substr(b)).push_back('\''); - val.append(path.substr(b)).push_back('\'');
- -
- return true; - return true;
@ -348,6 +349,7 @@
- return ARG_FAILURE; - return ARG_FAILURE;
- } else { - } else {
- remaining_args.push_back(args[i]); - remaining_args.push_back(args[i]);
+ {
+ std::ifstream exists(filename.c_str()); + std::ifstream exists(filename.c_str());
+ if (exists.good()) { + if (exists.good()) {
+ std::string existing_content; + std::string existing_content;
@ -494,6 +496,37 @@
- return false; - return false;
- } - }
- o = &f; - o = &f;
- }
-
- // If YAML stream output is used, then iterate over each string from
- // the sequence of strings returned by jsonnet_evaluate_snippet_stream,
- // and add the --- and ... as defined by the YAML spec.
- std::vector<std::string> r;
- for (const char *c = output; *c != '\0';) {
- const char *json = c;
- while (*c != '\0')
- ++c;
- ++c;
- r.emplace_back(json);
- }
- jsonnet_realloc(vm, output, 0);
- for (const auto &str : r) {
- (*o) << "---\n";
- (*o) << str;
- }
- if (r.size() > 0)
- (*o) << "...\n";
- o->flush();
-
- if (output_file.empty()) {
- std::cout.flush();
- } else {
- f.close();
- if (!f.good()) {
- std::string msg = "Writing to output file: " + output_file;
- perror(msg.c_str());
- return false;
- }
+bool write_output_stream(char *output, const std::string &output_file) { +bool write_output_stream(char *output, const std::string &output_file) {
+ std::ostream *o; + std::ostream *o;
+ std::ofstream f; + std::ofstream f;
@ -539,37 +572,6 @@
} }
+ } + }
- // If YAML stream output is used, then iterate over each string from
- // the sequence of strings returned by jsonnet_evaluate_snippet_stream,
- // and add the --- and ... as defined by the YAML spec.
- std::vector<std::string> r;
- for (const char *c = output; *c != '\0';) {
- const char *json = c;
- while (*c != '\0')
- ++c;
- ++c;
- r.emplace_back(json);
- }
- jsonnet_realloc(vm, output, 0);
- for (const auto &str : r) {
- (*o) << "---\n";
- (*o) << str;
- }
- if (r.size() > 0)
- (*o) << "...\n";
- o->flush();
-
- if (output_file.empty()) {
- std::cout.flush();
- } else {
- f.close();
- if (!f.good()) {
- std::string msg = "Writing to output file: " + output_file;
- perror(msg.c_str());
- return false;
- }
- }
-
- return true; - return true;
-} -}
- -

View File

@ -58,9 +58,9 @@ bool c_write_output_file(const char* output, const char* output_file) {
return write_output_file(output, s_output_file); return write_output_file(output, s_output_file);
} }
bool c_write_multi_output_files(char* output, char* output_dir) { bool c_write_multi_output_files(char* output, char* output_dir, bool show_output_file_names) {
std::string s_output_dir(output_dir); std::string s_output_dir(output_dir);
return write_multi_output_files(output, s_output_dir); return write_multi_output_files(output, s_output_dir, show_output_file_names);
} }
bool c_write_output_stream(char* output, char* output_file) { bool c_write_output_stream(char* output, char* output_file) {

View File

@ -48,11 +48,11 @@ extern "C" char* c_jsonnet_realloc(struct JsonnetVm* vm, char* str, size_t sz);
extern "C" bool c_write_multi_output_files(//struct JsonnetVm* vm, extern "C" bool c_write_multi_output_files(//struct JsonnetVm* vm,
char* output, char* output,
char* output_dir); char* output_dir, bool show_output_file_names);
bool write_multi_output_files(//struct JsonnetVm* vm, bool write_multi_output_files(//struct JsonnetVm* vm,
char* output, char* output,
const std::string& output_dir); const std::string& output_dir, bool show_output_file_names);
extern "C" bool c_write_output_stream(//struct JsonnetVm* vm, extern "C" bool c_write_output_stream(//struct JsonnetVm* vm,
char* output, char* output,

View File

@ -20,14 +20,14 @@ file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/tests/tests_output)
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/tests/tests_expected_output) file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/tests/tests_expected_output)
add_custom_target(test_preparation ALL add_custom_target(test_preparation ALL
COMMAND cp ${PROJECT_SOURCE_DIR}/examples/jsonnet_codes/multiple_files_example.jsonnet ${PROJECT_BINARY_DIR}/tests/tests_input COMMAND cp ${PROJECT_SOURCE_DIR}/examples/jsonnet_codes/* ${PROJECT_BINARY_DIR}/tests/tests_input
COMMAND cp ${PROJECT_SOURCE_DIR}/examples/jsonnet_codes/yaml_stream_example.jsonnet ${PROJECT_BINARY_DIR}/tests/tests_input #COMMAND cp ${PROJECT_SOURCE_DIR}/examples/jsonnet_codes/yaml_stream_example.jsonnet ${PROJECT_BINARY_DIR}/tests/tests_input
COMMAND cp ${PROJECT_SOURCE_DIR}/jsonnet/examples/arith.jsonnet ${PROJECT_BINARY_DIR}/tests/tests_input #COMMAND cp ${PROJECT_SOURCE_DIR}/jsonnet/examples/arith.jsonnet ${PROJECT_BINARY_DIR}/tests/tests_input
COMMAND cp ${PROJECT_SOURCE_DIR}/jsonnet/examples/negroni.jsonnet ${PROJECT_BINARY_DIR}/tests/tests_input #COMMAND cp ${PROJECT_SOURCE_DIR}/jsonnet/examples/negroni.jsonnet ${PROJECT_BINARY_DIR}/tests/tests_input
COMMAND cp ${PROJECT_SOURCE_DIR}/jsonnet/examples/utils.libsonnet ${PROJECT_BINARY_DIR}/tests/tests_input #COMMAND cp ${PROJECT_SOURCE_DIR}/jsonnet/examples/utils.libsonnet ${PROJECT_BINARY_DIR}/tests/tests_input
COMMAND cp ${PROJECT_SOURCE_DIR}/examples/jsonnet_codes_expected_output/* ${PROJECT_BINARY_DIR}/tests/tests_expected_output COMMAND cp ${PROJECT_SOURCE_DIR}/examples/jsonnet_codes_expected_output/* ${PROJECT_BINARY_DIR}/tests/tests_expected_output
COMMAND cp ${PROJECT_SOURCE_DIR}/jsonnet/examples/arith.jsonnet.golden ${PROJECT_BINARY_DIR}/tests/tests_expected_output #COMMAND cp ${PROJECT_SOURCE_DIR}/jsonnet/examples/arith.jsonnet.golden ${PROJECT_BINARY_DIR}/tests/tests_expected_output
COMMAND cp ${PROJECT_SOURCE_DIR}/jsonnet/examples/negroni.jsonnet.golden ${PROJECT_BINARY_DIR}/tests/tests_expected_output #COMMAND cp ${PROJECT_SOURCE_DIR}/jsonnet/examples/negroni.jsonnet.golden ${PROJECT_BINARY_DIR}/tests/tests_expected_output
) )
include_directories( include_directories(

View File

@ -20,6 +20,60 @@ class JsonnetTest : public JsonnetTestHelper, public testing::Test {
void TearDown() override { TestTearDown(); } void TearDown() override { TestTearDown(); }
}; };
TEST_F(JsonnetTest, DummyTest) { TEST_F(JsonnetTest, SetUp_TearDown) {
std::cout << "Stuff was done.\n"; ASSERT_FALSE(if_jsonnet_vm_was_used);
} ASSERT_FALSE(if_input_was_read);
}
TEST_F(JsonnetTest, One_file_no_dependencies) {
char input_file[] = "arith.jsonnet";
char output_file[] = "arith_output";
char output_to_read[] = "tests_output/arith_output";
char output_to_expect[] = "tests_expected_output/arith.golden";
Read_input(input_file);
Evaluate_jsonnet_code(input_file, BASE);
Write_output(output_file, BASE);
std::string produced_output = Read_output(output_to_read);
std::string expected_output = Read_output(output_to_expect);
ASSERT_STREQ(produced_output.c_str(), expected_output.c_str());
}
TEST_F(JsonnetTest, One_file_some_dependencies) {
char input_file[] = "negroni.jsonnet";
char output_file[] = "negroni_output";
char output_to_read[] = "tests_output/negroni_output";
char output_to_expect[] = "tests_expected_output/negroni.golden";
Read_input(input_file);
Evaluate_jsonnet_code(input_file, BASE);
Write_output(output_file, BASE);
std::string produced_output = Read_output(output_to_read);
std::string expected_output = Read_output(output_to_expect);
ASSERT_STREQ(produced_output.c_str(), expected_output.c_str());
}
TEST_F(JsonnetTest, Multiple_files) {
char input_file[] = "multiple_files_example.jsonnet";
char output_file[] = "";
char output_to_read_1[] = "tests_output/first_file.json";
char output_to_read_2[] = "tests_output/second_file.json";
char output_to_expect_1[] = "tests_expected_output/first_file.json";
char output_to_expect_2[] = "tests_expected_output/second_file.json";
Read_input(input_file);
Evaluate_jsonnet_code(input_file, MULTIPLE_FILES);
Write_output(output_file, MULTIPLE_FILES);
std::string produced_output_1 = Read_output(output_to_read_1);
std::string produced_output_2 = Read_output(output_to_read_2);
std::string expected_output_1 = Read_output(output_to_expect_1);
std::string expected_output_2 = Read_output(output_to_expect_2);
ASSERT_STREQ(produced_output_1.c_str(), expected_output_1.c_str());
ASSERT_STREQ(produced_output_2.c_str(), expected_output_2.c_str());
}

View File

@ -19,7 +19,10 @@
#include "sandboxed_api/util/status_matchers.h" #include "sandboxed_api/util/status_matchers.h"
#include <filesystem> #include <filesystem>
#include <iostream> #include <iostream>
#include <fstream>
#include <streambuf>
#include <string>
#include <unistd.h>
class JsonnetTestHelper { class JsonnetTestHelper {
protected: protected:
@ -31,6 +34,7 @@ class JsonnetTestHelper {
void Read_input(char* filename); void Read_input(char* filename);
void Evaluate_jsonnet_code(char* filename, Evaluation type); void Evaluate_jsonnet_code(char* filename, Evaluation type);
void Write_output(char* filename_or_directory, Evaluation type); void Write_output(char* filename_or_directory, Evaluation type);
std::string Read_output(char* filename);
std::unique_ptr<JsonnetBaseSandbox> sandbox; std::unique_ptr<JsonnetBaseSandbox> sandbox;
std::unique_ptr<JsonnetApi> api; std::unique_ptr<JsonnetApi> api;
@ -42,4 +46,4 @@ class JsonnetTestHelper {
bool if_jsonnet_vm_was_used; bool if_jsonnet_vm_was_used;
bool if_input_was_read; bool if_input_was_read;
}; };

View File

@ -19,8 +19,11 @@
void JsonnetTestHelper::TestSetUp() { void JsonnetTestHelper::TestSetUp() {
// Get paths to where input and output is stored. // Get paths to where input and output is stored.
std::filesystem::path input_path = std::filesystem::current_path() / "tests_input"; char buffer[256];
std::filesystem::path output_path = std::filesystem::current_path() / "tests_output"; int error = readlink("/proc/self/exe", buffer, 256);
std::filesystem::path binary_path = dirname(buffer);
std::filesystem::path input_path = binary_path / "tests_input" / "dummy_input";
std::filesystem::path output_path = binary_path / "tests_output" / "dummy_output";
// Set up sandbox and api. // Set up sandbox and api.
sandbox = std::make_unique<JsonnetBaseSandbox>(input_path.string(), output_path.string()); sandbox = std::make_unique<JsonnetBaseSandbox>(input_path.string(), output_path.string());
@ -28,7 +31,7 @@ void JsonnetTestHelper::TestSetUp() {
api = std::make_unique<JsonnetApi>(sandbox.get()); api = std::make_unique<JsonnetApi>(sandbox.get());
// Initialize library's main structure. // Initialize library's main structure.
SAPI_ASSERT_OK_AND_ASSIGN(JsonnetVm * vm_ptr, api->c_jsonnet_make()); SAPI_ASSERT_OK_AND_ASSIGN(JsonnetVm* vm_ptr, api->c_jsonnet_make());
vm = std::make_unique<sapi::v::RemotePtr>(vm_ptr); vm = std::make_unique<sapi::v::RemotePtr>(vm_ptr);
if_jsonnet_vm_was_used = false; if_jsonnet_vm_was_used = false;
@ -124,7 +127,7 @@ void JsonnetTestHelper::Write_output(char* filename_or_directory,
sapi::v::ConstCStr out_file_var(out_file_in_sandboxee.c_str()); sapi::v::ConstCStr out_file_var(out_file_in_sandboxee.c_str());
SAPI_ASSERT_OK_AND_ASSIGN( SAPI_ASSERT_OK_AND_ASSIGN(
success, api->c_write_multi_output_files(output.get(), success, api->c_write_multi_output_files(output.get(),
out_file_var.PtrBefore())); out_file_var.PtrBefore(), false));
break; break;
} }
@ -143,3 +146,9 @@ void JsonnetTestHelper::Write_output(char* filename_or_directory,
return; return;
} }
std::string JsonnetTestHelper::Read_output(char* filename) {
std::ifstream input_stream(filename);
std::string contents((std::istreambuf_iterator<char>(input_stream)), std::istreambuf_iterator<char>());
return contents;
}