Commit 34b61a1a authored by Rohit Gupta's avatar Rohit Gupta
Browse files

updated test case architecture for parallel/faster execution

parent d897ea3e
......@@ -6,41 +6,50 @@ Obj.# Case# Test# Description
01 pre-commit test case
01 01 Build OAI
01 01 01 Build oaisim.Rel8
01 01 02 Build oaisim.Rel8 + network device driver(nasmesh_fix)
01 01 03 Build (lte-softmodem.Rel8.EXMIMO + lte-softmodem.Rel10.EXMIMO + lte-softmodem.Rel10.USRP)
01 01 04 Build (dlsim.Rel10 + ulsim.Rel10 + pucchsim.Rel10 + prachsim.Rel10 + pdcchsim.Rel10 + pbchsim.Rel10 + mbmssim.Rel10
01 01 02 Build oaisim.Rel10
01 01 03 Build oaisim_noS1.Rel10
01 01 10 Build lte-softmodem_noS1.USRP.Rel10
01 01 11 Build lte-softmodem_noS1.EXMIMO.Rel10
01 01 12 Build lte-softmodem_noS1.BLADERF.Rel10
01 01 13 Build lte-softmodem_noS1.ETHERNET.Rel10
01 01 20 Build lte-softmodem.USRP.Rel10
01 01 21 Build lte-softmodem.EXMIMO.Rel10
01 01 22 Build lte-softmodem.BLADERF.Rel10
01 01 23 Build lte-softmodem.ETHERNET.Rel10
01 01 30 Build (dlsim.Rel10 + ulsim.Rel10 + pucchsim.Rel10 + prachsim.Rel10 + pdcchsim.Rel10 + pbchsim.Rel10 + mbmssim.Rel10
secu_knas_encrypt_eia1.Rel10 secu_kenb.Rel10 aes128_ctr_encrypt.Rel10 aes128_ctr_decrypt.Rel10 secu_knas_encrypt_eea2.Rel10
secu_knas.Rel10 secu_knas_encrypt_eea1.Rel10 kdf.Rel10 aes128_cmac_encrypt.Rel10 secu_knas_encrypt_eia2.Rel10)
01 01 06 Build oaisim.Rel8 + ITTI
01 01 07 Build oaisim.Rel10
01 01 08 Build oaisim.Rel10 + ITTI
01 01 20 Build Nasmesh
01 01 30 Build RRH Gateway
01 02 Run OAISIM Rel10 (TDD + 5MHz/10MHz/20MHz + TM 1,2,5,6), and check the operation
01 02 00 Run OAISIM Rel10 TDD, 1 eNB + 1 UE (5 MHz/10MHz/20MHz), (TM 1,2,5,6) and search for errors, segmentation fault or exit
01 02 01 Run OAISIM Rel10 TDD, 1 eNB + 1 UE (5 MHz/10MHz/20MHz), (TM 1,2,5,6) in PHY_ABSTRACTION mode and search for errors
01 02 02 Run OAISIM Rel10 TDD, 1 eNB + 3 UEs (5 MHz/10MHz/20MHz), (TM 1,2,5,6) and search for errors, segmentation fault or exit
01 02 03 Run OAISIM Rel10 TDD, 1 eNB + 3 UEs (5 MHz/10MHz/20MHz), (TM 1,2,5,6) in PHY_ABSTRACTION mode and search for errors
01 02 04 Run OAI Rel10 TDD, 1 eNB + 1 UE (5 MHz/10MHz/20MHz), (TM 1,2,5,6) without PHY_ABSTRACTION mode, ping from from eNB to UE,
01 01 40 Build RRH Gateway for USRP (Rel 10)
01 01 41 Build RRH Gateway for EXMIMO (Rel 10)
01 01 42 Build RRH Gateway for BLADERF (Rel 10)
01 02 Run OAISIM-NOS1 Rel10 (TDD + 5MHz/10MHz/20MHz + TM 1,2,5,6), and check the operation
01 02 00 Run OAISIM-NOS1 Rel10 TDD, 1 eNB + 1 UE (5 MHz/10MHz/20MHz), (TM 1,2,5,6) and search for errors, segmentation fault or exit
01 02 01 Run OAISIM-NOS1 Rel10 TDD, 1 eNB + 1 UE (5 MHz/10MHz/20MHz), (TM 1,2,5,6) in PHY_ABSTRACTION mode and search for errors
01 02 02 Run OAISIM-NOS1 Rel10 TDD, 1 eNB + 3 UEs (5 MHz/10MHz/20MHz), (TM 1,2,5,6) and search for errors, segmentation fault or exit
01 02 03 Run OAISIM-NOS1 Rel10 TDD, 1 eNB + 3 UEs (5 MHz/10MHz/20MHz), (TM 1,2,5,6) in PHY_ABSTRACTION mode and search for errors
01 02 04 Run OAISIM-NOS1 Rel10 TDD, 1 eNB + 1 UE (5 MHz/10MHz/20MHz), (TM 1,2,5,6) without PHY_ABSTRACTION mode, ping from from eNB to UE,
and for check for no packet losses
01 02 05 Run OAI Rel10 TDD, 1 eNB + 1 UE (5 MHz/10MHz/20MHz), (TM 1,2,5,6) in PHY_ABSTRACTION mode, send ping from from eNB to UE,
01 02 05 Run OAISIM-NOS1 Rel10 TDD, 1 eNB + 1 UE (5 MHz/10MHz/20MHz), (TM 1,2,5,6) in PHY_ABSTRACTION mode, send ping from from eNB to UE,
and check for no packet losses
01 03 Run OAISIM Rel10 (FDD + 5MHz/10MHz/20MHz + TM 1,2,5,6), and check the operation
01 03 00 Run OAISIM Rel10 FDD, 1 eNB + 1 UE 1 eNB (5 MHz/10MHz/20MHz), (TM 1,2,5,6) and search for errors, segmentation fault or exit
01 03 01 Run OAISIM Rel10 FDD, 1 eNB + 1 UE (5 MHz/10MHz/20MHz), (TM 1,2,5,6) in PHY_ABSTRACTION mode and search for errors
01 03 02 Run OAISIM Rel10 FDD, 1 eNB + 3 UEs (5 MHz/10MHz/20MHz), (TM 1,2,5,6) and search for errors, segmentation fault or exit
01 03 03 Run OAISIM Rel10 FDD, 1 eNB + 3 UEs (5 MHz/10MHz/20MHz), (TM 1,2,5,6) in PHY_ABSTRACTION mode and search for errors
01 03 04 Run OAI Rel10 FDD, 1 eNB + 1 UE (5 MHz/10MHz/20MHz), (TM 1,2,5,6) without PHY_ABSTRACTION mode, ping from from eNB to UE,
01 03 Run OAISIM-NOS1 Rel10 (FDD + 5MHz/10MHz/20MHz + TM 1,2,5,6), and check the operation
01 03 00 Run OAISIM-NOS1 Rel10 FDD, 1 eNB + 1 UE 1 eNB (5 MHz/10MHz/20MHz), (TM 1,2,5,6) and search for errors, segmentation fault or exit
01 03 01 Run OAISIM-NOS1 Rel10 FDD, 1 eNB + 1 UE (5 MHz/10MHz/20MHz), (TM 1,2,5,6) in PHY_ABSTRACTION mode and search for errors
01 03 02 Run OAISIM-NOS1 Rel10 FDD, 1 eNB + 3 UEs (5 MHz/10MHz/20MHz), (TM 1,2,5,6) and search for errors, segmentation fault or exit
01 03 03 Run OAISIM-NOS1 Rel10 FDD, 1 eNB + 3 UEs (5 MHz/10MHz/20MHz), (TM 1,2,5,6) in PHY_ABSTRACTION mode and search for errors
01 03 04 Run OAISIM-NOS1 Rel10 FDD, 1 eNB + 1 UE (5 MHz/10MHz/20MHz), (TM 1,2,5,6) without PHY_ABSTRACTION mode, ping from from eNB to UE,
and for check for no packet losses
01 03 05 Run OAI Rel10 FDD, 1 eNB + 1 UE (5 MHz/10MHz/20MHz), (TM 1,2,5,6) in PHY_ABSTRACTION mode, send ping from from eNB to UE,
01 03 05 Run OAISIM-NOS1 Rel10 FDD, 1 eNB + 1 UE (5 MHz/10MHz/20MHz), (TM 1,2,5,6) in PHY_ABSTRACTION mode, send ping from from eNB to UE,
and check for no packet losses
01 04 MBSFN Tests
01 04 OAISIM-NOS1 MBSFN Tests
01 04 00 Check if eMBMS procedure is not finished completely, make sure that the SIB13/MCCH have been correclty received by UEs
01 04 01 Check if eMBMS multicast/broadcast data is received, make sure that the SIB13/MCCH/MTCH have been correclty received by UEs
01 04 02 Check for eMBMS multicast/broadcast data received in fdd mode, make sure that the SIB13/MCCH/MTCH have been correctly
......
......@@ -43,8 +43,8 @@ function test_compile() {
xUnit_start
test_case_name=$1
log_dir=$tdir/log
log_file=$tdir/log/test.$1.txt
log_dir=$tdir/log/$test_case_name
log_file=$log_dir/test.$1.log.txt
compile_prog=$2
compile_args=$3
pre_exec_file=$4
......@@ -57,11 +57,18 @@ function test_compile() {
class=${12}
compile_prog_out=${13}
tags=${14}
build_dir=$tdir/$1/build
exec_file=$build_dir/$6
xmlfile_testcase=$log_dir/test.$1.xml
#build_dir=$tdir/$1/build
#exec_file=$build_dir/$6
#compile_prog_out=`eval "echo $compile_prog_out"`
#echo "compile_prog_out = $compile_prog_out"
read -a compile_prog_out_array <<< "$compile_prog_out"
#Temporary log file where execution log is stored.
temp_exec_log=$log_dir/temp_log.txt
rm -fr $log_dir
mkdir -p $log_dir
......@@ -77,44 +84,77 @@ function test_compile() {
compile_prog_array=()
read -a compile_prog_array <<<"$compile_prog"
tags_array=()
read -a tags_array <<<"$tags"
#tags_array=()
#read -a tags_array <<<"$tags"
pre_compile_prog_array=()
readarray -t pre_compile_prog_array <<< "$pre_compile_prog"
#pre_compile_prog_array=()
#readarray -t pre_compile_prog_array <<< "$pre_compile_prog"
result=1
result_string=""
for (( run_index=1; run_index <= $nruns; run_index++ ))
do
tags_array_index=0
for pre_compile_prog_array_index in "${pre_compile_prog_array[@]}"
do
#tags_array_index=0
#for pre_compile_prog_array_index in "${pre_compile_prog_array[@]}"
#do
for compile_prog_array_index in "${compile_prog_array[@]}"
do
echo "Compiling test case $test_case_name.$compile_prog_array_index.${tags_array[$tags_array_index]} Log file = $log_file"
echo "<COMPILATION LOG file=$compile_prog_array_index , Run = $run_index>" >> $log_file
rm -fr $build_dir
mkdir -p $build_dir
cd $build_dir
#for compile_prog_array_index in "${compile_prog_array[@]}"
#do
echo "Compiling test case $test_case_name.${tags} Log file = $log_file"
date=`date`
echo "<COMPILATION LOG file=$test_case_name.${tags} , Run = $run_index>, Date = $date " >> $log_file
#rm -fr $build_dir
#mkdir -p $build_dir
cd $log_dir
{
eval $pre_compile_prog_array_index
cmake ..
#rm -fv $exec_file
make -j`nproc` $compile_prog_array_index $compile_args
compile_log_dir=`eval echo \"$OPENAIR_DIR/cmake_targets/log/\"`
echo "Removing compilation log files in $compile_log_dir"
rm -frv $compile_log_dir
echo "Executing $compile_prog $compile_prog_args ...."
eval $compile_prog $compile_prog_args
echo "Copying compilation log files to test case log directory: $log_dir"
cp -fvr $OPENAIR_DIR/cmake_targets/log/ $log_dir/compile_log
}>> $log_file 2>&1
echo "</COMPILATION LOG>" >> $log_file 2>&1
if [ "$class" == "compilation" ]; then
if [ -s "$compile_prog_array_index" ] || [ -s "$compile_prog_out" ] ; then
echo_success "$test_case_name.$compile_prog_array_index.${tags_array[$tags_array_index]} compiled"
xUnit_success "compilation" "$test_case_name.$compile_prog_array_index.${tags_array[$tags_array_index]}" "PASS" "$run_index"
else
echo_error "$test_case_name.$exec_prog.${tags_array[$tags_array_index]} compilation failed"
xUnit_fail "compilation" "$test_case_name.$compile_prog_array_index.${tags_array[$tags_array_index]}" "FAIL" "$run_index"
for compile_prog_out_index in ${compile_prog_out_array[@]}
do
if [ -s "$compile_prog_out_index" ]; then
let "result = result&1"
echo_success "$test_case_name.${tags} RUN = $run_index $compile_prog_out_index = compiled"
else
let "result = result&0"
echo_error "$test_case_name.${tags} RUN = $run_index $compile_prog_out_index failed"
fi
done #end of for loop compile_prog_out_index
if [ "$result" == "1" ]; then
result_string=$result_string" Run_$run_index = PASS"
else
result_string=$result_string" Run_$run_index = FAIL"
fi
fi
let "tags_array_index++"
done # End of for loop compile_prog_array
done # End of for loop (pre_compile_prog_array_index)
#let "tags_array_index++"
#done # End of for loop compile_prog_array
#done # End of for loop (pre_compile_prog_array_index)
done #End of for loop (run_index)
#If for for some reason upper for loop does not execute, we fail the test case completely
if [ "$result_string" == "" ]; then
result=0
fi
if [ "$result" == "1" ]; then
echo_success "$test_case_name.${tags} PASSED"
xUnit_success "compilation" "$test_case_name.$tags" "PASS" "$result_string" "$xmlfile_testcase"
else
echo_success "$test_case_name.${tags} FAILED"
xUnit_success "compilation" "$test_case_name.$tags" "FAIL" "$result_string" "$xmlfile_testcase"
fi
}
......@@ -138,8 +178,8 @@ function test_compile() {
function test_compile_and_run() {
xUnit_start
test_case_name=$1
log_dir=$tdir/log
log_file=$tdir/log/test.$1.txt
log_dir=$tdir/log/$test_case_name
log_file=$log_dir/test.$1.log.txt
compile_prog=$2
compile_args=$3
pre_exec_file=$4
......@@ -155,11 +195,18 @@ function test_compile_and_run() {
tags=${14}
mypassword=${15}
build_dir=$tdir/$1/build
exec_file=$build_dir/$6
#exec_file=$build_dir/$6
xmlfile_testcase=$log_dir/test.$1.xml
#Temporary log file where execution log is stored.
temp_exec_log=$log_dir/temp_log.txt
rm -fr $log_dir
mkdir -p $log_dir
rm -fr $OPENAIR_DIR/cmake_targets/log
echo "" > $temp_exec_log
echo "" > $log_file
#echo "log_dir = $log_dir"
#echo "log_file = $log_file"
#echo "exec_file = $exec_file"
......@@ -169,64 +216,67 @@ function test_compile_and_run() {
#echo "nruns = $nruns"
echo "class = $class"
compile_prog_array=()
read -a compile_prog_array <<<"$compile_prog"
#compile_prog_array=()
#read -a compile_prog_array <<<"$compile_prog"
tags_array=()
read -a tags_array <<<"$tags"
main_exec_args_array=()
readarray -t main_exec_args_array <<< "$exec_args"
#for search_expr in "${compile_prog_array[@]}"
#do
echo "Compiling test case $test_case_name Log file = $log_file"
echo "<COMPILATION LOG file=$log_file>" >> $log_file
for search_expr in "${compile_prog_array[@]}"
do
echo "Compiling test case $test_case_name.$search_expr Log file = $log_file"
echo "<COMPILATION LOG file=$search_expr>" >> $log_file
rm -fr $build_dir
mkdir -p $build_dir
#rm -fr $build_dir
#mkdir -p $build_dir
cd $build_dir
cd $log_dir
{
eval $pre_compile_prog
cmake ..
#eval $pre_compile_prog
#cmake ..
#rm -fv $exec_file
make -j`nproc` $search_expr $compile_args
echo "Executing $compile_prog $compile_args" >> $log_file
eval "$compile_prog $compile_args"
echo "Copying compilation log files to test case log directory: $log_dir"
cp -fvr $OPENAIR_DIR/cmake_targets/log/ $log_dir/compile_log
}>> $log_file 2>&1
echo "</COMPILATION LOG>" >> $log_file 2>&1
if [ "$class" == "compilation" ]; then
if [ -s "$search_expr" ] ; then
echo_success "$test_case_name $search_expr compiled"
xUnit_success "compilation" "$test_name.$search_expr" "PASS" 1
else
echo_error "$test_case_name $exec_prog compilation failed"
xUnit_fail "compilation" "$test_name.$search_expr" "FAIL" 1
fi
fi
done
#done
#process the test case if it is that of execution
if [ "$class" == "execution" ]; then
tags_array_index=0
for main_exec_args_array_index in "${main_exec_args_array[@]}"
do
for (( run_index=1; run_index <= $nruns; run_index++ ))
global_result=1
result_string=""
for (( run_index=1; run_index <= $nruns; run_index++ ))
do
echo "Executing test case $test_case_name.$main_exec.${tags_array[$tags_array_index]}, Run Index = $run_index, Log file = $log_file"
temp_exec_log=$log_dir/test.$test_case_name.${tags_array[$tags_array_index]}.run_$run_index
echo "" > $temp_exec_log
echo "-----------------------------------------------------------------------------" >> $log_file 2>&1
echo "<EXECUTION LOG Run = $run_index >" >> $log_file 2>&1
echo "Executing test case $test_case_name.${tags_array[$tags_array_index]}, Run Index = $run_index, Execution Log file = $temp_exec_log"
echo "-----------------------------------------------------------------------------" >> $temp_exec_log 2>&1
echo "<EXECUTION LOG Test Case = $test_case_name.${tags_array[$tags_array_index]}, Run = $run_index >" >> $temp_exec_log 2>&1
if [ -n "$pre_exec_file" ]; then
{ eval " echo '$mypassword' |sudo -S -E $pre_exec_file $pre_exec_args " ; }>> $log_file 2>&1
{ echo " Executing $pre_exec_file $pre_exec_args "
eval " echo '$mypassword' |sudo -S -E $pre_exec_file $pre_exec_args " ; }>> $temp_exec_log 2>&1
fi
echo "Executing $exec_file $main_exec_args_array_index "
echo "Executing $exec_file $main_exec_args_array_index " >> $log_file
{ eval "$exec_file $main_exec_args_array_index" ;} > $temp_exec_log 2>&1
echo "Executing $main_exec $main_exec_args_array_index "
echo "Executing $main_exec $main_exec_args_array_index " >> $temp_exec_log
{ eval "$main_exec $main_exec_args_array_index" ;} >> $temp_exec_log 2>&1
echo "</EXECUTION LOG Test Case = $test_case_name.${tags_array[$tags_array_index]}, Run = $run_index >" >> $temp_exec_log 2>&1
cat $temp_exec_log >> $log_file 2>&1
echo "</EXECUTION LOG Test Case = $test_case_name.$main_exec.${tags_array[$tags_array_index]}, Run = $run_index >" >> $log_file 2>&1
result=1
for search_expr in "${search_expr_array[@]}"
......@@ -243,39 +293,50 @@ function test_compile_and_run() {
let "result = result & 1"
fi
done
#If we find a negative search result then there is crash of program and test case is failed even if above condition is true
search_result=`grep -iE "$search_expr_negative" $temp_exec_log`
if [ -n "$search_result" ]; then
result=0
fi
let "global_result = global_result & result"
#echo "result = $result"
test_case_result=""
#this is a result of this run
#test_case_result=""
if [ "$result" -eq "0" ]; then
test_case_result="FAIL"
result_string=$result_string" Run_$run_index =FAIL"
echo_error "$test_case_name.${tags_array[$tags_array_index]} RUN = $run_index Result = FAIL"
fi
if [ "$result" -eq "1" ]; then
test_case_result="PASS"
result_string=$result_string" Run_$run_index =PASS"
echo_success "$test_case_name.${tags_array[$tags_array_index]} RUN = $run_index Result = PASS"
fi
#If we find a negative search result then there is crash of program and test case is failed even if above condition is true
search_result=`grep -iE "$search_expr_negative" $temp_exec_log`
if [ -n "$search_result" ]; then
test_case_result="FAIL"
fi
if [ "$test_case_result" == "FAIL" ]; then
echo_error "execution $test_case_name.$compile_prog.${tags_array[$tags_array_index]} FAIL $run_index"
xUnit_fail "execution" "$test_case_name.$compile_prog.${tags_array[$tags_array_index]}" "FAIL" "$run_index"
fi
if [ "$test_case_result" == "PASS" ]; then
echo_success "execution $test_case_name.$compile_prog.${tags_array[$tags_array_index]} PASS $run_index"
xUnit_success "execution" "$test_case_name.$compile_prog.${tags_array[$tags_array_index]}" "PASS" "$run_index"
fi
done
done #End of for loop (nindex)
echo " Result String = $result_string"
if [ "$result_string" == "" ]; then
echo_error "execution $test_case_name.$compile_prog.${tags_array[$tags_array_index]} Run_Result = \"$result_string\" Result = FAIL"
xUnit_success "execution" "$test_case_name.${tags_array[$tags_array_index]}" "FAIL" "$result_string" "$xmlfile_testcase"
else
if [ "$global_result" == "0" ]; then
echo_error "execution $test_case_name.${tags_array[$tags_array_index]} Run_Result = \"$result_string\" Result = FAIL"
xUnit_fail "execution" "$test_case_name.${tags_array[$tags_array_index]}" "FAIL" "$result_string" "$xmlfile_testcase"
fi
if [ "$global_result" == "1" ]; then
echo_success "execution $test_case_name.${tags_array[$tags_array_index]} Run_Result = \"$result_string\" Result = PASS "
xUnit_success "execution" "$test_case_name.${tags_array[$tags_array_index]}" "PASS" "$result_string" "$xmlfile_testcase"
fi
fi
let "tags_array_index++"
done # End of for loop (nindex)
done
fi
rm -fr $build_dir
}
......@@ -376,6 +437,8 @@ for search_expr in "${test_case_array[@]}"
echo "Description = $desc"
echo "pre_compile_prog = $pre_compile_prog"
echo "compile_prog = $compile_prog"
echo "compile_prog_args = $compile_prog_args"
echo "compile_prog_out = $compile_prog_out"
echo "pre_exec = $pre_exec"
echo "pre_exec_args = $pre_exec_args"
echo "main_exec = $main_exec"
......@@ -385,6 +448,7 @@ for search_expr in "${test_case_array[@]}"
echo "nruns = $nruns"
#eval $pre_exec
compile_prog_out=`eval echo \"$compile_prog_out\"`
search_array_true=()
......
This diff is collapsed.
......@@ -24,15 +24,18 @@ xUnit_start() {
# \param $1 classname
# \param $2 testcase name
# \param $3 testcase result
# \param $4 run index
# \param $4 run result
# \param $5 XML file local to test case for storing its own results
xUnit_fail() {
class=$1
test_case=$2
result=$3
run_index=$4
run_result=$4
xmlfile_testcase=$5
currtime=$(date +%s.%N)
time=$(echo "$currtime - $XUNIT_START" | bc -l)
xml="<testcase classname='$class' name='$test_case' run='$run_index' time='$time' RESULT='$result'></testcase>"
xml="<testcase classname='$class' name='$test_case' Run_result='$run_result' time='$time' RESULT='$result'></testcase>"
echo -e $xml > $xmlfile_testcase
XUNIT_TESTCASES_XML="$XUNIT_TESTCASES_XML \n$xml"
XUNIT_FAILED=$((XUNIT_FAILED+1))
}
......@@ -43,15 +46,18 @@ xUnit_fail() {
# \param $1 classname
# \param $2 testcase name
# \param $3 testcase result
# \param $4 run index
# \param $4 run result
# \param $5 XML file local to test case for storing its own results
xUnit_success() {
class=$1
test_case=$2
result=$3
run_index=$4
run_result=$4
xmlfile_testcase=$5
currtime=$(date +%s.%N)
time=$(echo "$currtime - $XUNIT_START" | bc -l)
xml="<testcase classname='$class' name='$test_case' run='$run_index' time='$time' RESULT='$result'></testcase>"
xml="<testcase classname='$class' name='$test_case' Run_result='$run_result' time='$time' RESULT='$result'></testcase>"
echo -e $xml > $xmlfile_testcase
XUNIT_TESTCASES_XML="$XUNIT_TESTCASES_XML \n$xml"
XUNIT_SUCCESS=$((XUNIT_SUCCESS+1))
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment