#!/bin/sh
# info: test -argfile and @ variants
# syntax: $0 (define JDKDIR and AJBASE)
# @process-test ajc argfiles.sh # test -argfile and @ variants

[ -n "$DEBUG" ] && set -vx 

errMssg() {
    [ -n "$1" ] && echo "## $0 $1"
    [ -n "$2" ] && exit "$2"
}

## @testcase (support) NPE with -argfile foo.lst with "*.java"
testcaseDesign() {
cat<<EOF
## input variants
command line:  [ [-argfile | @] X <fileRef>{lst} ]...
fileRef:       [[local | relative | absolute] X [DOS|Unix|Mac]]
file line:     [ option | [@<fileRef>{lst} | <fileRef>{java|aj}] ]
option:        ajc options
refLocality:   [cwd | argfile]

## white box
- @, -argfile delegate to same file-creation method
- direct locality matters: null used for for locals and..
- indirect locality matters: referent varies

## design
-- structure
- invocation
  - could set up as unit tests of ConfigParser.java
    - if so, have also to test delivery to ajc? e.g., do package names
      get calculated correctly under different path variants?
      Probably not an issue now, but perhaps later when source-path
      searching is enabled.
  - could invoke ajc.Main programmatically - can ajc be run repeatedly?
    -> might be easier/safer to script, uncover [bash, DOS,...] shell quirks?
-- test case variants
- command-line 
  - test options
    - ajc
    - esp. multi-flag (-source 1.4) - separate lines?
    - VM/Javac?
  - @, -argfile is independent
  - test 0, 1, 3 on same line, interspersed
  - error: @java file, unflagged arg file
- fileRef depends on locality:
  - parm file: CWD, relative-up, relative down-up, absolute, wrong \/:
    - relative and absolute traversing through directories with
      spaces in them (not in package-named directories)
  - file line: same, with * variants 
    - * variants: [*.java | *.aj] [ empty | 1 | n>1 ]
- fileRef also depends on indirection path:
  - add traversal cases
    - 1-2 levels of indirection
- need to think about whether indirection depends on locality reference
  i.e., whether 1-2 levels of indirection need to be through
  all locality types (CWD, relative...)
- basic argfile
  - options
  - files
  - @ref
  - comments
  - empty lines
  - *.java, *.aj references - re

## implementation
- Source tree 
  - minimal, star, maximal: all need each other to compile
  - some in default package, others in named packages
  - some do not share the same source base (or file system?)
  - files:
  Minimal:
  src/
    Main.java
    pack/Main.java
  Star:
  star/
    Main.java
    empty/
    many/One.java
    many/Two.java
    
  Maximal:
  src1/
    Src1DefaultMain.java
    pack1/Src1Pack1Main.java
    pack2/Src1Pack2Main.java
  src2/
    Src2DefaultMain.java
    pack1/Src2Pack1Main.java
    pack2/Src2Pack2Main.java

-

EOF
}

generateCurrentSource() {
    genSource "" Main "Main SomeClass" > Main.java
    genSource "" SomeClass "Main SomeClass" > SomeClass.java

    cat > current_Main_0.lst <<EOF
*.java
EOF
    cat > current_SomeClass_0.lst <<EOF
*.java
EOF
    echo "current"
}

