Skip to content

Commit

Permalink
Bats tests for the example programs (#1)
Browse files Browse the repository at this point in the history
* Added CMakeCache to git ignore
* Bug fix in utils std.bash techo function
* Top level CMakeLists for all example programs
* Bats tests and tweaks for example programs
* Typo fix and corrected indentation
* Removed bc from bats test
* Refactored away some common relative paths
* Removed runtest.sh
* Improved error message when failing to find database file
* Added README for examples

Co-authored-by: Jack Crawford <jack.crawford@sky.com>
Co-authored-by: Enrico Steffinlongo <enrylongo@gmail.com>
  • Loading branch information
3 people authored Sep 4, 2020
1 parent 6b9ae8b commit 2a77427
Show file tree
Hide file tree
Showing 13 changed files with 408 additions and 93 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ __pycache__/
**.out
**.ptxt
**.ctxt
**/CMakeCache.txt

src/fhe.a
src/*.o
Expand Down
1 change: 1 addition & 0 deletions examples/BGV_binary_arithmetic/BGV_binary_arithmetic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ int main(int argc, char* argv[])
// which would result in several parallel slot-wise operations.
// For simplicity we place the same data into each slot of each ciphertext,
// printing out only the back of each vector.
// NB: fifteenOrLess4Four max is 15 bits. Later in the code we pop the MSB.
long bitSize = 16;
long outSize = 2 * bitSize;
long a_data = NTL::RandomBits_long(bitSize);
Expand Down
11 changes: 8 additions & 3 deletions examples/BGV_country_db_lookup/BGV_country_db_lookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ int main(int argc, char* argv[])
std::cout << "\n* based db search algorithm for demonstration purposes. *";
std::cout << "\n* *";
std::cout << "\n*********************************************************";
std::cout << std::endl;
std::cout << "\n" << std::endl;

std::cout << "---Initialising HE Environment ... ";
// Initialize context
Expand Down Expand Up @@ -177,8 +177,13 @@ int main(int argc, char* argv[])
std::cout << "\nNumber of slots: " << nslots << std::endl;

/************ Read in the database ************/
std::vector<std::pair<std::string, std::string>> country_db =
read_csv(db_filename);
std::vector<std::pair<std::string, std::string>> country_db;
try {
country_db = read_csv(db_filename);
} catch (std::runtime_error& e) {
std::cerr << "\n" << e.what() << std::endl;
exit(1);
}

// Convert strings into numerical vectors
std::cout << "\n---Initializing the encrypted key,value pair database ("
Expand Down
94 changes: 47 additions & 47 deletions examples/BGV_country_db_lookup/countries_dataset.csv
Original file line number Diff line number Diff line change
@@ -1,47 +1,47 @@
Albania, Tirana
Andorra, Andorra la Vella
Austria, Vienna
Belarus, Minsk
Belgium, Brussels
Bosnia and Herzegovina, Sarajevo
Bulgaria, Sofia
Croatia, Zagreb
Czech Republic, Prague
Denmark, Copenhagen
England, London
Estonia, Tallinn
Finland, Helsinki
France, Paris
Germany, Berlin
Greece, Athens
Hungary, Budapest
Iceland, Reykjavík
Ireland, Dublin
Italy, Rome
Latvia, Riga
Liechtenstein, Vaduz
Lithuania, Vilnius
Luxembourg, Luxembourg
Malta, Valletta
Moldova, Chisinau
Monaco, Monaco
Montenegro, Podgorica
Netherlands, Amsterdam
Northern Ireland, Belfast
Norway, Oslo
Poland, Warsaw
Portugal, Lisbon
Romania, Bucharest
Russia, Moscow
San Marino, San Marino
Scotland, Edinburgh
Serbia, Belgrade
Slovakia, Bratislava
Slovenia, Ljubljana
Spain, Madrid
Sweden, Stockholm
Switzerland, Bern
Turkey, Ankara
Ukraine, Kiev
Vatican City, Vatican City
Wales, Cardiff
Albania,Tirana
Andorra,Andorra la Vella
Austria,Vienna
Belarus,Minsk
Belgium,Brussels
Bosnia and Herzegovina,Sarajevo
Bulgaria,Sofia
Croatia,Zagreb
Czech Republic,Prague
Denmark,Copenhagen
England,London
Estonia,Tallinn
Finland,Helsinki
France,Paris
Germany,Berlin
Greece,Athens
Hungary,Budapest
Iceland,Reykjavík
Ireland,Dublin
Italy,Rome
Latvia,Riga
Liechtenstein,Vaduz
Lithuania,Vilnius
Luxembourg,Luxembourg
Malta,Valletta
Moldova,Chisinau
Monaco,Monaco
Montenegro,Podgorica
Netherlands,Amsterdam
Northern Ireland,Belfast
Norway,Oslo
Poland,Warsaw
Portugal,Lisbon
Romania,Bucharest
Russia,Moscow
San Marino,San Marino
Scotland,Edinburgh
Serbia,Belgrade
Slovakia,Bratislava
Slovenia,Ljubljana
Spain,Madrid
Sweden,Stockholm
Switzerland,Bern
Turkey,Ankara
Ukraine,Kiev
Vatican City,Vatican City
Wales,Cardiff
40 changes: 0 additions & 40 deletions examples/BGV_country_db_lookup/runtest.sh

This file was deleted.

8 changes: 5 additions & 3 deletions examples/BGV_packed_arithmetic/BGV_packed_arithmetic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,12 @@ int main(int argc, char* argv[])
// Decrypt the modified ciphertext
secret_key.Decrypt(plaintext_result, ctxt);

std::cout << "Operation: 2(a*a)/(a*a) - 2(a*a)/(a*a) = 0" << std::endl;
// Print the decrypted plaintext
// Should be [0] [0] [0] ... [0] [0]
std::cout << "Decrypted Plaintext: " << plaintext_result << std::endl;
std::cout << "Decrypted Result: " << plaintext_result << std::endl;
// Print the plaintext version result, should be the same as the ctxt version
std::cout << "Plaintext version: " << ptxt << std::endl;
std::cout << "Plaintext Result: " << ptxt << std::endl;

// We can also add constants
// [0] [0] [0] ... [0] [0] -> [1] [1] [1] ... [1] [1]
Expand All @@ -175,9 +176,10 @@ int main(int argc, char* argv[])
helib::Ptxt<helib::BGV> new_plaintext_result(context);
secret_key.Decrypt(new_plaintext_result, ctxt);

std::cout << "Operation: Enc{(0 + 1)*1} + (0 + 1)*1" << std::endl;
// Print the decrypted plaintext
// Should be [2] [2] [2] ... [2] [2]
std::cout << "Decrypted Plaintext: " << new_plaintext_result << std::endl;
std::cout << "Decrypted Result: " << new_plaintext_result << std::endl;

return 0;
}
38 changes: 38 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Copyright (C) 2020 IBM Corp.
# This program is 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. See accompanying LICENSE file.

