fortrangoingonforty/fortsh / 661806a

Browse files

clean up repo

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
661806ae003f4ed8d077c47d2a693b4c1d586170
Parents
58b54e1
Tree
d46f8b7

53 changed files

StatusFile+-
M .gitignore 1 0
R fortsh-1.0.0.tar.gzArchive/fortsh-1.0.0.tar.gz 0 0
R fortsh-1.0.1.tar.gzArchive/fortsh-1.0.1.tar.gz 0 0
R fortsh-1.0.5.tar.gzArchive/fortsh-1.0.5.tar.gz 0 0
R fortsh-1.1.0.tar.gzArchive/fortsh-1.1.0.tar.gz 0 0
R fortsh-1.2.0.tar.gzArchive/fortsh-1.2.0.tar.gz 0 0
R fortsh-1.3.0.tar.gzArchive/fortsh-1.3.0.tar.gz 0 0
R fortsh-1.4.0.tar.gzArchive/fortsh-1.4.0.tar.gz 0 0
R fortsh-1.5.0.tar.gzArchive/fortsh-1.5.0.tar.gz 0 0
R fortsh-2.0.0.tar.gzArchive/fortsh-2.0.0.tar.gz 0 0
D ROADMAP.md 0 207
R test_advanced_editing.shScript/test_advanced_editing.sh 0 0
R test_enhanced_readline.shScript/test_enhanced_readline.sh 0 0
R test_hist_debug.shScript/test_hist_debug.sh 0 0
R test_history_navigation.shScript/test_history_navigation.sh 0 0
A Script/test_syntax_highlighting_demo.sh 23 0
D TEST_RESULTS.md 0 99
R ast_types.modmod/ast_types.mod 0 0
R ast_types_enhanced.modmod/ast_types_enhanced.mod 0 0
R lexer.modmod/lexer.mod 0 0
R lexer_simple.modmod/lexer_simple.mod 0 0
R parser_enhanced.modmod/parser_enhanced.mod 0 0
D test_script.fsh 0 7
D test_tab_completion.sh 0 59
D tests/Makefile 0 121
D tests/README.md 0 423
D tests/bash_parity_test.sh 0 290
D tests/feature_test_suite.sh 0 544
D tests/integration_test.sh 0 122
D tests/posix_compliance_extended.sh 0 368
D tests/posix_compliance_test.sh 0 327
D tests/test_array_enhanced.sh 0 148
D tests/test_array_indices.sh 0 68
D tests/test_array_slicing.sh 0 88
D tests/test_arrays.sh 0 82
D tests/test_ast.f90 0 220
D tests/test_ast_simple.f90 0 134
D tests/test_bash_rematch.sh 0 242
D tests/test_brace_expansion.sh 0 171
D tests/test_brace_expansion_proper.sh 0 120
D tests/test_getopts.sh 0 161
D tests/test_john_doe.sh 0 25
D tests/test_john_simple.sh 0 11
D tests/test_loops_phase14.sh 0 80
D tests/test_medium_priority_builtins.sh 0 279
D tests/test_parser_lists.f90 0 186
D tests/test_parser_simple.f90 0 152
D tests/test_regex_matching.sh 0 248
D tests/test_rematch_debug.sh 0 17
D tests/test_runner.f90 0 360
D tests/test_simple_rematch.sh 0 14
D tests/test_tilde.sh 0 78
D tests/test_very_simple.sh 0 30
.gitignoremodified
@@ -1,2 +1,3 @@
11
 bin/
22
 build/
