#!/bin/bash

SCRIPT_DIR=$(dirname "$(realpath "${BASH_SOURCE[0]}")")

EXEC_CMD() {
	CMD=$1
	echo "Command:"$CMD
	eval $CMD
}

declare -i CHECK_MEM_TOTAL_CACSE_CNT=0
declare -i CHECK_MEM_PASS_CACSE_CNT=0
declare -i CHECK_MEM_FAILED_CACSE_CNT=0

# parameters list:
# decrease
# Total
# Name
check_mem() {
    decrease=$1
    Total=$2
    Name=$3

    CHECK_MEM_TOTAL_CACSE_CNT=$CHECK_MEM_TOTAL_CACSE_CNT+1

    echo "${Name} decrease:$decrease"
    echo "${Name} Total:$Total"

    # check memory decrease should not exceeds 5%
    max_decrease=$(($Total / 20))
    if [ "$decrease" -gt "$max_decrease" ]; then
        echo "Warning: $Name decreased by ${decrease} kB, which exceeds 5% limit."

        CHECK_MEM_FAILED_CACSE_CNT=$CHECK_MEM_FAILED_CACSE_CNT+1
    else
        echo "$Name decreased by ${decrease} kB, within the 5% limit."

        CHECK_MEM_PASS_CACSE_CNT=$CHECK_MEM_PASS_CACSE_CNT+1
    fi
}


###############################################################################
# for check memory leakage
###############################################################################
check_mem_before(){
    CHECK_MEM_TOTAL_CACSE_CNT=0
    CHECK_MEM_PASS_CACSE_CNT=0
    CHECK_MEM_FAILED_CACSE_CNT=0

    # sync cache to ROM, and drop caches
    EXEC_CMD "sync"
    EXEC_CMD "echo 3 > /proc/sys/vm/drop_caches"
    EXEC_CMD "echo 3 > /proc/sys/vm/drop_caches"
    EXEC_CMD "echo 3 > /proc/sys/vm/drop_caches"
    EXEC_CMD "echo 3 > /proc/sys/vm/drop_caches"

    # check memory leakage
    check_meminfo_before
    check_codec_mem_before
    check_gpu_memory_before
    check_pagetrace_before
    check_vmalloc_used_before

    # print memory status
    #print_mem_status
}

check_mem_after() {
    # print memory status
    #print_mem_status

    # sync cache to ROM, and drop caches
    EXEC_CMD "sync"
    EXEC_CMD "echo 3 > /proc/sys/vm/drop_caches"
    EXEC_CMD "echo 3 > /proc/sys/vm/drop_caches"
    EXEC_CMD "echo 3 > /proc/sys/vm/drop_caches"
    EXEC_CMD "echo 3 > /proc/sys/vm/drop_caches"

    # check memory leakage
    check_meminfo_after
    check_codec_mem_after
    check_gpu_memory_after
    check_pagetrace_after
    check_vmalloc_used_after
}


print_mem_status(){
    echo "###########################print_mem_status start############################"

    EXEC_CMD "free"
    EXEC_CMD "cat /proc/meminfo"

    EXEC_CMD "dmesg -C"
    EXEC_CMD "cat /sys/class/codec_mm/codec_mm_dump"
    EXEC_CMD "dmesg"

    EXEC_CMD "procrank"

    EXEC_CMD "cat /proc/pagetrace"

    EXEC_CMD "cat /sys/kernel/debug/mali0/gpu_memory"

    EXEC_CMD "cat /proc/vmallocinfo"

    EXEC_CMD "cat /proc/vmstat"

    echo "###########################print_mem_status end############################"
}


###############################################################################
# for proc/meminfo
###############################################################################
declare -i MemTotal_before=0
declare -i MemTotal_after=0

declare -i MemAvailable_before=0
declare -i MemAvailable_after=0

declare -i Shmem_before=0
declare -i Shmem_after=0

declare -i VmallocTotal_before=0
declare -i VmallocTotal_after=0

declare -i VmallocUsed_before=0
declare -i VmallocUsed_after=0

declare -i CmaTotal_before=0
declare -i CmaTotal_after=0

declare -i CmaFree_before=0
declare -i CmaFree_after=0