cmake_minimum_required(VERSION 3.10.2 FATAL_ERROR)

## Use -std=c++14 as default.
set(CMAKE_CXX_STANDARD 14)
## Disable C++ extensions
set(CMAKE_CXX_EXTENSIONS OFF)
## Require full C++ standard
set(CMAKE_CXX_STANDARD_REQUIRED ON)

project(utils LANGUAGES CXX)

# Define standard installation directories (GNU)
include(GNUInstallDirs)

# Set default output folder
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY
"${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY
"${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY
"${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}")

find_package(helib 1.1.0 EXACT REQUIRED)

add_subdirectory(BGV_binary_arithmetic)
add_subdirectory(BGV_country_db_lookup)
add_subdirectory(BGV_packed_arithmetic)
91 changes: 91 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Examples

## Introduction
The `examples` directory provides standalone example programs expressing the
various APIs as well as a simple use-case using HElib. The example programs
provided currently only use the BGV scheme.

## What is provided
Currently the examples provided comprise:
- BGV_binary_arithmetic
- BGV_country_db_lookup
- BGV_packed_arithmetic

More examples are expected to be released at a later date.

## Installation
To compile the examples, you must have HElib already installed on your system
(see [INSTALL.md](../INSTALL.md) in this distribution's root directory). The
process is pure CMake. First, create a build directory and move into it.
From `examples/build` run CMake,

```
cmake [-Dhelib_DIR=<directory-to-installed-HElib>/share/cmake/helib] <directory-to-examples> ..
```

then run make from the same directory with optional number of threads using the
`-j` flag for example,

```
make [-j<number-of-threads>]
```

The executables for each of the example programs can be found in the `bin`
directory.

## Running the examples

All examples have a help method by passing the `-h` flag, for example

```
./BGV_packed_arithmetic -h
```

The BGV_packed_arithmetic example shows some of the basic arithmetic APIs
available for ciphertext and plaintext objects.

The BGV_binary_arithmetic example shows the API for performing binary
arithmetic on a vector of ciphertexts where i-th ciphertext contains the i-th
bit of the binary number.

The BGV_country_db_lookup example shows a use-case for performing a database
lookup on countries and their capitals, more information on this can be found
[here](BGV_country_db_lookup/README.md).

## Running the tests

All tests for the examples are written in bats (a test framework for bash)
and requires [bats-core](https://github.com/bats-core/bats-core).

Note that the tests require that the examples have been successfully compiled
in the `build` directory and available in `build/bin`. To run the tests, one
can simply execute the scripts from within the `examples/tests` directory.

To run all tests type the command below. Optionally, the `-j` flag can use
threads to parallelize the tests. Note, this requires GNU parallel, see the
[bats](https://github.com/bats-core/bats-core) documentation for more
information.
```
bats . [-j <number-of-threads>]
```
To run a specific test file.
```
bats <testfile> [-j <number-of-threads>]
```
or
```
./<testfile> [-j <number-of-threads>]
```
To run a specific test by name add the `-f` flag e.g.
```
bats . -f <testname> [-j <number-of-threads>]
```

The `<testname>` can be a substring of the test name and will match all valid
matches.

For debugging, it is sometimes useful to view the artifacts generated by the
tests. For this, set the environment variable `DEBUG` to `true` or `1` such as,
```
DEBUG=1 bats . [-j <number-of-threads>]
```
60 changes: 60 additions & 0 deletions examples/tests/BGV_binary_arithmetic.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/env bats

# Copyright (C) 2020 IBM Corp.
# This program is 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. See accompanying LICENSE file.

load "std"

BGV_binary_arithmetic="$examples_bin/BGV_binary_arithmetic"

function setup {
mkdir -p $tmp_folder
cd $tmp_folder
print-info-location
}

function teardown {
cd -
remove-test-directory "$tmp_folder"
}

# Calculate the pop count
function popcount {
declare -i n="$1"
declare -i i="$2"
local count=0
while [ $n -ne 0 ] && [ $i -gt 0 ]; do
if [ $((n & 1)) -eq 1 ]; then
((count++))
fi
n=$((n >> 1))
((i--))
done
echo "$count"
}

@test "BGV_binary_arithmetic works" {
run $BGV_binary_arithmetic
a=$(echo -e "$output" | awk '/^a =/{ printf $3 }')
b=$(echo -e "$output" | awk '/^b =/{ printf $3 }')
c=$(echo -e "$output" | awk '/^c =/{ printf $3 }')
output1=$(echo -e "$output" | awk '/a\*b\+c/{ printf $3 }')
output2=$(echo -e "$output" | awk '/a\+b\+c/{ printf $3 }')
output3=$(echo -e "$output" | awk '/popcnt/{ printf $3 }')

result1=$(($a*$b+$c))
result2=$(($a+$b+$c))

assert [ "$output1" == "$result1" ]
assert [ "$output2" == "$result2" ]
# Note: The HE function for this has a maximum of 15 bits
assert [ "$output3" == "$(popcount $a 15)" ]
}
Loading

0 comments on commit 2a77427

Please sign in to comment.