generateMinimalSource() {
    mkdir -p src src/pack
    genSource "" Main "Main pack.Main" > src/Main.java
    genSource pack Main "pack.Main" > src/pack/Main.java

    cat > src/minimal_pack.Main_0.lst <<EOF
pack/Main.java
EOF
    cat > src/minimal_Main_1.lst <<EOF
Main.java
pack/Main.java
EOF
    cat > src/pack/minimal_Main_2.lst <<EOF
../Main.java
Main.java
EOF
    cat > src/pack/minimal_Main_3.lst <<EOF
../*.java
*.java
EOF
    cat > minimal_Main_4.lst <<EOF
@src/minimal_Main_1.lst
EOF
    cat > src/minimal_Main_5.lst <<EOF
@minimal_Main_1.lst
EOF
    cat > src/minimal_Main_6.lst <<EOF
@../src/minimal_Main_1.lst
EOF
    cat > src/minimal_Main_7.lst <<EOF
// starting comment
Main.java        // end of line comment
// middle comment
pack/Main.java
// end comment
EOF
    cat > src/minimal_Main_8.lst <<EOF
*.java
pack/*.java
EOF
    echo "minimal"
}

generateStarSource() {
    echo "todo incomplete"
    mkdir -p star star/many star/empty
    genSource "" Main "Main many.One many.Two" > star/Main.java
    genSource "many" Main "many.One many.Two" > star/many/One.java
    genSource "many" Main "many.One many.Two" > star/many/Two.java
    cat > star/star_Main_1.lst <<EOF
*.java
empty/*.java
many/*.java
EOF
  
    mkdir src1/pack1 src1/pack2 src2/pack1 src2/pack2
    refs="pack1.Src1Pack1Main pack2.Src1Pack2Main pack1.Src2Pack1Main pack2.Src2Pack2Main"
    genSource "" Main "Src1Main $refs" > src1/Src1Main.java
    genSource "" Main "Src2Main $refs" > src2/Src2Main.java
    genSource "pack1" Main "$refs" > src1/pack1/Src1Pack1Main.java
    genSource "pack2" Main "$refs" > src1/pack2/Src1Pack2Main.java
    genSource "pack1" Main "$refs" > src2/pack1/Src2Pack1Main.java
    genSource "pack2" Main "$refs" > src2/pack2/Src2Pack2Main.java
}

genSource() {
    package="$1"
    class="$2"
    refs="$3"
    if [ -z "$package" ] ; then
      name="$class"
    else
      echo "package $package;"
      name="$package.$class"
    fi
cat<<EOF
public class $class {
    public static final String NAME = "$name";
    public static String[] ARGS = new String[] 
EOF
    sep='{'
    for i in $refs ; do
      echo "    $sep ${i}.NAME"
      sep=','
    done
cat<<EOF
    };
    public static void main (String[] args) {
        util.Util.signal(NAME + ".main",ARGS);
    } 
} // class $class
EOF
}

getMain() {
    [ -n "$1" ] && echo "$1" | sed 's|.*_\([^_][^_]*\)_.*|\1|'
}

compile() {
  [ -d classes ] || mkdir classes
  rm -rf classes/*
  $JDKDIR/bin/java -classpath "$toolsjar" org.aspectj.tools.ajc.Main \
     -d classes -classpath "$utiljar${PS}$rtjar" "${@}"
}

run() {
  $JDKDIR/bin/java -classpath "$utiljar${PS}$rtjar${PS}classes" "${@}"
}

testAjc() {
  argfile="$1"
  [ -n "$VERBOSE" ] && echo "# $1"
  [ -f "$argfile" ] || errMssg "testAjc argfile: $1" 3
  main=`getMain "$argfile"`
  [ -n "$main" ]  || errMssg "testAjc no main for argfile: $1" 3
  compile -argfile "$argfile" || errMssg "testAjc compile 1 fail: $1" 3
  run "$main" || errMssg "testAjc run 1 fail: $1" 3
  compile @"$argfile" || errMssg "testAjc compile 2 fail: $1" 3
  run "$main" || errMssg "testAjc run 2 fail: $1" 3
}

createUtilJar() {
  mkdir util
  cat > util/Util.java <<EOF
package util;
public class Util {
    public static void signal(String label, String[] names) {
        boolean printing = $printing;
        if (printing) {
            StringBuffer sb = new StringBuffer();
            sb.append(label);
            sb.append("=[");
            for (int i = 0; i < names.length; i++) {
              if (i > 0) sb.append(", ");
              sb.append(names[i]);
            }
            sb.append("]");
            System.out.println(sb.toString());
        }
    }
}
EOF
compile util/Util.java
"$JDKDIR/bin/jar" cf "$utiljar" -C classes .
rm -rf util
}

getArgFiles() {
  name="$1"
  find . -name "$1"\*.lst | sed 's|./||'
}

echoSetup() {
cat<<EOF
##### setup for $0
  JDKDIR:    $JDKDIR
  AJ_BASE:   $AJ_BASE
  uname -a:  `uname -a`
EOF
}

############################################################## execution
printing=true # must be true or false
JDKDIR="${JDKDIR:-c:/home/apps/jdk13}"
AJ_BASE="${AJ_BASE:-c:/home/wes/aj/aj-dist/tools}"
[ -d "$JDKDIR" ] || errMssg "require JDKDIR=$JDKDIR" 3
[ -d "$AJ_BASE" ] || errMssg "require AJ_BASE=$AJ_BASE" 3
toolsjar="$AJ_BASE/lib/aspectjtools.jar"
rtjar="$AJ_BASE/lib/aspectjrt.jar"
utiljar="$AJ_BASE/lib/argfilesUtil.jar"
[ -f "$toolsjar" ] || errMssg "require toolsjar=$toolsjar" 3
[ -f "$rtjar" ] || errMssg "require rtjar=$rtjar" 3
[ -f "$utiljar" ] || createUtilJar
echoSetup

d=tempArgfiles
[ -d $d ] && rm -rf $d 
mkdir $d  && cd $d

name=`generateCurrentSource`
for i in `getArgFiles "$name"` ; do testAjc "$i"; done

name=`generateMinimalSource`
for i in `getArgFiles "$name"` ; do testAjc "$i"; done

# re-run without src prefix..
cd src
for i in `getArgFiles "$name"` ; do testAjc "$i"; done
echo "tests passed if no compiler failures, only output"