#!/usr/bin/env python3
#===============================================================================
# Copyright 2019 NetApp, Inc. All Rights Reserved,
# contribution by Jorge Mora <mora@netapp.com>
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#===============================================================================
import os
import errno
import traceback
import nfstest_config as c
from nfstest.test_util import TestUtil

# Module constants
__author__    = "Jorge Mora (%s)" % c.NFSTEST_AUTHOR_EMAIL
__copyright__ = "Copyright (C) 2019 NetApp, Inc."
__license__   = "GPL v2"
__version__   = "1.0"

USAGE = """%prog --server <server> [options]

NFS file compare
================
Create a file using one set of NFS mount options and then verify the data
is correct by reading the file using another set of NFS mount options.

Examples:
    Use positional arguments with nfsversion=3 for second mount:
        %prog -s 192.168.0.2 -e /exports --nfsopts :::3

    Use named arguments instead:
        %prog -s 192.168.0.2 -e /exports --nfsopts nfsversion=3

Notes:
    The user id in the local host must have access to run commands as root
    using the 'sudo' command without the need for a password."""

# Test script ID
SCRIPT_ID = "FCMP"

TESTNAMES = ["test01", "test02"]

class FcmpTest(TestUtil):
    """FcmpTest object

       FcmpTest() -> New test object

       Usage:
           x = FcmpTest(testnames=['test01'])

           # Run all the tests
           x.run_tests()
           x.exit()
    """
    def __init__(self, **kwargs):
        """Constructor

           Initialize object's private data.
        """
        TestUtil.__init__(self, **kwargs)

        hmsg = "NFS options used for comparing test file. " \
               "NFS mount definition is a list of arguments separated by a ':' " \
               "given in the following order if positional arguments are used " \
               "(see examples): " \
               "::export:nfsversion:port:proto:sec"
        self.test_opgroup.add_option("--nfsopts", default=None, help=hmsg)
        hmsg = "NFS mount options used for comparing test file other " \
               "than the ones specified in --nfsopts [default: '%default']"
        self.test_opgroup.add_option("--cmpopts", default="hard", help=hmsg)

        self.opts.version = "%prog " + __version__
        self.opts.set_defaults(nfiles=0)
        self.opts.set_defaults(filesize="1m")
        self.opts.set_defaults(rsize="64k")
        self.opts.set_defaults(wsize="64k")
        self.opts.set_defaults(mtopts="hard")

        self.scan_options()

        # Disable createtraces option
        self.createtraces = False

        nfsopts_item = self.process_client_option("nfsopts", remote=False)[0]
        # Create a copy of the nfsopts item
        client_args = dict(nfsopts_item)
        # Create a Host object for the given client
        client_args.pop("client", "")
        client_args["mtpoint"] = self.mtpoint
        client_args["mtopts"] = self.cmpopts
        self.create_host("", **client_args)

    def test01_test(self):
        """Verify data read from file is correct"""
        try:
            self.test_group("Verify data read from file is correct")
            self.test_info("Create file using second mount options")

            self.trace_start()
            self.clientobj.mount()
            self.mtdir = self.clientobj.mtdir
            try:
                fmsg = ""
                expr = True
                self.create_file(verbose=1, dlevels=["DBG2"])
            except OSError as error:
                expr = False
                err = error.errno
                fmsg = ", got error [%s] %s" % (errno.errorcode.get(err,err), os.strerror(err))
            self.test(expr, "File should be created", failmsg=fmsg)
            if not expr:
                return
        except Exception:
            self.test(False, traceback.format_exc())
            return
        finally:
            self.clientobj.umount()

        try:
            self.test_info("Compare file's data using main mount options")
            self.mount()
            self.verify_file_data("Data read from file is correct")
        except Exception:
            self.test(False, traceback.format_exc())
        finally:
            self.umount()
            self.trace_stop()

    def test02_test(self):
        """Verify data written to file is correct"""
        try:
            self.test_group("Verify data written to file is correct")
            self.test_info("Create file using main mount options")

            self.trace_start()
            self.mount()

            try:
                fmsg = ""
                expr = True
                self.create_file(verbose=1, dlevels=["DBG2"])
            except OSError as error:
                expr = False
                err = error.errno
                fmsg = ", got error [%s] %s" % (errno.errorcode.get(err,err), os.strerror(err))
            self.test(expr, "File should be created", failmsg=fmsg)
            if not expr:
                return
        except Exception:
            self.test(False, traceback.format_exc())
            return
        finally:
            self.umount()

        try:
            self.test_info("Compare file's data using second mount options")
            self.clientobj.mount()
            self.verify_file_data("Data written to file is correct")
        except Exception:
            self.test(False, traceback.format_exc())
        finally:
            self.clientobj.umount()
            self.trace_stop()

################################################################################
# Entry point
x = FcmpTest(usage=USAGE, testnames=TESTNAMES, sid=SCRIPT_ID)

try:
    # Run all the tests
    x.run_tests()
except Exception:
    x.test(False, traceback.format_exc())
finally:
    x.cleanup()
    x.exit()
