add test for per module

This commit is contained in:
citronneur
2014-11-06 22:04:21 +01:00
parent 119f31227f
commit 24096b5e8a
4 changed files with 272 additions and 66 deletions

View File

@@ -16,5 +16,5 @@ install:
- scons -C rdpy/core install - scons -C rdpy/core install
script: script:
- python -m unittest discover -s test - python -m unittest discover -s test -v

View File

@@ -1,16 +1,35 @@
''' #
@author: sylvain # Copyright (c) 2014 Sylvain Peyrefitte
''' #
# This file is part of rdpy.
#
# rdpy 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 3 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.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
Per encoded function
"""
from rdpy.network.type import UInt8, UInt16Be, UInt32Be, String from rdpy.network.type import UInt8, UInt16Be, UInt32Be, String
from rdpy.base.error import InvalidValue, InvalidExpectedDataException from rdpy.base.error import InvalidValue, InvalidExpectedDataException
def readLength(s): def readLength(s):
''' """
read length use in per specification @summary: read length use in per specification
@param s: Stream @param s: Stream
@return: int python @return: int python
''' """
byte = UInt8() byte = UInt8()
s.readType(byte) s.readType(byte)
size = 0 size = 0
@@ -24,95 +43,95 @@ def readLength(s):
return size return size
def writeLength(value): def writeLength(value):
''' """
write length as expected in per specification @summary: write length as expected in per specification
@param value: int or long python @param value: int or long python
@return: UInt8, UInt16Be depend on value @return: UInt8, UInt16Be depend on value
''' """
if value > 0x7f: if value > 0x7f:
return UInt16Be(value | 0x8000) return UInt16Be(value | 0x8000)
else: else:
return UInt8(value) return UInt8(value)
def readChoice(s): def readChoice(s):
''' """
read per choice format @summary: read per choice format
@param s: Stream @param s: Stream
@return: int that represent choice @return: int that represent choice
''' """
choice = UInt8() choice = UInt8()
s.readType(choice) s.readType(choice)
return choice.value return choice.value
def writeChoice(choice): def writeChoice(choice):
''' """
read per choice structure @summary: read per choice structure
@param choice: int choice value @param choice: int choice value
@return: UInt8 @return: UInt8
''' """
return UInt8(choice) return UInt8(choice)
def readSelection(s): def readSelection(s):
''' """
read per selection format @summary: read per selection format
@param s: Stream @param s: Stream
@return: int that represent selection @return: int that represent selection
''' """
choice = UInt8() choice = UInt8()
s.readType(choice) s.readType(choice)
return choice.value return choice.value
def writeSelection(selection): def writeSelection(selection):
''' """
read per selection structure @summary: read per selection structure
@param selection: int selection value @param selection: int selection value
@return: UInt8 @return: UInt8
''' """
return UInt8(selection) return UInt8(selection)
def readNumberOfSet(s): def readNumberOfSet(s):
''' """
read per numberOfSet format @summary: read per numberOfSet format
@param s: Stream @param s: Stream
@return: int that represent numberOfSet @return: int that represent numberOfSet
''' """
choice = UInt8() choice = UInt8()
s.readType(choice) s.readType(choice)
return choice.value return choice.value
def writeNumberOfSet(numberOfSet): def writeNumberOfSet(numberOfSet):
''' """
read per numberOfSet structure @summary: read per numberOfSet structure
@param numberOfSet: int numberOfSet value @param numberOfSet: int numberOfSet value
@return: UInt8 @return: UInt8
''' """
return UInt8(numberOfSet) return UInt8(numberOfSet)
def readEnumerates(s): def readEnumerates(s):
''' """
read per enumerate format @summary: read per enumerate format
@param s: Stream @param s: Stream
@return: int that represent enumerate @return: int that represent enumerate
''' """
choice = UInt8() choice = UInt8()
s.readType(choice) s.readType(choice)
return choice.value return choice.value
def writeEnumerates(enumer): def writeEnumerates(enumer):
''' """
read per enumerate structure @summary: read per enumerate structure
@param enumer: int enumerate value @param enumer: int enumerate value
@return: UInt8 @return: UInt8
''' """
return UInt8(enumer) return UInt8(enumer)
def readInteger(s): def readInteger(s):
''' """
read interger per format from stream @summary: read interger per format from stream
@param s: Stream @param s: Stream
@return: python int or long @return: python int or long
@raise InvalidValue: if size of integer is not correct @raise InvalidValue: if size of integer is not correct
''' """
result = None result = None
size = readLength(s) size = readLength(s)
if size == 1: if size == 1:
@@ -127,11 +146,11 @@ def readInteger(s):
return result.value return result.value
def writeInteger(value): def writeInteger(value):
''' """
write python long or int into per integer format @summary: write python long or int into per integer format
@param value: int or long python value @param value: int or long python value
@return: UInt8, UInt16Be or UInt32Be @return: UInt8, UInt16Be or UInt32Be
''' """
if value <= 0xff: if value <= 0xff:
return (writeLength(1), UInt8(value)) return (writeLength(1), UInt8(value))
elif value < 0xffff: elif value < 0xffff:
@@ -140,32 +159,32 @@ def writeInteger(value):
return (writeLength(4), UInt32Be(value)) return (writeLength(4), UInt32Be(value))
def readInteger16(s, minimum = 0): def readInteger16(s, minimum = 0):
''' """
read UInt16Be from stream s and add minimum @summary: read UInt16Be from stream s and add minimum
@param s: Stream @param s: Stream
@param minimum: minimum added to real value @param minimum: minimum added to real value
@return: int or long python value @return: int or long python value
''' """
result = UInt16Be() result = UInt16Be()
s.readType(result) s.readType(result)
return result.value + minimum return result.value + minimum
def writeInteger16(value, minimum = 0): def writeInteger16(value, minimum = 0):
''' """
write UInt16Be minus minimum @summary: write UInt16Be minus minimum
@param value: value to write @param value: value to write
@param minimum: value subtracted to real value @param minimum: value subtracted to real value
@return: UInt16Be @return: UInt16Be
''' """
return UInt16Be(value - minimum) return UInt16Be(value - minimum)
def readObjectIdentifier(s, oid): def readObjectIdentifier(s, oid):
''' """
read object identifier @summary: read object identifier
@param oid: must be a tuple of 6 elements @param oid: must be a tuple of 6 elements
@param s: Stream @param s: Stream
@return: true if oid is same as in stream @return: true if oid is same as in stream
''' """
size = readLength(s) size = readLength(s)
if size != 5: if size != 5:
raise InvalidValue("size of stream oid is wrong %d != 5"%size) raise InvalidValue("size of stream oid is wrong %d != 5"%size)
@@ -188,7 +207,7 @@ def readObjectIdentifier(s, oid):
def writeObjectIdentifier(oid): def writeObjectIdentifier(oid):
""" """
Create tuple of 6 UInt8 with oid values @summary: Create tuple of 6 UInt8 with oid values
@param oid: tuple of 6 int @param oid: tuple of 6 int
@return: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8) @return: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8)
""" """
@@ -196,7 +215,7 @@ def writeObjectIdentifier(oid):
def readNumericString(s, minValue): def readNumericString(s, minValue):
""" """
Read numeric string @summary: Read numeric string
@param s: Stream @param s: Stream
@param minValue: offset @param minValue: offset
""" """
@@ -205,12 +224,12 @@ def readNumericString(s, minValue):
s.read(length) s.read(length)
def writeNumericString(nStr, minValue): def writeNumericString(nStr, minValue):
''' """
write string in per format @summary: write string in per format
@param str: python string to write @param str: python string to write
@param min: min value @param min: min value
@return: String type that contain str encoded in per format @return: String type that contain str encoded in per format
''' """
length = len(nStr) length = len(nStr)
mlength = minValue mlength = minValue
if length - minValue >= 0: if length - minValue >= 0:
@@ -232,29 +251,29 @@ def writeNumericString(nStr, minValue):
return (writeLength(mlength), tuple(result)) return (writeLength(mlength), tuple(result))
def readPadding(s, length): def readPadding(s, length):
''' """
read length byte in stream @summary: read length byte in stream
@param s: Stream @param s: Stream
@param length: length of passing in bytes @param length: length of passing in bytes
''' """
s.read(length) s.read(length)
def writePadding(length): def writePadding(length):
''' """
create string with null char * length @summary: create string with null char * length
@param length: length of padding @param length: length of padding
@return: String with \x00 * length @return: String with \x00 * length
''' """
return String("\x00"*length) return String("\x00"*length)
def readOctetStream(s, octetStream, minValue = 0): def readOctetStream(s, octetStream, minValue = 0):
''' """
read string as octet stream and compare with octetStream @summary: read string as octet stream and compare with octetStream
@param octetStream: compare stream @param octetStream: compare stream
@param s: Stream @param s: Stream
@param minValue: min value @param minValue: min value
@return: if stream read from s is equal to octetStream @return: if stream read from s is equal to octetStream
''' """
size = readLength(s) + minValue size = readLength(s) + minValue
if size != len(octetStream): if size != len(octetStream):
raise InvalidValue("incompatible size %d != %d"(len(octetStream), size)) raise InvalidValue("incompatible size %d != %d"(len(octetStream), size))
@@ -267,12 +286,12 @@ def readOctetStream(s, octetStream, minValue = 0):
return True return True
def writeOctetStream(oStr, minValue = 0): def writeOctetStream(oStr, minValue = 0):
''' """
write string as octet stream with per header @summary: write string as octet stream with per header
@param oStr: octet stream to convert @param oStr: octet stream to convert
@param minValue: min length value @param minValue: min length value
@return: per header follow by tuple of UInt8 @return: per header follow by tuple of UInt8
''' """
length = len(oStr) length = len(oStr)
mlength = minValue mlength = minValue

