|
| 1 | +name: riscv64 zvl256b qemu test |
| 2 | + |
| 3 | +on: [push, pull_request] |
| 4 | + |
| 5 | +concurrency: |
| 6 | + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} |
| 7 | + cancel-in-progress: true |
| 8 | + |
| 9 | +permissions: |
| 10 | + contents: read # to fetch code (actions/checkout) |
| 11 | + |
| 12 | +jobs: |
| 13 | + TEST: |
| 14 | + if: "github.repository == 'OpenMathLib/OpenBLAS'" |
| 15 | + runs-on: ubuntu-latest |
| 16 | + env: |
| 17 | + triple: riscv64-unknown-linux-gnu |
| 18 | + riscv_gnu_toolchain: https://github.com/riscv-collab/riscv-gnu-toolchain |
| 19 | + riscv_gnu_toolchain_version: 13.2.0 |
| 20 | + riscv_gnu_toolchain_nightly_download_path: /releases/download/2024.02.02/riscv64-glibc-ubuntu-22.04-llvm-nightly-2024.02.02-nightly.tar.gz |
| 21 | + strategy: |
| 22 | + fail-fast: false |
| 23 | + matrix: |
| 24 | + include: |
| 25 | + - target: RISCV64_ZVL128B |
| 26 | + opts: TARGET=RISCV64_ZVL128B BINARY=64 ARCH=riscv64 |
| 27 | + qemu_cpu: rv64,g=true,c=true,v=true,vext_spec=v1.0,vlen=128,elen=64 |
| 28 | + - target: RISCV64_ZVL256B |
| 29 | + opts: TARGET=RISCV64_ZVL256B BINARY=64 ARCH=riscv64 |
| 30 | + qemu_cpu: rv64,g=true,c=true,v=true,vext_spec=v1.0,vlen=256,elen=64 |
| 31 | + |
| 32 | + steps: |
| 33 | + - name: Checkout repository |
| 34 | + uses: actions/checkout@v3 |
| 35 | + |
| 36 | + - name: install build deps |
| 37 | + run: | |
| 38 | + sudo apt-get update |
| 39 | + sudo apt-get install autoconf automake autotools-dev ninja-build make \ |
| 40 | + libgomp1-riscv64-cross ccache |
| 41 | + wget ${riscv_gnu_toolchain}/${riscv_gnu_toolchain_nightly_download_path} |
| 42 | + tar -xvf $(basename ${riscv_gnu_toolchain_nightly_download_path}) -C /opt |
| 43 | +
|
| 44 | + - name: Compilation cache |
| 45 | + uses: actions/cache@v3 |
| 46 | + with: |
| 47 | + path: ~/.ccache |
| 48 | + key: ccache-${{ runner.os }}-${{ matrix.target }}-${{ github.ref }}-${{ github.sha }} |
| 49 | + restore-keys: | |
| 50 | + ccache-${{ runner.os }}-${{ matrix.target }}-${{ github.ref }} |
| 51 | + ccache-${{ runner.os }}-${{ matrix.target }} |
| 52 | +
|
| 53 | + - name: Configure ccache |
| 54 | + run: | |
| 55 | + test -d ~/.ccache || mkdir -p ~/.ccache |
| 56 | + echo "max_size = 300M" > ~/.ccache/ccache.conf |
| 57 | + echo "compression = true" >> ~/.ccache/ccache.conf |
| 58 | + ccache -s |
| 59 | +
|
| 60 | + - name: build OpenBLAS libs |
| 61 | + run: | |
| 62 | + export PATH="/opt/riscv/bin:$PATH" |
| 63 | + make TARGET=${{ matrix.target }} CFLAGS="-DTARGET=${{ matrix.target }}" \ |
| 64 | + CC='ccache clang --rtlib=compiler-rt -target ${triple} --sysroot /opt/riscv/sysroot --gcc-toolchain=/opt/riscv/lib/gcc/riscv64-unknown-linux-gnu/${riscv_gnu_toolchain_version}/' \ |
| 65 | + AR='ccache ${triple}-ar' AS='ccache ${triple}-gcc' LD='ccache ${triple}-gcc' \ |
| 66 | + RANLIB='ccache ${triple}-ranlib' \ |
| 67 | + FC='ccache ${triple}-gfortran' ${{ matrix.opts }} \ |
| 68 | + HOSTCC=gcc HOSTFC=gfortran -j$(nproc) |
| 69 | +
|
| 70 | + - name: build OpenBLAS tests |
| 71 | + run: | |
| 72 | + export PATH="/opt/riscv/bin:$PATH" |
| 73 | + make TARGET=${{ matrix.target }} CFLAGS="-DTARGET=${{ matrix.target }}" \ |
| 74 | + CC='${triple}-gcc' \ |
| 75 | + AR='ccache ${triple}-ar' AS='ccache ${triple}-gcc' LD='ccache ${triple}-gcc' \ |
| 76 | + RANLIB='ccache ${triple}-ranlib' \ |
| 77 | + FC='ccache ${triple}-gfortran' ${{ matrix.opts }} \ |
| 78 | + HOSTCC=gcc HOSTFC=gfortran -j$(nproc) tests |
| 79 | +
|
| 80 | + - name: build lapack-netlib tests |
| 81 | + working-directory: ./lapack-netlib/TESTING |
| 82 | + run: | |
| 83 | + export PATH="/opt/riscv/bin:$PATH" |
| 84 | + make TARGET=${{ matrix.target }} CFLAGS="-DTARGET=${{ matrix.target }}" \ |
| 85 | + CC='${triple}-gcc' \ |
| 86 | + AR='ccache ${triple}-ar' AS='ccache ${triple}-gcc' LD='ccache ${triple}-gcc' \ |
| 87 | + RANLIB='ccache ${triple}-ranlib' \ |
| 88 | + FC='ccache ${triple}-gfortran' ${{ matrix.opts }} \ |
| 89 | + HOSTCC=gcc HOSTFC=gfortran -j$(nproc) \ |
| 90 | + LIN/xlintsts LIN/xlintstc LIN/xlintstd LIN/xlintstz LIN/xlintstrfs \ |
| 91 | + LIN/xlintstrfc LIN/xlintstrfd LIN/xlintstrfz LIN/xlintstds \ |
| 92 | + LIN/xlintstzc EIG/xeigtsts EIG/xeigtstc EIG/xeigtstd EIG/xeigtstz \ |
| 93 | +
|
| 94 | + - name: OpenBLAS tests |
| 95 | + shell: bash |
| 96 | + run: | |
| 97 | + export PATH="/opt/riscv/bin:$PATH" |
| 98 | + export QEMU_CPU=${{ matrix.qemu_cpu }} |
| 99 | + rm -rf ./test_out |
| 100 | + mkdir -p ./test_out |
| 101 | + run_test() { local DIR=$1; local CMD=$2; local DATA=$3; local OUTPUT="./test_out/$DIR.$CMD"; \ |
| 102 | + echo "`pwd`/$DIR/$CMD $DIR/$DATA" >> $OUTPUT; \ |
| 103 | + if [[ -z $DATA ]]; then qemu-riscv64 ./$DIR/$CMD |& tee $OUTPUT ; \ |
| 104 | + else qemu-riscv64 ./$DIR/$CMD < ./$DIR/$DATA |& tee $OUTPUT ; fi ; \ |
| 105 | + RV=$? ; if [[ $RV != 0 ]]; then echo "*** FAIL: nonzero exit code $RV" >> $OUTPUT ; fi \ |
| 106 | + } |
| 107 | + run_test test cblat1 & |
| 108 | + run_test test cblat2 cblat2.dat & |
| 109 | + run_test test cblat3 cblat3.dat & |
| 110 | + run_test test dblat1 & |
| 111 | + run_test test dblat2 dblat2.dat & |
| 112 | + run_test test dblat3 dblat3.dat & |
| 113 | + run_test test sblat1 & |
| 114 | + run_test test sblat2 sblat2.dat & |
| 115 | + run_test test sblat3 sblat3.dat & |
| 116 | + run_test test zblat1 & |
| 117 | + run_test test zblat2 zblat2.dat & |
| 118 | + run_test test zblat3 zblat3.dat & |
| 119 | + run_test ctest xccblat1 & |
| 120 | + run_test ctest xccblat2 cin2 & |
| 121 | + run_test ctest xccblat3 cin3 & |
| 122 | + run_test ctest xdcblat1 & |
| 123 | + run_test ctest xdcblat2 din2 & |
| 124 | + run_test ctest xdcblat3 din3 & |
| 125 | + run_test ctest xscblat1 & |
| 126 | + run_test ctest xscblat2 sin2 & |
| 127 | + run_test ctest xscblat3 sin3 & |
| 128 | + run_test ctest xzcblat1 & |
| 129 | + run_test ctest xzcblat2 zin2 & |
| 130 | + run_test ctest xzcblat3 zin3 & |
| 131 | + wait |
| 132 | + while IFS= read -r -d $'\0' LOG; do cat $LOG ; FAILURES=1 ; done < <(grep -lZ FAIL ./test_out/*) |
| 133 | + if [[ ! -z $FAILURES ]]; then echo "==========" ; echo "== FAIL ==" ; echo "==========" ; echo ; exit 1 ; fi |
| 134 | +
|
| 135 | + - name: netlib tests |
| 136 | + shell: bash |
| 137 | + run: | |
| 138 | + : # these take a very long time |
| 139 | + echo "Skipping netlib tests in CI" |
| 140 | + exit 0 |
| 141 | + : # comment out exit above to enable the tests |
| 142 | + : # probably we want to identify a subset to run in CI |
| 143 | + export PATH="/opt/riscv/bin:$PATH" |
| 144 | + export QEMU_CPU=${{ matrix.qemu_cpu }} |
| 145 | + rm -rf ./test_out |
| 146 | + mkdir -p ./test_out |
| 147 | + run_test() { local OUTPUT="./test_out/$1"; local DATA="./lapack-netlib/TESTING/$2"; local CMD="./lapack-netlib/TESTING/$3"; \ |
| 148 | + echo "$4" >> $OUTPUT; \ |
| 149 | + echo "$CMD" >> $OUTPUT; \ |
| 150 | + qemu-riscv64 $CMD < $DATA |& tee $OUTPUT; \ |
| 151 | + RV=$? ; if [[ $RV != 0 ]]; then echo "*** FAIL: nonzero exit code $RV" >> $OUTPUT ; fi; \ |
| 152 | + if grep -q fail $OUTPUT ; then echo "*** FAIL: log contains 'fail'" >> $OUTPUT ; fi ; \ |
| 153 | + if grep -q rror $OUTPUT | grep -v -q "passed" | grep -v "largest error" ; then echo "*** FAIL: log contains 'error'" >> $OUTPUT ; fi \ |
| 154 | + } |
| 155 | + run_test stest.out stest.in LIN/xlintsts "Testing REAL LAPACK linear equation routines" & |
| 156 | + run_test ctest.out ctest.in LIN/xlintstc "Testing COMPLEX LAPACK linear equation routines" & |
| 157 | + run_test dtest.out dtest.in LIN/xlintstd "Testing DOUBLE PRECISION LAPACK linear equation routines" & |
| 158 | + run_test ztest.out ztest.in LIN/xlintstz "Testing COMPLEX16 LAPACK linear equation routines" & |
| 159 | + run_test dstest.out dstest.in LIN/xlintstds "Testing SINGLE-DOUBLE PRECISION LAPACK prototype linear equation routines" & |
| 160 | + run_test zctest.out zctest.in LIN/xlintstzc "Testing COMPLEX-COMPLEX16 LAPACK prototype linear equation routines" & |
| 161 | + run_test stest_rfp.out stest_rfp.in LIN/xlintstrfs "Testing REAL LAPACK RFP prototype linear equation routines" & |
| 162 | + run_test dtest_rfp.out dtest_rfp.in LIN/xlintstrfd "Testing DOUBLE PRECISION LAPACK RFP prototype linear equation routines" & |
| 163 | + run_test ctest_rfp.out ctest_rfp.in LIN/xlintstrfc "Testing COMPLEX LAPACK RFP prototype linear equation routines" & |
| 164 | + run_test ztest_rfp.out ztest_rfp.in LIN/xlintstrfz "Testing COMPLEX16 LAPACK RFP prototype linear equation routines" & |
| 165 | + run_test snep.out nep.in EIG/xeigtsts "NEP - Testing Nonsymmetric Eigenvalue Problem routines" & |
| 166 | + run_test ssep.out sep.in EIG/xeigtsts "SEP - Testing Symmetric Eigenvalue Problem routines" & |
| 167 | + run_test sse2.out se2.in EIG/xeigtsts "SEP - Testing Symmetric Eigenvalue Problem routines" & |
| 168 | + run_test ssvd.out svd.in EIG/xeigtsts "SVD - Testing Singular Value Decomposition routines" & |
| 169 | + run_test sec.out sec.in EIG/xeigtsts "SEC - Testing REAL Eigen Condition Routines" & |
| 170 | + run_test sed.out sed.in EIG/xeigtsts "SEV - Testing REAL Nonsymmetric Eigenvalue Driver" & |
| 171 | + run_test sgg.out sgg.in EIG/xeigtsts "SGG - Testing REAL Nonsymmetric Generalized Eigenvalue Problem routines" & |
| 172 | + run_test sgd.out sgd.in EIG/xeigtsts "SGD - Testing REAL Nonsymmetric Generalized Eigenvalue Problem driver routines" & |
| 173 | + run_test ssb.out ssb.in EIG/xeigtsts "SSB - Testing REAL Symmetric Eigenvalue Problem routines" & |
| 174 | + run_test ssg.out ssg.in EIG/xeigtsts "SSG - Testing REAL Symmetric Generalized Eigenvalue Problem routines" & |
| 175 | + run_test sbal.out sbal.in EIG/xeigtsts "SGEBAL - Testing the balancing of a REAL general matrix" & |
| 176 | + run_test sbak.out sbak.in EIG/xeigtsts "SGEBAK - Testing the back transformation of a REAL balanced matrix" & |
| 177 | + run_test sgbal.out sgbal.in EIG/xeigtsts "SGGBAL - Testing the balancing of a pair of REAL general matrices" & |
| 178 | + run_test sgbak.out sgbak.in EIG/xeigtsts "SGGBAK - Testing the back transformation of a pair of REAL balanced matrices" & |
| 179 | + run_test sbb.out sbb.in EIG/xeigtsts "SBB - Testing banded Singular Value Decomposition routines" & |
| 180 | + run_test sglm.out glm.in EIG/xeigtsts "GLM - Testing Generalized Linear Regression Model routines" & |
| 181 | + run_test sgqr.out gqr.in EIG/xeigtsts "GQR - Testing Generalized QR and RQ factorization routines" & |
| 182 | + run_test sgsv.out gsv.in EIG/xeigtsts "GSV - Testing Generalized Singular Value Decomposition routines" & |
| 183 | + run_test scsd.out csd.in EIG/xeigtsts "CSD - Testing CS Decomposition routines" & |
| 184 | + run_test slse.out lse.in EIG/xeigtsts "LSE - Testing Constrained Linear Least Squares routines" & |
| 185 | + run_test cnep.out nep.in EIG/xeigtstc "NEP - Testing Nonsymmetric Eigenvalue Problem routines" & |
| 186 | + run_test csep.out sep.in EIG/xeigtstc "SEP - Testing Symmetric Eigenvalue Problem routines" & |
| 187 | + run_test cse2.out se2.in EIG/xeigtstc "SEP - Testing Symmetric Eigenvalue Problem routines" & |
| 188 | + run_test csvd.out svd.in EIG/xeigtstc "SVD - Testing Singular Value Decomposition routines" & |
| 189 | + run_test cec.out cec.in EIG/xeigtstc "CEC - Testing COMPLEX Eigen Condition Routines" & |
| 190 | + run_test ced.out ced.in EIG/xeigtstc "CES - Testing COMPLEX Nonsymmetric Schur Form Driver" & |
| 191 | + run_test cgg.out cgg.in EIG/xeigtstc "CGG - Testing COMPLEX Nonsymmetric Generalized Eigenvalue Problem routines" & |
| 192 | + run_test cgd.out cgd.in EIG/xeigtstc "CGD - Testing COMPLEX Nonsymmetric Generalized Eigenvalue Problem driver routines" & |
| 193 | + run_test csb.out csb.in EIG/xeigtstc "CHB - Testing Hermitian Eigenvalue Problem routines" & |
| 194 | + run_test csg.out csg.in EIG/xeigtstc "CSG - Testing Symmetric Generalized Eigenvalue Problem routines" & |
| 195 | + run_test cbal.out cbal.in EIG/xeigtstc "CGEBAL - Testing the balancing of a COMPLEX general matrix" & |
| 196 | + run_test cbak.out cbak.in EIG/xeigtstc "CGEBAK - Testing the back transformation of a COMPLEX balanced matrix" & |
| 197 | + run_test cgbal.out cgbal.in EIG/xeigtstc "CGGBAL - Testing the balancing of a pair of COMPLEX general matrices" & |
| 198 | + run_test cgbak.out cgbak.in EIG/xeigtstc "CGGBAK - Testing the back transformation of a pair of COMPLEX balanced matrices" & |
| 199 | + run_test cbb.out cbb.in EIG/xeigtstc "CBB - Testing banded Singular Value Decomposition routines" & |
| 200 | + run_test cglm.out glm.in EIG/xeigtstc "GLM - Testing Generalized Linear Regression Model routines" & |
| 201 | + run_test cgqr.out gqr.in EIG/xeigtstc "GQR - Testing Generalized QR and RQ factorization routines" & |
| 202 | + run_test cgsv.out gsv.in EIG/xeigtstc "GSV - Testing Generalized Singular Value Decomposition routines" & |
| 203 | + run_test ccsd.out csd.in EIG/xeigtstc "CSD - Testing CS Decomposition routines" & |
| 204 | + run_test clse.out lse.in EIG/xeigtstc "LSE - Testing Constrained Linear Least Squares routines" & |
| 205 | + run_test dnep.out nep.in EIG/xeigtstd "NEP - Testing Nonsymmetric Eigenvalue Problem routines" & |
| 206 | + run_test dsep.out sep.in EIG/xeigtstd "SEP - Testing Symmetric Eigenvalue Problem routines" & |
| 207 | + run_test dse2.out se2.in EIG/xeigtstd "SEP - Testing Symmetric Eigenvalue Problem routines" & |
| 208 | + run_test dsvd.out svd.in EIG/xeigtstd "SVD - Testing Singular Value Decomposition routines" & |
| 209 | + run_test dec.out dec.in EIG/xeigtstd "DEC - Testing DOUBLE PRECISION Eigen Condition Routines" & |
| 210 | + run_test ded.out ded.in EIG/xeigtstd "DEV - Testing DOUBLE PRECISION Nonsymmetric Eigenvalue Driver" & |
| 211 | + run_test dgg.out dgg.in EIG/xeigtstd "DGG - Testing DOUBLE PRECISION Nonsymmetric Generalized Eigenvalue Problem routines" & |
| 212 | + run_test dgd.out dgd.in EIG/xeigtstd "DGD - Testing DOUBLE PRECISION Nonsymmetric Generalized Eigenvalue Problem driver routines" & |
| 213 | + run_test dsb.out dsb.in EIG/xeigtstd "DSB - Testing DOUBLE PRECISION Symmetric Eigenvalue Problem routines" & |
| 214 | + run_test dsg.out dsg.in EIG/xeigtstd "DSG - Testing DOUBLE PRECISION Symmetric Generalized Eigenvalue Problem routines" & |
| 215 | + run_test dbal.out dbal.in EIG/xeigtstd "DGEBAL - Testing the balancing of a DOUBLE PRECISION general matrix" & |
| 216 | + run_test dbak.out dbak.in EIG/xeigtstd "DGEBAK - Testing the back transformation of a DOUBLE PRECISION balanced matrix" & |
| 217 | + run_test dgbal.out dgbal.in EIG/xeigtstd "DGGBAL - Testing the balancing of a pair of DOUBLE PRECISION general matrices" & |
| 218 | + run_test dgbak.out dgbak.in EIG/xeigtstd "DGGBAK - Testing the back transformation of a pair of DOUBLE PRECISION balanced matrices" & |
| 219 | + run_test dbb.out dbb.in EIG/xeigtstd "DBB - Testing banded Singular Value Decomposition routines" & |
| 220 | + run_test dglm.out glm.in EIG/xeigtstd "GLM - Testing Generalized Linear Regression Model routines" & |
| 221 | + run_test dgqr.out gqr.in EIG/xeigtstd "GQR - Testing Generalized QR and RQ factorization routines" & |
| 222 | + run_test dgsv.out gsv.in EIG/xeigtstd "GSV - Testing Generalized Singular Value Decomposition routines" & |
| 223 | + run_test dcsd.out csd.in EIG/xeigtstd "CSD - Testing CS Decomposition routines" & |
| 224 | + run_test dlse.out lse.in EIG/xeigtstd "LSE - Testing Constrained Linear Least Squares routines" & |
| 225 | + run_test znep.out nep.in EIG/xeigtstz "NEP - Testing Nonsymmetric Eigenvalue Problem routines" & |
| 226 | + run_test zsep.out sep.in EIG/xeigtstz "SEP - Testing Symmetric Eigenvalue Problem routines" & |
| 227 | + run_test zse2.out se2.in EIG/xeigtstz "SEP - Testing Symmetric Eigenvalue Problem routines" & |
| 228 | + run_test zsvd.out svd.in EIG/xeigtstz "SVD - Testing Singular Value Decomposition routines" & |
| 229 | + run_test zec.out zec.in EIG/xeigtstz "ZEC - Testing COMPLEX16 Eigen Condition Routines" & |
| 230 | + run_test zed.out zed.in EIG/xeigtstz "ZES - Testing COMPLEX16 Nonsymmetric Schur Form Driver" & |
| 231 | + run_test zgg.out zgg.in EIG/xeigtstz "ZGG - Testing COMPLEX16 Nonsymmetric Generalized Eigenvalue Problem routines" & |
| 232 | + run_test zgd.out zgd.in EIG/xeigtstz "ZGD - Testing COMPLEX16 Nonsymmetric Generalized Eigenvalue Problem driver routines" & |
| 233 | + run_test zsb.out zsb.in EIG/xeigtstz "ZHB - Testing Hermitian Eigenvalue Problem routines" & |
| 234 | + run_test zsg.out zsg.in EIG/xeigtstz "ZSG - Testing Symmetric Generalized Eigenvalue Problem routines" & |
| 235 | + run_test zbal.out zbal.in EIG/xeigtstz "ZGEBAL - Testing the balancing of a COMPLEX16 general matrix" & |
| 236 | + run_test zbak.out zbak.in EIG/xeigtstz "ZGEBAK - Testing the back transformation of a COMPLEX16 balanced matrix" & |
| 237 | + run_test zgbal.out zgbal.in EIG/xeigtstz "ZGGBAL - Testing the balancing of a pair of COMPLEX general matrices" & |
| 238 | + run_test zgbak.out zgbak.in EIG/xeigtstz "ZGGBAK - Testing the back transformation of a pair of COMPLEX16 balanced matrices" & |
| 239 | + run_test zbb.out zbb.in EIG/xeigtstz "ZBB - Testing banded Singular Value Decomposition routines" & |
| 240 | + run_test zglm.out glm.in EIG/xeigtstz "GLM - Testing Generalized Linear Regression Model routines" & |
| 241 | + run_test zgqr.out gqr.in EIG/xeigtstz "GQR - Testing Generalized QR and RQ factorization routines" & |
| 242 | + run_test zgsv.out gsv.in EIG/xeigtstz "GSV - Testing Generalized Singular Value Decomposition routines" & |
| 243 | + run_test zcsd.out csd.in EIG/xeigtstz "CSD - Testing CS Decomposition routines" & |
| 244 | + run_test zlse.out lse.in EIG/xeigtstz "LSE - Testing Constrained Linear Least Squares routines" & |
| 245 | + wait |
| 246 | + while IFS= read -r -d $'\0' LOG; do cat $LOG ; FAILURES=1 ; done < <(grep -lZ FAIL ./test_out/*) |
| 247 | + python ./lapack-netlib/lapack_testing.py -d ./test_out -e > netlib_summary |
| 248 | + TOTALS="$(grep 'ALL PRECISIONS' netlib_summary)" |
| 249 | + NUMERICAL_ERRORS=-1 |
| 250 | + OTHER_ERRORS=-1 |
| 251 | + . <(awk '/ALL PRECISIONS/{printf "NUMERICAL_ERRORS=%s\nOTHER_ERRORS=%s\n", $5, $7}' netlib_summary |
| 252 | + if (( NUMERICAL_ERRORS != 0 )) || (( OTHER_ERRORS != 0 )) ; then cat netlib_summary ; FAILURES=1 ; fi |
| 253 | + if [[ ! -z $FAILURES ]]; then echo "==========" ; echo "== FAIL ==" ; echo "==========" ; echo ; exit 1 ; fi |
0 commit comments