check_meminfo_before(){
    MemTotal_before=$( grep MemTotal /proc/meminfo | grep -o '[0-9]*' | tail -n 1 )
    echo "MemTotal_before:$MemTotal_before"

    MemAvailable_before=$( grep MemAvailable /proc/meminfo | grep -o '[0-9]*' | tail -n 1 )
    echo "MemAvailable_before:$MemAvailable_before"

    Shmem_before=$( grep Shmem /proc/meminfo | grep -o '[0-9]*' | tail -n 1 )
    echo "Shmem_before:$Shmem_before"

    VmallocTotal_before=$( grep VmallocTotal /proc/meminfo | grep -o '[0-9]*' | tail -n 1 )
    echo "VmallocTotal_before:$VmallocTotal_before"

    VmallocUsed_before=$( grep VmallocUsed /proc/meminfo | grep -o '[0-9]*' | tail -n 1 )
    echo "VmallocUsed_before:$VmallocUsed_before"

    CmaTotal_before=$( grep CmaTotal /proc/meminfo | grep -o '[0-9]*' | tail -n 1 )
    echo "CmaTotal_before:$CmaTotal_before"

    CmaFree_before=$( grep CmaFree /proc/meminfo | grep -o '[0-9]*' | tail -n 1 )
    echo "CmaFree_before:$CmaFree_before"
}

check_meminfo_after(){
    MemTotal_after=$( grep MemTotal /proc/meminfo | grep -o '[0-9]*' | tail -n 1 )
    echo "MemTotal_after:$MemTotal_after"

    MemAvailable_after=$( grep MemAvailable /proc/meminfo | grep -o '[0-9]*' | tail -n 1 )
    echo "MemAvailable_after:$MemAvailable_after"

    Shmem_after=$( grep Shmem: /proc/meminfo | grep -o '[0-9]*' | tail -n 1 )
    echo "Shmem_after:$Shmem_after"

    VmallocTotal_after=$( grep VmallocTotal /proc/meminfo | grep -o '[0-9]*' | tail -n 1 )
    echo "VmallocTotal_after:$VmallocTotal_after"

    VmallocUsed_after=$( grep VmallocUsed /proc/meminfo | grep -o '[0-9]*' | tail -n 1 )
    echo "VmallocUsed_after:$VmallocUsed_after"

    CmaTotal_after=$( grep CmaTotal /proc/meminfo | grep -o '[0-9]*' | tail -n 1 )
    echo "CmaTotal_after:$CmaTotal_after"

    CmaFree_after=$( grep CmaFree /proc/meminfo | grep -o '[0-9]*' | tail -n 1 )
    echo "CmaFree_after:$CmaFree_after"

    check_mem $(($MemTotal_before-$MemTotal_after)) $MemTotal_before "MemTotal"
    check_mem $(($MemAvailable_before-$MemAvailable_after)) $MemTotal_before "MemAvailable"
    #check_mem $Shmem_before $Shmem_after "Shmem"
    check_mem $(($VmallocUsed_after-$VmallocUsed_before)) $VmallocTotal_before "Vmalloc"
    check_mem $(($CmaFree_before-$CmaFree_after)) $CmaTotal_before "Cma"
}


###############################################################################
# codec mm
###############################################################################

declare -i codec_mm_total_before=0
declare -i codec_mm_total_after=0

declare -i codec_mm_allocated_before=0
declare -i codec_mm_allocated_after=0

check_codec_mem_before(){
    EXEC_CMD "dmesg -C"
    cat /sys/class/codec_mm/codec_mm_dump
    codec_mm_total_before=$( dmesg | grep "total codec mem size" | grep -o '[0-9]*' | tail -n 1 )
    codec_mm_total_before=$codec_mm_total_before*1024
    echo "codec_mm_total_before:$codec_mm_total_before"

    codec_mm_allocated_before=$( dmesg | grep "alloced size" | grep -o '[0-9]*' | tail -n 1 )
    codec_mm_allocated_before=$codec_mm_allocated_before*1024
    echo "codec_mm_allocated_before:$codec_mm_allocated_before"
}


check_codec_mem_after(){
    EXEC_CMD "dmesg -C"
    cat /sys/class/codec_mm/codec_mm_dump
    codec_mm_total_after=$( dmesg | grep "total codec mem size" | grep -o '[0-9]*' | tail -n 1 )
    codec_mm_total_after=$codec_mm_total_after*1024
    echo "codec_mm_total_after:$codec_mm_total_after"

    codec_mm_allocated_after=$( dmesg | grep "alloced size" | grep -o '[0-9]*' | tail -n 1 )
    codec_mm_allocated_after=$codec_mm_allocated_after*1024
    echo "codec_mm_allocated_after:$codec_mm_allocated_after"

    check_mem $(($codec_mm_allocated_after-$codec_mm_allocated_before)) $codec_mm_total_before "codec_mm"
}



###############################################################################
# for gpu_memory
###############################################################################

declare -i gpu_memory_before=0
declare -i gpu_memory_after=0