View File

@@ -0,0 +1,80 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
#
# This file is part of rdpy.
#
# rdpy 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 3 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.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
unit test for rdpy.protocol.rdp.ber module
"""
import os, sys
# Change path so we find rdpy
sys.path.insert(1, os.path.join(sys.path[0], '..'))
import unittest
import rdpy.protocol.rdp.ber as ber
import rdpy.network.type as type
import rdpy.base.error as error
class BERCase(unittest.TestCase):
"""
@summary: test case for ber layer (RDP)
"""
def test_ber_readLength(self):
"""
@summary: test readLength function in ber module
"""
s1 = type.Stream()
s1.writeType(type.UInt8(0x1a))
s1.pos = 0
l1 = ber.readLength(s1)
self.assertTrue(l1 == 0x1a, "readLength fail in small format")
s2 = type.Stream()
s2.writeType((type.UInt8(0x81),type.UInt8(0xab)))
s2.pos = 0
l2 = ber.readLength(s2)
self.assertTrue(l2 == 0xab, "readLength fail in big format of size 1")
s3 = type.Stream()
s3.writeType((type.UInt8(0x82),type.UInt16Be(0xabab)))
s3.pos = 0
l3 = ber.readLength(s3)
self.assertTrue(l3 == 0xabab, "readLength fail in big format of size 2")
def test_ber_writeLength(self):
"""
@summary: test writeLength function in ber module
"""
l1 = ber.writeLength(0x1a)
self.assertTrue(isinstance(l1, type.UInt8), "bad write length type in small case")
l2 = ber.writeLength(0x7f)
self.assertTrue(isinstance(l2, type.UInt8), "bad write length type in small case limit")
(h3, l3) = ber.writeLength(0x80)
self.assertTrue(h3.value == 0x82 and isinstance(l3, type.UInt16Be), "bad write length type in large case limit")
(h4, l4) = ber.writeLength(0xab)
self.assertTrue(h4.value == 0x82 and isinstance(l4, type.UInt16Be), "bad write length type in large case")

View File

@@ -0,0 +1,107 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
#
# This file is part of rdpy.
#
# rdpy 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 3 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.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
unit test for rdpy.protocol.rdp.per module
"""
import os, sys
# Change path so we find rdpy
sys.path.insert(1, os.path.join(sys.path[0], '..'))
import unittest
import rdpy.protocol.rdp.per as per
import rdpy.network.type as type
import rdpy.base.error as error
class PERCase(unittest.TestCase):
"""
@summary: test case for per layer (RDP)
"""
def test_per_readLength(self):
"""
@summary: test readLength function in per module
"""
s1 = type.Stream()
s1.writeType(type.UInt8(0x1a))
s1.pos = 0
l1 = per.readLength(s1)
self.assertTrue(l1 == 0x1a, "readLength fail in small format")
s2 = type.Stream()
s2.writeType(type.UInt16Be(0x1abc | 0x8000))
s2.pos = 0
l2 = per.readLength(s2)
self.assertTrue(l2 == 0x1abc, "readLength fail in big format")
def test_per_writeLength(self):
"""
@summary: test writeLength function in per module
"""
l1 = per.writeLength(0x1a)
self.assertTrue(isinstance(l1, type.UInt8), "bad write length type in small case")
l2 = per.writeLength(0x7f)
self.assertTrue(isinstance(l2, type.UInt8), "bad write length type in small case limit")
l3 = per.writeLength(0x80)
self.assertTrue(isinstance(l3, type.UInt16Be), "bad write length type in large case limit")
l4 = per.writeLength(0xab)
self.assertTrue(isinstance(l4, type.UInt16Be), "bad write length type in large case")
def test_per_readInteger(self):
"""
@summary: test readInteger function in per module
"""
for t in [type.UInt8, type.UInt16Be, type.UInt32Be]:
v = t(3)
s = type.Stream()
s.writeType((per.writeLength(type.sizeof(v)), v))
s.pos = 0
self.assertTrue(per.readInteger(s) == 3, "invalid readLength for type %s"%t)
#error case
for l in [0, 3, 5]:
s = type.Stream()
s.writeType(per.writeLength(l))
s.pos = 0
self.assertRaises(error.InvalidValue, per.readInteger, s)
def test_per_writeInteger(self):
"""
@summary: test writeInteger function in per module
"""
(s, i) = per.writeInteger(0xaf)
self.assertTrue(s.value == 1 and isinstance(i, type.UInt8), "invalid writeLength output in case of size 1")
(s, i) = per.writeInteger(0xaff)
self.assertTrue(s.value == 2 and isinstance(i, type.UInt16Be), "invalid writeLength output in case of size 2")
(s, i) = per.writeInteger(0xaffff)
self.assertTrue(s.value == 4 and isinstance(i, type.UInt32Be), "invalid writeLength output in case of size 4")