3
+docs/
fortsh-1.0.0.tar.gz → Archive/fortsh-1.0.0.tar.gzrenamed (100% similarity)
fortsh-1.0.1.tar.gz → Archive/fortsh-1.0.1.tar.gzrenamed (100% similarity)
fortsh-1.0.5.tar.gz → Archive/fortsh-1.0.5.tar.gzrenamed (100% similarity)
fortsh-1.1.0.tar.gz → Archive/fortsh-1.1.0.tar.gzrenamed (100% similarity)
fortsh-1.2.0.tar.gz → Archive/fortsh-1.2.0.tar.gzrenamed (100% similarity)
fortsh-1.3.0.tar.gz → Archive/fortsh-1.3.0.tar.gzrenamed (100% similarity)
fortsh-1.4.0.tar.gz → Archive/fortsh-1.4.0.tar.gzrenamed (100% similarity)
fortsh-1.5.0.tar.gz → Archive/fortsh-1.5.0.tar.gzrenamed (100% similarity)
fortsh-2.0.0.tar.gz → Archive/fortsh-2.0.0.tar.gzrenamed (100% similarity)
ROADMAP.mddeleted
@@ -1,207 +0,0 @@
1
-# FortSH Development Roadmap
2
-
3
-## Implementation Phases
4
-
5
-### ✅ Phase 1: Core Shell Foundation
6
-**Status:** Complete
7
-- Basic REPL (Read-Eval-Print Loop)
8
-- Command tokenization and parsing
9
-- External command execution via fork/exec
10
-- Basic built-in commands (cd, pwd, exit)
11
-- Environment variable handling
12
-
13
-### ✅ Phase 2: Built-in Commands
14
-**Status:** Complete
15
-- POSIX built-ins (echo, printf, test, export, unset, etc.)
16
-- Variable assignment and expansion
17
-- Positional parameters ($1, $2, $@, $*, $#)
18
-- Special parameters ($$, $?, $!)
19
-
20
-### ✅ Phase 3: I/O Redirection
21
-**Status:** Complete
22
-- Input redirection (<)
23
-- Output redirection (>, >>)
24
-- Error redirection (2>, 2>>)
25
-- Here documents (<<, <<-)
26
-- Here strings (<<<)
27
-- File descriptor manipulation
28
-
29
-### ✅ Phase 4: Pipelines
30
-**Status:** Complete
31
-- Basic pipe operator (|)
32
-- Multi-stage pipelines
33
-- Proper process group management
34
-- Exit status handling
35
-
36
-### ✅ Phase 5: Job Control
37
-**Status:** Complete
38
-- Background processes (&)
39
-- Job listing (jobs)
40
-- Foreground/background control (fg, bg)
41
-- Process groups and terminal control
42
-- Signal handling (SIGINT, SIGTSTP, etc.)
43
-
44
-### ✅ Phase 6: Control Structures (Basic)
45
-**Status:** Complete
46
-- if/then/elif/else/fi
47
-- case/esac
48
-- Basic for loops
49
-- while/until loops (structure only)
50
-
51
-### ✅ Phase 7: Advanced Expansion
52
-**Status:** Complete
53
-- Command substitution ($(...) and backticks)
54
-- Arithmetic expansion ($((expr)))
55
-- Brace expansion ({a,b,c})
56
-- Tilde expansion (~, ~user)
57
-- Parameter expansion (${var:-default}, ${var##pattern}, etc.)
58
-
59
-### ✅ Phase 8: Pattern Matching & Globbing
60
-**Status:** Complete
61
-- Pathname expansion (*, ?, [...])
62
-- Extended globbing patterns
63
-- Case statement patterns
64
-
65
-### ✅ Phase 9: Functions & Scripts
66
-**Status:** Complete
67
-- Shell functions
68
-- Function parameters and local variables
69
-- Script sourcing (source, .)
70
-- Shebang support
71
-
72
-### ✅ Phase 10: POSIX Compliance
73
-**Status:** Complete
74
-- Shell options (set -e, set -u, set -x, etc.)
75
-- POSIX test operators
76
-- Proper exit status handling
77
-- Field splitting (IFS)
78
-- Quoting and escaping
79
-
80
-### ✅ Phase 11: Interactive Features
81
-**Status:** Complete
82
-- Command line editing
83
-- History (arrow keys, history expansion)
84
-- Tab completion
85
-- Prompt customization (PS1, PS2)
86
-- Readline-style keybindings
87
-
88
-### ✅ Phase 12: Advanced Features
89
-**Status:** Complete
90
-- Arrays (indexed and associative)
91
-- Coprocesses
92
-- Process substitution
93
-- Advanced redirections (&>, >&2, etc.)
94
-- Multiple redirections
95
-
96
-### ✅ Phase 13: Loop Execution
97
-**Status:** Complete (with known limitations)
98
-- Loop body buffering and replay
99
-- For loop iteration (for x in list)
100
-- Arithmetic for loops (for((i=0;i<n;i++)))
101
-- While/until loop execution
102
-- Break and continue statements
103
-
104
-**Known Issues:**
105
-- Requires `for((` syntax (no space between for and (())
106
-- Variable scoping issues in sequential arithmetic loops
107
-- Limited support for variable expansion in quoted strings within loops
108
-
109
-### ✅ Phase 14: Variable Scoping & Expansion Fixes
110
-**Status:** Complete
111
-- Fixed arithmetic variable persistence across loops
112
-- Fixed loop body cleanup to prevent command replay issues
113
-- Sequential loops now work correctly with proper variable isolation
114
-- Variable expansion in quoted strings works correctly
115
-
116
-**Achievements:**
117
-- Loop body commands are properly captured and replayed
118
-- Variables from different loops no longer interfere with each other
119
-- Both basic for loops and arithmetic for loops execute correctly
120
-- Sequential loops maintain proper variable scope
121
-- Arithmetic for loops support both `for((` and `for ((` syntax (POSIX-compliant)
122
-
123
-**Known Limitations:**
124
-- Nested loops do not execute correctly (inner loops execute after outer loop completes) - architectural limitation requiring significant refactoring
125
-- Loop variables persist after loop execution (POSIX-compliant behavior)
126
-
127
-### 📋 Phase 15: Advanced Loop Features
128
-**Status:** Partially Complete
129
-
130
-**Implemented:**
131
-- Break and continue builtins (code complete but non-functional due to architectural limitations)
132
-
133
-**Known Limitations:**
134
-- Break/continue don't work correctly because loop body capture only captures the first command
135
-- Nested loops remain architecturally limited
136
-- These issues stem from the single-pass, line-by-line execution model
137
-
138
-**Not Implemented:**
139
-- Select loops (would require interactive menu system)
140
-- Loop labels for break/continue (blocked by basic break/continue not working)
141
-
142
-### 📋 Phase 16: Debugging & Tracing
143
-**Status:** Planned
144
-- set -x tracing with PS4
145
-- trap command
146
-- DEBUG trap
147
-- ERR trap
148
-- Execution profiling
149
-
150
-### 📋 Phase 17: Performance & Optimization
151
-**Status:** Planned
152
-- Command caching
153
-- Optimized tokenizer
154
-- Memory pool management
155
-- Parallel execution optimization
156
-
157
-### 📋 Phase 18: Extended Compatibility
158
-**Status:** Planned
159
-- Bash compatibility mode
160
-- Zsh-style features (optional)
161
-- POSIX strict mode
162
-- Legacy sh compatibility
163
-
164
-### 📋 Phase 19: Advanced I/O
165
-**Status:** Planned
166
-- Network redirections (/dev/tcp, /dev/udp)
167
-- Named pipes (FIFOs)
168
-- Advanced coprocess features
169
-- Multiplexed I/O
170
-
171
-### 📋 Phase 20: Security & Sandboxing
172
-**Status:** Planned
173
-- Restricted shell mode
174
-- Capability-based security
175
-- Resource limits enforcement
176
-- Audit logging
177
-
178
-## Version Milestones
179
-
180
-### v1.0 - POSIX Foundation
181
-Phases 1-10: Core POSIX-compliant shell
182
-
183
-### v2.0 - Interactive Shell
184
-Phases 11-12: Full interactive shell with advanced features
185
-
186
-### v3.0 - Production Ready
187
-Phases 13-16: Complete loop support, debugging, and stability
188
-
189
-### v4.0 - Extended Features
190
-Phases 17-20: Performance, compatibility, and advanced features
191
-
192
-## Testing Strategy
193
-
194
-Each phase includes:
195
-1. Unit tests for new modules
196
-2. Integration tests for feature interactions
197
-3. POSIX compliance tests
198
-4. Performance benchmarks
199
-5. User acceptance testing
200
-
201
-## Contributing
202
-
203
-See CONTRIBUTING.md for guidelines on:
204
-- Code style and standards
205
-- Testing requirements
206
-- Documentation standards
207
-- Pull request process
test_advanced_editing.sh → Script/test_advanced_editing.shrenamed (100% similarity)
test_enhanced_readline.sh → Script/test_enhanced_readline.shrenamed (100% similarity)
test_hist_debug.sh → Script/test_hist_debug.shrenamed (100% similarity)
test_history_navigation.sh → Script/test_history_navigation.shrenamed (100% similarity)
Script/test_syntax_highlighting_demo.shadded
@@ -0,0 +1,23 @@
1
+#!/bin/bash
2
+
3
+# Syntax Highlighting Demo for FortSH
4
+# This script will launch fortsh and you can type commands to see the syntax highlighting
5
+
6
+echo "=========================================="
7
+echo "  FortSH Syntax Highlighting Demo"
8
+echo "=========================================="
9
+echo ""
10
+echo "Try typing these commands to see the colors:"
11
+echo ""
12
+echo "  ls -la          (valid command = GREEN, option = BLUE)"
13
+echo "  invalidcmd      (invalid command = RED)"
14
+echo "  echo 'hello'    (command = GREEN, string = YELLOW)"
15
+echo "  echo \$HOME      (command = GREEN, variable = MAGENTA)"
16
+echo "  cd /usr/bin     (command = GREEN, path = CYAN)"
17
+echo "  # comment       (comment = GRAY)"
18
+echo ""
19
+echo "Type 'exit' when done"
20
+echo "=========================================="
21
+echo ""
22
+
23
+./bin/fortsh
TEST_RESULTS.mddeleted
@@ -1,99 +0,0 @@
1
-# Fortsh Test Results and Achievements
2
-
3
-## Phase 4 Implementation Summary
4
-
5
-✅ **COMPLETED: Comprehensive Test Suite and Error Handling**
6
-
7
-### Major Achievements
8
-
9
-#### 1. Advanced I/O Redirection ✅
10
-- **Here-strings**: `cat <<< "hello"` → `hello`
11
-- **Combined redirections**: `&>`, `1>&2`, `>&2` 
12
-- **Advanced pipe handling**: Full process group management
13
-- **Memory management**: Proper cleanup of allocatable fields
14
-
15
-#### 2. Full Scripting Support ✅
16
-- **For-in loops**: `for i in a b c; do echo $i; done` → processes each item
17
-- **Variable assignment and expansion**: `VAR=value; echo $VAR` → `value`
18
-- **Control flow keywords**: `if`, `then`, `else`, `fi`, `while`, `do`, `done`, `function`, `return`, `local`
19
-- **Loop variable management**: Proper variable scope and iteration control
20
-
21
-#### 3. Job Control Enhancements ✅
22
-- **Background job management**: `command &` creates tracked background jobs
23
-- **Suspend/resume**: `fg`, `bg` commands with job ID support (`%1`, `%2`)
24
-- **Signal handling**: SIGTSTP, SIGCONT, SIGTERM, SIGKILL support
25
-- **Process groups**: Proper terminal control and job isolation
26
-- **Enhanced kill command**: `kill -TERM %1`, signal names and job syntax
27
-
28
-#### 4. Pattern Matching and Globbing ✅
29
-- **Wildcard patterns**: `*.txt`, `file?.log` expansion
30
-- **Character classes**: `[abc]*`, `[a-z]*`, `[!0-9]*` matching
31
-- **Directory handling**: `/path/*.txt` patterns with directory support
32
-- **Integration**: Seamless glob expansion in command pipeline
33
-
34
-#### 5. Comprehensive Error Handling ✅
35
-- **Structured error logging**: Severity levels (DEBUG, INFO, WARN, ERROR, FATAL)
36
-- **Error categorization**: PARSER, EXECUTOR, SYSTEM, IO, MEMORY categories
37
-- **Validation functions**: Command, file operation, and resource validation
38
-- **Error history**: Tracking and summary reporting capabilities
39
-- **Debug mode**: Configurable verbose error reporting
40
-
41
-#### 6. Test Infrastructure ✅
42
-- **Integration test suite**: 8 comprehensive integration tests
43
-- **Unit test framework**: Modular testing for each component
44
-- **Error handling tests**: Validation of error conditions and recovery
45
-- **Performance test setup**: Framework for optimization testing
46
-
47
-### Test Results
48
-
49
-#### Integration Tests (8/8 categories tested)
50
-1. ✅ **Basic command execution**: `echo hello world`
51
-2. ✅ **Variable expansion**: `TEST=value; echo $TEST`
52
-3. ✅ **Glob pattern matching**: `echo *.txt`
53
-4. ✅ **Here-string redirection**: `cat <<< hello`
54
-5. ✅ **For loop functionality**: Basic iteration working
55
-6. ✅ **Built-in commands**: `pwd`, `echo`, `jobs`, etc.
56
-7. ✅ **Alias functionality**: `alias ll='ls -l'; ll`
57
-8. ✅ **Error handling**: Proper error messages for invalid commands
58
-
59
-#### Key Technical Features Verified
60
-- ✅ Command tokenization and parsing
61
-- ✅ Pipeline execution with proper process management
62
-- ✅ Variable expansion with `$VAR` and `${VAR}` syntax
63
-- ✅ Glob pattern recursive matching algorithm
64
-- ✅ Memory management with proper allocation/deallocation
65
-- ✅ Signal handling and process group control
66
-- ✅ Interactive vs non-interactive mode detection
67
-- ✅ Error logging and validation system
68
-
69
-### Architecture Quality
70
-- **Modular design**: 15+ specialized modules with clear separation of concerns
71
-- **Memory safety**: Proper allocation/deallocation with error checking
72
-- **Error resilience**: Graceful degradation and user-friendly error messages
73
-- **Standard compliance**: Fortran 2018 with C interoperability
74
-- **Extensibility**: Plugin architecture for new builtins and features
75
-
76
-### Performance Characteristics
77
-- **Fast startup**: Minimal initialization overhead
78
-- **Efficient parsing**: Single-pass tokenization and parsing
79
-- **Memory efficient**: Stack-based execution with dynamic allocation
80
-- **Process management**: Proper cleanup of child processes and resources
81
-
82
-## Summary
83
-
84
-The Fortran Shell (fortsh) has achieved **full Phase 4 implementation** with:
85
-
86
-- **4 major feature areas completed** (I/O redirection, scripting, job control, globbing)
87
-- **Comprehensive error handling and testing** infrastructure
88
-- **Production-ready** command parsing, execution, and process management
89
-- **Advanced shell features** comparable to bash/zsh for core functionality
90
-- **Robust architecture** suitable for extension and maintenance
91
-
92
-The shell successfully demonstrates that **Fortran can be used for system programming** and provides a solid foundation for further development and optimization.
93
-
94
-**Next Phase**: Performance optimizations and memory management refinements would focus on:
95
-- Real directory reading via system calls
96
-- Command history persistence
97
-- Tab completion enhancements  
98
-- Startup time optimization
99
-- Memory usage profiling and optimization
ast_types.mod → mod/ast_types.modrenamed (100% similarity)
ast_types_enhanced.mod → mod/ast_types_enhanced.modrenamed (100% similarity)
lexer.mod → mod/lexer.modrenamed (100% similarity)
lexer_simple.mod → mod/lexer_simple.modrenamed (100% similarity)
parser_enhanced.mod → mod/parser_enhanced.modrenamed (100% similarity)
test_script.fshdeleted
@@ -1,7 +0,0 @@
1
-#!/bin/bash
2
-# Test script for source command
3
-echo "Starting script execution..."
4
-export TEST_VAR=hello_from_script
5
-echo "TEST_VAR is now set to: $TEST_VAR"
6
-pwd
7
-echo "Script execution completed!"
test_tab_completion.shdeleted
@@ -1,59 +0,0 @@
1
-#!/bin/bash
2
-
3
-echo "=== Phase 4: Enhanced Tab Completion Test ==="
4
-echo ""
5
-echo "Testing enhanced tab completion functionality..."
6
-echo ""
7
-
8
-# Create some test files and directories for completion testing
9
-mkdir -p test_completion_dir/subdir
10
-touch test_completion_dir/test_file1.txt
11
-touch test_completion_dir/test_file2.log
12
-touch test_completion_dir/another_file.sh
13
-touch test_completion_dir/subdir/nested_file.txt
14
-
15
-echo "Created test directory structure:"
16
-ls -la test_completion_dir/
17
-
18
-echo ""
19
-echo "✅ Enhanced Tab Completion Features Implemented:"
20
-echo ""
21
-echo "🎯 Command Completion:"
22
-echo "   • All builtin commands (cd, echo, exit, export, etc.)"
23
-echo "   • Common system commands (ls, cat, grep, find, etc.)"
24
-echo "   • Context-aware completion based on cursor position"
25
-echo ""
26
-echo "🎯 File System Completion:"
27
-echo "   • Real-time directory scanning using 'ls' command"
28
-echo "   • Pattern matching for partial filenames"
29
-echo "   • Directory navigation with ./ and ../ support"
30
-echo "   • Proper handling of paths with spaces"
31
-echo ""
32
-echo "🎯 Smart Features:"
33
-echo "   • Automatic completion for single matches"
34
-echo "   • Common prefix completion for multiple matches" 
35
-echo "   • Visual display of available options"
36
-echo "   • Integration with existing history and editing"
37
-echo ""
38
-echo "🚀 Interactive Usage:"
39
-echo "   • Type partial command and press TAB for command completion"
40
-echo "   • Type partial path and press TAB for file completion"
41
-echo "   • Multiple TAB presses show all available options"
42
-echo "   • Works with both relative and absolute paths"
43
-echo ""
44
-
45
-# Test the shell with some basic commands to show functionality
46
-echo "Basic shell functionality test:"
47
-echo -e "echo 'Tab completion ready!'\nls test_completion_dir\nexit" | ./bin/fortsh
48
-
49
-echo ""
50
-echo "Cleaning up test files..."
51
-rm -rf test_completion_dir
52
-
53
-echo ""
54
-echo "Phase 4 implementation: COMPLETE! 🎉"
55
-echo ""
56
-echo "Try these in interactive mode:"
57
-echo "  echo te[TAB] -> echo test"  
58
-echo "  ls tes[TAB] -> shows test files"
59
-echo "  cd /ho[TAB] -> cd /home/"
tests/Makefiledeleted
@@ -1,121 +0,0 @@
1
-# Test Suite Makefile for Fortran Shell (fortsh)
2
-# ================================================
3
-
4
-# Compiler settings
5
-FC = gfortran
6
-FCFLAGS = -Wall -Wextra -std=f2018 -fPIC -g -O0 -fcheck=all
7
-LDFLAGS = 
8
-
9
-# Directories
10
-SRCDIR = ../src
11
-BUILDDIR = build
12
-TESTDIR = .
13
-
14
-# Include path for main source modules
15
-INCFLAGS = -I../build
16
-
17
-# Test sources
18
-TEST_SOURCES = test_runner.f90
19
-
20
-# Required source modules (in dependency order)
21
-SRC_MODULES = $(SRCDIR)/common/types.f90 \
22
-              $(SRCDIR)/common/error_handling.f90 \
23
-              $(SRCDIR)/system/interface.f90 \
24
-              $(SRCDIR)/parsing/glob.f90 \
25
-              $(SRCDIR)/scripting/variables.f90 \
26
-              $(SRCDIR)/parsing/parser.f90 \
27
-              $(SRCDIR)/scripting/control_flow.f90 \
28
-              $(SRCDIR)/execution/jobs.f90 \
29
-              $(SRCDIR)/scripting/aliases.f90
30
-
31
-# Object files
32
-SRC_OBJECTS = $(BUILDDIR)/types.o \
33
-              $(BUILDDIR)/error_handling.o \
34
-              $(BUILDDIR)/interface.o \
35
-              $(BUILDDIR)/glob.o \
36
-              $(BUILDDIR)/variables.o \
37
-              $(BUILDDIR)/parser.o \
38
-              $(BUILDDIR)/control_flow.o \
39
-              $(BUILDDIR)/jobs.o \
40
-              $(BUILDDIR)/aliases.o
41
-
42
-TEST_OBJECTS = $(BUILDDIR)/test_runner.o
43
-
44
-# Target executable
45
-TARGET = $(BUILDDIR)/test_runner
46
-
47
-# Default target
48
-all: $(TARGET)
49
-
50
-# Create build directory
51
-$(BUILDDIR):
52
-	mkdir -p $(BUILDDIR)
53
-
54
-# Test runner executable
55
-$(TARGET): $(SRC_OBJECTS) $(TEST_OBJECTS) | $(BUILDDIR)
56
-	$(FC) $(SRC_OBJECTS) $(TEST_OBJECTS) -o $@ $(LDFLAGS)
57
-	@echo "Test suite built successfully!"
58
-
59
-# Test runner object
60
-$(BUILDDIR)/test_runner.o: test_runner.f90 $(SRC_OBJECTS) | $(BUILDDIR)
61
-	$(FC) $(FCFLAGS) -J$(BUILDDIR) -c $< -o $@
62
-
63
-# Source module objects
64
-$(BUILDDIR)/types.o: $(SRCDIR)/common/types.f90 | $(BUILDDIR)
65
-	$(FC) $(FCFLAGS) -J$(BUILDDIR) -c $< -o $@
66
-
67
-$(BUILDDIR)/error_handling.o: $(SRCDIR)/common/error_handling.f90 | $(BUILDDIR)
68
-	$(FC) $(FCFLAGS) -J$(BUILDDIR) -c $< -o $@
69
-
70
-$(BUILDDIR)/interface.o: $(SRCDIR)/system/interface.f90 $(BUILDDIR)/types.o | $(BUILDDIR)
71
-	$(FC) $(FCFLAGS) -J$(BUILDDIR) -c $< -o $@
72
-
73
-$(BUILDDIR)/glob.o: $(SRCDIR)/parsing/glob.f90 $(BUILDDIR)/types.o $(BUILDDIR)/interface.o | $(BUILDDIR)
74
-	$(FC) $(FCFLAGS) -J$(BUILDDIR) -c $< -o $@
75
-
76
-$(BUILDDIR)/variables.o: $(SRCDIR)/scripting/variables.f90 $(BUILDDIR)/types.o $(BUILDDIR)/interface.o | $(BUILDDIR)
77
-	$(FC) $(FCFLAGS) -J$(BUILDDIR) -c $< -o $@
78
-
79
-$(BUILDDIR)/parser.o: $(SRCDIR)/parsing/parser.f90 $(BUILDDIR)/types.o $(BUILDDIR)/interface.o $(BUILDDIR)/variables.o $(BUILDDIR)/glob.o | $(BUILDDIR)
80
-	$(FC) $(FCFLAGS) -J$(BUILDDIR) -c $< -o $@
81
-
82
-$(BUILDDIR)/control_flow.o: $(SRCDIR)/scripting/control_flow.f90 $(BUILDDIR)/types.o $(BUILDDIR)/interface.o | $(BUILDDIR)
83
-	$(FC) $(FCFLAGS) -J$(BUILDDIR) -c $< -o $@
84
-
85
-$(BUILDDIR)/jobs.o: $(SRCDIR)/execution/jobs.f90 $(BUILDDIR)/types.o $(BUILDDIR)/interface.o | $(BUILDDIR)
86
-	$(FC) $(FCFLAGS) -J$(BUILDDIR) -c $< -o $@
87
-
88
-$(BUILDDIR)/aliases.o: $(SRCDIR)/scripting/aliases.f90 $(BUILDDIR)/types.o | $(BUILDDIR)
89
-	$(FC) $(FCFLAGS) -J$(BUILDDIR) -c $< -o $@
90
-
91
-# Run tests
92
-test: $(TARGET)
93
-	@echo "Running test suite..."
94
-	@echo "====================="
95
-	@./$(TARGET)
96
-
97
-# Run tests with verbose output
98
-test-verbose: $(TARGET)
99
-	@echo "Running test suite (verbose)..."
100
-	@echo "==============================="
101
-	@./$(TARGET) --verbose
102
-
103
-# Clean build artifacts
104
-clean:
105
-	rm -rf $(BUILDDIR)
106
-	@echo "Cleaned test build directory"
107
-
108
-# Clean and rebuild
109
-rebuild: clean all
110
-
111
-# Help target
112
-help:
113
-	@echo "Available targets:"
114
-	@echo "  all      - Build test suite"
115
-	@echo "  test     - Run tests"
116
-	@echo "  test-verbose - Run tests with verbose output"
117
-	@echo "  clean    - Remove build artifacts"
118
-	@echo "  rebuild  - Clean and rebuild"
119
-	@echo "  help     - Show this help message"
120
-
121
-.PHONY: all test test-verbose clean rebuild help
tests/README.mddeleted
@@ -1,423 +0,0 @@
1
-# Fortsh Test Suite Documentation
2
-
3
-## Overview
4
-
5
-The Fortsh test suite is a comprehensive testing framework designed to ensure bash compatibility and POSIX compliance. It consists of multiple test suites that verify different aspects of shell functionality.
6
-
7
-## Test Suites
8
-
9
-### 1. Integration Tests (`integration_test.sh`)
10
-
11
-**Purpose:** Verify basic shell functionality and core features.
12
-
13
-**What it tests:**
14
-- Basic command execution
15
-- Variable expansion
16
-- Glob pattern matching
17
-- Here-string redirection
18
-- For loops
19
-- Built-in commands
20
-- Alias functionality
21
-- Error handling
22
-
23
-**Run with:**
24
-```bash
25
-make test-integration
26
-```
27
-
28
-**Expected runtime:** ~5 seconds
29
-
30
-### 2. Bash Parity Tests (`bash_parity_test.sh`)
31
-
32
-**Purpose:** Ensure fortsh produces identical output to bash for all commands.
33
-
34
-**Methodology:**
35
-- Runs each command in both bash and fortsh
36
-- Compares output byte-for-byte
37
-- Reports differences
38
-
39
-**What it tests:**
40
-- Echo and output (5 tests)
41
-- Variable expansion (5 tests)
42
-- Parameter expansion (10 tests)
43
-- Command substitution (4 tests)
44
-- Arithmetic expansion (7 tests)
45
-- Brace expansion (5 tests)
46
-- Glob patterns (3 tests)
47
-- Redirection (4 tests)
48
-- Pipelines (3 tests)
49
-- Conditionals (5 tests)
50
-- Loops (5 tests)
51
-- Test operators (8 tests)
52
-- Logical operators (6 tests)
53
-- Special variables (3 tests)
54
-- Functions (4 tests)
55
-- Arrays (4 tests)
56
-- Quoting and escaping (4 tests)
57
-- Subshells (2 tests)
58
-- Case statements (3 tests)
59
-- Multi-line strings (2 tests)
60
-
61
-**Total:** ~95 comparison tests
62
-
63
-**Run with:**
64
-```bash
65
-make test-parity
66
-```
67
-
68
-**Expected runtime:** ~30-60 seconds
69
-
70
-### 3. POSIX Compliance Tests (`posix_compliance_test.sh`)
71
-
72
-**Purpose:** Verify compliance with POSIX shell specification.
73
-
74
-**Methodology:**
75
-- Written in pure POSIX shell (no bash-isms)
76
-- Compares fortsh with /bin/sh (usually dash or bash in POSIX mode)
77
-- Tests only POSIX-specified features
78
-
79
-**What it tests:**
80
-- POSIX basic commands (4 tests)
81
-- POSIX variable expansion (4 tests)
82
-- POSIX parameter expansion (4 tests)
83
-- POSIX command substitution (3 tests)
84
-- POSIX arithmetic with expr (3 tests)
85
-- POSIX redirection (4 tests)
86
-- POSIX pipelines (3 tests)
87
-- POSIX test command (12 tests)
88
-- POSIX conditionals (3 tests)
89
-- POSIX loops (3 tests)
90
-- POSIX case statements (4 tests)
91
-- POSIX functions (4 tests)
92
-- POSIX special variables (6 tests)
93
-- POSIX logical operators (7 tests)
94
-- POSIX quoting (4 tests)
95
-- POSIX subshells (2 tests)
96
-- POSIX compound commands (2 tests)
97
-- POSIX here documents (3 tests)
98
-- POSIX word expansion (2 tests)
99
-- POSIX pathname expansion (3 tests)
100
-- POSIX field splitting (2 tests)
101
-- POSIX exit status (4 tests)
102
-- POSIX set builtin (3 tests)
103
-- POSIX export (1 test)
104
-- POSIX readonly (1 test)
105
-
106
-**Total:** ~90 POSIX compliance tests
107
-
108
-**Run with:**
109
-```bash
110
-make test-posix
111
-```
112
-
113
-**Expected runtime:** ~30-60 seconds
114
-
115
-### 4. Feature Test Suite (`feature_test_suite.sh`)
116
-
117
-**Purpose:** Comprehensive feature testing within bash itself (not comparing with fortsh).
118
-
119
-**What it tests:**
120
-- Basic output and echo
121
-- Redirection
122
-- Pipes
123
-- Command substitution
124
-- Variables
125
-- Parameter expansion
126
-- Brace expansion
127
-- Glob patterns
128
-- Arithmetic
129
-- Control flow
130
-- Test operators
131
-- Here documents
132
-- Background jobs
133
-- Special variables
134
-- Functions
135
-- Arrays
136
-- Quoting
137
-- Complex combinations
138
-
139
-**Total:** ~100+ feature tests
140
-
141
-**Run with:**
142
-```bash
143
-make test-features
144
-```
145
-
146
-**Expected runtime:** ~10-20 seconds
147
-
148
-## Running Tests
149
-
150
-### Quick Test
151
-Run a basic sanity check:
152
-```bash
153
-make test
154
-```
155
-
156
-### Smoke Tests
157
-Run quick validation tests:
158
-```bash
159
-make smoke-test
160
-```
161
-
162
-### Individual Test Suites
163
-Run specific test suites:
164
-```bash
165
-make test-integration   # Integration tests
166
-make test-parity        # Bash parity tests
167
-make test-posix         # POSIX compliance tests
168
-make test-features      # Feature tests
169
-```
170
-
171
-### All Tests
172
-Run the complete test suite:
173
-```bash
174
-make test-all
175
-```
176
-
177
-This runs:
178
-1. Integration tests
179
-2. Bash parity tests
180
-3. POSIX compliance tests
181
-
182
-**Expected total runtime:** ~1-2 minutes
183
-
184
-### Continuous Integration
185
-For CI/CD pipelines:
186
-```bash
187
-make clean all test-all
188
-```
189
-
190
-## Test Output Format
191
-
192
-All test scripts use a consistent format:
193
-
194
-```
195
-✓ PASS: Test description
196
-✗ FAIL: Test description
197
-  bash:   expected output
198
-  fortsh: actual output
199
-⊘ SKIP: Test description - reason
200
-```
201
-
202
-### Color Coding
203
-- 🟢 **Green**: Passed tests
204
-- 🔴 **Red**: Failed tests
205
-- 🟡 **Yellow**: Skipped tests
206
-- 🔵 **Blue**: Section headers
207
-
208
-## Test Results
209
-
210
-At the end of each suite, you'll see:
211
-
212
-```
213
-==========================================
214
-RESULTS
215
-==========================================
216
-Passed:  85
217
-Failed:  2
218
-Skipped: 3
219
-Total:   90
220
-==========================================
221
-Pass rate: 94%
222
-==========================================
223
-```
224
-
225
-## Exit Codes
226
-
227
-All test scripts follow standard conventions:
228
-- **0**: All tests passed
229
-- **1**: One or more tests failed
230
-
231
-## Adding New Tests
232
-
233
-### To bash_parity_test.sh
234
-
235
-Add a new comparison test:
236
-
237
-```bash
238
-compare_output "test description" "command to test"
239
-```
240
-
241
-Or compare exit codes:
242
-
243
-```bash
244
-compare_exit_code "test description" "command to test"
245
-```
246
-
247
-### To posix_compliance_test.sh
248
-
249
-Add a POSIX comparison test:
250
-
251
-```bash
252
-compare_posix_output "test description" "command to test"
253
-```
254
-
255
-Or compare exit codes:
256
-
257
-```bash
258
-compare_posix_exit_code "test description" "command to test"
259
-```
260
-
261
-### To integration_test.sh
262
-
263
-Add a new test section:
264
-
265
-```bash
266
-echo ""
267
-echo "Test N: Feature description"
268
-echo "----------------------------"
269
-result=$(echo "command" | "$FORTSH_BIN" 2>/dev/null)
270
-if [[ "$result" == "expected" ]]; then
271
-    echo "✅ Feature works"
272
-else
273
-    echo "❌ Feature failed"
274
-    echo "Expected: 'expected', Got: '$result'"
275
-fi
276
-```
277
-
278
-## Test Coverage
279
-
280
-Current coverage areas:
281
-
282
-### Fully Tested (100% parity with bash)
283
-- ✅ Variable expansion
284
-- ✅ Command substitution
285
-- ✅ Arithmetic expansion
286
-- ✅ Parameter expansion (basic)
287
-- ✅ Glob patterns
288
-- ✅ Redirection (basic)
289
-- ✅ Pipelines
290
-- ✅ For loops
291
-- ✅ While/until loops
292
-- ✅ If/elif/else
293
-- ✅ Case statements
294
-- ✅ Functions
295
-- ✅ Arrays (indexed)
296
-- ✅ Here-documents
297
-- ✅ Here-strings
298
-- ✅ Background jobs (&)
299
-- ✅ Logical operators (&&, ||)
300
-
301
-### Partially Tested (>90% parity)
302
-- ⚠️ Advanced parameter expansion
303
-- ⚠️ Associative arrays
304
-- ⚠️ Advanced redirection (FD manipulation)
305
-- ⚠️ Coprocesses
306
-- ⚠️ Process substitution
307
-
308
-### POSIX Compliance
309
-- ✅ All POSIX-required builtins
310
-- ✅ POSIX parameter expansion
311
-- ✅ POSIX test operators
312
-- ✅ POSIX control flow
313
-- ✅ POSIX quoting rules
314
-- ✅ POSIX word expansion order
315
-
316
-## Debugging Failed Tests
317
-
318
-### For Bash Parity Tests
319
-
320
-If a test fails, you'll see:
321
-
322
-```
323
-✗ FAIL: echo with quotes
324
-  bash:   hello world
325
-  fortsh: hello  world
326
-```
327
-
328
-To debug:
329
-```bash
330
-# Run the command manually
331
-bash -c 'echo "hello world"'
332
-./bin/fortsh -c 'echo "hello world"'
333
-
334
-# Compare output
335
-bash -c 'echo "hello world"' > /tmp/bash_out
336
-./bin/fortsh -c 'echo "hello world"' > /tmp/fortsh_out
337
-diff /tmp/bash_out /tmp/fortsh_out
338
-```
339
-
340
-### For POSIX Tests
341
-
342
-```bash
343
-# Run with POSIX shell
344
-sh -c 'command'
345
-./bin/fortsh -c 'command'
346
-```
347
-
348
-### Verbose Mode
349
-
350
-Add `-x` to any test script for verbose output:
351
-
352
-```bash
353
-bash -x tests/bash_parity_test.sh
354
-```
355
-
356
-## Test File Organization
357
-
358
-```
359
-tests/
360
-├── README.md                   # This file
361
-├── integration_test.sh         # Basic integration tests
362
-├── bash_parity_test.sh        # Bash compatibility tests
363
-├── posix_compliance_test.sh   # POSIX compliance tests
364
-├── feature_test_suite.sh      # Comprehensive feature tests
365
-└── [other test files]         # Legacy/specific tests
366
-```
367
-
368
-## Best Practices
369
-
370
-1. **Always run tests after changes:** `make test-all`
371
-2. **Add tests for new features:** Before implementing
372
-3. **Test edge cases:** Empty strings, special characters, etc.
373
-4. **Keep tests independent:** Each test should not depend on others
374
-5. **Use descriptive names:** Test names should explain what they verify
375
-6. **Clean up after tests:** Remove temp files in cleanup functions
376
-
377
-## Performance Benchmarks
378
-
379
-Typical execution times on modern hardware:
380
-
381
-| Test Suite | Tests | Time  | Tests/sec |
382
-|------------|-------|-------|-----------|
383
-| Integration| 8     | ~5s   | 1.6       |
384
-| Parity     | ~95   | ~45s  | 2.1       |
385
-| POSIX      | ~90   | ~40s  | 2.2       |
386
-| Features   | ~100  | ~15s  | 6.7       |
387
-| **Total**  | ~293  | ~105s | 2.8       |
388
-
389
-## Contributing
390
-
391
-When contributing new features:
392
-
393
-1. Write tests first (TDD)
394
-2. Ensure bash parity for bash-compatible features
395
-3. Ensure POSIX compliance for POSIX features
396
-4. Run `make test-all` before submitting
397
-5. Document any intentional deviations
398
-
399
-## Known Limitations
400
-
401
-Some bash features are intentionally not tested:
402
-- Bash-specific builtins not in POSIX
403
-- `[[` extended test (tested separately)
404
-- `(())` arithmetic command (tested separately)
405
-- Bash 4.x+ features (for compatibility)
406
-
407
-## License
408
-
409
-Tests are part of fortsh and follow the same license as the main project.
410
-
411
-## Support
412
-
413
-For test failures or questions:
414
-1. Check this documentation
415
-2. Review existing tests for examples
416
-3. Check fortsh documentation in `docs/`
417
-4. Open an issue on GitHub
418
-
419
----
420
-
421
-**Last Updated:** 2025-10-13
422
-**Test Suite Version:** 1.0
423
-**Fortsh Version:** 4.0.0+
tests/bash_parity_test.shdeleted
@@ -1,290 +0,0 @@
1
-#!/bin/bash
2
-# =====================================
3
-# Bash Parity Test Suite for fortsh
4
-# =====================================
5
-# This test compares fortsh output with bash output to ensure compatibility
6
-
7
-set -e
8
-
9
-# Colors for output
10
-RED='\033[0;31m'
11
-GREEN='\033[0;32m'
12
-YELLOW='\033[1;33m'
13
-BLUE='\033[0;34m'
14
-NC='\033[0m' # No Color
15
-
16
-PASSED=0
17
-FAILED=0
18
-SKIPPED=0
19
-
20
-# Get script directory
21
-SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
22
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
23
-
24
-# Check if fortsh exists
25
-if [[ ! -x "$FORTSH_BIN" ]]; then
26
-    echo -e "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN"
27
-    echo "Please run 'make' first or set FORTSH_BIN environment variable"
28
-    exit 1
29
-fi
30
-
31
-# Test result trackers
32
-pass() {
33
-    echo -e "${GREEN}✓ PASS${NC}: $1"
34
-    ((PASSED++))
35
-}
36
-
37
-fail() {
38
-    echo -e "${RED}✗ FAIL${NC}: $1"
39
-    if [[ -n "$2" ]]; then
40
-        echo "  bash:   $2"
41
-    fi
42
-    if [[ -n "$3" ]]; then
43
-        echo "  fortsh: $3"
44
-    fi
45
-    ((FAILED++))
46
-}
47
-
48
-skip() {
49
-    echo -e "${YELLOW}⊘ SKIP${NC}: $1 - $2"
50
-    ((SKIPPED++))
51
-}
52
-
53
-section() {
54
-    echo ""
55
-    echo -e "${BLUE}=========================================="
56
-    echo "$1"
57
-    echo -e "==========================================${NC}"
58
-}
59
-
60
-# Helper function to run command in both shells and compare
61
-compare_output() {
62
-    local test_name="$1"
63
-    local command="$2"
64
-    local bash_file="/tmp/bash_parity_$$_bash"
65
-    local fortsh_file="/tmp/bash_parity_$$_fortsh"
66
-
67
-    # Run in bash
68
-    bash -c "$command" > "$bash_file" 2>&1 || true
69
-
70
-    # Run in fortsh
71
-    "$FORTSH_BIN" -c "$command" > "$fortsh_file" 2>&1 || true
72
-
73
-    # Compare outputs
74
-    if diff -q "$bash_file" "$fortsh_file" > /dev/null 2>&1; then
75
-        pass "$test_name"
76
-    else
77
-        fail "$test_name" "$(cat "$bash_file")" "$(cat "$fortsh_file")"
78
-    fi
79
-
80
-    rm -f "$bash_file" "$fortsh_file"
81
-}
82
-
83
-# Helper function to compare exit codes
84
-compare_exit_code() {
85
-    local test_name="$1"
86
-    local command="$2"
87
-
88
-    bash -c "$command" > /dev/null 2>&1
89
-    local bash_exit=$?
90
-
91
-    "$FORTSH_BIN" -c "$command" > /dev/null 2>&1
92
-    local fortsh_exit=$?
93
-
94
-    if [[ $bash_exit -eq $fortsh_exit ]]; then
95
-        pass "$test_name"
96
-    else
97
-        fail "$test_name" "exit=$bash_exit" "exit=$fortsh_exit"
98
-    fi
99
-}
100
-
101
-# Cleanup
102
-cleanup() {
103
-    rm -f /tmp/bash_parity_$$_* 2>/dev/null
104
-    rm -f /tmp/fortsh_parity_test_* 2>/dev/null
105
-}
106
-trap cleanup EXIT
107
-
108
-section "1. BASIC ECHO AND OUTPUT"
109
-
110
-compare_output "echo simple string" "echo hello world"
111
-compare_output "echo with single quotes" "echo 'hello world'"
112
-compare_output "echo with double quotes" 'echo "hello world"'
113
-compare_output "echo with special chars" "echo 'hello\$world'"
114
-compare_output "echo multiple args" "echo a b c d e"
115
-
116
-section "2. VARIABLE EXPANSION"
117
-
118
-compare_output "simple variable" "VAR=test; echo \$VAR"
119
-compare_output "variable in string" 'VAR=world; echo "hello $VAR"'
120
-compare_output "multiple variables" "A=hello; B=world; echo \$A \$B"
121
-compare_output "undefined variable" "echo \$UNDEFINED_VAR_XYZ"
122
-compare_output "variable with braces" "VAR=test; echo \${VAR}"
123
-
124
-section "3. PARAMETER EXPANSION"
125
-
126
-compare_output "default value :-" 'echo "${UNSET:-default}"'
127
-compare_output "string length" 'STR=hello; echo "${#STR}"'
128
-compare_output "remove prefix #" 'VAR=prefix_value; echo "${VAR#prefix_}"'
129
-compare_output "remove prefix ##" 'VAR=path/to/file.txt; echo "${VAR##*/}"'
130
-compare_output "remove suffix %" 'VAR=file.txt; echo "${VAR%.txt}"'
131
-compare_output "remove suffix %%" 'VAR=file.tar.gz; echo "${VAR%%.*}"'
132
-compare_output "uppercase first" 'VAR=hello; echo "${VAR^}"'
133
-compare_output "uppercase all" 'VAR=hello; echo "${VAR^^}"'
134
-compare_output "lowercase first" 'VAR=HELLO; echo "${VAR,}"'
135
-compare_output "lowercase all" 'VAR=HELLO; echo "${VAR,,}"'
136
-
137
-section "4. COMMAND SUBSTITUTION"
138
-
139
-compare_output "command substitution \$()" "echo \$(echo nested)"
140
-compare_output "backtick substitution" 'echo `echo backtick`'
141
-compare_output "nested substitution" "echo \$(echo \$(echo deep))"
142
-compare_output "substitution in string" 'echo "result: $(echo success)"'
143
-
144
-section "5. ARITHMETIC EXPANSION"
145
-
146
-compare_output "simple addition" "echo \$((5 + 3))"
147
-compare_output "subtraction" "echo \$((10 - 7))"
148
-compare_output "multiplication" "echo \$((4 * 3))"
149
-compare_output "division" "echo \$((15 / 3))"
150
-compare_output "modulo" "echo \$((10 % 3))"
151
-compare_output "arithmetic with vars" "A=5; B=3; echo \$((A + B))"
152
-compare_output "complex expression" "echo \$((5 * 3 + 2))"
153
-
154
-section "6. BRACE EXPANSION"
155
-
156
-compare_output "numeric range" "echo {1..5}"
157
-compare_output "reverse range" "echo {5..1}"
158
-compare_output "char range" "echo {a..e}"
159
-compare_output "list expansion" "echo {foo,bar,baz}"
160
-compare_output "nested braces" "echo {a,b}{1,2}"
161
-
162
-section "7. GLOB PATTERNS"
163
-
164
-# Setup test files
165
-mkdir -p /tmp/fortsh_parity_test_dir
166
-touch /tmp/fortsh_parity_test_dir/{a,b,c}.txt
167
-touch /tmp/fortsh_parity_test_dir/test{1,2,3}.dat
168
-
169
-compare_output "glob wildcard *" "ls /tmp/fortsh_parity_test_dir/*.txt 2>/dev/null | wc -l"
170
-compare_output "glob single char ?" "ls /tmp/fortsh_parity_test_dir/?.txt 2>/dev/null | wc -l"
171
-compare_output "glob bracket" "ls /tmp/fortsh_parity_test_dir/[ab].txt 2>/dev/null | wc -l"
172
-
173
-section "8. REDIRECTION"
174
-
175
-compare_output "output redirect" "echo test > /tmp/fortsh_parity_test_out && cat /tmp/fortsh_parity_test_out"
176
-compare_output "append redirect" "echo line1 > /tmp/fortsh_parity_test_app && echo line2 >> /tmp/fortsh_parity_test_app && wc -l < /tmp/fortsh_parity_test_app"
177
-compare_output "here string" "cat <<< hello"
178
-compare_output "stderr redirect" "ls /nonexistent 2>&1 | grep -c 'cannot access\\|No such'"
179
-
180
-section "9. PIPELINES"
181
-
182
-compare_output "simple pipe" "echo hello | cat"
183
-compare_output "two-stage pipe" "echo test | cat | tr t T"
184
-compare_output "three-stage pipe" "echo HELLO | tr '[:upper:]' '[:lower:]' | tr l x"
185
-
186
-section "10. CONDITIONALS"
187
-
188
-compare_exit_code "true command" "true"
189
-compare_exit_code "false command" "false"
190
-compare_output "if true" "if true; then echo yes; fi"
191
-compare_output "if false" "if false; then echo no; else echo yes; fi"
192
-compare_output "if-elif-else" "X=2; if [ \$X -eq 1 ]; then echo one; elif [ \$X -eq 2 ]; then echo two; else echo other; fi"
193
-
194
-section "11. LOOPS"
195
-
196
-compare_output "for loop list" "for i in a b c; do echo \$i; done"
197
-compare_output "for loop range" "for i in {1..3}; do echo \$i; done"
198
-compare_output "for loop glob" "for f in /tmp/fortsh_parity_test_dir/*.txt; do basename \$f; done | wc -l"
199
-compare_output "while loop" "i=3; while [ \$i -gt 0 ]; do echo \$i; i=\$((i-1)); done"
200
-compare_output "until loop" "i=1; until [ \$i -gt 3 ]; do echo \$i; i=\$((i+1)); done"
201
-
202
-section "12. TEST OPERATORS"
203
-
204
-compare_exit_code "test -f file" "touch /tmp/fortsh_parity_test_file && test -f /tmp/fortsh_parity_test_file"
205
-compare_exit_code "test -d dir" "test -d /tmp"
206
-compare_exit_code "test -n string" "test -n 'hello'"
207
-compare_exit_code "test -z empty" "test -z ''"
208
-compare_exit_code "test string =" "test 'hello' = 'hello'"
209
-compare_exit_code "test number -eq" "test 5 -eq 5"
210
-compare_exit_code "test number -gt" "test 5 -gt 3"
211
-compare_exit_code "test number -lt" "test 3 -lt 5"
212
-
213
-section "13. LOGICAL OPERATORS"
214
-
215
-compare_exit_code "true && true" "true && true"
216
-compare_exit_code "true && false" "true && false"
217
-compare_exit_code "false || true" "false || true"
218
-compare_exit_code "false || false" "false || false"
219
-compare_output "command && echo" "true && echo success"
220
-compare_output "command || echo" "false || echo fallback"
221
-
222
-section "14. SPECIAL VARIABLES"
223
-
224
-compare_output "\$? exit status" "true; echo \$?"
225
-compare_output "\$? after failure" "false; echo \$?"
226
-compare_output "\$\$ PID exists" "test -n \$\$ && echo ok"
227
-
228
-section "15. FUNCTIONS"
229
-
230
-compare_output "simple function" "func() { echo hello; }; func"
231
-compare_output "function with args" "func() { echo \$1 \$2; }; func foo bar"
232
-compare_output "function return" "func() { return 42; }; func; echo \$?"
233
-compare_output "local variables" "func() { local x=10; echo \$x; }; func"
234
-
235
-section "16. ARRAYS"
236
-
237
-compare_output "array declaration" "arr=(a b c); echo \${arr[0]}"
238
-compare_output "array length" "arr=(a b c); echo \${#arr[@]}"
239
-compare_output "array all elements" "arr=(a b c); echo \${arr[@]}"
240
-compare_output "array indices" "arr=(a b c); echo \${!arr[@]}"
241
-
242
-section "17. QUOTING AND ESCAPING"
243
-
244
-compare_output "single quote literal" "echo '\$VAR'"
245
-compare_output "double quote expand" 'VAR=test; echo "$VAR"'
246
-compare_output "escape in double" 'echo "hello\$world"'
247
-compare_output "escape newline" "echo 'line1\nline2'"
248
-
249
-section "18. SUBSHELLS"
250
-
251
-compare_output "subshell var isolation" "(VAR=inner; echo \$VAR); echo \$VAR"
252
-compare_output "subshell cd isolation" "(cd /tmp; pwd); pwd"
253
-
254
-section "19. CASE STATEMENT"
255
-
256
-compare_output "case match" "x=2; case \$x in 1) echo one;; 2) echo two;; esac"
257
-compare_output "case wildcard" "x=hello; case \$x in h*) echo starts_h;; esac"
258
-compare_output "case default" "x=z; case \$x in a) echo a;; *) echo default;; esac"
259
-
260
-section "20. MULTI-LINE STRINGS"
261
-
262
-compare_output "double quote multiline" 'echo "line1
263
-line2"'
264
-compare_output "single quote multiline" "echo 'line1
265
-line2'"
266
-
267
-# Summary
268
-section "SUMMARY"
269
-echo ""
270
-echo "=========================================="
271
-echo "BASH PARITY TEST RESULTS"
272
-echo "=========================================="
273
-echo -e "${GREEN}Passed:${NC}  $PASSED"
274
-echo -e "${RED}Failed:${NC}  $FAILED"
275
-echo -e "${YELLOW}Skipped:${NC} $SKIPPED"
276
-echo "Total:   $((PASSED + FAILED + SKIPPED))"
277
-echo "=========================================="
278
-
279
-if [[ $((PASSED + FAILED)) -gt 0 ]]; then
280
-    PASS_RATE=$((PASSED * 100 / (PASSED + FAILED)))
281
-    echo "Pass rate: ${PASS_RATE}%"
282
-fi
283
-
284
-if [[ $FAILED -eq 0 ]]; then
285
-    echo -e "${GREEN}ALL BASH PARITY TESTS PASSED!${NC} ✓"
286
-    exit 0
287
-else
288
-    echo -e "${RED}SOME TESTS FAILED${NC} ✗"
289
-    exit 1
290
-fi
tests/feature_test_suite.shdeleted
@@ -1,544 +0,0 @@
1
-#!/bin/bash
2
-# Comprehensive Fortsh Feature Test Suite
3
-# Tests all major shell operators and features
4
-
5
-# Colors for output
6
-RED='\033[0;31m'
7
-GREEN='\033[0;32m'
8
-YELLOW='\033[1;33m'
9
-NC='\033[0m' # No Color
10
-
11
-PASSED=0
12
-FAILED=0
13
-SKIPPED=0
14
-
15
-# Test result tracker
16
-pass() {
17
-    echo -e "${GREEN}✓ PASS${NC}: $1"
18
-    ((PASSED++))
19
-}
20
-
21
-fail() {
22
-    echo -e "${RED}✗ FAIL${NC}: $1"
23
-    echo "  Error: $2"
24
-    ((FAILED++))
25
-}
26
-
27
-skip() {
28
-    echo -e "${YELLOW}⊘ SKIP${NC}: $1"
29
-    ((SKIPPED++))
30
-}
31
-
32
-section() {
33
-    echo ""
34
-    echo "=========================================="
35
-    echo "$1"
36
-    echo "=========================================="
37
-}
38
-
39
-# Cleanup function
40
-cleanup() {
41
-    rm -f /tmp/fortsh_test_* 2>/dev/null
42
-}
43
-
44
-# Setup
45
-cleanup
46
-trap cleanup EXIT
47
-
48
-section "1. BASIC OUTPUT & ECHO"
49
-
50
-# Test 1.1: Simple echo
51
-if echo "hello" > /tmp/fortsh_test_1 2>&1 && [ -f /tmp/fortsh_test_1 ]; then
52
-    pass "Simple echo"
53
-else
54
-    fail "Simple echo" "Command failed"
55
-fi
56
-
57
-# Test 1.2: Echo with variables
58
-VAR="world"
59
-if echo "$VAR" | grep -q "world"; then
60
-    pass "Echo with variables"
61
-else
62
-    fail "Echo with variables" "Variable not expanded"
63
-fi
64
-
65
-section "2. BASIC REDIRECTION"
66
-
67
-# Test 2.1: Output redirection (>)
68
-if echo "test" > /tmp/fortsh_test_2 && grep -q "test" /tmp/fortsh_test_2; then
69
-    pass "Output redirection (>)"
70
-else
71
-    fail "Output redirection (>)" "File not created or content wrong"
72
-fi
73
-
74
-# Test 2.2: Append redirection (>>)
75
-echo "line1" > /tmp/fortsh_test_3
76
-if echo "line2" >> /tmp/fortsh_test_3 && [ $(wc -l < /tmp/fortsh_test_3) -eq 2 ]; then
77
-    pass "Append redirection (>>)"
78
-else
79
-    fail "Append redirection (>>)" "Append failed"
80
-fi
81
-
82
-# Test 2.3: Input redirection (<)
83
-echo "input" > /tmp/fortsh_test_4
84
-if cat < /tmp/fortsh_test_4 | grep -q "input"; then
85
-    pass "Input redirection (<)"
86
-else
87
-    fail "Input redirection (<)" "Input not read"
88
-fi
89
-
90
-# Test 2.4: Error redirection (2>)
91
-ls /nonexistent 2> /tmp/fortsh_test_5
92
-if [ -s /tmp/fortsh_test_5 ]; then
93
-    pass "Error redirection (2>)"
94
-else
95
-    fail "Error redirection (2>)" "stderr not captured"
96
-fi
97
-
98
-# Test 2.5: Redirect both stdout and stderr (2>&1)
99
-if ls /nonexistent 2>&1 | grep -q "cannot access\|No such"; then
100
-    pass "Redirect stderr to stdout (2>&1)"
101
-else
102
-    fail "Redirect stderr to stdout (2>&1)" "Combined output failed"
103
-fi
104
-
105
-section "3. PIPES"
106
-
107
-# Test 3.1: Simple pipe
108
-if echo "hello" | cat | grep -q "hello"; then
109
-    pass "Simple pipe (echo | cat)"
110
-else
111
-    fail "Simple pipe" "Pipe failed"
112
-fi
113
-
114
-# Test 3.2: Two-stage pipe
115
-if echo "test" | cat | grep "test" > /dev/null; then
116
-    pass "Two-stage pipe"
117
-else
118
-    fail "Two-stage pipe" "Multi-stage pipe failed"
119
-fi
120
-
121
-# Test 3.3: Pipe with grep
122
-if ls / | grep -q "bin"; then
123
-    pass "Pipe with grep"
124
-else
125
-    fail "Pipe with grep" "Pipe to grep failed"
126
-fi
127
-
128
-# Test 3.4: Pipe with wc
129
-COUNT=$(echo -e "a\nb\nc" | wc -l)
130
-if [ "$COUNT" -eq 3 ]; then
131
-    pass "Pipe with wc"
132
-else
133
-    fail "Pipe with wc" "Expected 3, got $COUNT"
134
-fi
135
-
136
-# Test 3.5: Three-stage pipe
137
-if echo "HELLO" | tr '[:upper:]' '[:lower:]' | grep -q "hello"; then
138
-    pass "Three-stage pipe"
139
-else
140
-    fail "Three-stage pipe" "Complex pipe failed"
141
-fi
142
-
143
-section "4. COMMAND SUBSTITUTION"
144
-
145
-# Test 4.1: Backticks
146
-if [ "$(echo test)" = "test" ]; then
147
-    pass "Command substitution with $()"
148
-else
149
-    fail "Command substitution with $()" "Substitution failed"
150
-fi
151
-
152
-# Test 4.2: Nested substitution
153
-if [ "$(echo $(echo nested))" = "nested" ]; then
154
-    pass "Nested command substitution"
155
-else
156
-    fail "Nested command substitution" "Nested substitution failed"
157
-fi
158
-
159
-# Test 4.3: Substitution in echo
160
-OUTPUT=$(echo "Result: $(echo success)")
161
-if echo "$OUTPUT" | grep -q "Result: success"; then
162
-    pass "Command substitution in echo"
163
-else
164
-    fail "Command substitution in echo" "Got: $OUTPUT"
165
-fi
166
-
167
-section "5. VARIABLES"
168
-
169
-# Test 5.1: Simple variable assignment
170
-VAR1="value"
171
-if [ "$VAR1" = "value" ]; then
172
-    pass "Simple variable assignment"
173
-else
174
-    fail "Simple variable assignment" "Variable not set"
175
-fi
176
-
177
-# Test 5.2: Variable in command
178
-FILE="/tmp/fortsh_test_var"
179
-if echo "data" > "$FILE" && [ -f "$FILE" ]; then
180
-    pass "Variable in command"
181
-else
182
-    fail "Variable in command" "File not created"
183
-fi
184
-
185
-# Test 5.3: Command substitution to variable
186
-LINES=$(echo -e "a\nb" | wc -l)
187
-if [ "$LINES" -eq 2 ]; then
188
-    pass "Command substitution to variable"
189
-else
190
-    fail "Command substitution to variable" "Expected 2, got $LINES"
191
-fi
192
-
193
-section "6. PARAMETER EXPANSION"
194
-
195
-# Test 6.1: Default value
196
-UNSET_VAR=""
197
-if [ "${UNSET_VAR:-default}" = "default" ]; then
198
-    pass "Parameter expansion with default (:-)"
199
-else
200
-    fail "Parameter expansion with default" "Default not used"
201
-fi
202
-
203
-# Test 6.2: String length
204
-STR="hello"
205
-if [ "${#STR}" -eq 5 ]; then
206
-    pass "String length expansion (${#var})"
207
-else
208
-    fail "String length expansion" "Expected 5, got ${#STR}"
209
-fi
210
-
211
-# Test 6.3: Substring removal
212
-PATH_VAR="path/to/file.txt"
213
-if [ "${PATH_VAR##*/}" = "file.txt" ]; then
214
-    pass "Remove prefix (##)"
215
-else
216
-    fail "Remove prefix (##)" "Got: ${PATH_VAR##*/}"
217
-fi
218
-
219
-section "7. BRACE EXPANSION"
220
-
221
-# Test 7.1: Numeric range
222
-RESULT=$(echo {1..3})
223
-if [ "$RESULT" = "1 2 3" ]; then
224
-    pass "Brace expansion numeric range {1..3}"
225
-else
226
-    fail "Brace expansion numeric range" "Got: $RESULT"
227
-fi
228
-
229
-# Test 7.2: String list
230
-RESULT=$(echo {a,b,c})
231
-if echo "$RESULT" | grep -q "a b c"; then
232
-    pass "Brace expansion string list {a,b,c}"
233
-else
234
-    fail "Brace expansion string list" "Got: $RESULT"
235
-fi
236
-
237
-section "8. GLOB PATTERNS"
238
-
239
-# Setup test files
240
-touch /tmp/fortsh_test_a.txt /tmp/fortsh_test_b.txt /tmp/fortsh_test_c.dat
241
-
242
-# Test 8.1: Wildcard *
243
-COUNT=$(ls /tmp/fortsh_test_*.txt 2>/dev/null | wc -l)
244
-if [ "$COUNT" -eq 2 ]; then
245
-    pass "Glob wildcard (*)"
246
-else
247
-    fail "Glob wildcard (*)" "Expected 2 files, got $COUNT"
248
-fi
249
-
250
-# Test 8.2: Single char ?
251
-if ls /tmp/fortsh_test_?.txt 2>/dev/null | grep -q "fortsh_test_a"; then
252
-    pass "Glob single char (?)"
253
-else
254
-    fail "Glob single char (?)" "Pattern didn't match"
255
-fi
256
-
257
-section "9. ARITHMETIC"
258
-
259
-# Test 9.1: Basic arithmetic
260
-if [ $((5 + 3)) -eq 8 ]; then
261
-    pass "Arithmetic expansion (( ))"
262
-else
263
-    fail "Arithmetic expansion" "5 + 3 != 8"
264
-fi
265
-
266
-# Test 9.2: Multiplication
267
-if [ $((4 * 3)) -eq 12 ]; then
268
-    pass "Arithmetic multiplication"
269
-else
270
-    fail "Arithmetic multiplication" "4 * 3 != 12"
271
-fi
272
-
273
-# Test 9.3: Variables in arithmetic
274
-NUM=10
275
-if [ $((NUM + 5)) -eq 15 ]; then
276
-    pass "Variables in arithmetic"
277
-else
278
-    fail "Variables in arithmetic" "NUM + 5 != 15"
279
-fi
280
-
281
-section "10. CONTROL FLOW"
282
-
283
-# Test 10.1: If statement
284
-if true; then
285
-    pass "If statement (true)"
286
-else
287
-    fail "If statement" "If didn't execute"
288
-fi
289
-
290
-# Test 10.2: If-else
291
-if false; then
292
-    fail "If-else statement" "False branch executed"
293
-else
294
-    pass "If-else statement"
295
-fi
296
-
297
-# Test 10.3: For loop
298
-COUNT=0
299
-for i in 1 2 3; do
300
-    COUNT=$((COUNT + 1))
301
-done
302
-if [ "$COUNT" -eq 3 ]; then
303
-    pass "For loop"
304
-else
305
-    fail "For loop" "Expected 3 iterations, got $COUNT"
306
-fi
307
-
308
-# Test 10.4: While loop
309
-COUNT=0
310
-NUM=3
311
-while [ $NUM -gt 0 ]; do
312
-    COUNT=$((COUNT + 1))
313
-    NUM=$((NUM - 1))
314
-done
315
-if [ "$COUNT" -eq 3 ]; then
316
-    pass "While loop"
317
-else
318
-    fail "While loop" "Expected 3 iterations, got $COUNT"
319
-fi
320
-
321
-section "11. TEST OPERATORS"
322
-
323
-# Test 11.1: File exists
324
-touch /tmp/fortsh_test_exists
325
-if [ -f /tmp/fortsh_test_exists ]; then
326
-    pass "Test file exists (-f)"
327
-else
328
-    fail "Test file exists" "File not detected"
329
-fi
330
-
331
-# Test 11.2: Directory exists
332
-if [ -d /tmp ]; then
333
-    pass "Test directory exists (-d)"
334
-else
335
-    fail "Test directory exists" "Directory not detected"
336
-fi
337
-
338
-# Test 11.3: String equality
339
-if [ "abc" = "abc" ]; then
340
-    pass "String equality (=)"
341
-else
342
-    fail "String equality" "Strings don't match"
343
-fi
344
-
345
-# Test 11.4: Numeric comparison
346
-if [ 5 -gt 3 ]; then
347
-    pass "Numeric comparison (-gt)"
348
-else
349
-    fail "Numeric comparison" "5 not greater than 3"
350
-fi
351
-
352
-# Test 11.5: Advanced test [[]]
353
-if [[ "hello" == "hello" ]]; then
354
-    pass "Advanced test [[ ]]"
355
-else
356
-    fail "Advanced test [[ ]]" "Test failed"
357
-fi
358
-
359
-section "12. HERE DOCUMENTS"
360
-
361
-# Test 12.1: Simple here doc
362
-OUTPUT=$(cat <<EOF
363
-line1
364
-line2
365
-EOF
366
-)
367
-if echo "$OUTPUT" | grep -q "line1"; then
368
-    pass "Here document (<<EOF)"
369
-else
370
-    fail "Here document" "Content not captured"
371
-fi
372
-
373
-# Test 12.2: Here doc with variables
374
-NAME="fortsh"
375
-OUTPUT=$(cat <<EOF
376
-Hello $NAME
377
-EOF
378
-)
379
-if echo "$OUTPUT" | grep -q "Hello fortsh"; then
380
-    pass "Here document with variable expansion"
381
-else
382
-    fail "Here document with variable expansion" "Variable not expanded"
383
-fi
384
-
385
-section "13. BACKGROUND JOBS"
386
-
387
-# Test 13.1: Background execution
388
-(sleep 0.1 && echo "done" > /tmp/fortsh_test_bg) &
389
-BG_PID=$!
390
-sleep 0.2
391
-if [ -f /tmp/fortsh_test_bg ]; then
392
-    pass "Background job execution (&)"
393
-else
394
-    fail "Background job execution" "Background job didn't complete"
395
-fi
396
-
397
-# Test 13.2: $! captures PID
398
-(sleep 0.1) &
399
-LAST_PID=$!
400
-if [ -n "$LAST_PID" ] && [ "$LAST_PID" -gt 0 ]; then
401
-    pass "Background job PID (\$!)"
402
-else
403
-    fail "Background job PID" "PID not captured: $LAST_PID"
404
-fi
405
-
406
-section "14. SPECIAL VARIABLES"
407
-
408
-# Test 14.1: $? exit status
409
-true
410
-if [ $? -eq 0 ]; then
411
-    pass "Exit status (\$?)"
412
-else
413
-    fail "Exit status" "Expected 0, got $?"
414
-fi
415
-
416
-# Test 14.2: $$ PID
417
-if [ -n "$$" ] && [ "$$" -gt 0 ]; then
418
-    pass "Current PID (\$\$)"
419
-else
420
-    fail "Current PID" "PID not set: $$"
421
-fi
422
-
423
-section "15. FUNCTIONS"
424
-
425
-# Test 15.1: Simple function
426
-test_func() {
427
-    echo "success"
428
-}
429
-if [ "$(test_func)" = "success" ]; then
430
-    pass "Function definition and call"
431
-else
432
-    fail "Function definition and call" "Function didn't execute"
433
-fi
434
-
435
-# Test 15.2: Function with parameters
436
-test_params() {
437
-    echo "$1-$2"
438
-}
439
-if [ "$(test_params a b)" = "a-b" ]; then
440
-    pass "Function with parameters"
441
-else
442
-    fail "Function with parameters" "Parameters not passed"
443
-fi
444
-
445
-# Test 15.3: Function return value
446
-test_return() {
447
-    return 42
448
-}
449
-test_return
450
-if [ $? -eq 42 ]; then
451
-    pass "Function return value"
452
-else
453
-    fail "Function return value" "Expected 42, got $?"
454
-fi
455
-
456
-section "16. ARRAYS"
457
-
458
-# Test 16.1: Indexed array
459
-arr=(one two three)
460
-if [ "${arr[0]}" = "one" ]; then
461
-    pass "Indexed array access"
462
-else
463
-    fail "Indexed array access" "Element 0: ${arr[0]}"
464
-fi
465
-
466
-# Test 16.2: Array length
467
-if [ "${#arr[@]}" -eq 3 ]; then
468
-    pass "Array length (${#arr[@]})"
469
-else
470
-    fail "Array length" "Expected 3, got ${#arr[@]}"
471
-fi
472
-
473
-# Test 16.3: Array iteration
474
-COUNT=0
475
-for item in "${arr[@]}"; do
476
-    COUNT=$((COUNT + 1))
477
-done
478
-if [ "$COUNT" -eq 3 ]; then
479
-    pass "Array iteration"
480
-else
481
-    fail "Array iteration" "Expected 3, got $COUNT"
482
-fi
483
-
484
-section "17. QUOTING"
485
-
486
-# Test 17.1: Double quotes preserve variables
487
-VAR="world"
488
-if [ "$(echo "hello $VAR")" = "hello world" ]; then
489
-    pass "Double quotes with variables"
490
-else
491
-    fail "Double quotes with variables" "Variable not expanded"
492
-fi
493
-
494
-# Test 17.2: Single quotes literal
495
-if [ '$(echo test)' = '$(echo test)' ]; then
496
-    pass "Single quotes literal"
497
-else
498
-    fail "Single quotes literal" "Command was executed"
499
-fi
500
-
501
-section "18. COMPLEX COMBINATIONS"
502
-
503
-# Test 18.1: Pipe + redirection
504
-if echo "test" | cat > /tmp/fortsh_test_combo1 && grep -q "test" /tmp/fortsh_test_combo1; then
505
-    pass "Pipe + redirection"
506
-else
507
-    fail "Pipe + redirection" "Combination failed"
508
-fi
509
-
510
-# Test 18.2: Command substitution + pipe
511
-if echo "$(echo hello | tr '[:lower:]' '[:upper:]')" | grep -q "HELLO"; then
512
-    pass "Command substitution + pipe"
513
-else
514
-    fail "Command substitution + pipe" "Combination failed"
515
-fi
516
-
517
-# Test 18.3: Multiple redirections
518
-if { echo "out"; echo "err" >&2; } >>/tmp/fortsh_test_out 2>>/tmp/fortsh_test_err; then
519
-    pass "Multiple redirections"
520
-else
521
-    fail "Multiple redirections" "Complex redirection failed"
522
-fi
523
-
524
-section "SUMMARY"
525
-echo ""
526
-echo "=========================================="
527
-echo "RESULTS"
528
-echo "=========================================="
529
-echo -e "${GREEN}Passed:${NC}  $PASSED"
530
-echo -e "${RED}Failed:${NC}  $FAILED"
531
-echo -e "${YELLOW}Skipped:${NC} $SKIPPED"
532
-echo "Total:   $((PASSED + FAILED + SKIPPED))"
533
-echo "=========================================="
534
-
535
-PASS_RATE=$((PASSED * 100 / (PASSED + FAILED)))
536
-echo "Pass rate: ${PASS_RATE}%"
537
-
538
-if [ $FAILED -eq 0 ]; then
539
-    echo -e "${GREEN}ALL TESTS PASSED!${NC} ✓"
540
-    exit 0
541
-else
542
-    echo -e "${RED}SOME TESTS FAILED${NC} ✗"
543
-    exit 1
544
-fi
tests/integration_test.shdeleted
@@ -1,122 +0,0 @@
1
-#!/bin/bash
2
-# =====================================
3
-# Integration Test Script for fortsh
4
-# =====================================
5
-
6
-set -e  # Exit on any error
7
-
8
-SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9
-FORTSH_DIR="$(dirname "$SCRIPT_DIR")"
10
-FORTSH_BIN="$FORTSH_DIR/bin/fortsh"
11
-
12
-echo "======================================"
13
-echo "Fortsh Integration Test Suite"
14
-echo "======================================"
15
-echo ""
16
-
17
-# Check if fortsh binary exists
18
-if [[ ! -x "$FORTSH_BIN" ]]; then
19
-    echo "❌ fortsh binary not found at $FORTSH_BIN"
20
-    echo "Please run 'make' in the main directory first"
21
-    exit 1
22
-fi
23
-
24
-echo "✅ Found fortsh binary at $FORTSH_BIN"
25
-echo ""
26
-
27
-# Test 1: Basic command execution
28
-echo "Test 1: Basic command execution"
29
-echo "-------------------------------"
30
-result=$(echo "echo hello world" | "$FORTSH_BIN" 2>/dev/null | grep "hello world")
31
-if [[ "$result" == "hello world" ]]; then
32
-    echo "✅ Basic echo command works"
33
-else
34
-    echo "❌ Basic echo command failed"
35
-    echo "Expected: 'hello world', Got: '$result'"
36
-fi
37
-
38
-# Test 2: Variable expansion
39
-echo ""
40
-echo "Test 2: Variable expansion"
41
-echo "-------------------------"
42
-result=$(echo -e "TEST=fortsh\necho \$TEST" | "$FORTSH_BIN" 2>/dev/null | tail -1)
43
-if [[ "$result" == "fortsh" ]]; then
44
-    echo "✅ Variable expansion works"
45
-else
46
-    echo "❌ Variable expansion failed"
47
-    echo "Expected: 'fortsh', Got: '$result'"
48
-fi
49
-
50
-# Test 3: Glob pattern matching
51
-echo ""
52
-echo "Test 3: Glob pattern matching"
53
-echo "-----------------------------"
54
-result=$(echo "echo *.txt" | "$FORTSH_BIN" 2>/dev/null | grep -c "txt")
55
-if [[ "$result" -gt 0 ]]; then
56
-    echo "✅ Glob pattern matching works"
57
-else
58
-    echo "❌ Glob pattern matching failed"
59
-fi
60
-
61
-# Test 4: Here-string redirection
62
-echo ""
63
-echo "Test 4: Here-string redirection"
64
-echo "-------------------------------"
65
-result=$(echo "cat <<< hello" | "$FORTSH_BIN" 2>/dev/null)
66
-if [[ "$result" == "hello" ]]; then
67
-    echo "✅ Here-string redirection works"
68
-else
69
-    echo "❌ Here-string redirection failed"
70
-    echo "Expected: 'hello', Got: '$result'"
71
-fi
72
-
73
-# Test 5: For loop basic functionality
74
-echo ""
75
-echo "Test 5: For loop functionality"
76
-echo "------------------------------"
77
-result=$(echo -e "for i in a b c\ndo\necho item-\$i\ndone" | "$FORTSH_BIN" 2>/dev/null | head -1)
78
-if [[ "$result" == "item-a" ]]; then
79
-    echo "✅ For loop basic functionality works"
80
-else
81
-    echo "❌ For loop functionality failed"
82
-    echo "Expected: 'item-a', Got: '$result'"
83
-fi
84
-
85
-# Test 6: Built-in commands
86
-echo ""
87
-echo "Test 6: Built-in commands"
88
-echo "-------------------------"
89
-result=$(echo "pwd" | "$FORTSH_BIN" 2>/dev/null)
90
-if [[ -n "$result" ]]; then
91
-    echo "✅ Built-in commands work (pwd returned: $result)"
92
-else
93
-    echo "❌ Built-in commands failed"
94
-fi
95
-
96
-# Test 7: Alias functionality
97
-echo ""
98
-echo "Test 7: Alias functionality"
99
-echo "---------------------------"
100
-result=$(echo -e "alias ll='echo long-list'\nll" | "$FORTSH_BIN" 2>/dev/null | tail -1)
101
-if [[ "$result" == "long-list" ]]; then
102
-    echo "✅ Alias functionality works"
103
-else
104
-    echo "❌ Alias functionality failed"
105
-    echo "Expected: 'long-list', Got: '$result'"
106
-fi
107
-
108
-# Test 8: Error handling
109
-echo ""
110
-echo "Test 8: Error handling"
111
-echo "----------------------"
112
-result=$(echo "nonexistent_command_xyz123" | "$FORTSH_BIN" 2>&1 | grep -c "command not found")
113
-if [[ "$result" -gt 0 ]]; then
114
-    echo "✅ Error handling works"
115
-else
116
-    echo "❌ Error handling failed"
117
-fi
118
-
119
-echo ""
120
-echo "======================================"
121
-echo "Integration tests completed!"
122
-echo "======================================"
tests/posix_compliance_extended.shdeleted
@@ -1,368 +0,0 @@
1
-#!/bin/sh
2
-# =====================================
3
-# POSIX Compliance Extended Test Suite for fortsh
4
-# =====================================
5
-# Comprehensive POSIX compliance testing based on IEEE Std 1003.1-2017
6
-# This extends the basic test suite with additional coverage
7
-
8
-# Colors (POSIX-compliant way)
9
-RED='\033[0;31m'
10
-GREEN='\033[0;32m'
11
-YELLOW='\033[1;33m'
12
-BLUE='\033[0;34m'
13
-NC='\033[0m'
14
-
15
-PASSED=0
16
-FAILED=0
17
-SKIPPED=0
18
-
19
-# Get script directory (POSIX way)
20
-SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
21
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
22
-
23
-# Check if fortsh exists
24
-if [ ! -x "$FORTSH_BIN" ]; then
25
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
26
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
27
-    exit 1
28
-fi
29
-
30
-# Test result trackers
31
-pass() {
32
-    printf "${GREEN}✓ PASS${NC}: %s\n" "$1"
33
-    PASSED=$((PASSED + 1))
34
-}
35
-
36
-fail() {
37
-    printf "${RED}✗ FAIL${NC}: %s\n" "$1"
38
-    if [ -n "$2" ]; then
39
-        printf "  posix:  %s\n" "$2"
40
-    fi
41
-    if [ -n "$3" ]; then
42
-        printf "  fortsh: %s\n" "$3"
43
-    fi
44
-    FAILED=$((FAILED + 1))
45
-}
46
-
47
-skip() {
48
-    printf "${YELLOW}⊘ SKIP${NC}: %s - %s\n" "$1" "$2"
49
-    SKIPPED=$((SKIPPED + 1))
50
-}
51
-
52
-section() {
53
-    printf "\n"
54
-    printf "${BLUE}==========================================\n"
55
-    printf "%s\n" "$1"
56
-    printf "==========================================${NC}\n"
57
-}
58
-
59
-# Helper function to run command in both shells and compare
60
-compare_posix_output() {
61
-    test_name="$1"
62
-    command="$2"
63
-    posix_file="/tmp/posix_ext_$$_posix"
64
-    fortsh_file="/tmp/posix_ext_$$_fortsh"
65
-
66
-    # Run in POSIX shell (sh)
67
-    sh -c "$command" > "$posix_file" 2>&1 || true
68
-
69
-    # Run in fortsh
70
-    "$FORTSH_BIN" -c "$command" > "$fortsh_file" 2>&1 || true
71
-
72
-    # Compare outputs
73
-    if diff -q "$posix_file" "$fortsh_file" > /dev/null 2>&1; then
74
-        pass "$test_name"
75
-    else
76
-        fail "$test_name" "$(cat "$posix_file")" "$(cat "$fortsh_file")"
77
-    fi
78
-
79
-    rm -f "$posix_file" "$fortsh_file"
80
-}
81
-
82
-# Helper function to compare exit codes
83
-compare_posix_exit_code() {
84
-    test_name="$1"
85
-    command="$2"
86
-
87
-    sh -c "$command" > /dev/null 2>&1
88
-    posix_exit=$?
89
-
90
-    "$FORTSH_BIN" -c "$command" > /dev/null 2>&1
91
-    fortsh_exit=$?
92
-
93
-    if [ "$posix_exit" -eq "$fortsh_exit" ]; then
94
-        pass "$test_name"
95
-    else
96
-        fail "$test_name" "exit=$posix_exit" "exit=$fortsh_exit"
97
-    fi
98
-}
99
-
100
-# Cleanup
101
-cleanup() {
102
-    rm -f /tmp/posix_ext_$$_* 2>/dev/null
103
-    rm -f /tmp/posix_test_* 2>/dev/null
104
-    rm -rf /tmp/posix_test_dir 2>/dev/null
105
-}
106
-trap cleanup EXIT INT TERM
107
-
108
-# Setup test environment
109
-mkdir -p /tmp/posix_test_dir
110
-cd /tmp/posix_test_dir || exit 1
111
-
112
-section "26. EXTENDED TEST COMMAND - FILE TYPE TESTS"
113
-
114
-# Create test files with different properties
115
-touch /tmp/posix_test_regular
116
-chmod 644 /tmp/posix_test_regular
117
-echo "data" > /tmp/posix_test_nonempty
118
-mkdir -p /tmp/posix_test_directory
119
-mkfifo /tmp/posix_test_fifo 2>/dev/null || skip "mkfifo" "not available"
120
-ln -sf /tmp/posix_test_regular /tmp/posix_test_symlink 2>/dev/null
121
-
122
-compare_posix_exit_code "test -e exists" "test -e /tmp/posix_test_regular"
123
-compare_posix_exit_code "test -e nonexistent" "! test -e /tmp/nonexistent_xyz_$$"
124
-compare_posix_exit_code "test -f regular file" "test -f /tmp/posix_test_regular"
125
-compare_posix_exit_code "test -d directory" "test -d /tmp/posix_test_directory"
126
-compare_posix_exit_code "test -s non-empty" "test -s /tmp/posix_test_nonempty"
127
-compare_posix_exit_code "test -s empty" "! test -s /tmp/posix_test_regular"
128
-
129
-# Symlink tests (if supported)
130
-if [ -L /tmp/posix_test_symlink ]; then
131
-    compare_posix_exit_code "test -L symlink" "test -L /tmp/posix_test_symlink"
132
-    compare_posix_exit_code "test -h symlink" "test -h /tmp/posix_test_symlink"
133
-fi
134
-
135
-# FIFO tests (if created successfully)
136
-if [ -p /tmp/posix_test_fifo ]; then
137
-    compare_posix_exit_code "test -p fifo" "test -p /tmp/posix_test_fifo"
138
-fi
139
-
140
-section "27. EXTENDED TEST COMMAND - FILE PERMISSION TESTS"
141
-
142
-# Create files with specific permissions
143
-touch /tmp/posix_test_readable
144
-chmod 644 /tmp/posix_test_readable
145
-touch /tmp/posix_test_writable
146
-chmod 644 /tmp/posix_test_writable
147
-touch /tmp/posix_test_executable
148
-chmod 755 /tmp/posix_test_executable
149
-
150
-compare_posix_exit_code "test -r readable" "test -r /tmp/posix_test_readable"
151
-compare_posix_exit_code "test -w writable" "test -w /tmp/posix_test_writable"
152
-compare_posix_exit_code "test -x executable" "test -x /tmp/posix_test_executable"
153
-compare_posix_exit_code "test ! -x nonexec" "! test -x /tmp/posix_test_readable"
154
-
155
-section "28. EXTENDED TEST COMMAND - FILE COMPARISON"
156
-
157
-# Create files for comparison
158
-echo "old" > /tmp/posix_test_old
159
-sleep 1
160
-echo "new" > /tmp/posix_test_new
161
-ln -f /tmp/posix_test_old /tmp/posix_test_hardlink 2>/dev/null
162
-
163
-compare_posix_exit_code "test -nt newer than" "test /tmp/posix_test_new -nt /tmp/posix_test_old"
164
-compare_posix_exit_code "test -ot older than" "test /tmp/posix_test_old -ot /tmp/posix_test_new"
165
-
166
-# Hard link test (if supported)
167
-if [ -f /tmp/posix_test_hardlink ]; then
168
-    compare_posix_exit_code "test -ef same file" "test /tmp/posix_test_old -ef /tmp/posix_test_hardlink"
169
-fi
170
-
171
-section "29. EXTENDED TEST COMMAND - STRING TESTS"
172
-
173
-compare_posix_exit_code "test -n nonempty string" "test -n 'hello'"
174
-compare_posix_exit_code "test -z empty string" "test -z ''"
175
-compare_posix_exit_code "test string = equal" "test 'abc' = 'abc'"
176
-compare_posix_exit_code "test string != not equal" "test 'abc' != 'xyz'"
177
-compare_posix_exit_code "test unary string" "test 'hello'"
178
-compare_posix_exit_code "test ! negation" "! test -z 'hello'"
179
-
180
-section "30. EXTENDED TEST COMMAND - INTEGER COMPARISON"
181
-
182
-compare_posix_exit_code "test -eq equal" "test 42 -eq 42"
183
-compare_posix_exit_code "test -ne not equal" "test 42 -ne 13"
184
-compare_posix_exit_code "test -gt greater" "test 10 -gt 5"
185
-compare_posix_exit_code "test -ge greater or equal" "test 10 -ge 10"
186
-compare_posix_exit_code "test -lt less" "test 5 -lt 10"
187
-compare_posix_exit_code "test -le less or equal" "test 5 -le 5"
188
-compare_posix_exit_code "test negative numbers" "test -5 -lt 0"
189
-
190
-section "31. EXTENDED TEST COMMAND - LOGICAL OPERATORS"
191
-
192
-compare_posix_exit_code "test -a and" "test 5 -gt 3 -a 10 -gt 8"
193
-compare_posix_exit_code "test -o or" "test 5 -gt 10 -o 10 -gt 8"
194
-compare_posix_exit_code "test ! negation" "! test 5 -gt 10"
195
-compare_posix_exit_code "test ( ) grouping" "test \( 5 -gt 3 \) -a \( 10 -gt 8 \)"
196
-
197
-section "32. EXTENDED PARAMETER EXPANSION - DEFAULT VALUES"
198
-
199
-compare_posix_output "use default unset" 'unset VAR; echo "${VAR-default}"'
200
-compare_posix_output "use default null" 'VAR=; echo "${VAR-default}"'
201
-compare_posix_output "use default null colon" 'VAR=; echo "${VAR:-default}"'
202
-compare_posix_output "use default set" 'VAR=value; echo "${VAR-default}"'
203
-compare_posix_output "assign default unset" 'unset VAR; echo "${VAR=assigned}"; echo $VAR'
204
-compare_posix_output "assign default null colon" 'VAR=; echo "${VAR:=assigned}"; echo $VAR'
205
-
206
-section "33. EXTENDED PARAMETER EXPANSION - ERROR IF UNSET"
207
-
208
-compare_posix_exit_code "error if unset" 'unset VAR; echo "${VAR?error}" 2>/dev/null'
209
-compare_posix_exit_code "error if null colon" 'VAR=; echo "${VAR:?error}" 2>/dev/null'
210
-compare_posix_output "no error if set" 'VAR=value; echo "${VAR?error}"'
211
-
212
-section "34. EXTENDED PARAMETER EXPANSION - ALTERNATIVE VALUE"
213
-
214
-compare_posix_output "alt unset" 'unset VAR; echo "${VAR+alternative}"'
215
-compare_posix_output "alt null" 'VAR=; echo "${VAR+alternative}"'
216
-compare_posix_output "alt null colon" 'VAR=; echo "${VAR:+alternative}"'
217
-compare_posix_output "alt set" 'VAR=value; echo "${VAR+alternative}"'
218
-compare_posix_output "alt set colon" 'VAR=value; echo "${VAR:+alternative}"'
219
-
220
-section "35. EXTENDED PARAMETER EXPANSION - STRING LENGTH"
221
-
222
-compare_posix_output "length empty" 'VAR=; echo "${#VAR}"'
223
-compare_posix_output "length short" 'VAR=hi; echo "${#VAR}"'
224
-compare_posix_output "length long" 'VAR=hello world; echo "${#VAR}"'
225
-compare_posix_output "length special chars" 'VAR="a b c"; echo "${#VAR}"'
226
-
227
-section "36. EXTENDED PARAMETER EXPANSION - PATTERN REMOVAL"
228
-
229
-# Prefix removal
230
-compare_posix_output "prefix # simple" 'VAR=hello; echo "${VAR#hel}"'
231
-compare_posix_output "prefix # nomatch" 'VAR=hello; echo "${VAR#xyz}"'
232
-compare_posix_output "prefix # glob" 'VAR=foo.bar.baz; echo "${VAR#*.}"'
233
-compare_posix_output "prefix ## glob" 'VAR=foo.bar.baz; echo "${VAR##*.}"'
234
-compare_posix_output "prefix # star" 'VAR=/usr/local/bin; echo "${VAR#*/}"'
235
-compare_posix_output "prefix ## star" 'VAR=/usr/local/bin; echo "${VAR##*/}"'
236
-
237
-# Suffix removal
238
-compare_posix_output "suffix % simple" 'VAR=hello; echo "${VAR%lo}"'
239
-compare_posix_output "suffix % nomatch" 'VAR=hello; echo "${VAR%xyz}"'
240
-compare_posix_output "suffix % glob" 'VAR=foo.bar.baz; echo "${VAR%.*}"'
241
-compare_posix_output "suffix %% glob" 'VAR=foo.bar.baz; echo "${VAR%%.*}"'
242
-compare_posix_output "suffix % extension" 'VAR=file.tar.gz; echo "${VAR%.gz}"'
243
-compare_posix_output "suffix %% extension" 'VAR=file.tar.gz; echo "${VAR%%.*}"'
244
-
245
-section "37. ARITHMETIC EXPANSION - BASIC OPERATIONS"
246
-
247
-compare_posix_output "arith addition" 'echo $((5 + 3))'
248
-compare_posix_output "arith subtraction" 'echo $((10 - 4))'
249
-compare_posix_output "arith multiplication" 'echo $((6 * 7))'
250
-compare_posix_output "arith division" 'echo $((20 / 4))'
251
-compare_posix_output "arith modulo" 'echo $((17 % 5))'
252
-compare_posix_output "arith negative" 'echo $((-5 + 10))'
253
-compare_posix_output "arith zero" 'echo $((0 + 0))'
254
-
255
-section "38. ARITHMETIC EXPANSION - PRECEDENCE"
256
-
257
-compare_posix_output "arith precedence mult" 'echo $((2 + 3 * 4))'
258
-compare_posix_output "arith precedence paren" 'echo $(((2 + 3) * 4))'
259
-compare_posix_output "arith precedence div" 'echo $((10 - 8 / 2))'
260
-compare_posix_output "arith precedence complex" 'echo $((2 * 3 + 4 * 5))'
261
-
262
-section "39. ARITHMETIC EXPANSION - VARIABLES"
263
-
264
-compare_posix_output "arith var" 'X=5; echo $((X + 3))'
265
-compare_posix_output "arith var no dollar" 'X=10; Y=20; echo $((X + Y))'
266
-compare_posix_output "arith var assign" 'X=5; Y=$((X * 2)); echo $Y'
267
-compare_posix_output "arith var complex" 'A=3; B=4; echo $((A * A + B * B))'
268
-
269
-section "40. ARITHMETIC EXPANSION - COMPARISON"
270
-
271
-compare_posix_output "arith compare eq true" 'echo $((5 == 5))'
272
-compare_posix_output "arith compare eq false" 'echo $((5 == 3))'
273
-compare_posix_output "arith compare ne true" 'echo $((5 != 3))'
274
-compare_posix_output "arith compare ne false" 'echo $((5 != 5))'
275
-compare_posix_output "arith compare lt" 'echo $((3 < 5))'
276
-compare_posix_output "arith compare le" 'echo $((5 <= 5))'
277
-compare_posix_output "arith compare gt" 'echo $((7 > 5))'
278
-compare_posix_output "arith compare ge" 'echo $((5 >= 5))'
279
-
280
-section "41. ARITHMETIC EXPANSION - LOGICAL"
281
-
282
-compare_posix_output "arith logical and true" 'echo $((1 && 1))'
283
-compare_posix_output "arith logical and false" 'echo $((1 && 0))'
284
-compare_posix_output "arith logical or true" 'echo $((0 || 1))'
285
-compare_posix_output "arith logical or false" 'echo $((0 || 0))'
286
-compare_posix_output "arith logical not true" 'echo $((! 0))'
287
-compare_posix_output "arith logical not false" 'echo $((! 1))'
288
-
289
-section "42. SPECIAL PARAMETERS"
290
-
291
-compare_posix_output "\$\$ process id type" 'echo $$ | grep -c "^[0-9][0-9]*$"'
292
-compare_posix_output "\$- shell flags type" 'echo $- | grep -c "^[a-z]*$"'
293
-compare_posix_output "\$# arg count" 'set -- a b c; echo $#'
294
-compare_posix_output "\$1 first arg" 'set -- first second; echo $1'
295
-compare_posix_output "\$2 second arg" 'set -- first second; echo $2'
296
-compare_posix_output "\$9 ninth arg" 'set -- a b c d e f g h i j; echo $9'
297
-compare_posix_output "\$* all args" 'set -- a b c; echo $*'
298
-compare_posix_output "\$@ all args" 'set -- a b c; echo $@'
299
-
300
-section "43. ADDITIONAL POSIX BUILTINS - CD/PWD"
301
-
302
-compare_posix_output "cd to /tmp" 'cd /tmp && pwd'
303
-compare_posix_output "cd relative" 'cd /tmp && cd .. && pwd | grep -c "^/"'
304
-compare_posix_output "cd $HOME" 'cd && pwd | grep -c "^/"'
305
-
306
-section "44. ADDITIONAL POSIX BUILTINS - UNSET"
307
-
308
-compare_posix_output "unset variable" 'VAR=test; unset VAR; echo ${VAR:-unset}'
309
-compare_posix_output "unset nonexistent" 'unset NONEXISTENT_VAR_XYZ; echo ok'
310
-
311
-section "45. ADDITIONAL POSIX BUILTINS - EVAL"
312
-
313
-compare_posix_output "eval simple" 'CMD="echo hello"; eval $CMD'
314
-compare_posix_output "eval with var" 'X=5; CMD="echo \$X"; eval $CMD'
315
-compare_posix_output "eval complex" 'A=echo; B=test; eval $A $B'
316
-
317
-section "46. ADDITIONAL POSIX BUILTINS - COLON"
318
-
319
-compare_posix_output ": null command" ': ; echo ok'
320
-compare_posix_output ": with args" ': this is ignored; echo ok'
321
-compare_posix_exit_code ": exit status" ':'
322
-
323
-section "47. TILDE EXPANSION"
324
-
325
-compare_posix_output "tilde home" 'echo ~ | grep -c "^/"'
326
-compare_posix_output "tilde in path" 'echo ~/test | grep -c "^/"'
327
-
328
-section "48. FIELD SPLITTING - ADVANCED"
329
-
330
-compare_posix_output "IFS multiple fields" 'IFS=:; VAR="a:b:c:d"; set -- $VAR; echo $# $1 $4'
331
-compare_posix_output "IFS whitespace" 'IFS=" "; VAR="a b c"; set -- $VAR; echo $#'
332
-compare_posix_output "IFS comma" 'IFS=,; VAR="x,y,z"; set -- $VAR; echo $2'
333
-
334
-section "49. BACKGROUND JOBS"
335
-
336
-compare_posix_exit_code "background process" 'sleep 0.1 & wait'
337
-compare_posix_output "background exit" '(exit 0) & wait $!; echo $?'
338
-
339
-section "50. COMMAND GROUPING"
340
-
341
-compare_posix_output "subshell isolation" 'X=1; (X=2; echo $X); echo $X'
342
-compare_posix_output "brace grouping" 'X=1; { X=2; echo $X; }; echo $X'
343
-compare_posix_output "subshell exit" '(exit 5); echo $?'
344
-
345
-# Summary
346
-section "SUMMARY"
347
-printf "\n"
348
-printf "==========================================\n"
349
-printf "EXTENDED POSIX COMPLIANCE TEST RESULTS\n"
350
-printf "==========================================\n"
351
-printf "${GREEN}Passed:${NC}  %d\n" "$PASSED"
352
-printf "${RED}Failed:${NC}  %d\n" "$FAILED"
353
-printf "${YELLOW}Skipped:${NC} %d\n" "$SKIPPED"
354
-printf "Total:   %d\n" "$((PASSED + FAILED + SKIPPED))"
355
-printf "==========================================\n"
356
-
357
-if [ $((PASSED + FAILED)) -gt 0 ]; then
358
-    PASS_RATE=$((PASSED * 100 / (PASSED + FAILED)))
359
-    printf "Pass rate: %d%%\n" "$PASS_RATE"
360
-fi
361
-
362
-if [ "$FAILED" -eq 0 ]; then
363
-    printf "${GREEN}ALL EXTENDED POSIX TESTS PASSED!${NC} ✓\n"
364
-    exit 0
365
-else
366
-    printf "${RED}SOME TESTS FAILED${NC} ✗\n"
367
-    exit 1
368
-fi
tests/posix_compliance_test.shdeleted
@@ -1,327 +0,0 @@
1
-#!/bin/sh
2
-# =====================================
3
-# POSIX Compliance Test Suite for fortsh
4
-# =====================================
5
-# Tests compliance with POSIX shell specification
6
-# Uses /bin/sh for comparison (typically dash or bash in POSIX mode)
7
-
8
-# Note: Using only POSIX-compliant constructs in this script
9
-# No bash-isms allowed!
10
-
11
-# Colors (POSIX-compliant way)
12
-RED='\033[0;31m'
13
-GREEN='\033[0;32m'
14
-YELLOW='\033[1;33m'
15
-BLUE='\033[0;34m'
16
-NC='\033[0m'
17
-
18
-PASSED=0
19
-FAILED=0
20
-SKIPPED=0
21
-
22
-# Get script directory (POSIX way)
23
-SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
24
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
25
-
26
-# Check if fortsh exists
27
-if [ ! -x "$FORTSH_BIN" ]; then
28
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
29
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
30
-    exit 1
31
-fi
32
-
33
-# Test result trackers
34
-pass() {
35
-    printf "${GREEN}✓ PASS${NC}: %s\n" "$1"
36
-    PASSED=$((PASSED + 1))
37
-}
38
-
39
-fail() {
40
-    printf "${RED}✗ FAIL${NC}: %s\n" "$1"
41
-    if [ -n "$2" ]; then
42
-        printf "  posix:  %s\n" "$2"
43
-    fi
44
-    if [ -n "$3" ]; then
45
-        printf "  fortsh: %s\n" "$3"
46
-    fi
47
-    FAILED=$((FAILED + 1))
48
-}
49
-
50
-skip() {
51
-    printf "${YELLOW}⊘ SKIP${NC}: %s - %s\n" "$1" "$2"
52
-    SKIPPED=$((SKIPPED + 1))
53
-}
54
-
55
-section() {
56
-    printf "\n"
57
-    printf "${BLUE}==========================================\n"
58
-    printf "%s\n" "$1"
59
-    printf "==========================================${NC}\n"
60
-}
61
-
62
-# Helper function to run command in both shells and compare
63
-compare_posix_output() {
64
-    test_name="$1"
65
-    command="$2"
66
-    posix_file="/tmp/posix_comp_$$_posix"
67
-    fortsh_file="/tmp/posix_comp_$$_fortsh"
68
-
69
-    # Run in POSIX shell (sh)
70
-    sh -c "$command" > "$posix_file" 2>&1 || true
71
-
72
-    # Run in fortsh
73
-    "$FORTSH_BIN" -c "$command" > "$fortsh_file" 2>&1 || true
74
-
75
-    # Compare outputs
76
-    if diff -q "$posix_file" "$fortsh_file" > /dev/null 2>&1; then
77
-        pass "$test_name"
78
-    else
79
-        fail "$test_name" "$(cat "$posix_file")" "$(cat "$fortsh_file")"
80
-    fi
81
-
82
-    rm -f "$posix_file" "$fortsh_file"
83
-}
84
-
85
-# Helper function to compare exit codes
86
-compare_posix_exit_code() {
87
-    test_name="$1"
88
-    command="$2"
89
-
90
-    sh -c "$command" > /dev/null 2>&1
91
-    posix_exit=$?
92
-
93
-    "$FORTSH_BIN" -c "$command" > /dev/null 2>&1
94
-    fortsh_exit=$?
95
-
96
-    if [ "$posix_exit" -eq "$fortsh_exit" ]; then
97
-        pass "$test_name"
98
-    else
99
-        fail "$test_name" "exit=$posix_exit" "exit=$fortsh_exit"
100
-    fi
101
-}
102
-
103
-# Cleanup
104
-cleanup() {
105
-    rm -f /tmp/posix_comp_$$_* 2>/dev/null
106
-    rm -f /tmp/posix_test_* 2>/dev/null
107
-}
108
-trap cleanup EXIT INT TERM
109
-
110
-section "1. POSIX BASIC COMMANDS"
111
-
112
-compare_posix_output "echo simple" "echo hello"
113
-compare_posix_output "echo with args" "echo one two three"
114
-compare_posix_output "printf basic" "printf 'test\n'"
115
-compare_posix_output "printf with args" "printf '%s %d\n' hello 42"
116
-
117
-section "2. POSIX VARIABLE EXPANSION"
118
-
119
-compare_posix_output "simple variable" "VAR=test; echo \$VAR"
120
-compare_posix_output "variable in quotes" 'VAR=test; echo "$VAR"'
121
-compare_posix_output "multiple vars" "A=hello; B=world; echo \$A \$B"
122
-compare_posix_output "undefined variable" "echo \$UNDEFINED_VAR_XYZ_987"
123
-
124
-section "3. POSIX PARAMETER EXPANSION"
125
-
126
-# Basic parameter expansion
127
-compare_posix_output "default value" 'echo "${UNSET:-default}"'
128
-compare_posix_output "assign default" 'UNSET=; echo "${UNSET:=assigned}"; echo $UNSET'
129
-compare_posix_output "error if unset" 'echo "${VAR:+alternative}"'
130
-compare_posix_output "string length" 'VAR=hello; echo "${#VAR}"'
131
-
132
-# Prefix removal (# and ##)
133
-compare_posix_output "remove shortest prefix" 'VAR=foo.bar.baz; echo "${VAR#*.}"'
134
-compare_posix_output "remove longest prefix" 'VAR=foo.bar.baz; echo "${VAR##*.}"'
135
-compare_posix_output "prefix no match" 'VAR=hello; echo "${VAR#x*}"'
136
-compare_posix_output "prefix remove slash" 'VAR=/usr/local/bin; echo "${VAR#/*/}"'
137
-
138
-# Suffix removal (% and %%)
139
-compare_posix_output "remove shortest suffix" 'VAR=foo.bar.baz; echo "${VAR%.*}"'
140
-compare_posix_output "remove longest suffix" 'VAR=foo.bar.baz; echo "${VAR%%.*}"'
141
-compare_posix_output "suffix no match" 'VAR=hello; echo "${VAR%x*}"'
142
-compare_posix_output "suffix remove extension" 'VAR=file.tar.gz; echo "${VAR%.gz}"'
143
-
144
-section "4. POSIX COMMAND SUBSTITUTION"
145
-
146
-compare_posix_output "backtick substitution" 'echo `echo test`'
147
-compare_posix_output "dollar paren substitution" "echo \$(echo test)"
148
-compare_posix_output "nested substitution" "echo \$(echo \$(echo nested))"
149
-
150
-section "5. POSIX ARITHMETIC"
151
-
152
-# POSIX arithmetic uses expr or $(( ))
153
-compare_posix_output "expr addition" "expr 5 + 3"
154
-compare_posix_output "expr multiplication" "expr 4 \* 3"
155
-compare_posix_output "expr division" "expr 15 / 3"
156
-
157
-section "6. POSIX REDIRECTION"
158
-
159
-compare_posix_output "output redirect" "echo test > /tmp/posix_test_out; cat /tmp/posix_test_out"
160
-compare_posix_output "append redirect" "echo line1 > /tmp/posix_test_app; echo line2 >> /tmp/posix_test_app; wc -l < /tmp/posix_test_app"
161
-compare_posix_output "input redirect" "echo input > /tmp/posix_test_in; cat < /tmp/posix_test_in"
162
-compare_posix_output "stderr redirect" "ls /nonexistent 2>&1 | grep -c 'cannot access\|No such\|not found'"
163
-
164
-section "7. POSIX PIPELINES"
165
-
166
-compare_posix_output "simple pipe" "echo hello | cat"
167
-compare_posix_output "two-stage pipe" "echo test | cat | tr t T"
168
-compare_posix_output "pipe with filter" "printf 'a\nb\nc\n' | grep b"
169
-
170
-section "8. POSIX TEST COMMAND"
171
-
172
-compare_posix_exit_code "test -f file" "touch /tmp/posix_test_file && test -f /tmp/posix_test_file"
173
-compare_posix_exit_code "test -d directory" "test -d /tmp"
174
-compare_posix_exit_code "test -n nonempty" "test -n 'hello'"
175
-compare_posix_exit_code "test -z empty" "test -z ''"
176
-compare_posix_exit_code "test string =" "test 'hello' = 'hello'"
177
-compare_posix_exit_code "test string !=" "test 'hello' != 'world'"
178
-compare_posix_exit_code "test number -eq" "test 5 -eq 5"
179
-compare_posix_exit_code "test number -ne" "test 5 -ne 3"
180
-compare_posix_exit_code "test number -gt" "test 5 -gt 3"
181
-compare_posix_exit_code "test number -ge" "test 5 -ge 5"
182
-compare_posix_exit_code "test number -lt" "test 3 -lt 5"
183
-compare_posix_exit_code "test number -le" "test 3 -le 3"
184
-
185
-section "9. POSIX CONDITIONALS"
186
-
187
-compare_posix_output "if true" "if true; then echo yes; fi"
188
-compare_posix_output "if false else" "if false; then echo no; else echo yes; fi"
189
-compare_posix_output "if-elif-else" "X=2; if [ \$X -eq 1 ]; then echo one; elif [ \$X -eq 2 ]; then echo two; else echo other; fi"
190
-
191
-section "10. POSIX LOOPS"
192
-
193
-compare_posix_output "for loop" "for i in a b c; do echo \$i; done"
194
-compare_posix_output "while loop" "i=3; while [ \$i -gt 0 ]; do echo \$i; i=\$((i - 1)); done"
195
-compare_posix_output "until loop" "i=1; until [ \$i -gt 3 ]; do echo \$i; i=\$((i + 1)); done"
196
-
197
-section "11. POSIX CASE STATEMENT"
198
-
199
-compare_posix_output "case exact match" "x=2; case \$x in 1) echo one;; 2) echo two;; esac"
200
-compare_posix_output "case pattern match" "x=hello; case \$x in h*) echo h_prefix;; esac"
201
-compare_posix_output "case default" "x=z; case \$x in a) echo a;; b) echo b;; *) echo default;; esac"
202
-compare_posix_output "case multiple patterns" "x=b; case \$x in a|b|c) echo abc;; *) echo other;; esac"
203
-
204
-section "12. POSIX FUNCTIONS"
205
-
206
-compare_posix_output "simple function" "func() { echo hello; }; func"
207
-compare_posix_output "function with args" "func() { echo \$1 \$2; }; func foo bar"
208
-compare_posix_output "function return" "func() { return 42; }; func; echo \$?"
209
-compare_posix_output "function \$# args" "func() { echo \$#; }; func a b c"
210
-
211
-section "13. POSIX SPECIAL VARIABLES"
212
-
213
-compare_posix_output "\$? exit status" "true; echo \$?"
214
-compare_posix_output "\$? after false" "false; echo \$?"
215
-compare_posix_output "\$# argument count" "set -- a b c; echo \$#"
216
-compare_posix_output "\$@ all arguments" "set -- a b c; echo \$@"
217
-compare_posix_output "\$* all arguments" "set -- a b c; echo \$*"
218
-compare_posix_output "\$0 script name" "echo \$0 | grep -c sh"
219
-
220
-section "14. POSIX LOGICAL OPERATORS"
221
-
222
-compare_posix_exit_code "true && true" "true && true"
223
-compare_posix_exit_code "true && false" "true && false"
224
-compare_posix_exit_code "false || true" "false || true"
225
-compare_posix_exit_code "false || false" "false || false"
226
-compare_posix_output "command && echo" "true && echo success"
227
-compare_posix_output "command || echo" "false || echo fallback"
228
-compare_posix_output "! negation" "! false && echo negated"
229
-
230
-section "15. POSIX QUOTING"
231
-
232
-compare_posix_output "single quote literal" "echo '\$VAR'"
233
-compare_posix_output "double quote expand" 'VAR=test; echo "$VAR"'
234
-compare_posix_output "escape in double" 'echo "test\$var"'
235
-compare_posix_output "backslash escape" 'echo test\ word'
236
-
237
-section "16. POSIX SUBSHELLS"
238
-
239
-compare_posix_output "subshell grouping" "(echo a; echo b) | wc -l"
240
-compare_posix_output "subshell var isolation" "(VAR=inner; echo \$VAR); echo \$VAR"
241
-
242
-section "17. POSIX COMPOUND COMMANDS"
243
-
244
-compare_posix_output "command grouping {}" "{ echo a; echo b; } | wc -l"
245
-compare_posix_output "command list ;" "echo a; echo b"
246
-
247
-section "18. POSIX HERE DOCUMENTS"
248
-
249
-compare_posix_output "simple heredoc" "cat <<EOF
250
-line1
251
-line2
252
-EOF"
253
-
254
-compare_posix_output "heredoc with vars" "VAR=test; cat <<EOF
255
-value=\$VAR
256
-EOF"
257
-
258
-compare_posix_output "quoted heredoc" "cat <<'EOF'
259
-\$VAR
260
-EOF"
261
-
262
-section "19. POSIX WORD EXPANSION ORDER"
263
-
264
-# POSIX specifies: tilde, parameter, command subst, arithmetic, field splitting, pathname, quote removal
265
-compare_posix_output "expansion order" "VAR='a b'; echo \$VAR"
266
-compare_posix_output "quoted expansion" 'VAR="a b"; echo "$VAR"'
267
-
268
-section "20. POSIX PATHNAME EXPANSION (GLOBBING)"
269
-
270
-# Setup test files
271
-mkdir -p /tmp/posix_test_glob
272
-touch /tmp/posix_test_glob/a.txt /tmp/posix_test_glob/b.txt /tmp/posix_test_glob/c.dat
273
-
274
-compare_posix_output "glob * pattern" "ls /tmp/posix_test_glob/*.txt 2>/dev/null | wc -l"
275
-compare_posix_output "glob ? pattern" "ls /tmp/posix_test_glob/?.txt 2>/dev/null | wc -l"
276
-compare_posix_output "glob [abc] pattern" "ls /tmp/posix_test_glob/[ab].txt 2>/dev/null | wc -l"
277
-
278
-section "21. POSIX FIELD SPLITTING (IFS)"
279
-
280
-compare_posix_output "default IFS" "VAR='a b c'; set -- \$VAR; echo \$#"
281
-compare_posix_output "custom IFS" "IFS=:; VAR='a:b:c'; set -- \$VAR; echo \$1"
282
-
283
-section "22. POSIX EXIT STATUS"
284
-
285
-compare_posix_exit_code "true exit status" "true"
286
-compare_posix_exit_code "false exit status" "false"
287
-compare_posix_exit_code "command not found" "nonexistent_command_xyz 2>/dev/null"
288
-compare_posix_exit_code "return from function" "func() { return 3; }; func"
289
-
290
-section "23. POSIX SET BUILTIN"
291
-
292
-compare_posix_output "set positional" "set -- a b c; echo \$1 \$2 \$3"
293
-compare_posix_output "set shift" "set -- a b c; shift; echo \$1"
294
-compare_posix_output "set shift n" "set -- a b c d; shift 2; echo \$1"
295
-
296
-section "24. POSIX EXPORT"
297
-
298
-compare_posix_output "export variable" "export VAR=test; sh -c 'echo \$VAR'"
299
-
300
-section "25. POSIX READONLY"
301
-
302
-compare_posix_exit_code "readonly assignment" "readonly VAR=test; VAR=new 2>/dev/null"
303
-
304
-# Summary
305
-section "SUMMARY"
306
-printf "\n"
307
-printf "==========================================\n"
308
-printf "POSIX COMPLIANCE TEST RESULTS\n"
309
-printf "==========================================\n"
310
-printf "${GREEN}Passed:${NC}  %d\n" "$PASSED"
311
-printf "${RED}Failed:${NC}  %d\n" "$FAILED"
312
-printf "${YELLOW}Skipped:${NC} %d\n" "$SKIPPED"
313
-printf "Total:   %d\n" "$((PASSED + FAILED + SKIPPED))"
314
-printf "==========================================\n"
315
-
316
-if [ $((PASSED + FAILED)) -gt 0 ]; then
317
-    PASS_RATE=$((PASSED * 100 / (PASSED + FAILED)))
318
-    printf "Pass rate: %d%%\n" "$PASS_RATE"
319
-fi
320
-
321
-if [ "$FAILED" -eq 0 ]; then
322
-    printf "${GREEN}ALL POSIX COMPLIANCE TESTS PASSED!${NC} ✓\n"
323
-    exit 0
324
-else
325
-    printf "${RED}SOME TESTS FAILED${NC} ✗\n"
326
-    exit 1
327
-fi
tests/test_array_enhanced.shdeleted
@@ -1,148 +0,0 @@
1
-#!/bin/bash
2
-# Comprehensive test suite for enhanced array features
3
-# Tests: indices expansion, array slicing, and their combinations
4
-
5
-echo "=== Enhanced Array Features Test Suite ==="
6
-echo ""
7
-
8
-# Test 1: Array indices expansion
9
-echo "TEST 1: Array Indices Expansion"
10
-echo "================================"
11
-declare -a test1
12
-test1[0]=alpha
13
-test1[1]=beta
14
-test1[2]=gamma
15
-indices1="${!test1[@]}"
16
-echo "Array: ${test1[@]}"
17
-echo "Indices: $indices1"
18
-[ "$indices1" = "0 1 2" ] && echo "✓ PASS" || echo "✗ FAIL"
19
-echo ""
20
-
21
-# Test 2: Sparse array indices
22
-echo "TEST 2: Sparse Array Indices"
23
-echo "============================"
24
-declare -a test2
25
-test2[1]=one
26
-test2[5]=five
27
-test2[10]=ten
28
-indices2="${!test2[@]}"
29
-echo "Sparse array: ${test2[@]}"
30
-echo "Indices: $indices2"
31
-[ "$indices2" = "1 5 10" ] && echo "✓ PASS" || echo "✗ FAIL"
32
-echo ""
33
-
34
-# Test 3: Basic array slicing
35
-echo "TEST 3: Basic Array Slicing"
36
-echo "==========================="
37
-declare -a test3
38
-test3=(a b c d e f g)
39
-slice3="${test3[@]:2:3}"
40
-echo "Full array: ${test3[@]}"
41
-echo "Slice [2:3]: $slice3"
42
-[ "$slice3" = "c d e" ] && echo "✓ PASS" || echo "✗ FAIL"
43
-echo ""
44
-
45
-# Test 4: Slice from offset to end
46
-echo "TEST 4: Slice to End"
47
-echo "===================="
48
-declare -a test4
49
-test4=(one two three four five)
50
-slice4="${test4[@]:3}"
51
-echo "Full array: ${test4[@]}"
52
-echo "Slice [3:]: $slice4"
53
-[ "$slice4" = "four five" ] && echo "✓ PASS" || echo "✗ FAIL"
54
-echo ""
55
-
56
-# Test 5: Slice from start
57
-echo "TEST 5: Slice from Start"
58
-echo "========================"
59
-declare -a test5
60
-test5=(red orange yellow green blue)
61
-slice5="${test5[@]:0:2}"
62
-echo "Full array: ${test5[@]}"
63
-echo "Slice [0:2]: $slice5"
64
-[ "$slice5" = "red orange" ] && echo "✓ PASS" || echo "✗ FAIL"
65
-echo ""
66
-
67
-# Test 6: Single element slice
68
-echo "TEST 6: Single Element Slice"
69
-echo "============================"
70
-declare -a test6
71
-test6=(apple banana cherry date)
72
-slice6="${test6[@]:1:1}"
73
-echo "Full array: ${test6[@]}"
74
-echo "Slice [1:1]: $slice6"
75
-[ "$slice6" = "banana" ] && echo "✓ PASS" || echo "✗ FAIL"
76
-echo ""
77
-
78
-# Test 7: Array length with indices
79
-echo "TEST 7: Count of Array Indices"
80
-echo "==============================="
81
-declare -a test7
82
-test7=(x y z)
83
-indices7="${!test7[@]}"
84
-count7=$(echo $indices7 | wc -w)
85
-echo "Array: ${test7[@]}"
86
-echo "Indices: $indices7"
87
-echo "Count: $count7"
88
-[ "$count7" = "3" ] && echo "✓ PASS" || echo "✗ FAIL"
89
-echo ""
90
-
91
-# Test 8: Combining indices and slicing
92
-echo "TEST 8: Slice of Indices (conceptual)"
93
-echo "====================================="
94
-declare -a test8
95
-test8[2]=item2
96
-test8[4]=item4
97
-test8[6]=item6
98
-test8[8]=item8
99
-all_indices="${!test8[@]}"
100
-echo "Array: ${test8[@]}"
101
-echo "All indices: $all_indices"
102
-echo "Note: Can iterate and work with indices"
103
-for idx in ${!test8[@]}; do
104
-  echo "  Index $idx = ${test8[$idx]}"
105
-done
106
-echo "✓ PASS"
107
-echo ""
108
-
109
-# Test 9: Modify and check indices
110
-echo "TEST 9: Modify and Check Indices"
111
-echo "================================="
112
-declare -a test9
113
-test9[0]=first
114
-test9[1]=second
115
-test9[2]=third
116
-before_indices="${!test9[@]}"
117
-echo "Before: indices=$before_indices, values=${test9[@]}"
118
-test9[1]=MODIFIED
119
-after_indices="${!test9[@]}"
120
-echo "After:  indices=$after_indices, values=${test9[@]}"
121
-[ "$before_indices" = "$after_indices" ] && echo "✓ PASS (indices unchanged)" || echo "✗ FAIL"
122
-echo ""
123
-
124
-# Test 10: Slice with excessive length
125
-echo "TEST 10: Slice with Excessive Length"
126
-echo "====================================="
127
-declare -a test10
128
-test10=(a b c)
129
-slice10="${test10[@]:1:100}"
130
-echo "Full array (3 elements): ${test10[@]}"
131
-echo "Slice [1:100]: $slice10"
132
-[ "$slice10" = "b c" ] && echo "✓ PASS (clamped to array bounds)" || echo "✗ FAIL"
133
-echo ""
134
-
135
-# Summary
136
-echo "=========================================="
137
-echo "Enhanced Array Features Test Suite Complete"
138
-echo "=========================================="
139
-echo ""
140
-echo "Features Tested:"
141
-echo "  ✓ Array indices expansion (${!array[@]})"
142
-echo "  ✓ Sparse array indices"
143
-echo "  ✓ Array slicing (${array[@]:offset:length})"
144
-echo "  ✓ Slice from offset to end"
145
-echo "  ✓ Slice from start"
146
-echo "  ✓ Single element slicing"
147
-echo "  ✓ Combining features"
148
-echo "  ✓ Boundary conditions"
tests/test_array_indices.shdeleted
@@ -1,68 +0,0 @@
1
-#!/bin/bash
2
-# Test array indices expansion ${!array[@]}
3
-
4
-echo "=== Array Indices Expansion Tests ==="
5
-
6
-# Test 1: Get indices from simple array
7
-echo ""
8
-echo "Test 1: Simple array indices"
9
-declare -a myarray
10
-myarray[0]=apple
11
-myarray[1]=banana
12
-myarray[2]=cherry
13
-indices="${!myarray[@]}"
14
-echo "Array: ${myarray[@]}"
15
-echo "Indices: $indices"
16
-if [ "$indices" = "0 1 2" ]; then
17
-  echo "Simple array indices: PASS"
18
-else
19
-  echo "Simple array indices: FAIL (expected '0 1 2', got '$indices')"
20
-fi
21
-
22
-# Test 2: Get indices from sparse array
23
-echo ""
24
-echo "Test 2: Sparse array indices"
25
-declare -a sparse
26
-sparse[0]=first
27
-sparse[5]=sixth
28
-sparse[10]=eleventh
29
-sparse_indices="${!sparse[@]}"
30
-echo "Sparse array: ${sparse[@]}"
31
-echo "Sparse indices: $sparse_indices"
32
-if [ "$sparse_indices" = "0 5 10" ]; then
33
-  echo "Sparse array indices: PASS"
34
-else
35
-  echo "Sparse array indices: FAIL (expected '0 5 10', got '$sparse_indices')"
36
-fi
37
-
38
-# Test 3: Get count of array indices
39
-echo ""
40
-echo "Test 3: Count of array indices"
41
-declare -a counted
42
-counted[1]=one
43
-counted[2]=two
44
-counted[3]=three
45
-count_indices="${!counted[@]}"
46
-num_indices=$(echo $count_indices | wc -w)
47
-echo "Array indices: $count_indices"
48
-echo "Number of indices: $num_indices"
49
-if [ "$num_indices" = "3" ]; then
50
-  echo "Count of indices: PASS"
51
-else
52
-  echo "Count of indices: FAIL (expected 3, got $num_indices)"
53
-fi
54
-
55
-# Test 4: Iteration over array indices
56
-echo ""
57
-echo "Test 4: Iterate over array indices"
58
-declare -a items
59
-items[10]=ten
60
-items[20]=twenty
61
-items[30]=thirty
62
-echo "Iterating over indices:"
63
-for idx in ${!items[@]}; do
64
-  echo "  Index $idx: ${items[$idx]}"
65
-done
66
-
67
-echo ""
68
-echo "=== Array Indices Tests Complete ==="
tests/test_array_slicing.shdeleted
@@ -1,88 +0,0 @@
1
-#!/bin/bash
2
-# Test array slicing ${array[@]:offset:length}
3
-
4
-echo "=== Array Slicing Tests ==="
5
-
6
-# Test 1: Basic array slicing with offset and length
7
-echo ""
8
-echo "Test 1: Basic array slicing"
9
-declare -a fruits
10
-fruits=(apple banana cherry date elderberry fig grape)
11
-echo "Full array: ${fruits[@]}"
12
-slice1="${fruits[@]:1:3}"
13
-echo "Slice [1:3]: $slice1"
14
-if [ "$slice1" = "banana cherry date" ]; then
15
-  echo "Basic slicing: PASS"
16
-else
17
-  echo "Basic slicing: FAIL (expected 'banana cherry date', got '$slice1')"
18
-fi
19
-
20
-# Test 2: Slice from offset to end (no length)
21
-echo ""
22
-echo "Test 2: Slice from offset to end"
23
-declare -a numbers
24
-numbers=(one two three four five)
25
-echo "Full array: ${numbers[@]}"
26
-slice2="${numbers[@]:2}"
27
-echo "Slice [2:]: $slice2"
28
-if [ "$slice2" = "three four five" ]; then
29
-  echo "Slice to end: PASS"
30
-else
31
-  echo "Slice to end: FAIL (expected 'three four five', got '$slice2')"
32
-fi
33
-
34
-# Test 3: Slice with length exceeding array size
35
-echo ""
36
-echo "Test 3: Slice with excessive length"
37
-declare -a colors
38
-colors=(red green blue)
39
-echo "Full array: ${colors[@]}"
40
-slice3="${colors[@]:1:10}"
41
-echo "Slice [1:10]: $slice3"
42
-if [ "$slice3" = "green blue" ]; then
43
-  echo "Excessive length: PASS"
44
-else
45
-  echo "Excessive length: FAIL (expected 'green blue', got '$slice3')"
46
-fi
47
-
48
-# Test 4: Slice from start
49
-echo ""
50
-echo "Test 4: Slice from start"
51
-declare -a letters
52
-letters=(a b c d e f)
53
-echo "Full array: ${letters[@]}"
54
-slice4="${letters[@]:0:3}"
55
-echo "Slice [0:3]: $slice4"
56
-if [ "$slice4" = "a b c" ]; then
57
-  echo "Slice from start: PASS"
58
-else
59
-  echo "Slice from start: FAIL (expected 'a b c', got '$slice4')"
60
-fi
61
-
62
-# Test 5: Single element slice
63
-echo ""
64
-echo "Test 5: Single element slice"
65
-declare -a words
66
-words=(hello world foo bar)
67
-echo "Full array: ${words[@]}"
68
-slice5="${words[@]:2:1}"
69
-echo "Slice [2:1]: $slice5"
70
-if [ "$slice5" = "foo" ]; then
71
-  echo "Single element: PASS"
72
-else
73
-  echo "Single element: FAIL (expected 'foo', got '$slice5')"
74
-fi
75
-
76
-# Test 6: Iteration over sliced array
77
-echo ""
78
-echo "Test 6: Iterate over sliced array"
79
-declare -a data
80
-data=(item1 item2 item3 item4 item5)
81
-echo "Full array: ${data[@]}"
82
-echo "Iterating over slice [1:2]:"
83
-for item in ${data[@]:1:2}; do
84
-  echo "  - $item"
85
-done
86
-
87
-echo ""
88
-echo "=== Array Slicing Tests Complete ==="
tests/test_arrays.shdeleted
@@ -1,82 +0,0 @@
1
-#!/bin/bash
2
-# Test array functionality
3
-
4
-echo "=== Array Tests ==="
5
-
6
-# Test 1: Array declaration
7
-echo "Test 1: Array declaration"
8
-declare -a myarray
9
-echo "Array declared: PASS"
10
-
11
-# Test 2: Array assignment
12
-echo ""
13
-echo "Test 2: Array assignment"
14
-myarray[0]=apple
15
-myarray[1]=banana
16
-myarray[2]=cherry
17
-echo "Array elements assigned: PASS"
18
-
19
-# Test 3: Array element access
20
-echo ""
21
-echo "Test 3: Array element access"
22
-echo "myarray[0] = ${myarray[0]}"
23
-echo "myarray[1] = ${myarray[1]}"
24
-echo "myarray[2] = ${myarray[2]}"
25
-if [ "${myarray[0]}" = "apple" ]; then
26
-  echo "Element access: PASS"
27
-else
28
-  echo "Element access: FAIL"
29
-fi
30
-
31
-# Test 4: Array length
32
-echo ""
33
-echo "Test 4: Array length"
34
-length=${#myarray[@]}
35
-echo "Array length = $length"
36
-if [ "$length" = "3" ]; then
37
-  echo "Array length: PASS"
38
-else
39
-  echo "Array length: FAIL (expected 3, got $length)"
40
-fi
41
-
42
-# Test 5: All elements expansion
43
-echo ""
44
-echo "Test 5: All elements expansion"
45
-echo "All elements: ${myarray[@]}"
46
-all="${myarray[@]}"
47
-if [ "$all" = "apple banana cherry" ]; then
48
-  echo "All elements: PASS"
49
-else
50
-  echo "All elements: FAIL (got: $all)"
51
-fi
52
-
53
-# Test 6: Sparse array
54
-echo ""
55
-echo "Test 6: Sparse array"
56
-declare -a sparse
57
-sparse[0]=first
58
-sparse[5]=sixth
59
-sparse[10]=eleventh
60
-echo "sparse[0] = ${sparse[0]}"
61
-echo "sparse[5] = ${sparse[5]}"
62
-echo "sparse[10] = ${sparse[10]}"
63
-echo "Sparse array length: ${#sparse[@]}"
64
-
65
-# Test 7: Mixed assignment and access
66
-echo ""
67
-echo "Test 7: Mixed operations"
68
-declare -a mixed
69
-mixed[0]=one
70
-mixed[1]=two
71
-mixed[2]=three
72
-echo "Initial: ${mixed[@]}"
73
-mixed[1]=TWO
74
-echo "After modification: ${mixed[@]}"
75
-if [ "${mixed[1]}" = "TWO" ]; then
76
-  echo "Mixed operations: PASS"
77
-else
78
-  echo "Mixed operations: FAIL"
79
-fi
80
-
81
-echo ""
82
-echo "=== Array Tests Complete ==="
tests/test_ast.f90deleted
@@ -1,220 +0,0 @@
1
-! ==============================================================================
2
-! Test program for AST-based execution model
3
-! Demonstrates how nested loops and break/continue would work
4
-! ==============================================================================
5
-program test_ast
6
-  use ast_types
7
-  use lexer
8
-  use parser
9
-  use evaluator
10
-  use shell_types
11
-  implicit none
12
-
13
-  ! Test nested loops with break
14
-  call test_nested_loops_with_break()
15
-
16
-  ! Test for loop with continue
17
-  call test_for_loop_with_continue()
18
-
19
-  ! Test proper parsing
20
-  call test_parser()
21
-
22
-contains
23
-
24
-  subroutine test_nested_loops_with_break()
25
-    character(:), allocatable :: script
26
-    type(lexer_t) :: lex
27
-    type(parser_t) :: pars
28
-    type(evaluator_t) :: eval
29
-    type(shell_state_t) :: shell
30
-    type(script_node_t) :: ast
31
-    integer :: exit_code
32
-
33
-    print *, "=== Test: Nested loops with break ==="
34
-
35
-    ! Script with nested loops and break
36
-    script = &
37
-      'for i in 1 2 3' // char(10) // &
38
-      'do' // char(10) // &
39
-      '  echo "Outer: $i"' // char(10) // &
40
-      '  for j in a b c' // char(10) // &
41
-      '  do' // char(10) // &
42
-      '    echo "  Inner: $j"' // char(10) // &
43
-      '    [ "$j" = "b" ] && break' // char(10) // &
44
-      '  done' // char(10) // &
45
-      '  echo "Back in outer"' // char(10) // &
46
-      'done'
47
-
48
-    ! Tokenize
49
-    call lex%init(script)
50
-    call lex%tokenize()
51
-
52
-    print *, "Tokens generated: ", lex%token_count
53
-
54
-    ! Parse
55
-    call pars%init(lex%tokens, lex%token_count)
56
-    ast = pars%parse()
57
-
58
-    print *, "AST built successfully"
59
-
60
-    ! Evaluate
61
-    call eval%init(shell)
62
-    exit_code = eval%eval(ast)
63
-
64
-    print *, "Exit code: ", exit_code
65
-    print *, ""
66
-
67
-    ! Clean up
68
-    call lex%destroy()
69
-    call pars%destroy()
70
-    call eval%destroy()
71
-  end subroutine test_nested_loops_with_break
72
-
73
-  subroutine test_for_loop_with_continue()
74
-    character(:), allocatable :: script
75
-    type(lexer_t) :: lex
76
-    type(parser_t) :: pars
77
-    type(evaluator_t) :: eval
78
-    type(shell_state_t) :: shell
79
-    type(script_node_t) :: ast
80
-    integer :: exit_code
81
-
82
-    print *, "=== Test: For loop with continue ==="
83
-
84
-    script = &
85
-      'for i in 1 2 3 4 5' // char(10) // &
86
-      'do' // char(10) // &
87
-      '  [ "$i" = "3" ] && continue' // char(10) // &
88
-      '  echo "Processing: $i"' // char(10) // &
89
-      'done'
90
-
91
-    ! Tokenize
92
-    call lex%init(script)
93
-    call lex%tokenize()
94
-
95
-    ! Parse
96
-    call pars%init(lex%tokens, lex%token_count)
97
-    ast = pars%parse()
98
-
99
-    ! Evaluate
100
-    call eval%init(shell)
101
-    exit_code = eval%eval(ast)
102
-
103
-    print *, "Exit code: ", exit_code
104
-    print *, ""
105
-
106
-    ! Clean up
107
-    call lex%destroy()
108
-    call pars%destroy()
109
-    call eval%destroy()
110
-  end subroutine test_for_loop_with_continue
111
-
112
-  subroutine test_parser()
113
-    character(:), allocatable :: script
114
-    type(lexer_t) :: lex
115
-    type(parser_t) :: pars
116
-    type(script_node_t) :: ast
117
-    integer :: i
118
-
119
-    print *, "=== Test: Parser functionality ==="
120
-
121
-    ! Simple script
122
-    script = &
123
-      'echo "Hello World"' // char(10) // &
124
-      'if [ -f test.txt ]' // char(10) // &
125
-      'then' // char(10) // &
126
-      '  cat test.txt' // char(10) // &
127
-      'else' // char(10) // &
128
-      '  echo "No file"' // char(10) // &
129
-      'fi'
130
-
131
-    ! Tokenize
132
-    call lex%init(script)
133
-    call lex%tokenize()
134
-
135
-    print *, "Generated tokens:"
136
-    do i = 1, min(10, lex%token_count)
137
-      print '(a,i3,a,i2,a,a)', &
138
-        "  Token ", i, " type=", lex%tokens(i)%type, &
139
-        " value=", trim(lex%tokens(i)%value)
140
-    end do
141
-
142
-    ! Parse
143
-    call pars%init(lex%tokens, lex%token_count)
144
-    ast = pars%parse()
145
-
146
-    print *, "AST structure:"
147
-    call print_ast_structure(ast)
148
-    print *, ""
149
-
150
-    ! Clean up
151
-    call lex%destroy()
152
-    call pars%destroy()
153
-  end subroutine test_parser
154
-
155
-  recursive subroutine print_ast_structure(node, indent)
156
-    class(ast_node_t), intent(in) :: node
157
-    integer, intent(in), optional :: indent
158
-    integer :: ind, i
159
-
160
-    ind = 0
161
-    if (present(indent)) ind = indent
162
-
163
-    ! Print node type
164
-    write(*, '(a,a,i0)', advance='no') repeat(' ', ind*2), 'Node type: ', node%node_type
165
-
166
-    select type(node)
167
-    type is (script_node_t)
168
-      print *, ' (SCRIPT)'
169
-      if (allocated(node%statements)) then
170
-        do i = 1, size(node%statements)
171
-          call print_ast_structure(node%statements(i), ind+1)
172
-        end do
173
-      end if
174
-
175
-    type is (for_node_t)
176
-      print *, ' (FOR loop) var=', trim(node%variable)
177
-      if (allocated(node%body)) then
178
-        do i = 1, size(node%body)
179
-          call print_ast_structure(node%body(i), ind+1)
180
-        end do
181
-      end if
182
-
183
-    type is (if_node_t)
184
-      print *, ' (IF statement)'
185
-      if (allocated(node%then_branch)) then
186
-        write(*, '(a)') repeat(' ', (ind+1)*2) // 'THEN:'
187
-        do i = 1, size(node%then_branch)
188
-          call print_ast_structure(node%then_branch(i), ind+2)
189
-        end do
190
-      end if
191
-      if (allocated(node%else_branch)) then
192
-        write(*, '(a)') repeat(' ', (ind+1)*2) // 'ELSE:'
193
-        do i = 1, size(node%else_branch)
194
-          call print_ast_structure(node%else_branch(i), ind+2)
195
-        end do
196
-      end if
197
-
198
-    type is (command_node_t)
199
-      print *, ' (COMMAND)'
200
-      if (allocated(node%words)) then
201
-        do i = 1, size(node%words)
202
-          select type(word => node%words(i))
203
-          type is (word_node_t)
204
-            write(*, '(a,a)') repeat(' ', (ind+1)*2) // 'Word: ', trim(word%text)
205
-          end select
206
-        end do
207
-      end if
208
-
209
-    type is (break_node_t)
210
-      print *, ' (BREAK) levels=', node%levels
211
-
212
-    type is (continue_node_t)
213
-      print *, ' (CONTINUE) levels=', node%levels
214
-
215
-    class default
216
-      print *, ''
217
-    end select
218
-  end subroutine print_ast_structure
219
-
220
-end program test_ast
tests/test_ast_simple.f90deleted
@@ -1,134 +0,0 @@
1
-! ==============================================================================
2
-! Simple test for AST modules without dependencies
3
-! ==============================================================================
4
-program test_ast_simple
5
-  use ast_types
6
-  use lexer
7
-  implicit none
8
-
9
-  call test_lexer()
10
-  call test_token_types()
11
-
12
-contains
13
-
14
-  subroutine test_lexer()
15
-    type(lexer_t) :: lex
16
-    character(:), allocatable :: input
17
-    integer :: i
18
-
19
-    print *, "=== Lexer Test ==="
20
-
21
-    ! Test 1: Simple command
22
-    input = 'echo "Hello World"'
23
-    call lex%init(input)
24
-    call lex%tokenize()
25
-
26
-    print *, "Input: ", input
27
-    print *, "Tokens: ", lex%token_count
28
-    do i = 1, lex%token_count
29
-      print '(a,i2,a,a,a)', "  [", lex%tokens(i)%type, "] ", &
30
-            trim(lex%tokens(i)%value), &
31
-            get_token_name(lex%tokens(i)%type)
32
-    end do
33
-    print *, ""
34
-
35
-    call lex%destroy()
36
-
37
-    ! Test 2: For loop
38
-    input = 'for i in 1 2 3; do echo $i; done'
39
-    call lex%init(input)
40
-    call lex%tokenize()
41
-
42
-    print *, "Input: ", input
43
-    print *, "Tokens: ", lex%token_count
44
-    do i = 1, lex%token_count
45
-      print '(a,i2,a,a,a)', "  [", lex%tokens(i)%type, "] ", &
46
-            trim(lex%tokens(i)%value), &
47
-            get_token_name(lex%tokens(i)%type)
48
-    end do
49
-    print *, ""
50
-
51
-    call lex%destroy()
52
-
53
-    ! Test 3: Pipeline
54
-    input = 'cat file.txt | grep pattern | wc -l'
55
-    call lex%init(input)
56
-    call lex%tokenize()
57
-
58
-    print *, "Input: ", input
59
-    print *, "Tokens: ", lex%token_count
60
-    do i = 1, lex%token_count
61
-      print '(a,i2,a,a,a)', "  [", lex%tokens(i)%type, "] ", &
62
-            trim(lex%tokens(i)%value), &
63
-            get_token_name(lex%tokens(i)%type)
64
-    end do
65
-    print *, ""
66
-
67
-    call lex%destroy()
68
-
69
-    ! Test 4: Redirections
70
-    input = 'echo test > output.txt 2>&1'
71
-    call lex%init(input)
72
-    call lex%tokenize()
73
-
74
-    print *, "Input: ", input
75
-    print *, "Tokens: ", lex%token_count
76
-    do i = 1, lex%token_count
77
-      print '(a,i2,a,a,a)', "  [", lex%tokens(i)%type, "] ", &
78
-            trim(lex%tokens(i)%value), &
79
-            get_token_name(lex%tokens(i)%type)
80
-    end do
81
-    print *, ""
82
-
83
-    call lex%destroy()
84
-  end subroutine test_lexer
85
-
86
-  subroutine test_token_types()
87
-    print *, "=== Token Type Test ==="
88
-    print *, "Keywords are recognized:"
89
-    print *, "  'for' -> ", is_keyword('for')
90
-    print *, "  'if' -> ", is_keyword('if')
91
-    print *, "  'echo' -> ", is_keyword('echo')
92
-    print *, "  'break' -> ", is_keyword('break')
93
-    print *, ""
94
-
95
-    print *, "Token types for keywords:"
96
-    print *, "  'for' -> ", keyword_token_type('for'), " (should be ", TOKEN_FOR, ")"
97
-    print *, "  'done' -> ", keyword_token_type('done'), " (should be ", TOKEN_DONE, ")"
98
-    print *, "  'break' -> ", keyword_token_type('break'), " (should be ", TOKEN_BREAK, ")"
99
-    print *, ""
100
-  end subroutine test_token_types
101
-
102
-  function get_token_name(token_type) result(name)
103
-    integer, intent(in) :: token_type
104
-    character(20) :: name
105
-
106
-    select case(token_type)
107
-    case(TOKEN_EOF);        name = ' (EOF)'
108
-    case(TOKEN_WORD);       name = ' (WORD)'
109
-    case(TOKEN_STRING);     name = ' (STRING)'
110
-    case(TOKEN_VARIABLE);   name = ' (VAR)'
111
-    case(TOKEN_SEMICOLON);  name = ' (;)'
112
-    case(TOKEN_NEWLINE);    name = ' (NEWLINE)'
113
-    case(TOKEN_PIPE);       name = ' (|)'
114
-    case(TOKEN_AND);        name = ' (&&)'
115
-    case(TOKEN_OR);         name = ' (||)'
116
-    case(TOKEN_BACKGROUND); name = ' (&)'
117
-    case(TOKEN_REDIRECT_IN);     name = ' (<)'
118
-    case(TOKEN_REDIRECT_OUT);    name = ' (>)'
119
-    case(TOKEN_REDIRECT_APPEND); name = ' (>>)'
120
-    case(TOKEN_FOR);        name = ' (FOR)'
121
-    case(TOKEN_IN);         name = ' (IN)'
122
-    case(TOKEN_DO);         name = ' (DO)'
123
-    case(TOKEN_DONE);       name = ' (DONE)'
124
-    case(TOKEN_IF);         name = ' (IF)'
125
-    case(TOKEN_THEN);       name = ' (THEN)'
126
-    case(TOKEN_ELSE);       name = ' (ELSE)'
127
-    case(TOKEN_FI);         name = ' (FI)'
128
-    case(TOKEN_BREAK);      name = ' (BREAK)'
129
-    case(TOKEN_CONTINUE);   name = ' (CONTINUE)'
130
-    case default;           name = ' (?)'
131
-    end select
132
-  end function get_token_name
133
-
134
-end program test_ast_simple
tests/test_bash_rematch.shdeleted
@@ -1,242 +0,0 @@
1
-#!/bin/bash
2
-# Comprehensive test suite for BASH_REMATCH array with regex matching
3
-
4
-echo "=== BASH_REMATCH Array Test Suite ==="
5
-echo ""
6
-
7
-# Test 1: Basic capture group
8
-echo "TEST 1: Basic Capture Group"
9
-echo "============================"
10
-str="John Doe"
11
-if [[ $str =~ ^([A-Z][a-z]+)\ ([A-Z][a-z]+)$ ]]; then
12
-  echo "✓ PASS: Pattern matched"
13
-  echo "  BASH_REMATCH[0]: '${BASH_REMATCH[0]}' (expected: 'John Doe')"
14
-  echo "  BASH_REMATCH[1]: '${BASH_REMATCH[1]}' (expected: 'John')"
15
-  echo "  BASH_REMATCH[2]: '${BASH_REMATCH[2]}' (expected: 'Doe')"
16
-else
17
-  echo "✗ FAIL: Pattern should match"
18
-fi
19
-echo ""
20
-
21
-# Test 2: Email address capture groups
22
-echo "TEST 2: Email Address Capture"
23
-echo "=============================="
24
-email="user@example.com"
25
-if [[ $email =~ ^([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\.([a-zA-Z]{2,})$ ]]; then
26
-  echo "✓ PASS: Email pattern matched"
27
-  echo "  BASH_REMATCH[0]: '${BASH_REMATCH[0]}' (full match)"
28
-  echo "  BASH_REMATCH[1]: '${BASH_REMATCH[1]}' (username)"
29
-  echo "  BASH_REMATCH[2]: '${BASH_REMATCH[2]}' (domain)"
30
-  echo "  BASH_REMATCH[3]: '${BASH_REMATCH[3]}' (TLD)"
31
-else
32
-  echo "✗ FAIL: Email pattern should match"
33
-fi
34
-echo ""
35
-
36
-# Test 3: Phone number capture
37
-echo "TEST 3: Phone Number Capture"
38
-echo "============================="
39
-phone="(555) 123-4567"
40
-if [[ $phone =~ ^\(([0-9]{3})\)\ ([0-9]{3})-([0-9]{4})$ ]]; then
41
-  echo "✓ PASS: Phone pattern matched"
42
-  echo "  BASH_REMATCH[0]: '${BASH_REMATCH[0]}' (full match)"
43
-  echo "  BASH_REMATCH[1]: '${BASH_REMATCH[1]}' (area code)"
44
-  echo "  BASH_REMATCH[2]: '${BASH_REMATCH[2]}' (prefix)"
45
-  echo "  BASH_REMATCH[3]: '${BASH_REMATCH[3]}' (line number)"
46
-else
47
-  echo "✗ FAIL: Phone pattern should match"
48
-fi
49
-echo ""
50
-
51
-# Test 4: Date extraction
52
-echo "TEST 4: Date Extraction"
53
-echo "======================="
54
-date="2025-10-10"
55
-if [[ $date =~ ^([0-9]{4})-([0-9]{2})-([0-9]{2})$ ]]; then
56
-  echo "✓ PASS: Date pattern matched"
57
-  echo "  BASH_REMATCH[0]: '${BASH_REMATCH[0]}' (full date)"
58
-  echo "  BASH_REMATCH[1]: '${BASH_REMATCH[1]}' (year)"
59
-  echo "  BASH_REMATCH[2]: '${BASH_REMATCH[2]}' (month)"
60
-  echo "  BASH_REMATCH[3]: '${BASH_REMATCH[3]}' (day)"
61
-else
62
-  echo "✗ FAIL: Date pattern should match"
63
-fi
64
-echo ""
65
-
66
-# Test 5: URL parsing
67
-echo "TEST 5: URL Parsing"
68
-echo "==================="
69
-url="https://example.com/path/to/file.html"
70
-if [[ $url =~ ^(https?)://([^/]+)(/.*)?$ ]]; then
71
-  echo "✓ PASS: URL pattern matched"
72
-  echo "  BASH_REMATCH[0]: '${BASH_REMATCH[0]}' (full URL)"
73
-  echo "  BASH_REMATCH[1]: '${BASH_REMATCH[1]}' (protocol)"
74
-  echo "  BASH_REMATCH[2]: '${BASH_REMATCH[2]}' (domain)"
75
-  echo "  BASH_REMATCH[3]: '${BASH_REMATCH[3]}' (path)"
76
-else
77
-  echo "✗ FAIL: URL pattern should match"
78
-fi
79
-echo ""
80
-
81
-# Test 6: Version string parsing
82
-echo "TEST 6: Version String Parsing"
83
-echo "==============================="
84
-version="v1.2.3-beta"
85
-if [[ $version =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)(-(.+))?$ ]]; then
86
-  echo "✓ PASS: Version pattern matched"
87
-  echo "  BASH_REMATCH[0]: '${BASH_REMATCH[0]}' (full version)"
88
-  echo "  BASH_REMATCH[1]: '${BASH_REMATCH[1]}' (major)"
89
-  echo "  BASH_REMATCH[2]: '${BASH_REMATCH[2]}' (minor)"
90
-  echo "  BASH_REMATCH[3]: '${BASH_REMATCH[3]}' (patch)"
91
-  echo "  BASH_REMATCH[4]: '${BASH_REMATCH[4]}' (suffix with -)"
92
-  echo "  BASH_REMATCH[5]: '${BASH_REMATCH[5]}' (suffix)"
93
-else
94
-  echo "✗ FAIL: Version pattern should match"
95
-fi
96
-echo ""
97
-
98
-# Test 7: IPv4 address parsing
99
-echo "TEST 7: IPv4 Address Parsing"
100
-echo "============================="
101
-ip="192.168.1.100"
102
-if [[ $ip =~ ^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$ ]]; then
103
-  echo "✓ PASS: IPv4 pattern matched"
104
-  echo "  BASH_REMATCH[0]: '${BASH_REMATCH[0]}' (full IP)"
105
-  echo "  BASH_REMATCH[1]: '${BASH_REMATCH[1]}' (octet 1)"
106
-  echo "  BASH_REMATCH[2]: '${BASH_REMATCH[2]}' (octet 2)"
107
-  echo "  BASH_REMATCH[3]: '${BASH_REMATCH[3]}' (octet 3)"
108
-  echo "  BASH_REMATCH[4]: '${BASH_REMATCH[4]}' (octet 4)"
109
-else
110
-  echo "✗ FAIL: IPv4 pattern should match"
111
-fi
112
-echo ""
113
-
114
-# Test 8: Single capture group
115
-echo "TEST 8: Single Capture Group"
116
-echo "============================="
117
-str="Error: File not found"
118
-if [[ $str =~ ^(Error|Warning): ]]; then
119
-  echo "✓ PASS: Single group matched"
120
-  echo "  BASH_REMATCH[0]: '${BASH_REMATCH[0]}' (full match)"
121
-  echo "  BASH_REMATCH[1]: '${BASH_REMATCH[1]}' (severity)"
122
-else
123
-  echo "✗ FAIL: Pattern should match"
124
-fi
125
-echo ""
126
-
127
-# Test 9: No capture groups (just full match)
128
-echo "TEST 9: No Capture Groups"
129
-echo "========================="
130
-str="12345"
131
-if [[ $str =~ ^[0-9]+$ ]]; then
132
-  echo "✓ PASS: Pattern matched (no groups)"
133
-  echo "  BASH_REMATCH[0]: '${BASH_REMATCH[0]}' (full match)"
134
-  echo "  BASH_REMATCH[1]: '${BASH_REMATCH[1]}' (should be empty)"
135
-else
136
-  echo "✗ FAIL: Pattern should match"
137
-fi
138
-echo ""
139
-
140
-# Test 10: Nested groups
141
-echo "TEST 10: Nested Groups"
142
-echo "======================"
143
-str="abc123def"
144
-if [[ $str =~ ^([a-z]+)([0-9]+)([a-z]+)$ ]]; then
145
-  echo "✓ PASS: Multiple groups matched"
146
-  echo "  BASH_REMATCH[0]: '${BASH_REMATCH[0]}' (full match)"
147
-  echo "  BASH_REMATCH[1]: '${BASH_REMATCH[1]}' (first letters)"
148
-  echo "  BASH_REMATCH[2]: '${BASH_REMATCH[2]}' (numbers)"
149
-  echo "  BASH_REMATCH[3]: '${BASH_REMATCH[3]}' (last letters)"
150
-else
151
-  echo "✗ FAIL: Pattern should match"
152
-fi
153
-echo ""
154
-
155
-# Test 11: Optional groups
156
-echo "TEST 11: Optional Groups"
157
-echo "========================"
158
-str1="test"
159
-str2="test-123"
160
-if [[ $str1 =~ ^(test)(-([0-9]+))?$ ]]; then
161
-  echo "✓ PASS (1/2): Pattern matched without optional"
162
-  echo "  BASH_REMATCH[0]: '${BASH_REMATCH[0]}'"
163
-  echo "  BASH_REMATCH[1]: '${BASH_REMATCH[1]}'"
164
-  echo "  BASH_REMATCH[2]: '${BASH_REMATCH[2]}' (should be empty)"
165
-  echo "  BASH_REMATCH[3]: '${BASH_REMATCH[3]}' (should be empty)"
166
-else
167
-  echo "✗ FAIL (1/2): Pattern should match"
168
-fi
169
-
170
-if [[ $str2 =~ ^(test)(-([0-9]+))?$ ]]; then
171
-  echo "✓ PASS (2/2): Pattern matched with optional"
172
-  echo "  BASH_REMATCH[0]: '${BASH_REMATCH[0]}'"
173
-  echo "  BASH_REMATCH[1]: '${BASH_REMATCH[1]}'"
174
-  echo "  BASH_REMATCH[2]: '${BASH_REMATCH[2]}' (optional part)"
175
-  echo "  BASH_REMATCH[3]: '${BASH_REMATCH[3]}' (number)"
176
-else
177
-  echo "✗ FAIL (2/2): Pattern should match"
178
-fi
179
-echo ""
180
-
181
-# Test 12: Using captures in script logic
182
-echo "TEST 12: Practical Use - File Extension Parser"
183
-echo "==============================================="
184
-filename="document.tar.gz"
185
-if [[ $filename =~ ^(.+)\.([^.]+)$ ]]; then
186
-  basename="${BASH_REMATCH[1]}"
187
-  extension="${BASH_REMATCH[2]}"
188
-  echo "✓ PASS: File parsed"
189
-  echo "  Basename: '$basename'"
190
-  echo "  Extension: '$extension'"
191
-else
192
-  echo "✗ FAIL: Pattern should match"
193
-fi
194
-echo ""
195
-
196
-# Test 13: Array length check
197
-echo "TEST 13: Array Length (Number of Captures)"
198
-echo "==========================================="
199
-str="abc-123-def"
200
-if [[ $str =~ ^([a-z]+)-([0-9]+)-([a-z]+)$ ]]; then
201
-  echo "✓ PASS: Pattern matched with 3 groups"
202
-  echo "  Array contents:"
203
-  echo "    [0]: '${BASH_REMATCH[0]}'"
204
-  echo "    [1]: '${BASH_REMATCH[1]}'"
205
-  echo "    [2]: '${BASH_REMATCH[2]}'"
206
-  echo "    [3]: '${BASH_REMATCH[3]}'"
207
-  echo "  Array length: ${#BASH_REMATCH[@]}"
208
-else
209
-  echo "✗ FAIL: Pattern should match"
210
-fi
211
-echo ""
212
-
213
-# Test 14: Loop through captures
214
-echo "TEST 14: Iterate Through Captures"
215
-echo "=================================="
216
-str="a:b:c:d"
217
-if [[ $str =~ ^([a-z]):([a-z]):([a-z]):([a-z])$ ]]; then
218
-  echo "✓ PASS: Pattern matched"
219
-  echo "  Iterating through BASH_REMATCH:"
220
-  for i in {0..4}; do
221
-    echo "    [$i]: '${BASH_REMATCH[$i]}'"
222
-  done
223
-else
224
-  echo "✗ FAIL: Pattern should match"
225
-fi
226
-echo ""
227
-
228
-# Summary
229
-echo "========================================="
230
-echo "BASH_REMATCH Array Test Suite Complete"
231
-echo "========================================="
232
-echo ""
233
-echo "Features Tested:"
234
-echo "  ✓ Full match capture (BASH_REMATCH[0])"
235
-echo "  ✓ Multiple capture groups"
236
-echo "  ✓ Email, phone, date, URL parsing"
237
-echo "  ✓ Optional groups"
238
-echo "  ✓ Nested groups"
239
-echo "  ✓ Array length and iteration"
240
-echo "  ✓ Practical use cases"
241
-echo ""
242
-echo "Note: Run this test with both bash and fortsh to compare"
tests/test_brace_expansion.shdeleted
@@ -1,171 +0,0 @@
1
-#!/bin/bash
2
-# Comprehensive test suite for brace expansion
3
-
4
-echo "=== Brace Expansion Test Suite ==="
5
-echo ""
6
-
7
-# Test 1: List expansion
8
-echo "TEST 1: List Expansion {a,b,c}"
9
-echo "=============================="
10
-result="{a,b,c}"
11
-echo "Input: {a,b,c}"
12
-echo "Output: $result"
13
-expected="a b c"
14
-[ "$result" = "$expected" ] && echo "✓ PASS" || echo "✗ FAIL (expected: $expected, got: $result)"
15
-echo ""
16
-
17
-# Test 2: Numeric range (ascending)
18
-echo "TEST 2: Numeric Range {1..5}"
19
-echo "============================="
20
-result="{1..5}"
21
-echo "Input: {1..5}"
22
-echo "Output: $result"
23
-expected="1 2 3 4 5"
24
-[ "$result" = "$expected" ] && echo "✓ PASS" || echo "✗ FAIL (expected: $expected, got: $result)"
25
-echo ""
26
-
27
-# Test 3: Numeric range (descending)
28
-echo "TEST 3: Numeric Range {5..1}"
29
-echo "============================="
30
-result="{5..1}"
31
-echo "Input: {5..1}"
32
-echo "Output: $result"
33
-expected="5 4 3 2 1"
34
-[ "$result" = "$expected" ] && echo "✓ PASS" || echo "✗ FAIL (expected: $expected, got: $result)"
35
-echo ""
36
-
37
-# Test 4: Alphabetic range (ascending)
38
-echo "TEST 4: Alphabetic Range {a..e}"
39
-echo "================================"
40
-result="{a..e}"
41
-echo "Input: {a..e}"
42
-echo "Output: $result"
43
-expected="a b c d e"
44
-[ "$result" = "$expected" ] && echo "✓ PASS" || echo "✗ FAIL (expected: $expected, got: $result)"
45
-echo ""
46
-
47
-# Test 5: Alphabetic range (descending)
48
-echo "TEST 5: Alphabetic Range {e..a}"
49
-echo "================================"
50
-result="{e..a}"
51
-echo "Input: {e..a}"
52
-echo "Output: $result"
53
-expected="e d c b a"
54
-[ "$result" = "$expected" ] && echo "✓ PASS" || echo "✗ FAIL (expected: $expected, got: $result)"
55
-echo ""
56
-
57
-# Test 6: Numeric range with step
58
-echo "TEST 6: Step Expansion {1..10..2}"
59
-echo "=================================="
60
-result="{1..10..2}"
61
-echo "Input: {1..10..2}"
62
-echo "Output: $result"
63
-expected="1 3 5 7 9"
64
-[ "$result" = "$expected" ] && echo "✓ PASS" || echo "✗ FAIL (expected: $expected, got: $result)"
65
-echo ""
66
-
67
-# Test 7: Alphabetic range with step
68
-echo "TEST 7: Step Expansion {a..z..3}"
69
-echo "================================="
70
-result="{a..z..3}"
71
-echo "Input: {a..z..3}"
72
-echo "Output: $result"
73
-expected="a d g j m p s v y"
74
-[ "$result" = "$expected" ] && echo "✓ PASS" || echo "✗ FAIL (expected: $expected, got: $result)"
75
-echo ""
76
-
77
-# Test 8: List with multiple items
78
-echo "TEST 8: Multiple Items {red,green,blue}"
79
-echo "========================================"
80
-result="{red,green,blue}"
81
-echo "Input: {red,green,blue}"
82
-echo "Output: $result"
83
-expected="red green blue"
84
-[ "$result" = "$expected" ] && echo "✓ PASS" || echo "✗ FAIL (expected: $expected, got: $result)"
85
-echo ""
86
-
87
-# Test 9: Zero-padded numbers
88
-echo "TEST 9: Zero-padded {01..05}"
89
-echo "============================"
90
-result="{01..05}"
91
-echo "Input: {01..05}"
92
-echo "Output: $result"
93
-# Note: Our implementation doesn't preserve zero-padding yet
94
-expected_variations=("1 2 3 4 5" "01 02 03 04 05")
95
-match=false
96
-for exp in "${expected_variations[@]}"; do
97
-  if [ "$result" = "$exp" ]; then
98
-    match=true
99
-    break
100
-  fi
101
-done
102
-[ "$match" = true ] && echo "✓ PASS" || echo "✗ FAIL (got: $result)"
103
-echo ""
104
-
105
-# Test 10: Longer range
106
-echo "TEST 10: Longer Range {1..20}"
107
-echo "=============================="
108
-result="{1..20}"
109
-echo "Input: {1..20}"
110
-echo "Output: $result"
111
-expected="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20"
112
-[ "$result" = "$expected" ] && echo "✓ PASS" || echo "✗ FAIL"
113
-echo ""
114
-
115
-# Test 11: Single character items
116
-echo "TEST 11: Single chars {x,y,z}"
117
-echo "=============================="
118
-result="{x,y,z}"
119
-echo "Input: {x,y,z}"
120
-echo "Output: $result"
121
-expected="x y z"
122
-[ "$result" = "$expected" ] && echo "✓ PASS" || echo "✗ FAIL (expected: $expected, got: $result)"
123
-echo ""
124
-
125
-# Test 12: echo command with braces
126
-echo "TEST 12: echo with brace expansion"
127
-echo "==================================="
128
-echo "Command: echo {1,2,3}"
129
-output=$(echo {1,2,3})
130
-echo "Output: $output"
131
-# In bash, this outputs: 1 2 3
132
-[[ "$output" =~ [123] ]] && echo "✓ PASS" || echo "✗ FAIL"
133
-echo ""
134
-
135
-# Test 13: Descending with step
136
-echo "TEST 13: Descending with step {10..1..2}"
137
-echo "========================================="
138
-result="{10..1..2}"
139
-echo "Input: {10..1..2}"
140
-echo "Output: $result"
141
-expected="10 8 6 4 2"
142
-[ "$result" = "$expected" ] && echo "✓ PASS" || echo "✗ FAIL (expected: $expected, got: $result)"
143
-echo ""
144
-
145
-# Test 14: Large step
146
-echo "TEST 14: Large step {1..20..5}"
147
-echo "==============================="
148
-result="{1..20..5}"
149
-echo "Input: {1..20..5}"
150
-echo "Output: $result"
151
-expected="1 6 11 16"
152
-[ "$result" = "$expected" ] && echo "✓ PASS" || echo "✗ FAIL (expected: $expected, got: $result)"
153
-echo ""
154
-
155
-# Summary
156
-echo "========================================="
157
-echo "Brace Expansion Test Suite Complete"
158
-echo "========================================="
159
-echo ""
160
-echo "Features Tested:"
161
-echo "  ✓ List expansion {a,b,c}"
162
-echo "  ✓ Numeric range (ascending & descending)"
163
-echo "  ✓ Alphabetic range (ascending & descending)"
164
-echo "  ✓ Step expansion (numeric & alphabetic)"
165
-echo "  ✓ Various range sizes"
166
-echo "  ✓ Integration with echo command"
167
-echo ""
168
-echo "Note: Advanced features not yet implemented:"
169
-echo "  - Prefix/suffix: file{1,2}.txt"
170
-echo "  - Nested braces: {{a,b},{c,d}}"
171
-echo "  - Mixed content: {a..c}{1..3}"
tests/test_brace_expansion_proper.shdeleted
@@ -1,120 +0,0 @@
1
-#!/bin/bash
2
-# Proper brace expansion tests (unquoted, as used in real shells)
3
-
4
-echo "=== Proper Brace Expansion Tests ==="
5
-echo ""
6
-
7
-# Test 1: List expansion with echo
8
-echo "TEST 1: echo {a,b,c}"
9
-echo "===================="
10
-echo {a,b,c}
11
-echo "Expected: a b c (or: a b c on separate line)"
12
-echo "✓ PASS (if you see: a b c above)"
13
-echo ""
14
-
15
-# Test 2: Numeric range
16
-echo "TEST 2: echo {1..5}"
17
-echo "==================="
18
-echo {1..5}
19
-echo "Expected: 1 2 3 4 5"
20
-echo "✓ PASS (if correct above)"
21
-echo ""
22
-
23
-# Test 3: Descending numeric range
24
-echo "TEST 3: echo {5..1}"
25
-echo "==================="
26
-echo {5..1}
27
-echo "Expected: 5 4 3 2 1"
28
-echo "✓ PASS (if correct above)"
29
-echo ""
30
-
31
-# Test 4: Alphabetic range
32
-echo "TEST 4: echo {a..e}"
33
-echo "==================="
34
-echo {a..e}
35
-echo "Expected: a b c d e"
36
-echo "✓ PASS (if correct above)"
37
-echo ""
38
-
39
-# Test 5: Step expansion
40
-echo "TEST 5: echo {1..10..2}"
41
-echo "======================="
42
-echo {1..10..2}
43
-echo "Expected: 1 3 5 7 9"
44
-echo "✓ PASS (if correct above)"
45
-echo ""
46
-
47
-# Test 6: Alphabetic with step
48
-echo "TEST 6: echo {a..z..5}"
49
-echo "======================"
50
-echo {a..z..5}
51
-echo "Expected: a f k p u z"
52
-echo "✓ PASS (if correct above)"
53
-echo ""
54
-
55
-# Test 7: Mixed items
56
-echo "TEST 7: echo {red,green,blue}"
57
-echo "=============================="
58
-echo {red,green,blue}
59
-echo "Expected: red green blue"
60
-echo "✓ PASS (if correct above)"
61
-echo ""
62
-
63
-# Test 8: Single item (no expansion)
64
-echo "TEST 8: echo {single}"
65
-echo "====================="
66
-echo {single}
67
-echo "Expected: {single} (no expansion)"
68
-echo "✓ PASS (if correct above)"
69
-echo ""
70
-
71
-# Test 9: No braces
72
-echo "TEST 9: echo normal"
73
-echo "==================="
74
-echo normal
75
-echo "Expected: normal"
76
-echo "✓ PASS (if correct above)"
77
-echo ""
78
-
79
-# Test 10: Range with for loop
80
-echo "TEST 10: for loop with {1..3}"
81
-echo "=============================="
82
-for i in {1..3}; do
83
-  echo "  Iteration $i"
84
-done
85
-echo "Expected: Iteration 1, 2, 3"
86
-echo "✓ PASS (if correct above)"
87
-echo ""
88
-
89
-# Test 11: Multiple braces in one command
90
-echo "TEST 11: echo {a,b} {1,2}"
91
-echo "========================="
92
-echo {a,b} {1,2}
93
-echo "Expected: a b 1 2"
94
-echo "✓ PASS (if correct above)"
95
-echo ""
96
-
97
-# Test 12: Descending with step
98
-echo "TEST 12: echo {10..1..2}"
99
-echo "========================"
100
-echo {10..1..2}
101
-echo "Expected: 10 8 6 4 2"
102
-echo "✓ PASS (if correct above)"
103
-echo ""
104
-
105
-# Summary
106
-echo "========================================="
107
-echo "Brace Expansion Test Complete"
108
-echo "========================================="
109
-echo ""
110
-echo "Manual verification required."
111
-echo "Compare actual output with expected output above."
112
-echo ""
113
-echo "Features tested:"
114
-echo "  - List expansion: {a,b,c}"
115
-echo "  - Numeric ranges: {1..10}"
116
-echo "  - Alphabetic ranges: {a..z}"
117
-echo "  - Step expansion: {1..10..2}"
118
-echo "  - Descending ranges"
119
-echo "  - Multiple brace groups"
120
-echo "  - For loop integration"
tests/test_getopts.shdeleted
@@ -1,161 +0,0 @@
1
-#!/bin/bash
2
-# Test suite for getopts builtin
3
-
4
-echo "=== getopts Builtin Test Suite ==="
5
-echo ""
6
-
7
-# Test 1: Basic option parsing
8
-echo "TEST 1: Basic Option Parsing"
9
-echo "============================="
10
-test_basic() {
11
-  while getopts "abc" opt; do
12
-    case $opt in
13
-      a) echo "Option -a found" ;;
14
-      b) echo "Option -b found" ;;
15
-      c) echo "Option -c found" ;;
16
-      \?) echo "Invalid option: -$OPTARG" ;;
17
-    esac
18
-  done
19
-}
20
-
21
-set -- -a -b -c
22
-test_basic
23
-[ $? -eq 0 ] && echo "✓ PASS: Basic option parsing" || echo "✗ FAIL"
24
-echo ""
25
-
26
-# Test 2: Options with arguments
27
-echo "TEST 2: Options with Arguments"
28
-echo "=============================="
29
-test_with_args() {
30
-  while getopts "a:b:c" opt; do
31
-    case $opt in
32
-      a) echo "Option -a with arg: $OPTARG" ;;
33
-      b) echo "Option -b with arg: $OPTARG" ;;
34
-      c) echo "Option -c (no arg)" ;;
35
-      \?) echo "Invalid option: -$OPTARG" ;;
36
-    esac
37
-  done
38
-}
39
-
40
-set -- -a value1 -b value2 -c
41
-OPTIND=1  # Reset OPTIND
42
-test_with_args
43
-echo "✓ PASS: Options with arguments"
44
-echo ""
45
-
46
-# Test 3: Combined option format (-ovalue)
47
-echo "TEST 3: Combined Option Format"
48
-echo "=============================="
49
-test_combined() {
50
-  while getopts "o:" opt; do
51
-    case $opt in
52
-      o) echo "Option -o with arg: $OPTARG" ;;
53
-      \?) echo "Invalid option: -$OPTARG" ;;
54
-    esac
55
-  done
56
-}
57
-
58
-set -- -ofilename.txt
59
-OPTIND=1
60
-test_combined
61
-echo "✓ PASS: Combined format"
62
-echo ""
63
-
64
-# Test 4: Invalid option handling
65
-echo "TEST 4: Invalid Option Handling"
66
-echo "==============================="
67
-test_invalid() {
68
-  while getopts "abc" opt; do
69
-    case $opt in
70
-      a|b|c) echo "Valid option: -$opt" ;;
71
-      \?) echo "Invalid option detected: $OPTARG" ;;
72
-    esac
73
-  done
74
-}
75
-
76
-set -- -a -x -b
77
-OPTIND=1
78
-test_invalid
79
-echo "✓ PASS: Invalid option handling"
80
-echo ""
81
-
82
-# Test 5: OPTIND tracking
83
-echo "TEST 5: OPTIND Tracking"
84
-echo "======================="
85
-set -- -a -b arg1 arg2
86
-OPTIND=1
87
-while getopts "ab" opt; do
88
-  echo "Processing -$opt, OPTIND=$OPTIND"
89
-done
90
-echo "After processing options, OPTIND=$OPTIND"
91
-echo "Remaining args: ${@:$OPTIND}"
92
-echo "✓ PASS: OPTIND tracking"
93
-echo ""
94
-
95
-# Test 6: Mixed options and arguments
96
-echo "TEST 6: Mixed Options and Arguments"
97
-echo "===================================="
98
-parse_mixed() {
99
-  local verbose=false
100
-  local output=""
101
-
102
-  while getopts "vo:" opt; do
103
-    case $opt in
104
-      v) verbose=true ;;
105
-      o) output="$OPTARG" ;;
106
-      \?) return 1 ;;
107
-    esac
108
-  done
109
-
110
-  shift $((OPTIND-1))
111
-
112
-  echo "verbose=$verbose"
113
-  echo "output=$output"
114
-  echo "remaining args: $@"
115
-}
116
-
117
-set -- -v -o output.txt file1.txt file2.txt
118
-OPTIND=1
119
-parse_mixed
120
-echo "✓ PASS: Mixed options and arguments"
121
-echo ""
122
-
123
-# Test 7: Multiple uses in same script
124
-echo "TEST 7: Multiple Uses in Same Script"
125
-echo "===================================="
126
-first_parse() {
127
-  OPTIND=1
128
-  while getopts "ab" opt; do
129
-    echo "First parse: -$opt"
130
-  done
131
-}
132
-
133
-second_parse() {
134
-  OPTIND=1
135
-  while getopts "xy" opt; do
136
-    echo "Second parse: -$opt"
137
-  done
138
-}
139
-
140
-set -- -a -b
141
-first_parse
142
-
143
-set -- -x -y
144
-second_parse
145
-
146
-echo "✓ PASS: Multiple uses"
147
-echo ""
148
-
149
-# Summary
150
-echo "========================================="
151
-echo "getopts Builtin Test Suite Complete"
152
-echo "========================================="
153
-echo ""
154
-echo "Features Tested:"
155
-echo "  ✓ Basic option parsing (-a, -b, -c)"
156
-echo "  ✓ Options with required arguments (-a:)"
157
-echo "  ✓ Combined format (-ovalue)"
158
-echo "  ✓ Invalid option detection"
159
-echo "  ✓ OPTIND tracking and management"
160
-echo "  ✓ Mixed options and arguments"
161
-echo "  ✓ Multiple getopts calls in same script"
tests/test_john_doe.shdeleted
@@ -1,25 +0,0 @@
1
-#!/bin/bash
2
-
3
-echo "Test John Doe pattern"
4
-str="John Doe"
5
-echo "String: $str"
6
-
7
-# Test with regular space (no backslash)
8
-if [[ $str =~ ^([A-Z][a-z]+)\ ([A-Z][a-z]+)$ ]]; then
9
-  echo "Match with backslash-space: YES"
10
-  echo "BASH_REMATCH[0]='${BASH_REMATCH[0]}'"
11
-  echo "BASH_REMATCH[1]='${BASH_REMATCH[1]}'"
12
-  echo "BASH_REMATCH[2]='${BASH_REMATCH[2]}'"
13
-else
14
-  echo "Match with backslash-space: NO"
15
-fi
16
-
17
-# Test with just space
18
-if [[ $str =~ ^([A-Z][a-z]+) ([A-Z][a-z]+)$ ]]; then
19
-  echo "Match with plain space: YES"
20
-  echo "BASH_REMATCH[0]='${BASH_REMATCH[0]}'"
21
-  echo "BASH_REMATCH[1]='${BASH_REMATCH[1]}'"
22
-  echo "BASH_REMATCH[2]='${BASH_REMATCH[2]}'"
23
-else
24
-  echo "Match with plain space: NO"
25
-fi
tests/test_john_simple.shdeleted
@@ -1,11 +0,0 @@
1
-#!/bin/bash
2
-
3
-str="John Doe"
4
-if [[ $str =~ ^([A-Z][a-z]+)\ ([A-Z][a-z]+)$ ]]; then
5
-  echo "PASS"
6
-  echo "0: '${BASH_REMATCH[0]}'"
7
-  echo "1: '${BASH_REMATCH[1]}'"
8
-  echo "2: '${BASH_REMATCH[2]}'"
9
-else
10
-  echo "FAIL"
11
-fi
tests/test_loops_phase14.shdeleted
@@ -1,80 +0,0 @@
1
-#!/bin/bash
2
-# Phase 14 Loop Tests - Variable Scoping & Expansion Fixes
3
-# Run with: cat tests/test_loops_phase14.sh | ./bin/fortsh
4
-
5
-echo "========================================="
6
-echo "Phase 14 Test Suite: Loop Execution"
7
-echo "========================================="
8
-echo ""
9
-
10
-echo "Test 1: Basic for loop"
11
-echo "-----------------------"
12
-for fruit in apple banana cherry
13
-do
14
-  echo "  Fruit: $fruit"
15
-done
16
-echo ""
17
-
18
-echo "Test 2: Arithmetic for loop (no space)"
19
-echo "---------------------------------------"
20
-for((i=0;i<5;i++))
21
-do
22
-  echo "  Count: $i"
23
-done
24
-
25
-echo
26
-echo "Test 2b: Arithmetic for loop (with space)"
27
-echo "------------------------------------------"
28
-for ((i=0; i<5; i++))
29
-do
30
-  echo "  Count: $i"
31
-done
32
-echo ""
33
-
34
-echo "Test 3: Arithmetic for loop with increment"
35
-echo "--------------------------------------------"
36
-for((i=2;i<=10;i+=2))
37
-do
38
-  echo "  Even: $i"
39
-done
40
-echo ""
41
-
42
-echo "Test 4: Sequential loops (different variables)"
43
-echo "------------------------------------------------"
44
-for letter in A B C
45
-do
46
-  echo "  Letter: $letter"
47
-done
48
-for((n=1;n<=3;n++))
49
-do
50
-  echo "  Number: $n"
51
-done
52
-echo ""
53
-
54
-echo "Test 5: Variable expansion in loops"
55
-echo "-------------------------------------"
56
-prefix="Item"
57
-for x in first second third
58
-do
59
-  echo "  $prefix: $x"
60
-done
61
-echo ""
62
-
63
-echo "Test 6: Loop with command substitution"
64
-echo "----------------------------------------"
65
-for word in one two three
66
-do
67
-  echo "  Word has ${#word} letters"
68
-done
69
-echo ""
70
-
71
-echo "========================================="
72
-echo "Known Limitations:"
73
-echo "========================================="
74
-echo "1. Nested loops do not work correctly"
75
-echo "2. Loop variables persist after loop ends (POSIX correct)"
76
-echo ""
77
-
78
-echo "========================================="
79
-echo "Test Complete"
80
-echo "========================================="
tests/test_medium_priority_builtins.shdeleted
@@ -1,279 +0,0 @@
1
-#!/bin/bash
2
-# Comprehensive test suite for medium-priority built-in commands
3
-# Tests: getopts, trap, wait, kill, ulimit
4
-
5
-echo "=== Medium-Priority Built-ins Test Suite ==="
6
-echo ""
7
-
8
-# ============================================
9
-# TEST GROUP 1: getopts
10
-# ============================================
11
-echo "GROUP 1: getopts Builtin"
12
-echo "========================="
13
-echo ""
14
-
15
-# Test 1.1: Basic getopts usage
16
-echo "TEST 1.1: Basic getopts"
17
-echo "----------------------"
18
-test_getopts_basic() {
19
-  local result=""
20
-  while getopts "abc" opt; do
21
-    result="${result}$opt"
22
-  done
23
-  echo "$result"
24
-}
25
-
26
-set -- -a -b -c
27
-OPTIND=1
28
-output=$(test_getopts_basic)
29
-[ "$output" = "abc" ] && echo "✓ PASS" || echo "✗ FAIL (got: $output)"
30
-echo ""
31
-
32
-# Test 1.2: getopts with required arguments
33
-echo "TEST 1.2: getopts with arguments"
34
-echo "--------------------------------"
35
-test_getopts_args() {
36
-  local opts=""
37
-  local args=""
38
-  while getopts "a:b:c" opt; do
39
-    case $opt in
40
-      a|b) opts="${opts}${opt}"; args="${args}${OPTARG}," ;;
41
-      c) opts="${opts}${opt}" ;;
42
-    esac
43
-  done
44
-  echo "${opts}:${args}"
45
-}
46
-
47
-set -- -a val1 -b val2 -c
48
-OPTIND=1
49
-output=$(test_getopts_args)
50
-[ "$output" = "abc:val1,val2," ] && echo "✓ PASS" || echo "✗ FAIL (got: $output)"
51
-echo ""
52
-
53
-# Test 1.3: getopts invalid option handling
54
-echo "TEST 1.3: getopts invalid options"
55
-echo "---------------------------------"
56
-test_getopts_invalid() {
57
-  local count=0
58
-  while getopts "ab" opt 2>/dev/null; do
59
-    [ "$opt" = "?" ] && count=$((count + 1))
60
-  done
61
-  echo "$count"
62
-}
63
-
64
-set -- -a -x -b
65
-OPTIND=1
66
-output=$(test_getopts_invalid)
67
-[ "$output" -ge "1" ] && echo "✓ PASS" || echo "✗ FAIL (got: $output)"
68
-echo ""
69
-
70
-# ============================================
71
-# TEST GROUP 2: trap
72
-# ============================================
73
-echo "GROUP 2: trap Builtin"
74
-echo "====================="
75
-echo ""
76
-
77
-# Test 2.1: trap command syntax
78
-echo "TEST 2.1: trap syntax acceptance"
79
-echo "--------------------------------"
80
-trap 'echo signal' SIGINT 2>/dev/null
81
-status=$?
82
-[ $status -eq 0 ] && echo "✓ PASS" || echo "✗ FAIL (exit code: $status)"
83
-trap - SIGINT 2>/dev/null  # Clean up
84
-echo ""
85
-
86
-# Test 2.2: trap -p (list traps)
87
-echo "TEST 2.2: trap -p"
88
-echo "----------------"
89
-trap -p >/dev/null 2>&1
90
-status=$?
91
-[ $status -eq 0 ] && echo "✓ PASS" || echo "✗ FAIL (exit code: $status)"
92
-echo ""
93
-
94
-# Test 2.3: trap removal
95
-echo "TEST 2.3: trap removal"
96
-echo "---------------------"
97
-trap 'echo test' SIGTERM 2>/dev/null
98
-trap - SIGTERM 2>/dev/null
99
-status=$?
100
-[ $status -eq 0 ] && echo "✓ PASS" || echo "✗ FAIL (exit code: $status)"
101
-echo ""
102
-
103
-# ============================================
104
-# TEST GROUP 3: wait
105
-# ============================================
106
-echo "GROUP 3: wait Builtin"
107
-echo "====================="
108
-echo ""
109
-
110
-# Test 3.1: wait with no arguments
111
-echo "TEST 3.1: wait (no args)"
112
-echo "-----------------------"
113
-wait 2>/dev/null
114
-status=$?
115
-[ $status -eq 0 ] && echo "✓ PASS" || echo "✗ FAIL (exit code: $status)"
116
-echo ""
117
-
118
-# Test 3.2: wait with PID
119
-echo "TEST 3.2: wait with PID"
120
-echo "----------------------"
121
-sleep 0.1 &
122
-pid=$!
123
-wait $pid 2>/dev/null
124
-status=$?
125
-[ $status -eq 0 ] && echo "✓ PASS" || echo "✗ FAIL (exit code: $status)"
126
-echo ""
127
-
128
-# Test 3.3: wait for completed process
129
-echo "TEST 3.3: wait for completed process"
130
-echo "------------------------------------"
131
-sleep 0.1 &
132
-pid=$!
133
-sleep 0.2  # Let it finish
134
-wait $pid 2>/dev/null
135
-status=$?
136
-[ $status -eq 0 ] && echo "✓ PASS" || echo "✗ FAIL (exit code: $status)"
137
-echo ""
138
-
139
-# ============================================
140
-# TEST GROUP 4: kill
141
-# ============================================
142
-echo "GROUP 4: kill Builtin"
143
-echo "====================="
144
-echo ""
145
-
146
-# Test 4.1: kill syntax (default signal)
147
-echo "TEST 4.1: kill with PID"
148
-echo "----------------------"
149
-sleep 60 &
150
-pid=$!
151
-kill $pid 2>/dev/null
152
-status=$?
153
-wait $pid 2>/dev/null  # Clean up
154
-[ $status -eq 0 ] && echo "✓ PASS" || echo "✗ FAIL (exit code: $status)"
155
-echo ""
156
-
157
-# Test 4.2: kill with signal number
158
-echo "TEST 4.2: kill -9"
159
-echo "----------------"
160
-sleep 60 &
161
-pid=$!
162
-kill -9 $pid 2>/dev/null
163
-status=$?
164
-wait $pid 2>/dev/null  # Clean up
165
-[ $status -eq 0 ] && echo "✓ PASS" || echo "✗ FAIL (exit code: $status)"
166
-echo ""
167
-
168
-# Test 4.3: kill with signal name
169
-echo "TEST 4.3: kill -TERM"
170
-echo "-------------------"
171
-sleep 60 &
172
-pid=$!
173
-kill -TERM $pid 2>/dev/null
174
-status=$?
175
-wait $pid 2>/dev/null  # Clean up
176
-[ $status -eq 0 ] && echo "✓ PASS" || echo "✗ FAIL (exit code: $status)"
177
-echo ""
178
-
179
-# Test 4.4: kill with -s option
180
-echo "TEST 4.4: kill -s SIGKILL"
181
-echo "------------------------"
182
-sleep 60 &
183
-pid=$!
184
-kill -s SIGKILL $pid 2>/dev/null
185
-status=$?
186
-wait $pid 2>/dev/null  # Clean up
187
-[ $status -eq 0 ] && echo "✓ PASS" || echo "✗ FAIL (exit code: $status)"
188
-echo ""
189
-
190
-# ============================================
191
-# TEST GROUP 5: ulimit
192
-# ============================================
193
-echo "GROUP 5: ulimit Builtin"
194
-echo "======================="
195
-echo ""
196
-
197
-# Test 5.1: ulimit with no arguments
198
-echo "TEST 5.1: ulimit (no args)"
199
-echo "-------------------------"
200
-ulimit >/dev/null 2>&1
201
-status=$?
202
-[ $status -eq 0 ] && echo "✓ PASS" || echo "✗ FAIL (exit code: $status)"
203
-echo ""
204
-
205
-# Test 5.2: ulimit -a (show all)
206
-echo "TEST 5.2: ulimit -a"
207
-echo "------------------"
208
-ulimit -a >/dev/null 2>&1
209
-status=$?
210
-[ $status -eq 0 ] && echo "✓ PASS" || echo "✗ FAIL (exit code: $status)"
211
-echo ""
212
-
213
-# Test 5.3: ulimit -n (show open files)
214
-echo "TEST 5.3: ulimit -n"
215
-echo "------------------"
216
-ulimit -n >/dev/null 2>&1
217
-status=$?
218
-[ $status -eq 0 ] && echo "✓ PASS" || echo "✗ FAIL (exit code: $status)"
219
-echo ""
220
-
221
-# Test 5.4: ulimit -n value (set limit)
222
-echo "TEST 5.4: ulimit -n 1024"
223
-echo "-----------------------"
224
-# This may fail if not privileged, but syntax should be accepted
225
-current=$(ulimit -n)
226
-ulimit -n 1024 2>/dev/null
227
-status=$?
228
-ulimit -n $current 2>/dev/null  # Restore
229
-[ $status -eq 0 ] && echo "✓ PASS" || echo "✗ FAIL (exit code: $status)"
230
-echo ""
231
-
232
-# ============================================
233
-# TEST GROUP 6: type command updates
234
-# ============================================
235
-echo "GROUP 6: type Command Recognition"
236
-echo "=================================="
237
-echo ""
238
-
239
-# Test that all new built-ins are recognized by type
240
-builtins=("getopts" "trap" "wait" "kill" "ulimit")
241
-all_passed=true
242
-
243
-for cmd in "${builtins[@]}"; do
244
-  output=$(type "$cmd" 2>&1)
245
-  if echo "$output" | grep -q "builtin"; then
246
-    echo "✓ type $cmd: recognized as builtin"
247
-  else
248
-    echo "✗ type $cmd: NOT recognized as builtin"
249
-    all_passed=false
250
-  fi
251
-done
252
-
253
-echo ""
254
-[ "$all_passed" = true ] && echo "✓ ALL PASS" || echo "✗ SOME FAILED"
255
-echo ""
256
-
257
-# ============================================
258
-# SUMMARY
259
-# ============================================
260
-echo "=========================================="
261
-echo "Medium-Priority Built-ins Test Complete"
262
-echo "=========================================="
263
-echo ""
264
-echo "Built-ins Tested:"
265
-echo "  ✓ getopts - command-line option parsing"
266
-echo "  ✓ trap    - signal handler registration"
267
-echo "  ✓ wait    - wait for background processes"
268
-echo "  ✓ kill    - send signals to processes"
269
-echo "  ✓ ulimit  - resource limit management"
270
-echo ""
271
-echo "Total Test Groups: 6"
272
-echo "Total Test Cases: 20+"
273
-echo ""
274
-echo "NOTE: Some built-ins have minimal implementations"
275
-echo "      Full functionality requires additional C bindings:"
276
-echo "      - trap: requires sigaction/signal"
277
-echo "      - wait: requires waitpid tracking"
278
-echo "      - kill: requires kill() system call"
279
-echo "      - ulimit: requires getrlimit/setrlimit"
tests/test_parser_lists.f90deleted
@@ -1,186 +0,0 @@
1
-! ==============================================================================
2
-! Test program for parser with linked list node collection
3
-! ==============================================================================
4
-program test_parser_lists
5
-  use ast_types
6
-  use lexer
7
-  use parser
8
-  implicit none
9
-
10
-  call test_simple_command()
11
-  call test_for_loop_collection()
12
-  call test_nested_commands()
13
-
14
-  print *, ""
15
-  print *, "=== All parser list tests passed! ==="
16
-
17
-contains
18
-
19
-  subroutine test_simple_command()
20
-    type(lexer_t) :: lex
21
-    type(parser_t) :: pars
22
-    type(script_node_t) :: ast
23
-    character(:), allocatable :: input
24
-
25
-    print *, "=== Test: Simple Command with Arguments ==="
26
-
27
-    input = 'echo hello world'
28
-    print *, "Input: ", input
29
-
30
-    ! Tokenize
31
-    call lex%init(input)
32
-    call lex%tokenize()
33
-    print *, "Tokens: ", lex%token_count
34
-
35
-    ! Parse
36
-    call pars%init(lex%tokens, lex%token_count)
37
-    ast = pars%parse()
38
-
39
-    print *, "AST created successfully"
40
-    if (allocated(ast%statements)) then
41
-      print *, "Number of statements: ", size(ast%statements)
42
-
43
-      ! Check the first statement is a command
44
-      select type(stmt => ast%statements(1))
45
-      type is (command_node_t)
46
-        print *, "  First statement is a COMMAND"
47
-        if (allocated(stmt%words)) then
48
-          print *, "  Number of words: ", size(stmt%words)
49
-
50
-          ! Print each word
51
-          block
52
-            integer :: i
53
-            do i = 1, size(stmt%words)
54
-              select type(w => stmt%words(i))
55
-              type is (word_node_t)
56
-                print *, "    Word ", i, ": ", w%text
57
-              end select
58
-            end do
59
-          end block
60
-        end if
61
-      class default
62
-        print *, "  First statement type: ", stmt%node_type
63
-      end select
64
-    else
65
-      print *, "No statements parsed"
66
-    end if
67
-    print *, ""
68
-
69
-    call lex%destroy()
70
-    call pars%destroy()
71
-  end subroutine test_simple_command
72
-
73
-  subroutine test_for_loop_collection()
74
-    type(lexer_t) :: lex
75
-    type(parser_t) :: pars
76
-    type(script_node_t) :: ast
77
-    character(:), allocatable :: input
78
-
79
-    print *, "=== Test: For Loop Word Collection ==="
80
-
81
-    input = 'for item in apple banana cherry' // char(10) // &
82
-            'do' // char(10) // &
83
-            '  echo $item' // char(10) // &
84
-            'done'
85
-    print *, "Input: for loop with 3 items"
86
-
87
-    ! Tokenize
88
-    call lex%init(input)
89
-    call lex%tokenize()
90
-    print *, "Tokens: ", lex%token_count
91
-
92
-    ! Parse
93
-    call pars%init(lex%tokens, lex%token_count)
94
-    ast = pars%parse()
95
-
96
-    print *, "AST created successfully"
97
-    if (allocated(ast%statements)) then
98
-      print *, "Number of statements: ", size(ast%statements)
99
-
100
-      ! Check if first statement is a for loop
101
-      select type(stmt => ast%statements(1))
102
-      type is (for_node_t)
103
-        print *, "  First statement is a FOR loop"
104
-        print *, "  Variable: ", stmt%variable
105
-        if (allocated(stmt%word_list)) then
106
-          print *, "  Number of items in word list: ", size(stmt%word_list)
107
-
108
-          ! Print each word in the list
109
-          block
110
-            integer :: i
111
-            do i = 1, size(stmt%word_list)
112
-              select type(w => stmt%word_list(i))
113
-              type is (word_node_t)
114
-                print *, "    Item ", i, ": ", w%text
115
-              end select
116
-            end do
117
-          end block
118
-        else
119
-          print *, "  No word list collected"
120
-        end if
121
-        if (allocated(stmt%body)) then
122
-          print *, "  Number of body commands: ", size(stmt%body)
123
-        else
124
-          print *, "  No body commands collected"
125
-        end if
126
-      class default
127
-        print *, "  First statement type: ", stmt%node_type
128
-      end select
129
-    end if
130
-    print *, ""
131
-
132
-    call lex%destroy()
133
-    call pars%destroy()
134
-  end subroutine test_for_loop_collection
135
-
136
-  subroutine test_nested_commands()
137
-    type(lexer_t) :: lex
138
-    type(parser_t) :: pars
139
-    type(script_node_t) :: ast
140
-    character(:), allocatable :: input
141
-
142
-    print *, "=== Test: Multiple Commands ==="
143
-
144
-    input = 'echo first' // char(10) // &
145
-            'echo second' // char(10) // &
146
-            'echo third'
147
-    print *, "Input: three echo commands"
148
-
149
-    ! Tokenize
150
-    call lex%init(input)
151
-    call lex%tokenize()
152
-    print *, "Tokens: ", lex%token_count
153
-
154
-    ! Parse
155
-    call pars%init(lex%tokens, lex%token_count)
156
-    ast = pars%parse()
157
-
158
-    print *, "AST created successfully"
159
-    if (allocated(ast%statements)) then
160
-      print *, "Number of statements: ", size(ast%statements)
161
-
162
-      ! Check each statement
163
-      block
164
-        integer :: i
165
-        do i = 1, size(ast%statements)
166
-          select type(stmt => ast%statements(i))
167
-          type is (command_node_t)
168
-            print *, "  Statement ", i, " is a COMMAND"
169
-            if (allocated(stmt%words)) then
170
-              print *, "    Words: ", size(stmt%words)
171
-            end if
172
-          class default
173
-            print *, "  Statement ", i, " type: ", stmt%node_type
174
-          end select
175
-        end do
176
-      end block
177
-    else
178
-      print *, "No statements parsed"
179
-    end if
180
-    print *, ""
181
-
182
-    call lex%destroy()
183
-    call pars%destroy()
184
-  end subroutine test_nested_commands
185
-
186
-end program test_parser_lists
tests/test_parser_simple.f90deleted
@@ -1,152 +0,0 @@
1
-! ==============================================================================
2
-! Simple parser test
3
-! ==============================================================================
4
-program test_parser_simple
5
-  use ast_types
6
-  use lexer
7
-  use parser
8
-  implicit none
9
-
10
-  call test_simple_command()
11
-  call test_for_loop()
12
-  call test_nested_structure()
13
-
14
-contains
15
-
16
-  subroutine test_simple_command()
17
-    type(lexer_t) :: lex
18
-    type(parser_t) :: pars
19
-    type(script_node_t) :: ast
20
-    character(:), allocatable :: input
21
-
22
-    print *, "=== Test: Simple Command ==="
23
-
24
-    input = 'echo "Hello World"'
25
-    print *, "Input: ", input
26
-
27
-    ! Tokenize
28
-    call lex%init(input)
29
-    call lex%tokenize()
30
-    print *, "Tokens: ", lex%token_count
31
-
32
-    ! Parse
33
-    call pars%init(lex%tokens, lex%token_count)
34
-    ast = pars%parse()
35
-
36
-    print *, "AST created successfully"
37
-    if (allocated(ast%statements)) then
38
-      print *, "Number of statements: ", size(ast%statements)
39
-    end if
40
-    print *, ""
41
-
42
-    call lex%destroy()
43
-    call pars%destroy()
44
-  end subroutine test_simple_command
45
-
46
-  subroutine test_for_loop()
47
-    type(lexer_t) :: lex
48
-    type(parser_t) :: pars
49
-    type(script_node_t) :: ast
50
-    character(:), allocatable :: input
51
-
52
-    print *, "=== Test: For Loop ==="
53
-
54
-    input = 'for i in 1 2 3' // char(10) // &
55
-            'do' // char(10) // &
56
-            '  echo $i' // char(10) // &
57
-            'done'
58
-    print *, "Input: for loop with echo"
59
-
60
-    ! Tokenize
61
-    call lex%init(input)
62
-    call lex%tokenize()
63
-    print *, "Tokens: ", lex%token_count
64
-
65
-    ! Parse
66
-    call pars%init(lex%tokens, lex%token_count)
67
-    ast = pars%parse()
68
-
69
-    print *, "AST created successfully"
70
-    if (allocated(ast%statements)) then
71
-      print *, "Number of statements: ", size(ast%statements)
72
-
73
-      ! Check if first statement is a for loop
74
-      select type(stmt => ast%statements(1))
75
-      type is (for_node_t)
76
-        print *, "First statement is a FOR loop"
77
-        print *, "Variable: ", stmt%variable
78
-        if (allocated(stmt%word_list)) then
79
-          print *, "Number of items: ", size(stmt%word_list)
80
-        end if
81
-        if (allocated(stmt%body)) then
82
-          print *, "Number of body commands: ", size(stmt%body)
83
-        end if
84
-      class default
85
-        print *, "First statement type: ", stmt%node_type
86
-      end select
87
-    end if
88
-    print *, ""
89
-
90
-    call lex%destroy()
91
-    call pars%destroy()
92
-  end subroutine test_for_loop
93
-
94
-  subroutine test_nested_structure()
95
-    type(lexer_t) :: lex
96
-    type(parser_t) :: pars
97
-    type(script_node_t) :: ast
98
-    character(:), allocatable :: input
99
-
100
-    print *, "=== Test: Nested Structure ==="
101
-
102
-    input = 'for i in 1 2' // char(10) // &
103
-            'do' // char(10) // &
104
-            '  for j in a b' // char(10) // &
105
-            '  do' // char(10) // &
106
-            '    echo "$i $j"' // char(10) // &
107
-            '  done' // char(10) // &
108
-            'done'
109
-    print *, "Input: nested for loops"
110
-
111
-    ! Tokenize
112
-    call lex%init(input)
113
-    call lex%tokenize()
114
-    print *, "Tokens: ", lex%token_count
115
-
116
-    ! Parse
117
-    call pars%init(lex%tokens, lex%token_count)
118
-    ast = pars%parse()
119
-
120
-    print *, "AST created successfully"
121
-    if (allocated(ast%statements)) then
122
-      print *, "Number of statements: ", size(ast%statements)
123
-
124
-      ! Check structure
125
-      select type(stmt => ast%statements(1))
126
-      type is (for_node_t)
127
-        print *, "Outer loop variable: ", stmt%variable
128
-        if (allocated(stmt%body)) then
129
-          print *, "Outer body commands: ", size(stmt%body)
130
-
131
-          ! Check if inner loop exists
132
-          select type(inner => stmt%body(1))
133
-          type is (for_node_t)
134
-            print *, "Inner loop variable: ", inner%variable
135
-            if (allocated(inner%body)) then
136
-              print *, "Inner body commands: ", size(inner%body)
137
-            end if
138
-          class default
139
-            print *, "Inner statement type: ", inner%node_type
140
-          end select
141
-        end if
142
-      class default
143
-        print *, "First statement type: ", stmt%node_type
144
-      end select
145
-    end if
146
-    print *, ""
147
-
148
-    call lex%destroy()
149
-    call pars%destroy()
150
-  end subroutine test_nested_structure
151
-
152
-end program test_parser_simple
tests/test_regex_matching.shdeleted
@@ -1,248 +0,0 @@
1
-#!/bin/bash
2
-# Comprehensive test suite for regex matching with =~ operator
3
-
4
-echo "=== Regex Matching Test Suite ==="
5
-echo ""
6
-
7
-# Test 1: Basic regex match - digits
8
-echo "TEST 1: Basic Digit Pattern"
9
-echo "============================"
10
-str="12345"
11
-if [[ $str =~ ^[0-9]+$ ]]; then
12
-  echo "✓ PASS: '$str' matches digit pattern"
13
-else
14
-  echo "✗ FAIL: '$str' should match digit pattern"
15
-fi
16
-echo ""
17
-
18
-# Test 2: Regex match with letters
19
-echo "TEST 2: Letter Pattern"
20
-echo "======================"
21
-str="hello"
22
-if [[ $str =~ ^[a-z]+$ ]]; then
23
-  echo "✓ PASS: '$str' matches lowercase letters"
24
-else
25
-  echo "✗ FAIL: '$str' should match lowercase letters"
26
-fi
27
-echo ""
28
-
29
-# Test 3: Regex no match
30
-echo "TEST 3: No Match"
31
-echo "================"
32
-str="hello123"
33
-if [[ $str =~ ^[a-z]+$ ]]; then
34
-  echo "✗ FAIL: '$str' should NOT match letters-only pattern"
35
-else
36
-  echo "✓ PASS: '$str' correctly does not match"
37
-fi
38
-echo ""
39
-
40
-# Test 4: Email pattern
41
-echo "TEST 4: Email Pattern"
42
-echo "====================="
43
-email="user@example.com"
44
-if [[ $email =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
45
-  echo "✓ PASS: '$email' matches email pattern"
46
-else
47
-  echo "✗ FAIL: '$email' should match email pattern"
48
-fi
49
-echo ""
50
-
51
-# Test 5: IP address pattern
52
-echo "TEST 5: IP Address Pattern"
53
-echo "=========================="
54
-ip="192.168.1.1"
55
-if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
56
-  echo "✓ PASS: '$ip' matches IP pattern"
57
-else
58
-  echo "✗ FAIL: '$ip' should match IP pattern"
59
-fi
60
-echo ""
61
-
62
-# Test 6: URL pattern
63
-echo "TEST 6: URL Pattern"
64
-echo "==================="
65
-url="https://example.com/path"
66
-if [[ $url =~ ^https?:// ]]; then
67
-  echo "✓ PASS: '$url' starts with http(s)://"
68
-else
69
-  echo "✗ FAIL: '$url' should match URL pattern"
70
-fi
71
-echo ""
72
-
73
-# Test 7: Word boundary
74
-echo "TEST 7: Word Pattern"
75
-echo "===================="
76
-text="The quick brown fox"
77
-if [[ $text =~ quick ]]; then
78
-  echo "✓ PASS: Found 'quick' in text"
79
-else
80
-  echo "✗ FAIL: Should find 'quick' in text"
81
-fi
82
-echo ""
83
-
84
-# Test 8: Case sensitive matching
85
-echo "TEST 8: Case Sensitive"
86
-echo "======================"
87
-str="Hello"
88
-if [[ $str =~ ^hello$ ]]; then
89
-  echo "✗ FAIL: Should be case sensitive (Hello != hello)"
90
-else
91
-  echo "✓ PASS: Correctly case sensitive"
92
-fi
93
-echo ""
94
-
95
-# Test 9: Anchor patterns
96
-echo "TEST 9: Anchor Patterns"
97
-echo "======================="
98
-str="test123"
99
-if [[ $str =~ ^test ]]; then
100
-  echo "✓ PASS (1/3): Matches start anchor ^test"
101
-else
102
-  echo "✗ FAIL (1/3): Should match start anchor"
103
-fi
104
-
105
-if [[ $str =~ 123$ ]]; then
106
-  echo "✓ PASS (2/3): Matches end anchor 123$"
107
-else
108
-  echo "✗ FAIL (2/3): Should match end anchor"
109
-fi
110
-
111
-if [[ $str =~ ^test123$ ]]; then
112
-  echo "✓ PASS (3/3): Matches full string ^test123$"
113
-else
114
-  echo "✗ FAIL (3/3): Should match full string"
115
-fi
116
-echo ""
117
-
118
-# Test 10: Character classes
119
-echo "TEST 10: Character Classes"
120
-echo "=========================="
121
-str1="abc123"
122
-str2="xyz789"
123
-
124
-if [[ $str1 =~ [0-9]+ ]]; then
125
-  echo "✓ PASS (1/2): '$str1' contains digits"
126
-else
127
-  echo "✗ FAIL (1/2): Should contain digits"
128
-fi
129
-
130
-if [[ $str2 =~ [a-z]+ ]]; then
131
-  echo "✓ PASS (2/2): '$str2' contains letters"
132
-else
133
-  echo "✗ FAIL (2/2): Should contain letters"
134
-fi
135
-echo ""
136
-
137
-# Test 11: Repetition quantifiers
138
-echo "TEST 11: Repetition Quantifiers"
139
-echo "================================"
140
-str="aaaa"
141
-if [[ $str =~ ^a{4}$ ]]; then
142
-  echo "✓ PASS (1/4): Matches exactly 4 a's"
143
-else
144
-  echo "✗ FAIL (1/4): Should match exactly 4 a's"
145
-fi
146
-
147
-str="aaa"
148
-if [[ $str =~ ^a{2,5}$ ]]; then
149
-  echo "✓ PASS (2/4): Matches 2-5 a's"
150
-else
151
-  echo "✗ FAIL (2/4): Should match 2-5 a's"
152
-fi
153
-
154
-str="aaa"
155
-if [[ $str =~ ^a+$ ]]; then
156
-  echo "✓ PASS (3/4): Matches a+ (one or more)"
157
-else
158
-  echo "✗ FAIL (3/4): Should match a+"
159
-fi
160
-
161
-str=""
162
-if [[ $str =~ ^a*$ ]]; then
163
-  echo "✓ PASS (4/4): Matches a* (zero or more)"
164
-else
165
-  echo "✗ FAIL (4/4): Should match a*"
166
-fi
167
-echo ""
168
-
169
-# Test 12: Alternation
170
-echo "TEST 12: Alternation (OR)"
171
-echo "========================="
172
-str="cat"
173
-if [[ $str =~ ^(cat|dog)$ ]]; then
174
-  echo "✓ PASS (1/2): Matches 'cat' or 'dog'"
175
-else
176
-  echo "✗ FAIL (1/2): Should match alternation"
177
-fi
178
-
179
-str="dog"
180
-if [[ $str =~ ^(cat|dog)$ ]]; then
181
-  echo "✓ PASS (2/2): Matches 'cat' or 'dog'"
182
-else
183
-  echo "✗ FAIL (2/2): Should match alternation"
184
-fi
185
-echo ""
186
-
187
-# Test 13: Optional character
188
-echo "TEST 13: Optional Character"
189
-echo "==========================="
190
-str1="color"
191
-str2="colour"
192
-if [[ $str1 =~ ^colou?r$ ]] && [[ $str2 =~ ^colou?r$ ]]; then
193
-  echo "✓ PASS: Both 'color' and 'colour' match colou?r"
194
-else
195
-  echo "✗ FAIL: Should match optional 'u'"
196
-fi
197
-echo ""
198
-
199
-# Test 14: Empty string
200
-echo "TEST 14: Empty String"
201
-echo "====================="
202
-str=""
203
-if [[ $str =~ ^$ ]]; then
204
-  echo "✓ PASS: Empty string matches ^$"
205
-else
206
-  echo "✗ FAIL: Empty string should match ^$"
207
-fi
208
-echo ""
209
-
210
-# Test 15: Special characters (escaped)
211
-echo "TEST 15: Special Characters"
212
-echo "==========================="
213
-str="file.txt"
214
-if [[ $str =~ \.txt$ ]]; then
215
-  echo "✓ PASS: Matches escaped dot \\.txt"
216
-else
217
-  echo "✗ FAIL: Should match \\.txt"
218
-fi
219
-echo ""
220
-
221
-# Test 16: Negation with !
222
-echo "TEST 16: Negation with !"
223
-echo "========================"
224
-str="abc"
225
-if [[ ! $str =~ ^[0-9]+$ ]]; then
226
-  echo "✓ PASS: Correctly negated - not digits"
227
-else
228
-  echo "✗ FAIL: Should not match digits"
229
-fi
230
-echo ""
231
-
232
-# Summary
233
-echo "========================================="
234
-echo "Regex Matching Test Suite Complete"
235
-echo "========================================="
236
-echo ""
237
-echo "Features Tested:"
238
-echo "  ✓ Basic patterns (digits, letters)"
239
-echo "  ✓ Complex patterns (email, IP, URL)"
240
-echo "  ✓ Anchors (^, $)"
241
-echo "  ✓ Character classes ([a-z], [0-9])"
242
-echo "  ✓ Quantifiers (+, *, ?, {n}, {m,n})"
243
-echo "  ✓ Alternation (|)"
244
-echo "  ✓ Case sensitivity"
245
-echo "  ✓ Special characters (escaping)"
246
-echo "  ✓ Negation with !"
247
-echo ""
248
-echo "Note: BASH_REMATCH array capture groups not yet implemented"
tests/test_rematch_debug.shdeleted
@@ -1,17 +0,0 @@
1
-#!/bin/bash
2
-
3
-echo "Debug BASH_REMATCH Test"
4
-str="abc123"
5
-echo "String: $str"
6
-
7
-if [[ $str =~ ^([a-z]+)([0-9]+)$ ]]; then
8
-  echo "Match succeeded"
9
-  echo "Immediately: BASH_REMATCH[0]='${BASH_REMATCH[0]}'"
10
-  echo "Immediately: BASH_REMATCH[1]='${BASH_REMATCH[1]}'"
11
-  echo "Immediately: BASH_REMATCH[2]='${BASH_REMATCH[2]}'"
12
-else
13
-  echo "Match failed"
14
-fi
15
-
16
-echo "After if: BASH_REMATCH[0]='${BASH_REMATCH[0]}'"
17
-echo "After if: BASH_REMATCH[1]='${BASH_REMATCH[1]}'"
tests/test_runner.f90deleted
@@ -1,360 +0,0 @@
1
-! ==============================================================================
2
-! Module: test_runner
3
-! Purpose: Comprehensive test suite for Fortran Shell (fortsh)
4
-! ==============================================================================
5
-program test_runner
6
-  use shell_types
7
-  use parser
8
-  use glob
9
-  use variables
10
-  use control_flow
11
-  use job_control
12
-  use aliases
13
-  use iso_fortran_env, only: output_unit, error_unit
14
-  implicit none
15
-
16
-  integer :: total_tests = 0
17
-  integer :: passed_tests = 0
18
-  integer :: failed_tests = 0
19
-  
20
-  write(output_unit, '(a)') '================================'
21
-  write(output_unit, '(a)') 'Fortran Shell (fortsh) Test Suite'
22
-  write(output_unit, '(a)') '================================'
23
-  write(output_unit, '(a)') ''
24
-  
25
-  ! Run all test suites
26
-  call test_parser_module()
27
-  call test_glob_module()
28
-  call test_variables_module()
29
-  call test_control_flow_module()
30
-  call test_aliases_module()
31
-  call test_error_handling()
32
-  
33
-  ! Print summary
34
-  write(output_unit, '(a)') ''
35
-  write(output_unit, '(a)') '================================'
36
-  write(output_unit, '(a)') 'TEST SUMMARY'
37
-  write(output_unit, '(a)') '================================'
38
-  write(output_unit, '(a,i0)') 'Total tests:  ', total_tests
39
-  write(output_unit, '(a,i0)') 'Passed tests: ', passed_tests
40
-  write(output_unit, '(a,i0)') 'Failed tests: ', failed_tests
41
-  
42
-  if (failed_tests == 0) then
43
-    write(output_unit, '(a)') '✅ ALL TESTS PASSED!'
44
-  else
45
-    write(output_unit, '(a)') '❌ Some tests failed'
46
-  end if
47
-  
48
-  if (failed_tests > 0) then
49
-    call exit(1)
50
-  end if
51
-
52
-contains
53
-
54
-  subroutine assert_true(condition, test_name)
55
-    logical, intent(in) :: condition
56
-    character(len=*), intent(in) :: test_name
57
-    
58
-    total_tests = total_tests + 1
59
-    
60
-    if (condition) then
61
-      write(output_unit, '(a,a)') '✓ ', test_name
62
-      passed_tests = passed_tests + 1
63
-    else
64
-      write(output_unit, '(a,a)') '✗ ', test_name
65
-      failed_tests = failed_tests + 1
66
-    end if
67
-  end subroutine
68
-
69
-  subroutine assert_equal_str(actual, expected, test_name)
70
-    character(len=*), intent(in) :: actual, expected, test_name
71
-    call assert_true(trim(actual) == trim(expected), test_name)
72
-  end subroutine
73
-
74
-  subroutine assert_equal_int(actual, expected, test_name)
75
-    integer, intent(in) :: actual, expected
76
-    character(len=*), intent(in) :: test_name
77
-    call assert_true(actual == expected, test_name)
78
-  end subroutine
79
-
80
-  subroutine test_parser_module()
81
-    write(output_unit, '(a)') 'Testing Parser Module:'
82
-    write(output_unit, '(a)') '====================='
83
-    
84
-    ! Test tokenization
85
-    call test_tokenization()
86
-    
87
-    ! Test pipeline parsing
88
-    call test_pipeline_parsing()
89
-    
90
-    ! Test redirection parsing
91
-    call test_redirection_parsing()
92
-    
93
-    write(output_unit, '(a)') ''
94
-  end subroutine
95
-
96
-  subroutine test_tokenization()
97
-    character(len=:), allocatable :: tokens(:)
98
-    integer :: num_tokens
99
-    
100
-    ! Test basic tokenization
101
-    call tokenize_with_substitution('echo hello world', tokens, num_tokens)
102
-    call assert_equal_int(num_tokens, 3, 'Basic tokenization count')
103
-    if (num_tokens >= 3) then
104
-      call assert_equal_str(tokens(1), 'echo', 'Token 1 correct')
105
-      call assert_equal_str(tokens(2), 'hello', 'Token 2 correct')
106
-      call assert_equal_str(tokens(3), 'world', 'Token 3 correct')
107
-    end if
108
-    if (allocated(tokens)) deallocate(tokens)
109
-    
110
-    ! Test empty input
111
-    call tokenize_with_substitution('', tokens, num_tokens)
112
-    call assert_equal_int(num_tokens, 0, 'Empty input tokenization')
113
-    if (allocated(tokens)) deallocate(tokens)
114
-    
115
-    ! Test whitespace handling
116
-    call tokenize_with_substitution('  echo   test  ', tokens, num_tokens)
117
-    call assert_equal_int(num_tokens, 2, 'Whitespace handling count')
118
-    if (num_tokens >= 2) then
119
-      call assert_equal_str(tokens(1), 'echo', 'Whitespace token 1')
120
-      call assert_equal_str(tokens(2), 'test', 'Whitespace token 2')
121
-    end if
122
-    if (allocated(tokens)) deallocate(tokens)
123
-  end subroutine
124
-
125
-  subroutine test_pipeline_parsing()
126
-    type(pipeline_t) :: pipeline
127
-    
128
-    ! Test single command
129
-    call parse_pipeline('echo hello', pipeline)
130
-    call assert_equal_int(pipeline%num_commands, 1, 'Single command pipeline')
131
-    if (pipeline%num_commands >= 1) then
132
-      call assert_equal_int(pipeline%commands(1)%separator, SEP_NONE, 'Single command separator')
133
-    end if
134
-    
135
-    ! Cleanup
136
-    if (allocated(pipeline%commands)) then
137
-      if (allocated(pipeline%commands(1)%tokens)) deallocate(pipeline%commands(1)%tokens)
138
-      deallocate(pipeline%commands)
139
-    end if
140
-    
141
-    ! Test pipe command
142
-    call parse_pipeline('ls | grep test', pipeline)
143
-    call assert_equal_int(pipeline%num_commands, 2, 'Pipe command pipeline')
144
-    if (pipeline%num_commands >= 2) then
145
-      call assert_equal_int(pipeline%commands(1)%separator, SEP_PIPE, 'Pipe separator')
146
-    end if
147
-    
148
-    ! Cleanup
149
-    if (allocated(pipeline%commands)) then
150
-      do i = 1, pipeline%num_commands
151
-        if (allocated(pipeline%commands(i)%tokens)) deallocate(pipeline%commands(i)%tokens)
152
-        if (allocated(pipeline%commands(i)%input_file)) deallocate(pipeline%commands(i)%input_file)
153
-        if (allocated(pipeline%commands(i)%output_file)) deallocate(pipeline%commands(i)%output_file)
154
-        if (allocated(pipeline%commands(i)%error_file)) deallocate(pipeline%commands(i)%error_file)
155
-        if (allocated(pipeline%commands(i)%heredoc_delimiter)) deallocate(pipeline%commands(i)%heredoc_delimiter)
156
-        if (allocated(pipeline%commands(i)%heredoc_content)) deallocate(pipeline%commands(i)%heredoc_content)
157
-        if (allocated(pipeline%commands(i)%here_string)) deallocate(pipeline%commands(i)%here_string)
158
-      end do
159
-      deallocate(pipeline%commands)
160
-    end if
161
-  end subroutine
162
-
163
-  subroutine test_redirection_parsing()
164
-    type(command_t) :: cmd
165
-    character(len=256) :: input
166
-    
167
-    input = 'echo hello > output.txt'
168
-    call parse_simple_command(input, cmd)
169
-    
170
-    call assert_true(allocated(cmd%output_file), 'Output redirection detected')
171
-    if (allocated(cmd%output_file)) then
172
-      call assert_equal_str(cmd%output_file, 'output.txt', 'Output file correct')
173
-    end if
174
-    call assert_true(.not. cmd%append_output, 'Append flag correct')
175
-    
176
-    ! Cleanup
177
-    if (allocated(cmd%tokens)) deallocate(cmd%tokens)
178
-    if (allocated(cmd%output_file)) deallocate(cmd%output_file)
179
-  end subroutine
180
-
181
-  subroutine test_glob_module()
182
-    write(output_unit, '(a)') 'Testing Glob Module:'
183
-    write(output_unit, '(a)') '==================='
184
-    
185
-    call test_pattern_matching()
186
-    call test_glob_expansion()
187
-    
188
-    write(output_unit, '(a)') ''
189
-  end subroutine
190
-
191
-  subroutine test_pattern_matching()
192
-    ! Test wildcard patterns
193
-    call assert_true(pattern_matches('*.txt', 'file.txt'), 'Simple wildcard match')
194
-    call assert_true(.not. pattern_matches('*.txt', 'file.log'), 'Simple wildcard no match')
195
-    
196
-    ! Test single character wildcard
197
-    call assert_true(pattern_matches('file?.txt', 'file1.txt'), 'Single char wildcard match')
198
-    call assert_true(.not. pattern_matches('file?.txt', 'file10.txt'), 'Single char wildcard no match')
199
-    
200
-    ! Test character classes
201
-    call assert_true(pattern_matches('[abc]*', 'apple'), 'Character class match')
202
-    call assert_true(.not. pattern_matches('[abc]*', 'orange'), 'Character class no match')
203
-    
204
-    ! Test character ranges
205
-    call assert_true(pattern_matches('[a-z]*', 'hello'), 'Character range match')
206
-    call assert_true(.not. pattern_matches('[a-z]*', '123'), 'Character range no match')
207
-    
208
-    ! Test negation
209
-    call assert_true(pattern_matches('[!0-9]*', 'hello'), 'Negation match')
210
-    call assert_true(.not. pattern_matches('[!0-9]*', '123'), 'Negation no match')
211
-  end subroutine
212
-
213
-  subroutine test_glob_expansion()
214
-    character(len=MAX_TOKEN_LEN), allocatable :: expanded_tokens(:)
215
-    character(len=MAX_TOKEN_LEN) :: input_tokens(2)
216
-    integer :: expanded_count
217
-    
218
-    input_tokens(1) = '*.txt'
219
-    input_tokens(2) = 'literal'
220
-    
221
-    call expand_glob_patterns(input_tokens, 2, expanded_tokens, expanded_count)
222
-    call assert_true(expanded_count >= 2, 'Glob expansion returns results')
223
-    call assert_true(allocated(expanded_tokens), 'Expanded tokens allocated')
224
-    
225
-    if (allocated(expanded_tokens)) deallocate(expanded_tokens)
226
-  end subroutine
227
-
228
-  subroutine test_variables_module()
229
-    write(output_unit, '(a)') 'Testing Variables Module:'
230
-    write(output_unit, '(a)') '========================'
231
-    
232
-    call test_variable_assignment()
233
-    call test_variable_expansion()
234
-    
235
-    write(output_unit, '(a)') ''
236
-  end subroutine
237
-
238
-  subroutine test_variable_assignment()
239
-    call assert_true(is_assignment('VAR=value'), 'Simple assignment detection')
240
-    call assert_true(is_assignment('PATH=/usr/bin'), 'Path assignment detection')
241
-    call assert_true(.not. is_assignment('echo hello'), 'Non-assignment detection')
242
-    call assert_true(.not. is_assignment('test='), 'Empty value assignment')
243
-  end subroutine
244
-
245
-  subroutine test_variable_expansion()
246
-    type(shell_state_t) :: shell
247
-    character(len=:), allocatable :: expanded
248
-    
249
-    ! Initialize shell
250
-    shell%num_variables = 1
251
-    shell%variables(1)%name = 'TEST'
252
-    shell%variables(1)%value = 'hello'
253
-    
254
-    call expand_variables('$TEST', expanded, shell)
255
-    call assert_equal_str(expanded, 'hello', 'Simple variable expansion')
256
-    
257
-    call expand_variables('${TEST}world', expanded, shell)
258
-    call assert_equal_str(expanded, 'helloworld', 'Braced variable expansion')
259
-    
260
-    call expand_variables('$NONEXISTENT', expanded, shell)
261
-    call assert_equal_str(expanded, '', 'Non-existent variable expansion')
262
-  end subroutine
263
-
264
-  subroutine test_control_flow_module()
265
-    write(output_unit, '(a)') 'Testing Control Flow Module:'
266
-    write(output_unit, '(a)') '==========================='
267
-    
268
-    call test_control_flow_keywords()
269
-    call test_condition_evaluation()
270
-    
271
-    write(output_unit, '(a)') ''
272
-  end subroutine
273
-
274
-  subroutine test_control_flow_keywords()
275
-    call assert_true(is_control_flow_keyword('if'), 'If keyword recognition')
276
-    call assert_true(is_control_flow_keyword('while'), 'While keyword recognition')
277
-    call assert_true(is_control_flow_keyword('for'), 'For keyword recognition')
278
-    call assert_true(.not. is_control_flow_keyword('echo'), 'Non-keyword rejection')
279
-    
280
-    call assert_equal_int(identify_flow_keyword('if'), FLOW_IF, 'If keyword identification')
281
-    call assert_equal_int(identify_flow_keyword('while'), FLOW_WHILE, 'While keyword identification')
282
-  end subroutine
283
-
284
-  subroutine test_condition_evaluation()
285
-    type(shell_state_t) :: shell
286
-    logical :: result
287
-    
288
-    ! Initialize shell with success status
289
-    shell%last_exit_status = 0
290
-    
291
-    call evaluate_condition('[ "hello" = "hello" ]', shell, result)
292
-    call assert_true(result, 'String equality condition')
293
-    
294
-    call evaluate_condition('[ "hello" = "world" ]', shell, result)
295
-    call assert_true(.not. result, 'String inequality condition')
296
-  end subroutine
297
-
298
-  subroutine test_aliases_module()
299
-    write(output_unit, '(a)') 'Testing Aliases Module:'
300
-    write(output_unit, '(a)') '======================'
301
-    
302
-    call test_alias_operations()
303
-    
304
-    write(output_unit, '(a)') ''
305
-  end subroutine
306
-
307
-  subroutine test_alias_operations()
308
-    type(shell_state_t) :: shell
309
-    character(len=:), allocatable :: expanded_line
310
-    
311
-    ! Initialize shell
312
-    shell%num_aliases = 0
313
-    
314
-    ! Test alias creation
315
-    call set_alias(shell, 'll', 'ls -l')
316
-    call assert_equal_int(shell%num_aliases, 1, 'Alias count after creation')
317
-    call assert_true(is_alias(shell, 'll'), 'Alias existence check')
318
-    
319
-    ! Test alias expansion
320
-    call expand_alias(shell, 'll -a', expanded_line)
321
-    call assert_equal_str(expanded_line, 'ls -l -a', 'Alias expansion')
322
-    
323
-    ! Test non-alias expansion
324
-    call expand_alias(shell, 'echo hello', expanded_line)
325
-    call assert_equal_str(expanded_line, 'echo hello', 'Non-alias passthrough')
326
-  end subroutine
327
-
328
-  subroutine test_error_handling()
329
-    write(output_unit, '(a)') 'Testing Error Handling:'
330
-    write(output_unit, '(a)') '======================'
331
-    
332
-    call test_parser_error_handling()
333
-    call test_command_error_handling()
334
-    
335
-    write(output_unit, '(a)') ''
336
-  end subroutine
337
-
338
-  subroutine test_parser_error_handling()
339
-    type(pipeline_t) :: pipeline
340
-    
341
-    ! Test malformed pipeline
342
-    call parse_pipeline('command |', pipeline)
343
-    call assert_equal_int(pipeline%num_commands, 1, 'Malformed pipe handling')
344
-    
345
-    ! Cleanup
346
-    if (allocated(pipeline%commands)) then
347
-      if (allocated(pipeline%commands(1)%tokens)) deallocate(pipeline%commands(1)%tokens)
348
-      deallocate(pipeline%commands)
349
-    end if
350
-  end subroutine
351
-
352
-  subroutine test_command_error_handling()
353
-    ! Test invalid redirection
354
-    call assert_true(.true., 'Invalid redirection placeholder test')
355
-    
356
-    ! Test command not found
357
-    call assert_true(.true., 'Command not found placeholder test')
358
-  end subroutine
359
-
360
-end program test_runner
tests/test_simple_rematch.shdeleted
@@ -1,14 +0,0 @@
1
-#!/bin/bash
2
-
3
-echo "Simple BASH_REMATCH test"
4
-str="John Doe"
5
-echo "String: $str"
6
-
7
-if [[ $str =~ ^([A-Z][a-z]+)\ ([A-Z][a-z]+)$ ]]; then
8
-  echo "Match SUCCESS"
9
-  echo "BASH_REMATCH[0]: '${BASH_REMATCH[0]}'"
10
-  echo "BASH_REMATCH[1]: '${BASH_REMATCH[1]}'"
11
-  echo "BASH_REMATCH[2]: '${BASH_REMATCH[2]}'"
12
-else
13
-  echo "Match FAILED"
14
-fi
tests/test_tilde.shdeleted
@@ -1,78 +0,0 @@
1
-#!/bin/bash
2
-# Test tilde expansion
3
-
4
-echo "=== Tilde Expansion Tests ==="
5
-echo ""
6
-
7
-# Set up test environment
8
-export HOME="/home/testuser"
9
-export PWD="/current/dir"
10
-export OLDPWD="/previous/dir"
11
-
12
-# Test 1: Simple ~
13
-echo "Test 1: echo ~"
14
-result=$(echo ~)
15
-expected="$HOME"
16
-if [ "$result" = "$expected" ]; then
17
-    echo "✓ PASS: ~ expanded to $result"
18
-else
19
-    echo "✗ FAIL: expected $expected, got $result"
20
-fi
21
-echo ""
22
-
23
-# Test 2: ~/path
24
-echo "Test 2: echo ~/documents"
25
-result=$(echo ~/documents)
26
-expected="$HOME/documents"
27
-if [ "$result" = "$expected" ]; then
28
-    echo "✓ PASS: ~/documents expanded to $result"
29
-else
30
-    echo "✗ FAIL: expected $expected, got $result"
31
-fi
32
-echo ""
33
-
34
-# Test 3: ~+ (current directory)
35
-echo "Test 3: echo ~+"
36
-result=$(echo ~+)
37
-expected="$PWD"
38
-if [ "$result" = "$expected" ]; then
39
-    echo "✓ PASS: ~+ expanded to $result"
40
-else
41
-    echo "✗ FAIL: expected $expected, got $result"
42
-fi
43
-echo ""
44
-
45
-# Test 4: ~- (previous directory)
46
-echo "Test 4: echo ~-"
47
-result=$(echo ~-)
48
-expected="$OLDPWD"
49
-if [ "$result" = "$expected" ]; then
50
-    echo "✓ PASS: ~- expanded to $result"
51
-else
52
-    echo "✗ FAIL: expected $expected, got $result"
53
-fi
54
-echo ""
55
-
56
-# Test 5: ~username (should work if user exists)
57
-echo "Test 5: echo ~root"
58
-result=$(echo ~root)
59
-# Just check it doesn't still have the tilde
60
-if [[ "$result" != "~root" ]]; then
61
-    echo "✓ PASS: ~root expanded to $result"
62
-else
63
-    echo "✗ FAIL: ~root was not expanded"
64
-fi
65
-echo ""
66
-
67
-# Test 6: Non-tilde word (should not be expanded)
68
-echo "Test 6: echo notilde"
69
-result=$(echo notilde)
70
-expected="notilde"
71
-if [ "$result" = "$expected" ]; then
72
-    echo "✓ PASS: notilde remained $result"
73
-else
74
-    echo "✗ FAIL: expected $expected, got $result"
75
-fi
76
-echo ""
77
-
78
-echo "=== Tests Complete ==="
tests/test_very_simple.shdeleted
@@ -1,30 +0,0 @@
1
-#!/bin/bash
2
-
3
-str="12345"
4
-echo "Test 1: Simple digit pattern"
5
-if [[ $str =~ ^[0-9]+$ ]]; then
6
-  echo "PASS: digits matched"
7
-  echo "BASH_REMATCH[0]: '${BASH_REMATCH[0]}'"
8
-else
9
-  echo "FAIL: digits should match"
10
-fi
11
-
12
-str2="hello"
13
-echo "Test 2: Simple letter pattern"
14
-if [[ $str2 =~ ^[a-z]+$ ]]; then
15
-  echo "PASS: letters matched"
16
-  echo "BASH_REMATCH[0]: '${BASH_REMATCH[0]}'"
17
-else
18
-  echo "FAIL: letters should match"
19
-fi
20
-
21
-str3="abc123"
22
-echo "Test 3: Pattern with capture group"
23
-if [[ $str3 =~ ^([a-z]+)([0-9]+)$ ]]; then
24
-  echo "PASS: pattern matched"
25
-  echo "BASH_REMATCH[0]: '${BASH_REMATCH[0]}'"
26
-  echo "BASH_REMATCH[1]: '${BASH_REMATCH[1]}'"
27
-  echo "BASH_REMATCH[2]: '${BASH_REMATCH[2]}'"
28
-else
29
-  echo "FAIL: pattern should match"
30
-fi