%env CLIENT bitrepository-client-1.9-RC1

!wget -Nq "https://sbforge.org/download/attachments/25395346/${CLIENT}.zip"
!unzip -quo ${CLIENT}.zip

%alias bitmag ${CLIENT}/bin/bitmag.sh %l

#Some imports we will need later
import random
import string

"""
Explanation: Setup command line client
The following is code to get the client and set it up.
End of explanation
"""


TESTFILE1='README.md'

"""
Explanation: Describes the tests needed to validate the PutFile functionality.
The commands presented are just examples of what the actual command to test with could look like.
Basic put
Put a file to all pillars
Run put command on a file which is not present in the collection.
End of explanation
"""


%bitmag get-file-ids -c integrationtest2 -i {TESTFILE1}

"""
Explanation: Check this by running
End of explanation
"""


hash=!cat {TESTFILE1} | md5sum - | cut -d' ' -f1
print("md5: {}".format(hash))

%bitmag delete -c integrationtest2 -i {TESTFILE1} -C {hash.s} -p "sbtape2"
%bitmag delete -c integrationtest2 -i {TESTFILE1} -C {hash.s}  -p "reference2"
%bitmag delete -c integrationtest2 -i {TESTFILE1} -C {hash.s}  -p "checksum2"
%bitmag delete -c integrationtest2 -i {TESTFILE1} -C {hash.s}  -p "sbdisk1"
%bitmag delete -c integrationtest2 -i {TESTFILE1} -C {hash.s}  -p "kbpillar2"

%bitmag put-file -c integrationtest2 -f {TESTFILE1}

"""
Explanation: The response should be
Count:  Size:   FileID:

Indicating that no pillar had the file.
If the file is found, delete it with the following command
See https://www.safaribooksonline.com/blog/2014/02/12/using-shell-commands-effectively-ipython/ for how this works
End of explanation
"""


%bitmag get-file-ids -c integrationtest2 -i {TESTFILE1}

%bitmag get-checksums -c integrationtest2 -i {TESTFILE1}

"""
Explanation: Verify that it is now present at all pillars, and that it has the same checksum at all pillars
End of explanation
"""


TESTFILE2=''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(10))

%bitmag put-file -c integrationtest2 -f {TESTFILE1} -i {TESTFILE2}

"""
Explanation: Put a file with a different file-id to all pillars
Run put command on a file and use the file-id parameter (-i)
End of explanation
"""


%bitmag get-file-ids -c integrationtest2 -i {TESTFILE2}

%bitmag get-checksums -c integrationtest2 -i {TESTFILE2}

"""
Explanation: Verify that it is now present at all pillars, and that it has the same checksum at all pillars
End of explanation
"""


TESTFILE3=''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(10))
URL='http://sandkasse-01.kb.dk/dav/test.txt'

hash=!curl -s {URL} | md5sum - | cut -d' ' -f1
print("md5: {}".format(hash))
%bitmag put-file -c integrationtest2 -u {URL} -i {TESTFILE3} -C {hash.s}

"""
Explanation: Put a file by using an URL
Use the URL and Checksum to put a file, already on the webdav server.
End of explanation
"""


%bitmag get-file-ids -c integrationtest2 -i {TESTFILE3}

%bitmag get-checksums -c integrationtest2 -i {TESTFILE3}

"""
Explanation: Verify that it is now present at al pillars, with the requested checksum
End of explanation
"""


%bitmag put-file -c integrationtest2 -f {TESTFILE1}

"""
Explanation: Idempotent test
Attempt to put a file with an fileID that is already present in the collection suppling the same checksum
The putFile request should succeed.
End of explanation
"""


import hmac
import hashlib
import urllib.request

def getSaltedChecksum(url,salt,algorithm):
    saltBytes = bytes.fromhex(salt)
    digester = hmac.new(saltBytes,None,algorithm)
    with urllib.request.urlopen(url) as from_fh:
        while True:
            chunk = from_fh.read()
            if not chunk:
                break
            digester.update(chunk)
    return digester.hexdigest().lower()

saltedChecksum=getSaltedChecksum(url=URL,salt='abcd',algorithm=hashlib.sha1)
print(saltedChecksum)

"""
Explanation: Put with returned checksums
Put a file including a request of a salted checksum calculated on the pillar, which should be returned.
End of explanation
"""


TESTFILE4=''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(10))

"""
Explanation: Use the request-checksum-algorithm and request-checksum-salt arguments (-R and -S):
End of explanation
"""


hash=!curl -s {URL} | md5sum - | cut -d' ' -f1
print("md5: {}".format(hash))
%bitmag put-file -c integrationtest2 -u {URL} -i {TESTFILE4} -C {hash.s} -S 'abcd' -R HMAC_SHA1

"""
Explanation: Note, this will return the stored MD5 hashes, if the file is already put'et
End of explanation
"""


%bitmag get-checksums -c integrationtest2 -i {TESTFILE4} -R HMAC_SHA1 -S 'abcd'

"""
Explanation: Verify that the checksumpillar does not reply with a checksum.
End of explanation
"""


%bitmag get-file-ids -c integrationtest2 -i {TESTFILE4}

"""
Explanation: Verify that the checksumpillar and all the other pillars have the file
End of explanation
"""


TESTFILE5=''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(10))

hash=!curl -s {URL} | md5sum - | cut -d' ' -f1
print("md5: {}".format(hash))

%bitmag put-file -c integrationtest2 -u {URL} -i {TESTFILE5} -C {hash.s} -R SHA1 -S 'abcd'

"""
Explanation: Put a file including a request for checksum, but using both a salt and a non-salt algorithm.
Use the request-checksum-algorithm and request-checksum-salt arguments (-R and -S):
End of explanation
"""


hash=!curl -s {URL} | md5sum - | cut -d' ' -f1
print("md5: {}".format(hash))

hash=!curl -s {URL} | sha1sum - | cut -d' ' -f1
print("sha1: {}".format(hash))

%bitmag get-checksums -c integrationtest2 -i {TESTFILE5}

"""
Explanation: Verify that all the data pillars return the same checksum, and that it is identical to the previous test (where '-R HMAC_SHA1')
Put a file including a request for checksum, but using a salt algorithm but not giving a salt.
Use the request-checksum-algorithm and request-checksum-salt arguments (-R and no -S):
End of explanation
"""


%bitmag put-file -c integrationtest2 -f .gitignore -i {TESTFILE1}

"""
Explanation: Verify that the data pillars all deliver the same checksum, which must be different from the checksum in the previous two tests.
Error scenarios
Attempt to put a file with an fileID that is already present in the collection (ensure that the file has a different checksum from the already archived)
The putFile request should fail informing the user that a file with the given file ID already exists in the collection.
End of explanation
"""


%bitmag put-file -c integrationtest2 -f ThisFileDoesNotExist

"""
Explanation: Attempt to put a file which does not exist
Client should fail immediately
End of explanation
"""


%bitmag put-file -c integrationtest3 -i {TESTFILE1}

"""
Explanation: Attempt to put a file to a non-existing collection
Client should fail immediately
End of explanation
"""


%bitmag put-file -c integrationtest1 -i {TESTFILE1} -p non-existing-pillar

"""
Explanation: Attempt to put a file to a non-existing pillar
Client should fail immediately
End of explanation
"""


