#!/usr/bin/env python3

import os
import sys

from checkbox.parsers.dmidecode import DmidecodeParser
from checkbox.parsers.meminfo import MeminfoParser

THRESHOLD = 10

class DmiResult:

    total_size = 0

    def addDmiDevice(self, device):
        form = getattr(device, "form", None)

        if form and "IMM" in form:
            try:
                self.total_size += int(getattr(device, "size", 0))
            except ValueError:
                pass

def get_installed_memory_size():
    dmi = DmidecodeParser(os.popen('dmidecode'))
    result = DmiResult()

    dmi.run(result)

    return result.total_size

class MeminfoResult:

    memtotal = 0

    def setMemory(self, memory):
        self.memtotal = memory['total']

def get_visible_memory_size():
    parser = MeminfoParser(open('/proc/meminfo'))
    result = MeminfoResult()
    parser.run(result)

    return result.memtotal

def main():
    if os.geteuid() != 0:
        print("This script must be run as root.", file=sys.stderr)
        return 1

    installed_memory = get_installed_memory_size()
    visible_memory = get_visible_memory_size()

    difference = installed_memory - visible_memory
    try:
        percentage = difference / installed_memory * 100
    except ZeroDivisionError:
        print("FAIL: Either dmi or /proc/meminfo returned a memory size of 0 kB", file=sys.stderr)
        print("\t/proc/meminfo reports:\t%s kB" % visible_memory, file=sys.stderr)
        print("\tdmi reports:\t%s kB" % installed_memory, file=sys.stderr)
        return 1
    
    if percentage <= THRESHOLD:
        print("PASS: Difference is %d bytes (%.2f%%) and less than the %d%% threshold." % (difference, percentage, THRESHOLD))
        print("\t/proc/meminfo reports:\t%s kB" % visible_memory)
        print("\tdmi reports:\t%s kB" % installed_memory)
        return 0
    else:
        print("FAIL: Difference is %d bytes (%.2f%%) and greater than the %d%% threshold." % (difference, percentage, THRESHOLD), file=sys.stderr)
        print("\t/proc/meminfo reports:\t%s kB" % visible_memory, file=sys.stderr)
        print("\tdmi reports:\t%s kB" % installed_memory, file=sys.stderr)
        return 1

if __name__ == "__main__":
    sys.exit(main())
