Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
TeamSPoon authored Aug 14, 2024
2 parents b6f833b + 6b5a2d9 commit 56975c5
Show file tree
Hide file tree
Showing 20 changed files with 2,243 additions and 372 deletions.
46 changes: 46 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: CI Job to Generate JUnit Report

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
generate-report:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.x'

- name: Make Shell Script Executable
run: chmod +x scripts/generate_input.sh

- name: Run Shell Script to Generate Input File
run: |
./scripts/run_commit_tests.sh
- name: Run JUnit Report Generation Script
run: |
python scripts/into_junit.py /tmp/SHARED.UNITS > junit.xml
- name: Upload JUnit Report
uses: actions/upload-artifact@v3
with:
name: junit-report
path: junit.xml

- name: Display JUnit Test Results
uses: dorny/test-reporter@v1
with:
name: 'JUnit Results'
path: 'junit.xml'
reporter: 'junit'
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ cd metta-wam
. scripts/ensure_venv # ensures we are runing in a python venv
pip install ansi2html # needed for running tests
pip install hyperon # needed for running tests
pip install junit2html # needed for test report generation
chmod +x INSTALL.sh # Make sure the script is executable
. ./INSTALL.sh # Follow the default prompts
Expand Down Expand Up @@ -102,6 +103,7 @@ mettalog tests/baseline_compat/hyperon-experimental_scripts/b0_chaining_prelim.m




** Launch Jupyter notebook: (in progress) **
- Contains a Jupyter Kernel for MeTTa (allows runing of MeTTa scripts remotely)
```
Expand Down Expand Up @@ -291,3 +293,13 @@ clear ; mettalog --test --v=./src/canary --log --html --compile=false tests/base

```
# Metta Functions Task List
| Function Name | Doc. (@doc) | Test Created | Impl. in Interpreter | Impl. in Transpiler | Arg Types Declared |
|----------------|-------------|--------------|----------------------|---------------------|--------------------|
| `functionA` | - [ ] | - [ ] | - [ ] | - [ ] | - [ ] |
| `functionB` | - [ ] | - [ ] | - [ ] | - [ ] | - [ ] |
| `functionC` | - [ ] | - [ ] | - [ ] | - [ ] | - [ ] |
1 change: 1 addition & 0 deletions mettalog
Original file line number Diff line number Diff line change
Expand Up @@ -954,6 +954,7 @@ if [[ "$html_flag" == "enable" ]]; then
if [ ! -z "$OUTPUT_DIR" ] ;then
HTML_OUT="${OUTPUT_DIR}/${HTML_OUT}"
fi
export HTML_FILE="${HTML_OUT}"
fi

export TYPESCRIPT=1
Expand Down
73 changes: 73 additions & 0 deletions scripts/into_junit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import xml.etree.ElementTree as ET
import sys
import re

def create_testcase_element(testclass, testname, stdout, identifier, got, expected, status, url):
testcase = ET.Element("testcase", classname=testclass, name=testname)

description = f"Test {identifier} with URL: {url}"

if status == "PASS":
system_out = ET.SubElement(testcase, "system-out")
system_out.text = f"<![CDATA[\n<a href=\"{url}\">Test Report</a>\n\nAssertion: {stdout}\nExpected: {expected}\nActual: {got}\n]]>"
else: # status == "FAIL"
failure_message = f"Test failed: Expected '{expected}' but got '{got}'"
failure = ET.SubElement(testcase, "failure", message=failure_message, type="AssertionError")
failure.text = f"<![CDATA[\nAssertionError: {failure_message}\n]]>"
system_out = ET.SubElement(testcase, "system-out")
system_out.text = f"<![CDATA[\n<a href=\"{url}\">Test Report</a>\n\nAssertion: {stdout}\nExpected: {expected}\nActual: {got}\n]]>"

return testcase

def parse_test_line(line):
parts = re.split(r'\s*\|\s*(?![^()]*\))', line.strip())
if len(parts) < 7:
raise ValueError(f"Line does not have the expected number of parts: {len(parts)} found")

