a gleam implementation of a CS assignment originally written in cpp

feat: add verse parser

-2
.gitignore
···
-
lab66
-
lab66.output
build/
.DS_Store
-64
COVERSHEET.md
···
-
---
-
Project: "#6"
-
Professor: "Professor Knoerr"
-
Class: "CS 1210 – Fall 2025"
-
Author: "Kieran Klukas"
-
---
-
-
# Requirements
-
-
<!--Restate the problem specifications in your own words-->
-
-
Search a provided old testament text file for arbitrary reference. It prompts the user for book, chapter, and verse and then searches for that verse. If book is not found then output `Book does not exist in the Old Testament`. If chapter isn't found then `Chapter # does not exist in Book`. Finally if the verse isn't found then output `Verse # does not exist in Book #`. Once the verse is found then append the verse to `verses.txt`.
-
-
# Design
-
-
<!--How did you attack the problem? What choices did you make in your design, and why?-->
-
-
I started with outlining the basic input system [`532c6cf`](https://github.com/cu-cs1210/lab-6-kieranklukas/commit/5b2ced23798fc7cbce79eb445c9592cccf16d6a6). Then worked on setting up a while loop to read the file line by line. I spent a while puzzling over exactly how I wanted to implement this and I am not entirely satisfied with my current solution. It would be interesting to try this problem in a functional language like gleam or erlang and see how much more cleanly I can parse the file. I implemented each reference part sequentially and then went back and made it check for barrier strings to stay within the proper book and chapter. I ended up realizing that the book of Psalms is referenced differently and so made some logic to permit its idiosyncracies [`7c18fff`](https://github.com/cu-cs1210/lab-6-kieranklukas/commit/7c18fffa30ab3e43bcb05ad4dff44f275987cbb8).
-
-
# Implementation
-
-
<!--Outline any interesting implementation details.-->
-
-
I used a single input variable to parse the file word by word until we get to the correct verse. I also check if the input book is listed as `Psalm` or `Psalms` and add or remove an `s` when doing checks or output as appropriate. The output file is also never opened until we find the verse and is immediately closed afterward. Also a minor note of intrest is that you can change the default paths that the program loads from and saves to by adding the paths as arguments (eg. `lab66 test/OT.txt build/verses.txt`).
-
-
# Testing
-
-
<!--
-
Explain how you tested your program, enumerating the tests if possible.
-
Explain why your test set was sufficient to believe that the software is working properly,
-
i.e., what were the range of possibilities of errors that you were testing for.
-
-->
-
-
I updated the `makefile` to add `make run` so I could compile and run it more easily and updated the test file to have the Zylabs test states as well as more granularly check a happy path and some adversarial paths.
-
-
# Outside Help
-
-
<!--Did you get help from anyone else on this project? Document their contribution to your learning.-->
-
-
No outside help was used beyond minor googling for how to capitalize an entire string and the proper syntax for appending (not covered in zybooks as far as I can tell but I'm sure you will cover it in lectures next week).
-
-
# Summary/Conclusion
-
-
<!--Present your results. Did it work properly? Are there any limitations?-->
-
-
The program works well and should cover most edgecases! As far as I can tell there isn't anything that should be able to break it beyond changing the `OT.txt` to be several GB in size.
-
-
# AI Use
-
-
<!--How did you use Generative AI in this project?-->
-
-
I used claude to generate a more complex test file and then modified it to add the rest of the zybooks tests as I got closer to finishing the project.
-
-
# Lessons Learned
-
-
<!--List any lessons learned. What might you have done differently if you were going to attack this again.-->
-
-
I would definetly want to try a different language for sure if I was doing this independantly but overal I think this implementation is fairly solid and I wouldn't change much. I did find out in this lab that it is always a good idea to check the whole input or you might run into weird bugs like how `PSALMS` is formatted.
-
-
# Time Spent
-
-
<!--Approximately how many hours did you spend on this project?-->
-
-
![hackatime badge](https://hackatime-badge.hackclub.com/U062UG485EE/lab-6)
+15 -63
README.md
···
-
# Lab 6
-
-
![screenshot of the code generated by freeze](docs/freeze.jpeg)
-
-
For this lab the program must parse `OT.txt` (format below) to find specific references and produce scoped errors if the reference isn't found.
-
-
```text
-
THE BOOK OF GENESIS
-
-
CHAPTER 1
-
1 In the beginning God created the heaven and the earth.
-
2 And the earth was without form, and void; and darkness [was] upon the face of the deep. And the Spirit of God moved upon the face of the waters.
-
3 And God said, Let there be light: and there was light.
-
4 And God saw the light, that [it was] good: and God divided the light from the darkness.
+
# bible_search_gleam
-
THE BOOK OF PSALMS
+
[![Package Version](https://img.shields.io/hexpm/v/bible_search_gleam)](https://hex.pm/packages/bible_search_gleam)
+
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/bible_search_gleam/)
-
PSALM 1
-
1 Blessed [is] the man that walketh not in the counsel of the ungodly, nor standeth in the way of sinners, nor sitteth in the seat of the scornful.
-
2 But his delight [is] in the law of the LORD; and in his law doth he meditate day and night.
-
3 And he shall be like a tree planted by the rivers of water, that bringeth forth his fruit in his season; his leaf also shall not wither; and whatsoever he doeth shall prosper.
+
```sh
+
gleam add bible_search_gleam@1
```
-
-
The project is layed out as follows:
-
-
```bash
-
.
-
├── build # this directory isn't committed and is ephemeral
-
│   └── lab66
-
├── COVERSHEET.md
-
├── LICENSE.md
-
├── makefile
-
├── README.md
-
├── src
-
│   └── lab66.cpp
-
└── test
-
├── OT.txt
-
└── test.sh
+
```gleam
+
import bible_search_gleam
-
4 directories, 8 files
+
pub fn main() -> Nil {
+
// TODO: An example of the project in use
+
}
```
-
### Build scripts
+
Further documentation can be found at <https://hexdocs.pm/bible_search_gleam>.
-
The preferred way to run the program is through make:
+
## Development
-
```bash
-
make # compiles and runs tests
-
make run # compiles and runs the program
-
make clean # clean up the build dir
+
```sh
+
gleam run # Run the project
+
gleam test # Run the tests
```
-
-
it is however possible to still do things manually:
-
-
```bash
-
mkdir build
-
cd build
-
g++ ../src/lab66.cpp -o lab66
-
./lab66 ../test/OT.txt verses.txt
-
```
-
-
<p align="center">
-
<img src="https://raw.githubusercontent.com/taciturnaxolotl/carriage/main/.github/images/line-break.svg" />
-
</p>
-
-
<p align="center">
-
<i><code>&copy 2025-present <a href="https://github.com/taciturnaxololt">Kieran Klukas</a></code></i>
-
</p>
-
-
<p align="center">
-
<a href="https://github.com/cu-cs1210/lab-6-kieranklukas/blob/main/LICENSE.md"><img src="https://img.shields.io/static/v1.svg?style=for-the-badge&label=License&message=MIT&logoColor=d9e0ee&colorA=363a4f&colorB=b7bdf8"/></a>
-
</p>
docs/freeze.jpeg

This is a binary file and will not be displayed.

+21
gleam.toml
···
+
name = "bible_search"
+
version = "1.0.0"
+
+
# Fill out these fields if you intend to generate HTML documentation or publish
+
# your project to the Hex package manager.
+
#
+
# description = ""
+
# licences = ["Apache-2.0"]
+
# repository = { type = "github", user = "", repo = "" }
+
# links = [{ title = "Website", href = "" }]
+
#
+
# For a full reference of all the available options, you can have a look at
+
# https://gleam.run/writing-gleam/gleam-toml/.
+
+
[dependencies]
+
gleam_stdlib = ">= 0.44.0 and < 2.0.0"
+
simplifile = ">= 2.3.0 and < 3.0.0"
+
input = ">= 1.0.1 and < 2.0.0"
+
+
[dev-dependencies]
+
gleeunit = ">= 1.0.0 and < 2.0.0"
-16
makefile
···
-
all: lab66 test
-
-
lab66: src/lab66.cpp
-
mkdir -p build && g++ src/lab66.cpp -Wall -o build/lab66
-
-
test: lab66
-
cd test && ./test.sh
-
-
exec:
-
./build/lab66 test/OT.txt build/verses.txt
-
-
run: lab66 exec
-
-
clean:
-
rm -rf build
-
+16
manifest.toml
···
+
# This file was generated by Gleam
+
# You typically do not need to edit this file
+
+
packages = [
+
{ name = "filepath", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "B06A9AF0BF10E51401D64B98E4B627F1D2E48C154967DA7AF4D0914780A6D40A" },
+
{ name = "gleam_stdlib", version = "0.65.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "7C69C71D8C493AE11A5184828A77110EB05A7786EBF8B25B36A72F879C3EE107" },
+
{ name = "gleeunit", version = "1.6.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "FDC68A8C492B1E9B429249062CD9BAC9B5538C6FBF584817205D0998C42E1DAC" },
+
{ name = "input", version = "1.0.1", build_tools = ["gleam"], requirements = [], otp_app = "input", source = "hex", outer_checksum = "FE84CDADC78A1367E4AFD561A529825A8FEC88D165CBDF511FD3226CABCDEE6F" },
+
{ name = "simplifile", version = "2.3.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "0A868DAC6063D9E983477981839810DC2E553285AB4588B87E3E9C96A7FB4CB4" },
+
]
+
+
[requirements]
+
gleam_stdlib = { version = ">= 0.44.0 and < 2.0.0" }
+
gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
+
input = { version = ">= 1.0.1 and < 2.0.0" }
+
simplifile = { version = ">= 2.3.0 and < 3.0.0" }
+47
src/bible_search.gleam
···
+
import gleam/int
+
import gleam/io
+
import gleam/list
+
import gleam/string
+
import input.{input}
+
import simplifile
+
+
const filepath = "./OT.txt"
+
+
pub type Reference {
+
Reference(book: String, chapter: Int, verse: Int)
+
}
+
+
pub fn parse_reference(input: String) -> Result(Reference, String) {
+
let parts = string.split(input, on: " ")
+
+
case parts {
+
[book, chapter_s, verse_s] ->
+
case int.parse(chapter_s) {
+
Ok(chapter) ->
+
case int.parse(verse_s) {
+
Ok(verse) ->
+
Ok(Reference(book: string.uppercase(book), chapter:, verse:))
+
Error(_) -> Error("Invalid verse" <> verse_s)
+
}
+
Error(_) -> Error("Invalid chapter" <> chapter_s)
+
}
+
_ -> Error("invalid parse")
+
}
+
}
+
+
pub fn main() -> Nil {
+
let assert Ok(bible) = simplifile.read(from: filepath)
+
+
let biblelines = string.split(bible, on: "\n")
+
+
let assert Ok(search) = input(prompt: "> ")
+
+
let assert Ok(reference) = parse_reference(search)
+
+
list.each(biblelines, fn(line) {
+
case line {
+
"THE BOOK OF " <> book if book == reference.book -> io.println(book)
+
_ -> io.print("")
+
}
+
})
+
}
-143
src/lab66.cpp
···
-
/*********************************************************
-
* Summary: find verses from the old testament
-
* appending them to file as found
-
*
-
* Author: Kieran Klukas
-
* Created: October 2025
-
*
-
********************************************************/
-
-
#include <iostream>
-
#include <cstdlib>
-
#include <fstream>
-
-
using namespace std;
-
-
int main(int argc, char **argv) {
-
-
ifstream OT;
-
ofstream OF;
-
string inputFilename = "OT.txt";
-
string outputFilename = "verses.txt";
-
-
string book;
-
string normalizedBook;
-
int chapter;
-
int verse;
-
-
// get path to OT.txt if provided otherwise use default path
-
// and then do the same for the verses.txt
-
if (argc >= 2) inputFilename = argv[1];
-
if (argc >= 3) outputFilename = argv[2];
-
-
OT.open(inputFilename);
-
-
if (!OT.is_open()) {
-
cout << inputFilename << ": failed to open file";
-
return 1;
-
}
-
-
cout << "Please enter the reference of the verse you would like" << endl;
-
-
cout << "the book: ";
-
getline(cin, book);
-
for (int i = 0; i < book.length(); i++)
-
normalizedBook += toupper(book[i]);
-
if (normalizedBook == "PSALMS")
-
normalizedBook = "PSALM";
-
-
cout << "the chapter: ";
-
cin >> chapter;
-
-
cout << "the verse: ";
-
cin >> verse;
-
-
cout << endl;
-
-
bool foundBook = false;
-
bool foundChapter = false;
-
bool foundVerse = false;
-
string verseString;
-
while (!OT.eof()) {
-
string input;
-
-
if (!foundBook) {
-
OT >> input; // THE
-
if (input != "THE") continue;
-
OT >> input; // BOOK
-
if (input != "BOOK") continue;
-
OT >> input; // OF
-
if (input != "OF") continue;
-
-
OT.ignore(); // skip the single space
-
-
getline(OT, input); // handle multi word books
-
-
// second check is for the book of psalms
-
if (input == normalizedBook || input == (normalizedBook + "S")) {
-
foundBook = true;
-
-
getline(OT, input); // discard empty line
-
continue;
-
}
-
} else {
-
if (!foundChapter) {
-
OT >> input;
-
if (input != "CHAPTER" && input != "PSALM") {
-
if (input == "THE") break;
-
-
continue;
-
}
-
-
OT >> input;
-
if (input == to_string(chapter)) {
-
foundChapter = true;
-
continue;
-
}
-
} else {
-
OT >> input;
-
-
if (input == "CHAPTER" || input == "PSALM") break;
-
-
if (input == to_string(verse)) {
-
foundVerse = true;
-
OT.ignore(); // ignore space
-
getline(OT, verseString);
-
break;
-
}
-
}
-
}
-
}
-
-
if (foundVerse) {
-
cout << verse << " " << verseString << endl;
-
-
OF.open(outputFilename, ios_base::app);
-
-
if (!OF.is_open()) {
-
cout << outputFilename << ": error saving file" << endl;
-
return 1;
-
}
-
-
OF << verse << " " << verseString << endl;
-
-
OF.close();
-
} else {
-
if (!foundBook) {
-
cout << (normalizedBook == "PSALM" ? book += "s" : book) << " does not exist in the Old Testament";
-
} else {
-
if (!foundChapter) {
-
cout << (normalizedBook == "PSALM" ? "Psalm " : "Chapter ") << chapter;
-
cout << " does not exist in " << (normalizedBook == "PSALM" ? book += "s" : book);
-
} else if (!foundVerse) {
-
cout << "Verse " << verse << " does not exist in " << book << " " << chapter;
-
}
-
}
-
-
cout << endl;
-
}
-
-
OT.close();
-
-
return 0;
-
}
test/OT.txt OT.txt
+13
test/bible_search_gleam_test.gleam
···
+
import gleeunit
+
+
pub fn main() -> Nil {
+
gleeunit.main()
+
}
+
+
// gleeunit test functions end in `_test`
+
pub fn hello_world_test() {
+
let name = "Joe"
+
let greeting = "Hello, " <> name <> "!"
+
+
assert greeting == "Hello, Joe!"
+
}
-362
test/test.sh
···
-
#!/bin/bash
-
-
# Test script with configurable timeout support
-
# Usage: ./test.sh [timeout_seconds]
-
# Example: ./test.sh 5 (uses 5 second timeout)
-
# Default: 1 second timeout
-
-
# Colors for output
-
RED='\033[0;31m'
-
GREEN='\033[0;32m'
-
YELLOW='\033[1;33m'
-
BLUE='\033[0;34m'
-
NC='\033[0m' # No Color
-
-
# Test configuration
-
temp_file="lab66.output"
-
program="../build/lab66"
-
output_file="../build/verses.txt"
-
test_timeout=${1:-1}
-
-
# Test counters
-
total_tests=0
-
passed_tests=0
-
-
# Cleanup function
-
cleanup() {
-
rm -f "$temp_file" "$output_file"
-
}
-
-
# Error trap
-
trap cleanup EXIT ERR
-
-
# Function to print test results
-
print_result() {
-
local test_name="$1"
-
local result="$2"
-
local message="$3"
-
-
total_tests=$((total_tests + 1))
-
-
if [ "$result" = "PASS" ]; then
-
echo -e "${GREEN}[PASS]${NC} $test_name: $message"
-
passed_tests=$((passed_tests + 1))
-
elif [ "$result" = "TIMEOUT" ]; then
-
echo -e "${YELLOW}[TIMEOUT]${NC} $test_name: $message"
-
else
-
echo -e "${RED}[FAIL]${NC} $test_name: $message"
-
fi
-
}
-
-
# Function to print test section header
-
print_section() {
-
echo -e "\n${BLUE}=== $1 ===${NC}"
-
}
-
-
# Build program if needed
-
if [ ! -f "$program" ]; then
-
print_section "Building Program"
-
cd .. && make lab66 > /dev/null 2>&1
-
build_result=$?
-
cd test
-
if [ $build_result -ne 0 ]; then
-
print_result "Program Build" "FAIL" "Could not build $program"
-
exit 1
-
fi
-
print_result "Program Build" "PASS" "Program built successfully"
-
fi
-
-
# Test 1: Program compilation/existence
-
if [ ! -f "$program" ]; then
-
print_section "Test 1: Program Availability"
-
print_result "Program Existence" "FAIL" "Program $program not found"
-
exit 1
-
fi
-
-
# Test 2: Basic Bible Verse Lookup Test (Genesis 1:1)
-
print_section "Basic Bible Verse Lookup Test"
-
-
# Test with known valid verse
-
basic_input="Genesis\n1\n1"
-
resp=$(timeout "$test_timeout" bash -c "echo -e '$basic_input' | '$program' OT.txt '$output_file'" 2>&1)
-
exit_code=$?
-
-
# Print the output
-
if [ -n "$resp" ]; then
-
echo "$resp"
-
else
-
echo "(No output produced)"
-
fi
-
echo
-
-
if [ $exit_code -eq 124 ]; then
-
print_result "Basic Execution" "TIMEOUT" "Program timed out after ${test_timeout}s"
-
exit 1
-
elif [ $exit_code -ne 0 ]; then
-
print_result "Basic Execution" "FAIL" "Program exited with code $exit_code"
-
exit 1
-
else
-
print_result "Basic Execution" "PASS" "Program executed successfully"
-
fi
-
-
# Check if output contains required prompts
-
if [[ "$resp" == *"Please enter the reference of the verse you would like"* ]]; then
-
print_result "Initial Prompt" "PASS" "Program shows initial prompt"
-
else
-
print_result "Initial Prompt" "FAIL" "Program missing initial prompt"
-
fi
-
-
if [[ "$resp" == *"the book:"* ]]; then
-
print_result "Book Prompt" "PASS" "Program prompts for book"
-
else
-
print_result "Book Prompt" "FAIL" "Program missing book prompt"
-
fi
-
-
if [[ "$resp" == *"the chapter:"* ]]; then
-
print_result "Chapter Prompt" "PASS" "Program prompts for chapter"
-
else
-
print_result "Chapter Prompt" "FAIL" "Program missing chapter prompt"
-
fi
-
-
if [[ "$resp" == *"the verse:"* ]]; then
-
print_result "Verse Prompt" "PASS" "Program prompts for verse"
-
else
-
print_result "Verse Prompt" "FAIL" "Program missing verse prompt"
-
fi
-
-
# Check for verse output format
-
if [[ "$resp" == *"1 In the beginning God created the heaven and the earth"* ]]; then
-
print_result "Verse Format" "PASS" "Program outputs verse in correct format"
-
else
-
print_result "Verse Format" "FAIL" "Program missing or incorrect verse format"
-
fi
-
-
# Check if test/verses.txt file was created
-
if [ -f "$output_file" ]; then
-
verses_content=$(cat "$output_file")
-
if [[ "$verses_content" == *"In the beginning God created the heaven and the earth"* ]]; then
-
print_result "File Output" "PASS" "verses.txt created with correct content in build directory"
-
else
-
print_result "File Output" "FAIL" "verses.txt has incorrect content"
-
fi
-
else
-
print_result "File Output" "FAIL" "verses.txt file not created in build directory"
-
fi
-
-
# Function to run verse lookup test
-
run_verse_test() {
-
local test_name="$1"
-
local book="$2"
-
local chapter="$3"
-
local verse="$4"
-
local expected_pattern="$5"
-
local should_create_file="$6"
-
-
# Clean up previous test
-
rm -f "$output_file"
-
-
input="$book\n$chapter\n$verse"
-
output=$(timeout "$test_timeout" bash -c "echo -e '$input' | '$program' OT.txt '$output_file'" 2>&1)
-
exit_code=$?
-
-
if [ $exit_code -eq 124 ]; then
-
print_result "$test_name" "TIMEOUT" "Program timed out after ${test_timeout}s"
-
return
-
elif [ $exit_code -ne 0 ]; then
-
print_result "$test_name" "FAIL" "Program crashed (exit code $exit_code)"
-
return
-
fi
-
-
# Check if expected pattern is found in output
-
pattern_found=false
-
if [[ "$output" == *"$expected_pattern"* ]]; then
-
pattern_found=true
-
fi
-
-
# For tests expecting specific output, pattern must be found
-
if [ -n "$expected_pattern" ] && [ "$pattern_found" = "false" ]; then
-
print_result "$test_name" "FAIL" "Expected '$expected_pattern' not found in output"
-
return
-
fi
-
-
# Check file creation expectations
-
if [ "$should_create_file" = "true" ]; then
-
if [ -f "$output_file" ] && [ "$pattern_found" = "true" ]; then
-
print_result "$test_name" "PASS" "Expected output found and file created"
-
elif [ ! -f "$output_file" ]; then
-
print_result "$test_name" "FAIL" "Expected file verses.txt not created in build directory"
-
else
-
print_result "$test_name" "FAIL" "File created but expected output not found"
-
fi
-
else
-
if [ ! -f "$output_file" ] && [ "$pattern_found" = "true" ]; then
-
print_result "$test_name" "PASS" "Expected error output and no file created"
-
elif [ -f "$output_file" ]; then
-
print_result "$test_name" "FAIL" "verses.txt file should not be created for error cases"
-
else
-
print_result "$test_name" "FAIL" "Expected error message not found"
-
fi
-
fi
-
}
-
-
# Valid Verse Tests
-
print_section "Valid Verse Tests"
-
-
run_verse_test "Exodus 20:3" "Exodus" "20" "3" "3 Thou shalt have no other gods before me" true
-
run_verse_test "Psalm 23:1" "Psalm" "23" "1" "1 The LORD [is] my shepherd; I shall not want." true
-
-
# Error Case Tests
-
print_section "Error Case Tests"
-
-
run_verse_test "Invalid Book" "Matthew" "1" "1" "Matthew does not exist in the Old Testament" false
-
run_verse_test "Invalid Chapter" "Esther" "18" "3" "Chapter 18 does not exist in Esther" false
-
run_verse_test "Invalid Verse" "Psalm" "117" "5" "Verse 5 does not exist in Psalm 117" false
-
-
# Adversarial Testing Section
-
print_section "Adversarial Tests"
-
-
# Test edge cases
-
run_verse_test "Empty Book Name" "" "1" "1" "Please enter the reference" false
-
run_verse_test "Non-numeric Chapter" "Genesis" "abc" "1" "Please enter the reference" false
-
run_verse_test "Non-numeric Verse" "Genesis" "1" "xyz" "Please enter the reference" false
-
run_verse_test "Zero Chapter" "Genesis" "0" "1" "Please enter the reference" false
-
run_verse_test "Zero Verse" "Genesis" "1" "0" "Please enter the reference" false
-
run_verse_test "Negative Chapter" "Genesis" "-1" "1" "Please enter the reference" false
-
run_verse_test "Negative Verse" "Genesis" "1" "-1" "Please enter the reference" false
-
run_verse_test "Very Large Chapter" "Genesis" "999999" "1" "Please enter the reference" false
-
run_verse_test "Very Large Verse" "Genesis" "1" "999999" "Please enter the reference" false
-
-
# Test case sensitivity
-
run_verse_test "Lowercase Book" "genesis" "1" "1" "1 In the beginning God created the heaven and the earth." true
-
run_verse_test "Mixed Case Book" "GEnesis" "1" "1" "1 In the beginning God created the heaven and the earth." true
-
-
# Test two-word books
-
run_verse_test "First Samuel" "First Samuel" "1" "1" "1 Now there was a certain man of Ramathaim-zophim, of mount Ephraim, and his name [was] Elkanah, the son of Jeroham, the son of Elihu, the son of Tohu, the son of Zuph, an Ephrathite:" true
-
run_verse_test "Second Kings" "Second Kings" "1" "1" "1 Then Moab rebelled against Israel after the death of Ahab" true
-
-
# Appending Tests
-
print_section "Appending & File Path Tests"
-
-
# Function to run appending test
-
run_appending_test() {
-
local test_name="$1"
-
-
# Clean up previous test
-
rm -f "$output_file"
-
-
# First verse lookup
-
input1="Genesis\n1\n1"
-
output1=$(timeout "$test_timeout" bash -c "echo -e '$input1' | '$program' OT.txt '$output_file'" 2>&1)
-
exit_code1=$?
-
-
if [ $exit_code1 -ne 0 ]; then
-
print_result "$test_name - First Lookup" "FAIL" "First verse lookup failed"
-
return
-
fi
-
-
# Check first verse was written
-
if [ ! -f "$output_file" ]; then
-
print_result "$test_name - First File" "FAIL" "First verse file not created"
-
return
-
fi
-
-
first_content=$(cat "$output_file")
-
-
# Second verse lookup
-
input2="Genesis\n1\n2"
-
output2=$(timeout "$test_timeout" bash -c "echo -e '$input2' | '$program' OT.txt '$output_file'" 2>&1)
-
exit_code2=$?
-
-
if [ $exit_code2 -ne 0 ]; then
-
print_result "$test_name - Second Lookup" "FAIL" "Second verse lookup failed"
-
return
-
fi
-
-
# Check if file still exists and has content
-
if [ ! -f "$output_file" ]; then
-
print_result "$test_name - Second File" "FAIL" "File disappeared after second lookup"
-
return
-
fi
-
-
second_content=$(cat "$output_file")
-
-
# Check if both verses are in the file (appending behavior)
-
if [[ "$second_content" == *"1 In the beginning God created the heaven and the earth"* ]] && [[ "$second_content" == *"2 And the earth was without form, and void"* ]]; then
-
print_result "$test_name" "PASS" "Both verses found in file (appending works)"
-
elif [[ "$second_content" == *"2 And the earth was without form, and void"* ]] && [[ "$second_content" != *"1 In the beginning God created the heaven and the earth"* ]]; then
-
print_result "$test_name" "FAIL" "Only second verse found (overwriting instead of appending)"
-
else
-
print_result "$test_name" "FAIL" "Unexpected file content after second lookup"
-
fi
-
}
-
-
run_appending_test "Multiple Verse Appending"
-
-
# Function to run file path test
-
run_file_path_test() {
-
local test_name="$1"
-
local file_path="$2"
-
local expected_pattern="$3"
-
local should_succeed="$4"
-
-
# Clean up previous test
-
rm -f "$output_file"
-
-
# Provide verse lookup input for file path tests
-
input="Genesis\n1\n1"
-
-
if [ -n "$file_path" ]; then
-
output=$(timeout "$test_timeout" bash -c "echo -e '$input' | '$program' '$file_path' '$output_file'" 2>&1)
-
else
-
output=$(timeout "$test_timeout" bash -c "echo -e '$input' | '$program' OT.txt '$output_file'" 2>&1)
-
fi
-
exit_code=$?
-
-
if [ $exit_code -eq 124 ]; then
-
print_result "$test_name" "TIMEOUT" "Program timed out after ${test_timeout}s"
-
return
-
fi
-
-
if [ "$should_succeed" = "true" ]; then
-
if [ $exit_code -eq 0 ]; then
-
print_result "$test_name" "PASS" "Program accepted file path successfully"
-
else
-
print_result "$test_name" "FAIL" "Program failed with exit code $exit_code: $output"
-
fi
-
else
-
if [ $exit_code -ne 0 ] && [[ "$output" == *"$expected_pattern"* ]]; then
-
print_result "$test_name" "PASS" "Program correctly rejected invalid file path"
-
elif [ $exit_code -eq 0 ]; then
-
print_result "$test_name" "FAIL" "Program should have failed with invalid file path"
-
else
-
print_result "$test_name" "FAIL" "Expected error message '$expected_pattern' not found: $output"
-
fi
-
fi
-
}
-
-
# Test with existing file (absolute path)
-
run_file_path_test "Existing File (Absolute)" "/Users/kierank/code/school/lab-6/test/OT.txt" "" true
-
-
# Test with existing file (relative path)
-
run_file_path_test "Existing File (Relative)" "OT.txt" "" true
-
-
# Test with non-existing file
-
run_file_path_test "Non-existing File" "nonexistent.txt" "failed to open file" false
-
-
# Test with invalid path
-
run_file_path_test "Invalid Path" "/invalid/path/file.txt" "failed to open file" false
-
-
# Test with empty path
-
run_file_path_test "Empty Path" "" "" true
-
-
# Test summary
-
print_section "Test Summary"
-
echo -e "${BLUE}Tests passed: $passed_tests/$total_tests${NC}"
-
-
if [ $passed_tests -eq $total_tests ]; then
-
echo -e "${GREEN}All tests passed!${NC}"
-
exit 0
-
else
-
echo -e "${RED}Some tests failed!${NC}"
-
exit 1
-
fi