Batch cipher translations to go faster

Python has a high startup cost, so go back to invoking it only once per
server start, rather than once per client start. This is a measurable
performance improvement (running time ~*0.5 with PSK, less dramatic with
asymmetric crypto).

Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
diff --git a/tests/compat.sh b/tests/compat.sh
index 3f9070e..754b1ee 100755
--- a/tests/compat.sh
+++ b/tests/compat.sh
@@ -239,9 +239,14 @@
     G_CIPHERS=""
 }
 
-check_translation()
+# translate_ciphers {g|m|o} {STANDARD_CIPHER_SUITE_NAME...}
+# Set $ciphers to the cipher suite name translations for the specified
+# program (gnutls, mbedtls or openssl). $ciphers is a space-separated
+# list of entries of the form "STANDARD_NAME=PROGRAM_NAME".
+translate_ciphers()
 {
-    if [ $1 -ne 0 ]; then
+    ciphers=$(scripts/translate_ciphers.py "$@")
+    if [ $? -ne 0 ]; then
         echo "translate_ciphers.py failed with exit code $1" >&2
         echo "$2" >&2
         exit 1
@@ -789,7 +794,7 @@
     echo "EXIT: $EXIT" >> $CLI_OUT
 }
 
-# run_client <name> <cipher>
+# run_client PROGRAM_NAME STANDARD_CIPHER_SUITE PROGRAM_CIPHER_SUITE
 run_client() {
     # announce what we're going to do
     TESTS=$(( $TESTS + 1 ))
@@ -800,13 +805,6 @@
     LEN=$(( 72 - `echo "$TITLE" | wc -c` ))
     for i in `seq 1 $LEN`; do printf '.'; done; printf ' '
 
-    # Calculate the argument $c to pass to translate_ciphers.py
-    client=$(echo $1 | head -c1)
-    c=$(echo $client | tr '[:upper:]' '[:lower:]')
-    # Translate ciphersuite names based on client's naming convention
-    t_cipher=$(./scripts/translate_ciphers.py $c $2)
-    check_translation $? "$t_cipher"
-
     # should we skip?
     if [ "X$SKIP_NEXT" = "XYES" ]; then
         SKIP_NEXT="NO"
@@ -818,7 +816,7 @@
     # run the command and interpret result
     case $1 in
         [Oo]pen*)
-            CLIENT_CMD="$OPENSSL s_client $O_CLIENT_ARGS -cipher $t_cipher"
+            CLIENT_CMD="$OPENSSL s_client $O_CLIENT_ARGS -cipher $3"
             log "$CLIENT_CMD"
             echo "$CLIENT_CMD" > $CLI_OUT
             printf 'GET HTTP/1.0\r\n\r\n' | $CLIENT_CMD >> $CLI_OUT 2>&1 &
@@ -843,7 +841,7 @@
             else
                 G_HOST="localhost"
             fi
-            CLIENT_CMD="$GNUTLS_CLI $G_CLIENT_ARGS --priority $G_PRIO_MODE:$t_cipher $G_HOST"
+            CLIENT_CMD="$GNUTLS_CLI $G_CLIENT_ARGS --priority $G_PRIO_MODE:$3 $G_HOST"
             log "$CLIENT_CMD"
             echo "$CLIENT_CMD" > $CLI_OUT
             printf 'GET HTTP/1.0\r\n\r\n' | $CLIENT_CMD >> $CLI_OUT 2>&1 &
@@ -865,7 +863,7 @@
             ;;
 
         mbed*)
-            CLIENT_CMD="$M_CLI $M_CLIENT_ARGS force_ciphersuite=$t_cipher"
+            CLIENT_CMD="$M_CLI $M_CLIENT_ARGS force_ciphersuite=$3"
             if [ "$MEMCHECK" -gt 0 ]; then
                 CLIENT_CMD="valgrind --leak-check=full $CLIENT_CMD"
             fi
@@ -1028,17 +1026,19 @@
 
                     if [ "X" != "X$M_CIPHERS" ]; then
                         start_server "OpenSSL"
-                        for i in $M_CIPHERS; do
+                        translate_ciphers m $M_CIPHERS
+                        for i in $ciphers; do
                             check_openssl_server_bug
-                            run_client mbedTLS $i
+                            run_client mbedTLS ${i%%=*} ${i#*=}
                         done
                         stop_server
                     fi
 
                     if [ "X" != "X$O_CIPHERS" ]; then
                         start_server "mbedTLS"
-                        for i in $O_CIPHERS; do
-                            run_client OpenSSL $i
+                        translate_ciphers o $O_CIPHERS
+                        for i in $ciphers; do
+                            run_client OpenSSL ${i%%=*} ${i#*=}
                         done
                         stop_server
                     fi
@@ -1054,16 +1054,18 @@
 
                     if [ "X" != "X$M_CIPHERS" ]; then
                         start_server "GnuTLS"
-                        for i in $M_CIPHERS; do
-                            run_client mbedTLS $i
+                        translate_ciphers m $M_CIPHERS
+                        for i in $ciphers; do
+                            run_client mbedTLS ${i%%=*} ${i#*=}
                         done
                         stop_server
                     fi
 
                     if [ "X" != "X$G_CIPHERS" ]; then
                         start_server "mbedTLS"
-                        for i in $G_CIPHERS; do
-                            run_client GnuTLS $i
+                        translate_ciphers g $G_CIPHERS
+                        for i in $ciphers; do
+                            run_client GnuTLS ${i%%=*} ${i#*=}
                         done
                         stop_server
                     fi
@@ -1081,8 +1083,9 @@
 
                     if [ "X" != "X$M_CIPHERS" ]; then
                         start_server "mbedTLS"
-                        for i in $M_CIPHERS; do
-                            run_client mbedTLS $i
+                        translate_ciphers m $M_CIPHERS
+                        for i in $ciphers; do
+                            run_client mbedTLS ${i%%=*} ${i#*=}
                         done
                         stop_server
                     fi
diff --git a/tests/scripts/translate_ciphers.py b/tests/scripts/translate_ciphers.py
index c622a67..a8db4bb 100755
--- a/tests/scripts/translate_ciphers.py
+++ b/tests/scripts/translate_ciphers.py
@@ -179,7 +179,7 @@
          "o": translate_ossl,
          "m": translate_mbedtls
         }[mode]
-    return " ".join(t(c) for c in names)
+    return " ".join(c + '=' + t(c) for c in names)
 
 def main(target, names):
     print(format_ciphersuite_names(target, names))