diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml
index 17b2e72..333602b 100644
--- a/.github/workflows/CI.yml
+++ b/.github/workflows/CI.yml
@@ -15,5 +15,33 @@ jobs:
with:
distribution: 'temurin'
java-version: '21'
- - name: Install
- run: cd learner; ./install.sh
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.12'
+ - name: Install TCP-Fuzzer
+ run: ./install.sh
+
+ Linux_basic:
+ if: ${{ !contains(github.event.head_commit.message, 'ci skip') }}
+ runs-on: ubuntu-24.04
+ strategy:
+ fail-fast: true
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v6
+ - name: Set up JDK 21
+ uses: actions/setup-java@v5
+ with:
+ distribution: 'temurin'
+ java-version: '21'
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.12'
+ - name: Install TCP-Fuzzer
+ run: ./install.sh
+ - name: Test Ubuntu 24.04
+ run: |
+ ./run.sh -alphabet config/basic.xml -output output/ubuntu -eqvQueries 100
+ ./diff_hyps.sh experiments/models/linux-6.17.0_basic output/ubuntu 3
diff --git a/config/basic.xml b/config/basic.xml
new file mode 100644
index 0000000..fff7855
--- /dev/null
+++ b/config/basic.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/config/alphabet.xml b/config/full_data.xml
similarity index 100%
rename from config/alphabet.xml
rename to config/full_data.xml
diff --git a/config/learner_args b/config/learner_args
index 7044e21..b57dfed 100644
--- a/config/learner_args
+++ b/config/learner_args
@@ -4,6 +4,10 @@ localhost:18200
-tcpMapperAddress
localhost:18200
-alphabet
-${fuzzer.dir}/config/alphabet.xml
--memQueryRuns
-3
+${fuzzer.dir}/config/full_data.xml
+#-memQueryRuns
+#3
+-command
+python3 ${fuzzer.dir}/sutadapter/serverAdapter.py --port 9000
+-startWait
+50
diff --git a/diff_hyps.sh b/diff_hyps.sh
new file mode 100755
index 0000000..7b4b630
--- /dev/null
+++ b/diff_hyps.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+
+dir1=$1
+dir2=$2
+num_rounds=$3
+
+if [[ $# != 3 ]]; then
+ echo "Usage: ${0##*/} dir1 dir2 num_rounds"
+ echo "Diffs the first num_rounds hypotheses stored in two dirs"
+ exit 1
+fi
+
+if [[ ! -d ${dir1} ]]; then
+ echo "${dir1}"": No such directory"
+ exit 1
+fi
+if [[ ! -d ${dir2} ]]; then
+ echo "${dir2}"": No such directory"
+ exit 1
+fi
+
+for ((i = 1 ; i <= num_rounds ; i++)); do
+ if ! diff --unified=0 "${dir1}"/hyp"${i}".dot "${dir2}"/hyp"${i}".dot; then
+ exit 1
+ fi
+done
diff --git a/experiments/models/linux-6.17.0_basic/alphabet.xml b/experiments/models/linux-6.17.0_basic/alphabet.xml
new file mode 100644
index 0000000..fff7855
--- /dev/null
+++ b/experiments/models/linux-6.17.0_basic/alphabet.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/experiments/models/linux-6.17.0_basic/command.args b/experiments/models/linux-6.17.0_basic/command.args
new file mode 100644
index 0000000..7649d81
--- /dev/null
+++ b/experiments/models/linux-6.17.0_basic/command.args
@@ -0,0 +1,17 @@
+state-fuzzer-server
+-connect
+localhost:18200
+-tcpMapperAddress
+localhost:18200
+-alphabet
+${fuzzer.dir}/config/alphabet.xml
+#-memQueryRuns
+#3
+-command
+python3 ${fuzzer.dir}/sutadapter/serverAdapter.py --port 9000
+-startWait
+50
+-alphabet
+/home/pfg666/GitHub/tools/TCP-Fuzzer/config/basic.xml
+-eqvQueries
+100
diff --git a/experiments/models/linux-6.17.0_basic/hyp1.dot b/experiments/models/linux-6.17.0_basic/hyp1.dot
new file mode 100644
index 0000000..9bc7844
--- /dev/null
+++ b/experiments/models/linux-6.17.0_basic/hyp1.dot
@@ -0,0 +1,11 @@
+digraph g {
+
+ s0 [shape="circle" label="s0"];
+ s0 -> s0 [label="S / SA"];
+ s0 -> s0 [label="A / timeout"];
+ s0 -> s0 [label="FA / timeout"];
+
+__start0 [label="" shape="none" width="0" height="0"];
+__start0 -> s0;
+
+}
diff --git a/experiments/models/linux-6.17.0_basic/hyp2.dot b/experiments/models/linux-6.17.0_basic/hyp2.dot
new file mode 100644
index 0000000..777684b
--- /dev/null
+++ b/experiments/models/linux-6.17.0_basic/hyp2.dot
@@ -0,0 +1,23 @@
+digraph g {
+
+ s0 [shape="circle" label="s0"];
+ s1 [shape="circle" label="s1"];
+ s2 [shape="circle" label="s2"];
+ s3 [shape="circle" label="s3"];
+ s0 -> s1 [label="S / SA"];
+ s0 -> s0 [label="A / timeout"];
+ s0 -> s0 [label="FA / timeout"];
+ s1 -> s0 [label="S / timeout"];
+ s1 -> s3 [label="A / timeout"];
+ s1 -> s2 [label="FA / FA"];
+ s2 -> s2 [label="S / SOCKET_CLOSED"];
+ s2 -> s2 [label="A / SOCKET_CLOSED"];
+ s2 -> s2 [label="FA / SOCKET_CLOSED"];
+ s3 -> s1 [label="S / A"];
+ s3 -> s3 [label="A / timeout"];
+ s3 -> s2 [label="FA / FA"];
+
+__start0 [label="" shape="none" width="0" height="0"];
+__start0 -> s0;
+
+}
diff --git a/experiments/models/linux-6.17.0_basic/hyp3.dot b/experiments/models/linux-6.17.0_basic/hyp3.dot
new file mode 100644
index 0000000..7a97c32
--- /dev/null
+++ b/experiments/models/linux-6.17.0_basic/hyp3.dot
@@ -0,0 +1,27 @@
+digraph g {
+
+ s0 [shape="circle" label="s0"];
+ s1 [shape="circle" label="s1"];
+ s2 [shape="circle" label="s2"];
+ s3 [shape="circle" label="s3"];
+ s4 [shape="circle" label="s4"];
+ s0 -> s1 [label="S / SA"];
+ s0 -> s0 [label="A / timeout"];
+ s0 -> s0 [label="FA / timeout"];
+ s1 -> s0 [label="S / timeout"];
+ s1 -> s3 [label="A / timeout"];
+ s1 -> s2 [label="FA / FA"];
+ s2 -> s2 [label="S / SOCKET_CLOSED"];
+ s2 -> s2 [label="A / SOCKET_CLOSED"];
+ s2 -> s2 [label="FA / SOCKET_CLOSED"];
+ s3 -> s4 [label="S / A"];
+ s3 -> s3 [label="A / timeout"];
+ s3 -> s2 [label="FA / FA"];
+ s4 -> s3 [label="S / timeout"];
+ s4 -> s3 [label="A / timeout"];
+ s4 -> s2 [label="FA / FA"];
+
+__start0 [label="" shape="none" width="0" height="0"];
+__start0 -> s0;
+
+}
diff --git a/experiments/models/linux-6.17.0_basic/learnedModel.dot b/experiments/models/linux-6.17.0_basic/learnedModel.dot
new file mode 100644
index 0000000..7a97c32
--- /dev/null
+++ b/experiments/models/linux-6.17.0_basic/learnedModel.dot
@@ -0,0 +1,27 @@
+digraph g {
+
+ s0 [shape="circle" label="s0"];
+ s1 [shape="circle" label="s1"];
+ s2 [shape="circle" label="s2"];
+ s3 [shape="circle" label="s3"];
+ s4 [shape="circle" label="s4"];
+ s0 -> s1 [label="S / SA"];
+ s0 -> s0 [label="A / timeout"];
+ s0 -> s0 [label="FA / timeout"];
+ s1 -> s0 [label="S / timeout"];
+ s1 -> s3 [label="A / timeout"];
+ s1 -> s2 [label="FA / FA"];
+ s2 -> s2 [label="S / SOCKET_CLOSED"];
+ s2 -> s2 [label="A / SOCKET_CLOSED"];
+ s2 -> s2 [label="FA / SOCKET_CLOSED"];
+ s3 -> s4 [label="S / A"];
+ s3 -> s3 [label="A / timeout"];
+ s3 -> s2 [label="FA / FA"];
+ s4 -> s3 [label="S / timeout"];
+ s4 -> s3 [label="A / timeout"];
+ s4 -> s2 [label="FA / FA"];
+
+__start0 [label="" shape="none" width="0" height="0"];
+__start0 -> s0;
+
+}
diff --git a/experiments/models/linux-6.17.0_basic/learnedModel.pdf b/experiments/models/linux-6.17.0_basic/learnedModel.pdf
new file mode 100644
index 0000000..3d080e5
Binary files /dev/null and b/experiments/models/linux-6.17.0_basic/learnedModel.pdf differ
diff --git a/experiments/models/linux-6.17.0_basic/statistics.txt b/experiments/models/linux-6.17.0_basic/statistics.txt
new file mode 100644
index 0000000..93dc94a
--- /dev/null
+++ b/experiments/models/linux-6.17.0_basic/statistics.txt
@@ -0,0 +1,100 @@
+=== RUN DESCRIPTION ===
+Alphabet: [S, A, FA]
+
+### StateFuzzerConfigStandard Parameters
+# -help
+# -debug
+# -quiet
+-output
+output/o_2026-04-30_12-16-06
+
+### LearnerConfigStandard Parameters
+-alphabet
+/home/pfg666/GitHub/tools/TCP-Fuzzer/config/basic.xml
+-learningAlgorithm
+TTT
+-equivalenceAlgorithms
+RANDOM_WP_METHOD
+-depth
+1
+-minLength
+5
+-maxLength
+15
+-randLength
+5
+-eqvQueries
+100
+-memQueryRuns
+1
+-memQueryRetries
+3
+# -logQueries
+-probReset
+0.0
+# -testFile
+-seed
+0
+# -cacheTests
+# -ceSanitizationDisable
+# -skipNonDetTests
+-ceReruns
+3
+# -probabilisticSanitizationDisable
+# -timeLimit
+# -testLimit
+# -roundLimit
+-eqvThreads
+1
+
+### SULConfigStandard Parameters
+-responseWait
+100
+# -inputResponseTimeout
+-command
+python3 /home/pfg666/GitHub/tools/TCP-Fuzzer/sutadapter/serverAdapter.py --port 9000
+# -terminateCommand
+# -processDir
+# -redirectOutputStreams
+-processTrigger
+NEW_TEST
+-startWait
+50
+
+### SULServerConfigStandard Parameters
+-connect
+localhost:18200
+
+### MapperConfigStandard Parameters
+# -mapperConnectionConfig
+# -repeatingOutputs
+# -socketClosedAsTimeout
+# -disabledAsTimeout
+# -dontMergeRepeating
+
+### SULAdapterConfigStandard Parameters
+# -adapterPort
+-adapterAddress
+localhost
+
+=== STATISTICS ===
+Learning finished: true
+Size of the input alphabet: 3
+Number of states: 5
+Number of hypotheses: 3
+Number of inputs: 1120
+Number of tests: 109
+Number of learning inputs: 89
+Number of learning tests: 27
+Number of inputs up to last hypothesis: 239
+Number of tests up to last hypothesis: 41
+Time (ms) to learn model: 302925
+Counterexamples:
+CE 1:Query[ε|A A FA FA FA S FA FA S A FA / timeout timeout timeout timeout timeout SA FA SOCKET_CLOSED SOCKET_CLOSED SOCKET_CLOSED SOCKET_CLOSED]
+CE 2:Query[ε|S A A S S A A FA S FA S S / SA timeout timeout A timeout timeout timeout FA SOCKET_CLOSED SOCKET_CLOSED SOCKET_CLOSED SOCKET_CLOSED]
+Number of inputs when hypothesis was generated: [3, 95, 239]
+Number of tests when hypothesis was generated: [3, 23, 41]
+Time (ms) when hypothesis was generated: [2799, 43975, 95216]
+Number of inputs when counterexample was found: [47, 201]
+Number of tests when counterexample was found: [7, 33]
+Time (ms) when counterexample was found: [16834, 74894]
diff --git a/install.sh b/install.sh
index 103a4da..6dcdc56 100755
--- a/install.sh
+++ b/install.sh
@@ -16,27 +16,27 @@ function install_learner() {
if [[ $? -ne 0 ]]; then
echo "Failed to install Learner"
- exit
+ exit 1
else
echo "Learner installed successfully"
fi
}
-function install_mapper_env() {
- echo "Installing Mapper environment"
+function install_mapper() {
+ echo "Installing Mapper"
(
cd ${MAPPER_DIR};
- ./install_env.sh
+ ./install.sh
)
if [[ $? -ne 0 ]]; then
- echo "Failed to install Mapper environment"
- exit
+ echo "Failed to install Mapper"
+ exit 1
else
- echo "Mapper environment installed successfully"
+ echo "Mapper installed successfully"
fi
}
# Installing learner and mapper components
install_learner
-install_mapper_env
+install_mapper
diff --git a/mapper/install_env.sh b/mapper/install.sh
similarity index 70%
rename from mapper/install_env.sh
rename to mapper/install.sh
index 6e3aa15..ac2dee1 100755
--- a/mapper/install_env.sh
+++ b/mapper/install.sh
@@ -2,6 +2,11 @@ MAPPER_SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && p
readonly MAPPER_SCRIPT_DIR
readonly ENV_DIR=${MAPPER_SCRIPT_DIR}/.venv
+# Installing dependencies
+echo "Installing dependencies where necessary."
+sudo apt-get update
+sudo apt-get install -y libpcap-dev tcpdump || (echo "Failed to install libraries"; exit 1)
+
if [[ -d ${ENV_DIR} ]]
then
echo "Detected Python virtual environment. Skipping Python environment creation."
@@ -10,7 +15,8 @@ else
python3 -m venv $ENV_DIR
source $ENV_DIR/bin/activate
echo "Installing required libraries"
- pip install -r requirements.txt
+ pip install --upgrade pip
+ pip install -r ${MAPPER_SCRIPT_DIR}/requirements.txt || (echo "Fail to install required Python packages"; exit 1)
fi
# If the script is being sourced, activate the environment
diff --git a/run.sh b/run.sh
new file mode 100755
index 0000000..760517e
--- /dev/null
+++ b/run.sh
@@ -0,0 +1,65 @@
+#!/usr/bin/env bash
+SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
+
+set -euo pipefail
+
+learner_config=$SCRIPT_DIR/config/learner_args
+mapper_config=$SCRIPT_DIR/config/mapperconfig.toml
+
+# These values have to be consistent with the arguments in config
+#SERVER_PORT=9000
+HOST=127.0.0.1
+MAPPER_PORT=18200
+
+
+# Clean up background processes on exit
+cleanup() {
+ echo "Cleaning up..."
+ kill "$MAPPER_PID" 2>/dev/null || true
+ sudo iptables --flush OUTPUT
+}
+trap cleanup EXIT
+
+start_mapper() {
+ # Start TCP Mapper
+ echo "Starting Mapper..."
+ (
+ sudo iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP
+ source $SCRIPT_DIR/mapper/.venv/bin/activate
+ echo sudo $SCRIPT_DIR/mapper/.venv/bin/python $SCRIPT_DIR/mapper/main.py $mapper_config
+ sudo $SCRIPT_DIR/mapper/.venv/bin/python $SCRIPT_DIR/mapper/main.py $mapper_config
+ ) &
+
+ MAPPER_PID=$!
+ # Wait for mapper to be ready
+ echo "Wait for mapper to be ready"
+ until ss -ltn sport = :$MAPPER_PORT | grep -q LISTEN; do
+ sleep 0.1
+ done
+ echo "Mapper started (PID $MAPPER_PID)"
+ sleep 1
+}
+
+start_learner() {
+ # Start learner
+ echo "Starting Learner..."
+ echo java -jar $SCRIPT_DIR/learner/target/TCP-Learner.jar $learner_config $@
+ java -jar $SCRIPT_DIR/learner/target/TCP-Learner.jar $learner_config $@
+}
+
+while [[ "$1" =~ ^- ]]; do case $1 in
+ -lc | --learner-config )
+ shift;
+ learner_config=$1
+ ;;
+ -mc | --mapper-config )
+ shift;
+ mapper_config=$1
+ ;;
+ * )
+ break
+ ;;
+ esac; shift; done
+
+start_mapper
+start_learner $@
\ No newline at end of file