full_identifier = parts[1].strip() # The second field contains the test class and name
status = parts[2].strip() # The third field contains the pass/fail status
url = re.search(r'\((.*?)\)', parts[3]).group(1).strip() # Extract the URL inside the parentheses
stdout = parts[4].strip() # The fifth field contains the assertion
got = parts[5].strip()
expected = parts[6].strip()

try:
testclass, testname = full_identifier.rsplit('.', 1)
if '.' in testclass:
testname = f"{testclass.split('.')[-1]}.{testname}" # Combine to form the correct testname
if not testclass or not testname:
raise ValueError("Test class or test name is empty after splitting.")
except ValueError as e:
raise ValueError(f"Identifier does not contain the expected format: {full_identifier}. Error: {str(e)}")

return testclass, testname, stdout, full_identifier, got, expected, status, url

def generate_junit_xml(input_file):
testsuites = ET.Element("testsuites")
testsuite = ET.Element("testsuite", name="Metta Tests")
testsuites.append(testsuite)

with open(input_file, 'r') as file:
for line in file:
parts = None
if line.startswith("|"):
try:
parts = re.split(r'\s*\|\s*(?![^()]*\))', line.strip())
testclass, testname, stdout, full_identifier, got, expected, status, url = parse_test_line(line)
testcase = create_testcase_element(testclass, testname, stdout, full_identifier, got, expected, status, url)
testsuite.append(testcase)
print(f"Processing {testclass}.{testname}: {status}", file=sys.stderr)
except ValueError as e:
print(f"Skipping line due to error: {e}\nLine: {line}\nParts: {parts}", file=sys.stderr)

tree = ET.ElementTree(testsuites)
return ET.tostring(testsuites, encoding="utf-8", xml_declaration=True).decode("utf-8")

if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python generate_junit.py <input_file>")
sys.exit(1)

input_file = sys.argv[1]
junit_xml = generate_junit_xml(input_file)
print(junit_xml)
29 changes: 29 additions & 0 deletions scripts/open-metta-file.reg
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
Windows Registry Editor Version 5.00

; Associate .metta files with run-metta.cmd
[HKEY_CLASSES_ROOT\.metta]
@="MettaFile"

[HKEY_CLASSES_ROOT\MettaFile]
@="Metta Script File"

; Set a system icon for .metta files
[HKEY_CLASSES_ROOT\MettaFile\DefaultIcon]
@="%SystemRoot%\\regedit.exe,0"

[HKEY_CLASSES_ROOT\MettaFile\shell]
@="open"

; Default action (open)
[HKEY_CLASSES_ROOT\MettaFile\shell\open]
@="Run with Metta"

[HKEY_CLASSES_ROOT\MettaFile\shell\open\command]
@="\"H:\\opt\\hyperon\\metta-wam\\mettalog.cmd\" \"%1\""

; Add 'Edit with Notepad' to the context menu
[HKEY_CLASSES_ROOT\MettaFile\shell\edit]
@="Edit with Notepad"

[HKEY_CLASSES_ROOT\MettaFile\shell\edit\command]
@="notepad.exe \"%1\""
8 changes: 8 additions & 0 deletions scripts/run_commit_tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash

# This script generates the input file used by the Python script.
# Replace the following lines with the actual commands to generate the input file.

echo "| ANTI-REGRESSION.BC-COMP.01 | PASS |(https://example.com/test-report) | (assertEqualToResult (add-atom &kb (: axiom (nums 2 3)))) | (()) | (()) |" > /tmp/SHARED.UNITS

# You can add more lines or commands to generate additional input data
25 changes: 19 additions & 6 deletions scripts/test_in_metta.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/bin/bash

SHOULD_EXIT=0
SHARED_UNITS=/tmp/SHARED.UNITS

