--- /dev/null
+<configuration>
+
+ <!-- File Appender -->
+ <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+ <!-- Log file path -->
+ <file>test_log.txt</file>
+ <append>true</append>
+ <encoder>
+ <pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSS'Z'} [%thread] %-5level %logger{36} - %msg%n</pattern>
+ </encoder>
+ </appender>
+
+ <!-- Root Logger -->
+ <root level="info">
+ <appender-ref ref="FILE" />
+ </root>
+
+</configuration>
--- /dev/null
+package com.ReasoningTechnology.Mosaic;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.time.Instant;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+
+public class Mosaic_Logger {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(Mosaic_Logger.class);
+ private static final DateTimeFormatter ISO_UTC_FORMATTER =
+ DateTimeFormatter.ISO_INSTANT.withZone(ZoneOffset.UTC);
+
+ // Formats and logs an output related to a specific test
+ public static void output(String test_name, String stream, String output_data) {
+ String timestamp = iso_utc_time();
+ String formatted_log = String.format(
+ "\n%s -----------------------------------------------------------\n" +
+ "Test: %s\n" +
+ "Stream: %s\n" +
+ "Output:\n%s\n",
+ timestamp, test_name, stream, output_data
+ );
+
+ LOGGER.info(formatted_log);
+ }
+
+ // Logs a general message for a test
+ public static void message(String test_name, String message) {
+ String timestamp = iso_utc_time();
+ String formatted_log = String.format(
+ "\n%s -----------------------------------------------------------\n" +
+ "Test: %s\n" +
+ "Message:\n%s\n",
+ timestamp, test_name, message
+ );
+
+ LOGGER.info(formatted_log);
+ }
+
+ // Logs an error with stack trace
+ public static void error(String test_name, String message, Throwable error) {
+ String timestamp = iso_utc_time();
+ StringBuilder stack_trace = new StringBuilder();
+ for (StackTraceElement element : error.getStackTrace()) {
+ stack_trace.append(element.toString()).append("\n");
+ }
+
+ String formatted_log = String.format(
+ "\n%s -----------------------------------------------------------\n" +
+ "Test: %s\n" +
+ "Message:\n%s\n" +
+ "Error:\n%s\n",
+ timestamp, test_name, message, stack_trace
+ );
+
+ LOGGER.error(formatted_log);
+ }
+
+ // Utility to fetch the current time in ISO UTC format
+ private static String iso_utc_time() {
+ return ISO_UTC_FORMATTER.format(Instant.now());
+ }
+}
if(successful_redirect){
io.clear_buffers(); // Start each test with empty buffers
} else {
- Mosaic_Util.log_message(test_name, "Error: I/O redirection failed before running the test.");
+ Mosaic_Logger.message(test_name, "Error: I/O redirection failed before running the test.");
System.out.println("Warning: Failed to redirect I/O for test: " + test_name);
}
if(fail_exception) System.out.println("Test failed: '" + test_name + "' threw an exception: " + exception_string);
if(fail_extraneous_stdout){
System.out.println("Test failed: '" + test_name + "' produced extraneous stdout.");
- Mosaic_Util.log_output(test_name, "stdout", io.get_out_content());
+ Mosaic_Logger.output(test_name, "stdout", io.get_out_content());
}
if(fail_extraneous_stderr){
System.out.println("Test failed: '" + test_name + "' produced extraneous stderr.");
- Mosaic_Util.log_output(test_name, "stderr", io.get_err_content());
+ Mosaic_Logger.output(test_name, "stderr", io.get_err_content());
}
// Determine final test result
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintStream;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.time.format.DateTimeFormatter;
import java.util.function.Predicate;
-
public class Mosaic_Util{
// Linear search with a predicate
return Instant.now().atOffset(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT);
}
- // used to report if a test completed with data still on an output streams
- public static void log_output(String test_name ,String stream ,String output_data){
- try(FileWriter log_writer = new FileWriter("test_log.txt" ,true)){ // Append mode
- log_writer.write("\n" + iso_utc_time() + " -----------------------------------------------------------\n");
- log_writer.write("Test: " + test_name + "\n");
- log_writer.write("Stream: " + stream + "\n");
- log_writer.write("Output:\n" + output_data + "\n");
- } catch(IOException e) {
- System.err.println("Error writing to log for test: " + test_name + ", stream: " + stream);
- e.printStackTrace(System.err);
- }
- }
-
- // used to log a general message about a test
- public static void log_message(String test_name ,String message){
- try(FileWriter log_writer = new FileWriter("test_log.txt" ,true)){ // Append mode
- log_writer.write("\n" + iso_utc_time() + " -----------------------------------------------------------\n");
- log_writer.write("Test: " + test_name + "\n");
- log_writer.write("Message:\n" + message + "\n");
- } catch(IOException e){
- System.err.println
- (
- "Error writing message \""
- + message
- + "\" to log for test \'"
- + test_name
- + "\'"
- );
- e.printStackTrace(System.err);
- }
- }
-
- public static Object make_all_public_methods_proxy( Class<?> class_metadata ) {
+ public static Object make_all_public_proxy( Class<?> class_metadata ) {
try {
- // Check if the class is public
- int modifiers = class_metadata.getModifiers();
- if (!java.lang.reflect.Modifier.isPublic( modifiers )) {
- throw new IllegalAccessException(
- "The class " + class_metadata.getName() + " is not public and cannot be proxied."
+ // Validate that the class implements at least one interface
+ if( class_metadata.getInterfaces().length == 0 ) {
+ throw new IllegalArgumentException(
+ "The class " + class_metadata.getName() + " does not implement any interfaces."
);
}
- // Create the proxy
- Object proxy = java.lang.reflect.Proxy.newProxyInstance(
- class_metadata.getClassLoader()
- ,class_metadata.getInterfaces()
- ,(proxy_object ,method ,args) -> {
- Method original_method = class_metadata.getDeclaredMethod(
- method.getName()
- ,method.getParameterTypes()
- );
- original_method.setAccessible( true );
- Object real_instance = class_metadata.getDeclaredConstructor().newInstance();
- return original_method.invoke( real_instance ,args );
+ Object proxy = Proxy.newProxyInstance(
+ class_metadata.getClassLoader()
+ ,class_metadata.getInterfaces()
+ ,(proxy_object ,method ,args) -> {
+ // Ensure the target method is accessible
+ Method target_method = class_metadata.getDeclaredMethod(
+ method.getName()
+ ,method.getParameterTypes()
+ );
+ target_method.setAccessible( true );
+
+ // Create an instance of the target class
+ Object real_instance = class_metadata.getDeclaredConstructor().newInstance();
+
+ // Invoke the target method
+ return target_method.invoke( real_instance ,args );
}
);
return proxy;
- } catch (Exception e) {
+ } catch( Throwable e ) {
+ // Log the error to assist with debugging
+ Mosaic_Logger.message( "make_all_public_proxy" ,"Failed to create proxy: " + e.getMessage() );
throw new RuntimeException(
- "Failed to create proxy for class: " + class_metadata.getName()
- ,e
+ "Failed to create proxy for class: " + class_metadata.getName() ,e
);
}
}
-
}
:"$JAVA_HOME"/bin\
:"$PATH"
-# so we can run the stuff we built locally.
+# for the developers ad hoc testing
+#
export CLASSPATH=\
-"$REPO_HOME"/developer/jvm\
-:"$REPO_HOME"/developer/jvm/"$PROJECT".jar\
-:"$JAVA_HOME"/lib\
+"$JAVA_HOME"/lib\
+:"$REPO_HOME"/developer/config\
+:"$REPO_HOME"/developer/scratchpad\
+:"$LOGGER_FACADE"\
+:"$LOGGER"\
:"$CLASSPATH"
+export SOURCEPATH=\
+"$REPO_HOME"/developer/javacđź–‰/\
+:"$SOURCEPATH"
+
export PATH=\
"$REPO_HOME"/developer/bash\
:"$PATH"
echo "Compiling files..."
set -x
- javac -g -d scratchpad javacđź–‰/*.java
+ javac -Xlint:deprecation -g -d scratchpad javacđź–‰/*.java
set +x
if [ $? -ne 0 ]; then
echo "Compilation failed."
exit 1
fi
-echo "Creating JAR file..."
- set -x
- jar_file=jvm/"$PROJECT".jar
- mkdir -p jvm
- jar cf $jar_file -C scratchpad .
- set +x
- if [ $? -eq 0 ]; then
- echo "JAR file created successfully: $jar_file"
- else
- echo "Failed to create JAR file."
- exit 1
- fi
-
echo "Creating bash wrappers..."
mkdir -p bash
# wrapper is a space separated list
env_must_be="developer/toolđź–‰/env"
if [ "$ENV" != "$env_must_be" ]; then
- echo "$(script_fp):: error: must be run in the $env_must_be environment"
+ echo "$(script_fp):: must be run in the $env_must_be environment"
exit 1
fi
-# script local environment
+ cd "$REPO_HOME"/developer
- release_dir="$REPO_HOME/release"
- bash_dir="$REPO_HOME/developer/bash"
- project_jar_fp="$REPO_HOME/developer/jvm/"$PROJECT".jar"
- wrapper=$(bash_wrapper_list)
+ if [ ! -d scratchpad ]; then
+ echo "$(script_fp):: no scratchpad directory"
+ exit 1
+ fi
- if [ ! -d "$release_dir" ]; then
- mkdir -p "$release_dir"
- fi
+# Inform the user
+
+ echo "The pwd for this script is `pwd`."
+ echo "Expanding .jar files to be included with Mosaic into scratchpad."
+ echo "Gathering all the contents of scrathpad into jvm/\$PROJECT.jar"
+ echo "Will copy jvm/\$PROJECT.jar and other files for release to ../release"
+ echo "..."
+
+# Function to copy and set permissions
- # Function to copy and set permissions
install_file() {
source_fp="$1"
target_dp="$2"
echo "Installed $(basename "$source_fp") to $target_dp with permissions $perms"
fi
}
-
-# do the release
- echo "Starting release process..."
+# script local environment
+
+ release_dir="$REPO_HOME/release"
+ bash_dir="$REPO_HOME/developer/bash"
+ project_jar_fp="$REPO_HOME/developer/jvm/"$PROJECT".jar"
+ wrapper=$(bash_wrapper_list)
+
+ mkdir -p "$release_dir"
+ mkdir -p jvm
+
+# third party tools to be included
+
+ third_party_jars=(
+ "$LOGGER_FACADE"
+ "$LOGGER"
+ )
+
+ for jar in "${third_party_jars[@]}"; do
+ if [ -f "$jar" ]; then
+ set -x
+ jar -xf "$jar" -C scratchpad
+ set +x
+ else
+ echo "Warning: JAR file not found: $jar"
+ fi
+ done
+
+ jar_file=jvm/"$PROJECT".jar
+ set -x
+ jar cf $jar_file -C scratchpad .
+ set +x
+ if [ $? -ne 0 ]; then
+ echo "Failed to create $jar_file file."
+ exit 1
+ fi
+
+# move files to the release dir
- # Install the JAR file
install_file "$project_jar_fp" "$release_dir" "ug+r"
- # Install bash wrappers
for wrapper in $wrapper; do
- install_file "$bash_dir/$wrapper" "$release_dir" "ug+r+x"
+ install_file "$bash_dir"/"$wrapper" "$release_dir" "ug+r+x"
done
echo "$(script_fp) done."
7. should check stdin for unused input and report error also.
8. move 'unlock_class` from Ariadne tests to Mosaic_Util.
+
+9. consider adding Maven for the third party tools dependencies.
+
+10. really should move the developer/release 'install' script to the bespokeđź–‰/env script
+
+2024-12-10T14:25:40Z
+
+ Gives an error, but still passes? Is this right?
+ ... Running Test_Testbench
+ Expected output: Structural problem message for dummy_invalid_return_method.
+ Structural problem: dummy_invalid_return_method does not return Boolean.
+ Test_Testbench Total tests run: 3
+ Test_Testbench Total tests passed: 3
+ Test_Testbench Total tests failed: 0
--- /dev/null
+<configuration>
+
+ <!-- File Appender -->
+ <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+ <!-- Log file path -->
+ <file>test_log.txt</file>
+ <append>true</append>
+ <encoder>
+ <pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSS'Z'} [%thread] %-5level %logger{36} - %msg%n</pattern>
+ </encoder>
+ </appender>
+
+ <!-- Root Logger -->
+ <root level="info">
+ <appender-ref ref="FILE" />
+ </root>
+
+</configuration>
--- /dev/null
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Proxy;
+
+import com.ReasoningTechnology.Mosaic.Mosaic_IO;
+import com.ReasoningTechnology.Mosaic.Mosaic_Testbench;
+import com.ReasoningTechnology.Mosaic.Mosaic_Util;
+import com.ReasoningTechnology.Mosaic.Mosaic_Logger;
+
+public class Test_Util_proxy{
+
+ public class TestSuite{
+
+ public Boolean create_proxy_non_public_class( Mosaic_IO io ){
+ Boolean[] conditions = new Boolean[2];
+ int i = 0;
+
+ try{
+ Object proxy = Mosaic_Util.make_all_public_proxy( NonPublicClass.class );
+ conditions[i++] = proxy != null;
+ conditions[i++] = Proxy.isProxyClass( proxy.getClass() );
+ }catch( Exception e ){
+ Mosaic_Logger.error("Test_Util_proxy" ,"create_proxy_non_public_class" ,e);
+ return false;
+ }
+
+ return Mosaic_Util.all( conditions );
+ }
+
+ public Boolean invoke_proxied_non_public_method(Mosaic_IO io) {
+ Boolean[] conditions = new Boolean[2];
+ int i = 0;
+
+ try {
+ NonPublicInterface proxy = (NonPublicInterface) Mosaic_Util.make_all_public_proxy(NonPublicClass.class);
+ String result = proxy.hidden_method();
+ conditions[i++] = result.equals("Accessed hidden method!");
+ conditions[i++] = Proxy.isProxyClass(proxy.getClass());
+ } catch (Exception e) {
+ Mosaic_Logger.error("invoke_proxied_non_public_method", "Unexpected exception: " + e.getMessage(), e);
+ return false;
+ }
+
+ return Mosaic_Util.all(conditions);
+ }
+
+ public Boolean create_and_invoke_public_class_proxy( Mosaic_IO io ){
+ Boolean[] conditions = new Boolean[2];
+ int i = 0;
+
+ try{
+ PublicInterface proxy = (PublicInterface) Mosaic_Util.make_all_public_proxy( PublicClass.class );
+ String result = proxy.say_hello();
+ conditions[i++] = result.equals( "Hello from PublicClass!" );
+ conditions[i++] = Proxy.isProxyClass( proxy.getClass() );
+ }catch( Exception e ){
+ Mosaic_Logger.error("Test_Util_proxy" ,"create_and_invoke_public_class_proxy" ,e);
+ return false;
+ }
+
+ return Mosaic_Util.all( conditions );
+ }
+
+ }
+
+ public interface PublicInterface{
+ String say_hello();
+ }
+
+ public static class PublicClass implements PublicInterface{
+ @Override
+ public String say_hello(){
+ return "Hello from PublicClass!";
+ }
+ }
+
+ interface NonPublicInterface{
+ String hidden_method();
+ }
+
+ static class NonPublicClass implements NonPublicInterface{
+ @Override
+ public String hidden_method(){
+ return "Accessed hidden method!";
+ }
+ }
+
+ public static void main( String[] args ){
+ Test_Util_proxy outer = new Test_Util_proxy();
+ TestSuite suite = outer.new TestSuite();
+ int result = Mosaic_Testbench.run( suite );
+ System.exit( result );
+ }
+}
--- /dev/null
+#!/bin/env bash
+script_afp=$(realpath "${BASH_SOURCE[0]}")
+
+# input guards
+env_must_be="tester/toolđź–‰/env"
+if [ "$ENV" != "$env_must_be" ]; then
+ echo "$(script_fp):: error: must be run in the $env_must_be environment"
+ exit 1
+fi
+
+# space separated list of bash interface wrappers
+echo Test0 Test_Util Test_IO Test_Testbench Test_MockClass_0 Test_Util_proxy
#!/usr/bin/env bash
script_afp=$(realpath "${BASH_SOURCE[0]}")
-# Caveat: the 'shell' directory is for built wrapper
-# functions. `clean_build_directories` will remove all the files in this
-# directory. For bespoke scripts used by the tester, put them in the `tool`
-# directory.
-
# input guards
env_must_be="tester/toolđź–‰/env"
if [ "$ENV" != "$env_must_be" ]; then
# class/source paths
# ----
-# debug to find failing tests
+# Settings to debug to find failing tests on release candidate.
+# See next section for settings for debugging the sources.
+# note the possible aliasing between the Test_$PROJECT and release classes
export CLASSPATH=\
"$JAVA_HOME"/lib\
-:"$REPO_HOME"/release/"$PROJECT".jar\
+:"$REPO_HOME"/tester/config\
:"$REPO_HOME"/tester/jvm/Test_"$PROJECT".jar\
+:"$REPO_HOME"/release/"$PROJECT".jar\
:"$CLASSPATH"
# note the developer sources on the scratchpad, if they are even there
:"$SOURCEPATH"
# ----
-# debug directly from developer sources
+# for debugging developer sources
#
# export CLASSPATH=\
# "$JAVA_HOME"/lib\
-# :"$REPO_HOME"/developer/scratchpad\
+# :"$REPO_HOME"/tester/config\
# :"$REPO_HOME"/tester/jvm/Test_"$PROJECT".jar\
+# :"$REPO_HOME"/developer/scratchpad\
+# :"$LOGGER_FACADE"
+# :"$LOGGER"
# :"$CLASSPATH"
+# developer must `distribute_source` for this to work
# export SOURCEPATH=\
-# "$REPO_HOME"/tester/javađź–‰/\
+# "$REPO_HOME"/tester/javacđź–‰/\
# :"$REPO_HOME"/developer/scratchpad\
# :"$SOURCEPATH"
+# ----
+# Another possible configuration is expand the developer release into scratchpad along with the tests. Then everything points at scratcpad. If the developer `distributed_source` to put the sources into the release candidate jar, the sources will be available in the debugger; however, editing them will not effect the developer's version (the origin version) of the sources.
+#
+# export CLASSPATH=\
+# "$JAVA_HOME"/lib\
+# :"$REPO_HOME"/tester/config\
+# :"$REPO_HOME"/tester/scratchpad\
+# :"$CLASSPATH"
+
+# developer must `distribute_source` for this to work
+# export SOURCEPATH=\
+# "$REPO_HOME"/tester/javacđź–‰/\
+# "$REPO_HOME"/tester/scratchpad/\
+# :"$SOURCEPATH"
+
# end of the class/source path settings
#`--------------------------------------------------------------------------------
jar cf jvm/Test_"$PROJECT".jar -C scratchpad .
set +x
-echo "Creating shell wrappers..."
+echo "Creating bash wrappers..."
mkdir -p bash
# wrapper is a space separated list
- wrapper=$(shell_wrapper_list)
+ wrapper=$(bash_wrapper_list)
for file in $wrapper;do
cat > bash/$file << EOL
#!/bin/env bash
script_afp=$(realpath "${BASH_SOURCE[0]}")
# input guards
-env_must_be="tester/tool/env"
+env_must_be="tester/toolđź–‰/env"
if [ "$ENV" != "$env_must_be" ]; then
echo "$(script_fp):: error: must be run in the $env_must_be environment"
exit 1
exit 1
fi
-# Navigate to the shell directory
+# Navigate to the bash directory
cd "$REPO_HOME/tester/bash" || exit
-# Get the list of test scripts in the specific order from shell_wrapper_list
-test_list=$(shell_wrapper_list)
+# Get the list of test scripts in the specific order from bash_wrapper_list
+test_list=$(bash_wrapper_list)
+echo test_list: $test_list
# Execute each test in the specified order
for file in $test_list; do
+ echo
if [[ -x "$file" && ! -d "$file" ]]; then
- echo -n "Running $file..."
+ echo "... Running $file"
./"$file"
else
echo "Skipping $file (not executable or is a directory)"
+++ /dev/null
-#!/bin/env bash
-script_afp=$(realpath "${BASH_SOURCE[0]}")
-
-# input guards
-env_must_be="tester/toolđź–‰/env"
-if [ "$ENV" != "$env_must_be" ]; then
- echo "$(script_fp):: error: must be run in the $env_must_be environment"
- exit 1
-fi
-
-# space separated list of shell interface wrappers
-echo Test0 Test_Util Test_IO Test_Testbench Test_MockClass_0
-
# PATH="$REPO_HOME/tool_shared/third_party/idea-IC-243.21565.193/:$PATH"
JAVA_HOME="$REPO_HOME/tool_shared/third_party/jdk-23.0.1"
+ LOGGER_FACADE="$REPO_HOME"/tool_shared/third_party/slf4j-api-2.0.9.jar
+ LOGGER="$REPO_HOME"/tool_shared/third_party/logback-classic-1.5.12.jar
- export PATH JAVA_HOME
+ export PATH JAVA_HOME LOGGER_FACADE LOGGER
# --------------------------------------------------------------------------------
# the following functions are provided for other scripts to use.
edit $REPO_HOME/tool_shared/bespoke/env, and update JAVA_HOME:
export JAVA_HOME="$REPO_HOME/tool_shared/third_party/jdk-23.0.1"
+----------------------------------------
+Logging
+
+curl -O https://repo1.maven.org/maven2/org/slf4j/slf4j-api/2.0.9/slf4j-api-2.0.9.jar
+
+curl -O https://repo1.maven.org/maven2/ch/qos/logback/logback-classic/1.5.12/logback-classic-1.5.12.jar
+
+add to bespokeđź–‰/env names for these for use in CLASSPATH
+
----------------------------------------
IDE