Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

code coverage #105

Merged
merged 9 commits into from
Dec 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
codecov:
branch: main
require_ci_to_pass: yes

coverage:
precision: 2
round: down
range: "85...100"

parsers:
gcov:
branch_detection:
conditional: yes
loop: yes
method: no
macro: no

comment:
layout: "reach,diff,flags,files,footer"
behavior: default
require_changes: no
20 changes: 10 additions & 10 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ jobs:
- name: Build Debug Build
run: cmake --build cmake-build-debug
- name: Run Tests
run: |
cd cmake-build-debug/src/tests/
./omega_test -d yes --order lex
working-directory: cmake-build-debug/src/tests/
run: ./omega_test -d yes --order lex
- name: Create Node v10 Virtual Environment
run: nodeenv --node=10.24.1 venv
- name: Prepare To Build Node v10 Bindings
Expand All @@ -46,17 +45,18 @@ jobs:
with:
fetch-depth: 0
- name: Setup Debug Build
run: cmake -S . -B cmake-build-debug
run: cmake -S . -B cmake-build-debug -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS=--coverage -DCMAKE_C_FLAGS=--coverage
- name: Build Debug Build
run: cmake --build cmake-build-debug
- name: Run Tests
run: |
cd cmake-build-debug/src/tests/
./omega_test -d yes --order lex
working-directory: cmake-build-debug/src/tests/
run: ./omega_test -d yes --order lex
- name: Collect code coverage
working-directory: cmake-build-debug/src/tests/
run: bash <(curl -s https://codecov.io/bash)
- name: Run Tests Under Valgrind
run: |
cd cmake-build-debug/src/tests/
valgrind --leak-check=full --show-leak-kinds=all --error-exitcode=1 ./omega_test -d yes --order lex
working-directory: cmake-build-debug/src/tests/
run: valgrind --leak-check=full --show-leak-kinds=all --leak-resolution=med --track-origins=yes --vgdb=no --error-exitcode=1 ./omega_test -d yes --order lex
- name: Create Node v10 Virtual Environment
run: nodeenv --node=10.24.1 venv
- name: Prepare To Build Node v10 Bindings
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Ωedit Library
![Build Status](https://github.com/scholarsmate/omega-edit/workflows/Unit%20Tests/badge.svg)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fscholarsmate%2Fomega-edit.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fscholarsmate%2Fomega-edit?ref=badge_shield)
[![codecov](https://codecov.io/gh/scholarsmate/omega-edit/branch/master/graph/badge.svg)](https://codecov.io/gh/scholarsmate/omega-edit)

<img alt="Omega Edit Logo" src="https://raw.githubusercontent.com/scholarsmate/omega-edit/main/images/OmegaEditLogo.png" width=64 style="float: left">
The goal of this project is to provide an open source library for building editors that can handle massive files, multiple authors, and multiple viewports.
Expand All @@ -12,7 +13,7 @@ If you are using just the command line you will need these things installed:
- C/C++ compiler (such as clang, gcc, or mingw)
- CMake (https://cmake.org/download/)
- make or ninja
- nodeenv
- nvm or nodeenv

If developing the Ωedit API, you'll need SWIG installed as well.

Expand Down
49 changes: 33 additions & 16 deletions src/lib/edit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,24 @@ static omega_model_segment_ptr_t clone_model_segment_(const omega_model_segment_
return result;
}

static inline void free_session_changes_(omega_session_t *session_ptr) {
for (auto &change_ptr : session_ptr->model_ptr_->changes) {
if (change_ptr->kind != change_kind_t::CHANGE_DELETE && 7 < change_ptr->length) {
delete[] const_cast<omega_change_t *>(change_ptr.get())->data.bytes_ptr;
}
}
session_ptr->model_ptr_->changes.clear();
}

static inline void free_session_changes_undone_(omega_session_t *session_ptr) {
for (auto &change_ptr : session_ptr->model_ptr_->changes_undone) {
if (change_ptr->kind != change_kind_t::CHANGE_DELETE && 7 < change_ptr->length) {
delete[] const_cast<omega_change_t *>(change_ptr.get())->data.bytes_ptr;
}
}
session_ptr->model_ptr_->changes_undone.clear();
}

/* --------------------------------------------------------------------------------------------------------------------
The objective here is to model the edits using segments. Essentially creating a contiguous model of the file by
keeping track of what to do. The verbs here are READ, INSERT, and OVERWRITE. We don't need to model DELETE because
Expand All @@ -151,14 +169,16 @@ static omega_model_segment_ptr_t clone_model_segment_(const omega_model_segment_
static int update_model_helper_(omega_model_t *model_ptr, const_omega_change_ptr_t &change_ptr) {
int64_t read_offset = 0;

if (model_ptr->model_segments.empty() && change_ptr->kind != change_kind_t::CHANGE_DELETE) {
// The model is empty, and we have a change with content
auto insert_segment_ptr = std::make_unique<omega_model_segment_t>();
insert_segment_ptr->computed_offset = change_ptr->offset;
insert_segment_ptr->computed_length = change_ptr->length;
insert_segment_ptr->change_offset = 0;
insert_segment_ptr->change_ptr = change_ptr;
model_ptr->model_segments.push_back(std::move(insert_segment_ptr));
if (model_ptr->model_segments.empty()) {
if (change_ptr->kind != change_kind_t::CHANGE_DELETE) {
// The model is empty, and we have a change with content
auto insert_segment_ptr = std::make_unique<omega_model_segment_t>();
insert_segment_ptr->computed_offset = change_ptr->offset;
insert_segment_ptr->computed_length = change_ptr->length;
insert_segment_ptr->change_offset = 0;
insert_segment_ptr->change_ptr = change_ptr;
model_ptr->model_segments.push_back(std::move(insert_segment_ptr));
}
return 0;
}
for (auto iter = model_ptr->model_segments.begin(); iter != model_ptr->model_segments.end(); ++iter) {
Expand Down Expand Up @@ -253,7 +273,7 @@ static int64_t update_(omega_session_t *session_ptr, const_omega_change_ptr_t ch
undone_change_ptr->serial *= -1;
} else if (!session_ptr->model_ptr_->changes_undone.empty()) {
// This is not a redo change, so any changes undone are now invalid and must be cleared
session_ptr->model_ptr_->changes_undone.clear();
free_session_changes_undone_(session_ptr);
}
session_ptr->model_ptr_->changes.push_back(change_ptr);
if (0 != update_model_(session_ptr->model_ptr_.get(), change_ptr)) { return -1; }
Expand Down Expand Up @@ -289,11 +309,8 @@ omega_session_t *omega_edit_create_session(const char *file_path, omega_session_
void omega_edit_destroy_session(omega_session_t *session_ptr) {
if (session_ptr->file_ptr) { fclose(session_ptr->file_ptr); }
while (!session_ptr->viewports_.empty()) { omega_edit_destroy_viewport(session_ptr->viewports_.back().get()); }
for (auto &change_ptr : session_ptr->model_ptr_->changes) {
if (change_ptr->kind != change_kind_t::CHANGE_DELETE && 7 < change_ptr->length) {
delete[] const_cast<omega_change_t *>(change_ptr.get())->data.bytes_ptr;
}
}
free_session_changes_(session_ptr);
free_session_changes_undone_(session_ptr);
delete session_ptr;
}

Expand Down Expand Up @@ -349,7 +366,7 @@ int64_t omega_edit_insert(omega_session_t *session_ptr, int64_t offset, const ch

int64_t omega_edit_overwrite_bytes(omega_session_t *session_ptr, int64_t offset, const omega_byte_t *bytes,
int64_t length) {
return (0 <= length && offset < omega_session_get_computed_file_size(session_ptr))
return (0 <= length && offset <= omega_session_get_computed_file_size(session_ptr))
? update_(session_ptr, ovr_(1 + static_cast<int64_t>(omega_session_get_num_changes(session_ptr)),
offset, bytes, length))
: 0;
Expand Down Expand Up @@ -405,7 +422,7 @@ int omega_edit_clear_changes(omega_session_t *session_ptr) {
length = ftello(session_ptr->file_ptr);
}
initialize_model_segments_(session_ptr->model_ptr_->model_segments, length);
session_ptr->model_ptr_->changes.clear();
free_session_changes_(session_ptr);
for (const auto &viewport_ptr : session_ptr->viewports_) {
viewport_ptr->data_segment.capacity = -1 * std::abs(viewport_ptr->data_segment.capacity);// indicate dirty read
omega_viewport_execute_on_change(viewport_ptr.get(), nullptr);
Expand Down
40 changes: 29 additions & 11 deletions src/tests/omega_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,9 @@ TEST_CASE("Buffer Shift", "[BufferShift]") {
auto buff_len = (int64_t) strlen((const char *) buffer);

// Shift the buffer 3 bits to the right
auto rc = omega_util_right_shift_buffer(buffer, buff_len, 3);
REQUIRE(rc == 0);
REQUIRE(0 == omega_util_right_shift_buffer(buffer, buff_len, 3));
// Shift the buffer 5 bits to the right
rc = omega_util_right_shift_buffer(buffer, buff_len, 5);
REQUIRE(rc == 0);
REQUIRE(0 == omega_util_right_shift_buffer(buffer, buff_len, 5));
// We shifted a total of 8 bits (one byte) to the right, so compare the buffer against the fill plus one byte
REQUIRE(strcmp((const char *) fill + 1, (const char *) buffer) == 0);

Expand All @@ -63,14 +61,16 @@ TEST_CASE("Buffer Shift", "[BufferShift]") {
REQUIRE(strcmp((const char *) fill, (const char *) buffer) == 0);

// Shift the buffer 6 bits to the left
rc = omega_util_left_shift_buffer(buffer, buff_len, 6);
REQUIRE(rc == 0);
REQUIRE(0 == omega_util_left_shift_buffer(buffer, buff_len, 6));
// Shift the buffer 2 bits to the left
rc = omega_util_left_shift_buffer(buffer, buff_len, 2);
REQUIRE(0 == rc);
REQUIRE(0 == omega_util_left_shift_buffer(buffer, buff_len, 2));
// We shifted a total of 8 bits (one byte) to the left, so compare the buffer against the fill plus one byte
REQUIRE(strcmp((const char *) fill + 1, (const char *) buffer) == 0);

// Negative tests. Shifting 8 or more bits in either direction should be an error.
REQUIRE(-1 == omega_util_left_shift_buffer(buffer, buff_len, 8));
REQUIRE(-1 == omega_util_right_shift_buffer(buffer, buff_len, 8));

free(buffer);
}

Expand All @@ -85,6 +85,17 @@ TEST_CASE("File Compare", "[UtilTests]") {
}
}

TEST_CASE("File Exists", "[UtilTests]") {
REQUIRE(omega_util_file_exists("data/test1.dat"));
REQUIRE(!omega_util_file_exists("data/IDonTExist.DaT"));
}

TEST_CASE("Current Directory", "[UtilTests]") {
using Catch::Matchers::Contains;
using Catch::Matchers::EndsWith;
REQUIRE_THAT(omega_util_get_current_dir(), Contains("src") && EndsWith("tests"));
}

static inline omega_byte_t to_lower(omega_byte_t byte) { return tolower(byte); }
static inline omega_byte_t to_upper(omega_byte_t byte) { return toupper(byte); }

Expand Down Expand Up @@ -148,9 +159,16 @@ TEST_CASE("Empty File Test", "[EmptyFileTests]") {
REQUIRE(session_ptr);
REQUIRE(strcmp(omega_session_get_file_path(session_ptr), in_filename) == 0);
REQUIRE(omega_session_get_computed_file_size(session_ptr) == file_size);
REQUIRE(0 < omega_edit_insert_bytes(session_ptr, 0, reinterpret_cast<const omega_byte_t *>("0"), 0));
file_size += 1;
REQUIRE(omega_session_get_computed_file_size(session_ptr) == file_size);
REQUIRE(0 == omega_edit_undo_last_change(session_ptr));
auto change_serial = omega_edit_insert_bytes(session_ptr, 0, reinterpret_cast<const omega_byte_t *>("1234567890"), 0);
REQUIRE(0 < change_serial);
file_size += 10;
REQUIRE(file_size == omega_session_get_computed_file_size(session_ptr));
REQUIRE((change_serial * -1) == omega_edit_undo_last_change(session_ptr));
REQUIRE(0 == omega_session_get_computed_file_size(session_ptr));
change_serial = omega_edit_overwrite_string(session_ptr, 0, "abcdefghhijklmnopqrstuvwxyz");
REQUIRE(0 < change_serial);
REQUIRE(27 == omega_session_get_computed_file_size(session_ptr));
omega_edit_destroy_session(session_ptr);
}

Expand Down