When your commands go to server, all the variables are replaced by its values.
The 'echo '${test1[$m]}' at the end of your command is evaluated by your local system (the first element of the array since it cannot make out what $m is) and would be replaced by 'test1' by the time it reaches the server . So it prints the same for all the iterations.
But that's the nice thing about BASH, there's no "No way out" problem:
#!/bin/bash
TEST=test
TEST1=(test1 test2 test3)
ssh server 'TEST2=('${TEST1
[*]}') ; for m in $(seq 0 $(eval echo \${TEST2
[*]} | tr " " "\n" | wc -l)); eval echo \${TEST2[$m]}; done'
Declaring a Variable, that is iterated before the loop, so that the array gets populated as expected and then iterated together with the loop variable $m.
Another way around the variable problem, a particularly robust one, is this:
ssh username@host /bin/sh -s arg1 arg2 arg3 <<"EOF"
literal script contents
that don't even need
extra quotes
or escaping
EOF
Also, "${ARRAY[@]}" is a safer way to expand an array, because it splits upon elements, not spaces. It works for commandline arguments too. Also, your loop can be simplified quite a lot. How about this:
ssh username@host /bin/sh -s "${TEST1[@]}" <<"EOF"
echo "$@"
echo "${1}"
N=0
for m in "$@" # Expands into $1 $2 $3 ...
do
echo $m
echo $N
let N=N+1
done
EOF