check_gpu_memory_before(){
    gpu_memory_before=$(cat /sys/kernel/debug/mali0/gpu_memory | grep "total used_pages" | grep -o '[0-9]*' | tail -n 1 )

    # page is 4k
    gpu_memory_before=$gpu_memory_before*4
    echo "gpu_memory_before:$gpu_memory_before"
}


check_gpu_memory_after(){
    gpu_memory_after=$(cat /sys/kernel/debug/mali0/gpu_memory | grep "total used_pages" | grep -o '[0-9]*' | tail -n 1 )

    # page is 4k
    gpu_memory_after=$gpu_memory_after*4
    echo "gpu_memory_after:$gpu_memory_after"

    #check_mem $gpu_memory_before $gpu_memory_after "gpu_memory"
}



###############################################################################
# for pagetrace
###############################################################################

declare -i ZONE_DMA32_Total_before=0
declare -i ZONE_DMA32_Total_after=0

declare -i ZONE_DMA32_free_before=0
declare -i ZONE_DMA32_free_after=0

declare -i ZONE_Normal_Total_before=0
declare -i ZONE_Normal_Total_after=0

declare -i ZONE_Normal_free_before=0
declare -i ZONE_Normal_free_after=0

check_pagetrace_before(){
    ZONE_DMA32_Total_before=$( cat /proc/pagetrace | grep -E "Zone\s+DMA32"  | grep -o '[0-9]*' | tail -n 3 | head -n 1 )
    echo "ZONE_DMA32_Total_before:$ZONE_DMA32_Total_before"

    ZONE_DMA32_free_before=$( cat /proc/pagetrace | grep -E "Zone\s+DMA32"  | grep -o '[0-9]*' | tail -n 2 | head -n 1 )
    echo "ZONE_DMA32_free_before:$ZONE_DMA32_free_before"

    ZONE_Normal_Total_before=$( cat /proc/pagetrace | grep -E "Zone\s+Normal"  | grep -o '[0-9]*' | tail -n 3 | head -n 1 )
    echo "ZONE_Normal_Total_before:$ZONE_Normal_Total_before"

    ZONE_Normal_free_before=$( cat /proc/pagetrace | grep -E "Zone\s+ Normal"  | grep -o '[0-9]*' | tail -n 2 | head -n 1 )
    echo "ZONE_Normal_free_before:$ZONE_Normal_free_before"
}


check_pagetrace_after(){
    ZONE_DMA32_Total_after=$( cat /proc/pagetrace | grep -E "Zone\s+DMA32"  | grep -o '[0-9]*' | tail -n 3 | head -n 1 )
    echo "ZONE_DMA32_Total_after:$ZONE_DMA32_Total_after"

    ZONE_DMA32_free_after=$( cat /proc/pagetrace | grep -E "Zone\s+DMA32"  | grep -o '[0-9]*' | tail -n 2 | head -n 1 )
    echo "ZONE_DMA32_free_after:$ZONE_DMA32_free_after"

    ZONE_Normal_Total_after=$( cat /proc/pagetrace | grep -E "Zone\s+Normal"  | grep -o '[0-9]*' | tail -n 3 | head -n 1  )
    echo "ZONE_Normal_Total_after:$ZONE_Normal_Total_after"

    ZONE_Normal_free_after=$( cat /proc/pagetrace | grep -E "Zone\s+Normal"  | grep -o '[0-9]*' | tail -n 2 | head -n 1 )
    echo "ZONE_Normal_free_after:$ZONE_Normal_free_after"

    check_mem $(($ZONE_DMA32_free_before-$ZONE_DMA32_free_after)) $ZONE_DMA32_Total_before "ZONE_DMA32"
    check_mem $(($ZONE_Normal_free_before-$ZONE_Normal_free_after)) $ZONE_Normal_Total_before "ZONE_Normal"
}


###############################################################################
# for vmalloc
###############################################################################
declare -i vmalloc_used_before=0
declare -i vmalloc_used_after=0

check_vmalloc_used_before(){
    vmalloc_used_before=$(cat /proc/vmallocinfo | grep vmalloc | awk  '{sum+=$2;} END{print sum;}')

    # Byte ->kB
    vmalloc_used_before=$vmalloc_used_before/1024
    echo "vmalloc_used_before:$vmalloc_used_before"
}


check_vmalloc_used_after(){
    vmalloc_used_after=$(cat /proc/vmallocinfo | grep vmalloc | awk  '{sum+=$2;} END{print sum;}')

    # Byte ->kB
    vmalloc_used_after=$vmalloc_used_after/1024
    echo "vmalloc_used_after:$vmalloc_used_after"

    check_mem $(($vmalloc_used_after-$vmalloc_used_before)) $VmallocTotal_before "vmalloc"
}