DEBUG_WHY() {
DEBUG "${GREEN}WHY: ${BOLD}${*}${NC}"
Expand Down Expand Up @@ -430,10 +431,16 @@ generate_final_MeTTaLog() {
# Change to the script directory
cd "$METTALOG_DIR" || exit 1

python3 ./scripts/into_junit.py "${SHARED_UNITS}" > "$METTALOG_OUTPUT/junit.xml"

junit2html "$METTALOG_OUTPUT/junit.xml"
junit2html "$METTALOG_OUTPUT/junit.xml" --summary-matrix
echo "saved to $METTALOG_OUTPUT/junit.xml.html"


# Calculate the number of passed and failed tests
passed=$(grep -c "| PASS |" /tmp/SHARED.UNITS)
failed=$(grep -c "| FAIL |" /tmp/SHARED.UNITS)
passed=$(grep -c "| PASS |" "${SHARED_UNITS}")
failed=$(grep -c "| FAIL |" "${SHARED_UNITS}")
total=$((passed + failed))

# Check if total is zero to avoid divide by zero error
Expand All @@ -443,10 +450,11 @@ generate_final_MeTTaLog() {
percent_passed=$(awk -v passed="$passed" -v total="$total" 'BEGIN { printf "%.2f", (passed/total)*100 }')
fi


# Create a markdown file with test links and headers
{ echo "| STATUS | TEST NAME | TEST CONDITION | ACTUAL RESULT | EXPECTED RESULT |"
echo "|--------|-----------|----------------|---------------|-----------------|"
cat /tmp/SHARED.UNITS | awk -F'\\(|\\) \\| \\(' '{ print $2 " " $0 }' | sort | cut -d' ' -f2- | tac | awk '!seen[$0]++' | tac
{ echo "| TEST NAME | STATUS | URL LOCATION | TEST CONDITION | ACTUAL RESULT | EXPECTED RESULT |"
echo "|-----------|--------|--------------|----------------|---------------|-----------------|"
cat "${SHARED_UNITS}" | awk -F'\\(|\\) \\| \\(' '{ print $1 " " $0 }' | sort | cut -d' ' -f2- | tac | awk '!seen[$0]++' | tac
} > ./$METTALOG_OUTPUT/PASS_FAIL.md


Expand Down Expand Up @@ -632,7 +640,7 @@ fi
# Delete HTML files if the clean flag is set
if [ $clean -eq 1 ]; then
delete_html_files
cat /dev/null > /tmp/SHARED.UNITS
cat /dev/null > "${SHARED_UNITS}"
fi

# Prompt user to rerun all tests if run_tests_auto_reply is not set
Expand All @@ -652,6 +660,11 @@ fi
INTERP_SRC_DIR="$(realpath "${INTERP_SRC_DIR}")"

DEBUG "INTERP_SRC_DIR=$INTERP_SRC_DIR"
DEBUG "METTALOG_OUTPUT=$METTALOG_OUTPUT"

if [[ ! -f "${METTALOG_OUTPUT}/src/" ]]; then
cat /dev/null > "${SHARED_UNITS}"
fi

mkdir -p "${METTALOG_OUTPUT}/src/"
cp -af "${INTERP_SRC_DIR}/"* "${METTALOG_OUTPUT}/src/"
Expand Down
25 changes: 1 addition & 24 deletions src/canary/metta_compiler.pl
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@

dedupe_p1(P):- current_predicate(_,P),
forall((copy_term(P,P2),
clause(P,Bd,Ref),
clause(P,Bd,Ref),
clause(P2,Bd2,Ref2), Ref@<Ref2,
a2(P,Bd)=@=a2(P2,Bd2),
erase(Ref2), fail),true).
Expand Down Expand Up @@ -113,29 +113,6 @@
into_list_args0(C,[F|Args]):- compound_name_arguments(C,F,Args),!.


:- use_module(library(filesex)). % Ensure you have the necessary module for file time operations

metta2pl(File) :-
file_name_extension(Name, _, File),
file_name_extension(Name, pl, PlFile),
metta2pl(File, PlFile).

metta2pl(File, PlFile) :-
( exists_file(PlFile),
time_file(PlFile, PlTime),
time_file(File, FileTime),
PlTime > FileTime
-> true % PLFile is newer, no need to convert
; convert_metta_to_pl(File, PlFile) % Replace this with your actual conversion logic
).

convert_metta_to_pl(File, PlFile) :-
% Your conversion logic here
% For example:
format('Converting ~w to ~w~n', [File, PlFile]),
convert_metta_to_datalog(File,PlFile).



compound_name_list(AsPred,FP,PredArgs):- var(AsPred),!,AsPred=[FP|PredArgs].
compound_name_list(AsPred,FP,PredArgs):- iz_conz(AsPred),!,AsPred=[FP|PredArgs].
Expand Down
2 changes: 1 addition & 1 deletion src/canary/metta_compiler_inlining.pl
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@
(( AllCases = Cases,
call(ValueCode),
once((member(caseOption(MatchVar,MatchCode,BodyResult,BodyCode),AllCases),
both_of(ValueResult,MatchCode,unify_enough(ValueResult,MatchVar)))),
both_of(ValueResult,MatchCode,unify_enough(ValueResult,MatchVar)))),
call(BodyCode),
BodyResult=RetResult)))).
Expand Down
8 changes: 7 additions & 1 deletion src/canary/metta_eval.pl
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,8 @@
is_progn('progn').

eval_20(Eq,RetType,Depth,Self,[Comma,X ],Res):- is_progn(Comma),!, eval_args(Eq,RetType,Depth,Self,X,Res).
%eval_20(Eq,RetType,Depth,Self,[Comma,X,Y],Res):- is_progn(Comma),!, eval_args(Eq,_,Depth,Self,X,_),eval_args(Eq,RetType,Depth,Self,Y,Res).
%eval_20(Eq,RetType,Depth,Self,[Comma,X,Y],Res):- is_progn(Comma),!, eval_args(Eq,_,Depth,Self,X,_),
% eval_args(Eq,RetType,Depth,Self,Y,Res).
eval_20(Eq,RetType,Depth,Self,[Comma,X|Y],Res):- is_progn(Comma),!, eval_args(Eq,_,Depth,Self,X,_),
eval_args(Eq,RetType,Depth,Self,[Comma|Y],Res).

Expand Down Expand Up @@ -1232,6 +1233,11 @@
string_chars(EFormat, FormatChars), user_io(with_output_to(string(Result), format_args(FormatChars, 0, EArgs))).
% string_chars(EFormat, FormatChars), wots(Result, format_args(FormatChars, 0, EArgs)).

eval_20(Eq,RetType,_Depth,_Self,['flip'],Bool):-
ignore(RetType='Bool'), !, as_tf(random(0,2,0),Bool),
check_returnval(Eq,RetType,Bool).


% =================================================================
% =================================================================
% =================================================================
Expand Down
8 changes: 8 additions & 0 deletions src/canary/metta_interp.pl
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,7 @@
% Get Type of Value
'get-type'(Value, Type):- eval_H(['get-type', Value], Type).


% ============================
% %%%% String Utilities
% ============================
Expand All @@ -613,6 +614,13 @@
'charsToString'(Chars, String) :- eval_H(['charsToString', Chars], String).
'format-args'(Format, Args, Result) :- eval_H(['format-args', Format, Args], Result).

% ============================
% %%%% Random Utilities
% ============================
'flip'(Bool) :- eval_H(['flip'], Bool). % see `flip` in metta_eval.pl as `eval_20/6`



metta_argv(Args):- current_prolog_flag(metta_argv, Args),!.
metta_argv(Before):- current_prolog_flag(os_argv,OSArgv), append(_,['--args'|AArgs],OSArgv),
before_arfer_dash_dash(AArgs,Before,_),!,set_metta_argv(Before).
Expand Down
2 changes: 1 addition & 1 deletion src/canary/metta_ontology.pfc.pl
Original file line number Diff line number Diff line change
Expand Up @@ -462,4 +462,4 @@
properties('&corelib','stringToChars', [string_operations, qhelp("Convert a string to a list of chars."), string_to_chars]).
properties('&corelib','charsToString', [string_operations, qhelp("Convert a list of chars to a string."), chars_to_string]).
properties('&corelib','format-args', [string_operations, qhelp("Generate a formatted string using a format specifier."), format_args]).

properties('&corelib','flip', [random, qhelp("Return a random boolean."), random_boolean]).
Loading

0 comments on commit 56975c5

Please sign in to comment.