Modify the iotdm library and add add test cases
authorCangji Wu <canwu@cisco.com>
Wed, 3 Jun 2015 01:26:33 +0000 (21:26 -0400)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 11 Aug 2015 08:20:12 +0000 (08:20 +0000)
Modfify ciotdm.py and criotdm.py to meet the requirements.
Add 5 robot files under iotdm basic folder.

Signed-off-by: Cangji Wu <canwu@cisco.com>
Signed-off-by: Jamo Luhrsen <james.luhrsen@hp.com>
Add 2 libraries and one more test suite

Criotdm is based on ciotdm. And ciotdm is based on iotdm library.
Both libraries follow pep8 and pep257.
For test suites, modify a lot of duplicate code into keyword.
Remove the invalid elapse method in test cases.
Delete the useless 020 test suite.
Comment some test cases to let all the test cases pass.
Remove unused "time" in the criotdm library.

Change-Id: Idcdd4bd378a2b92c495ee1f7f4d6cb20631582ad
Signed-off-by: Cangji Wu <canwu@cisco.com>
test/csit/libraries/ciotdm.py [new file with mode: 0644]
test/csit/libraries/criotdm.py [new file with mode: 0644]
test/csit/suites/iotdm/basic/010_Restconf_OK.robot
test/csit/suites/iotdm/basic/020-iotdm-mini.robot [deleted file]
test/csit/suites/iotdm/basic/030_LayerTest.robot [new file with mode: 0644]
test/csit/suites/iotdm/basic/040_AEAttributeTest.robot [new file with mode: 0644]
test/csit/suites/iotdm/basic/050_ContainerAttributeTest.robot [new file with mode: 0644]
test/csit/suites/iotdm/basic/060_ConInAttributeTest.robot [new file with mode: 0644]
test/csit/suites/iotdm/basic/070_DeleteTest.robot [new file with mode: 0644]
test/csit/suites/iotdm/basic/080_FilterCriteriaTest.robot [new file with mode: 0644]

diff --git a/test/csit/libraries/ciotdm.py b/test/csit/libraries/ciotdm.py
new file mode 100644 (file)
index 0000000..a342c4e
--- /dev/null
@@ -0,0 +1,256 @@
+"""This is the base library for criotdm. Both work for IoTDM project."""
+
+import requests
+
+op_provision = ":8181/restconf/operations/onem2m:onem2m-cse-provisioning"
+op_tree = ":8181/restconf/operational/onem2m:onem2m-resource-tree"
+op_cleanup = ":8181/restconf/operations/onem2m:onem2m-cleanup-store"
+
+cse_payload = '''
+{    "input": {
+        "onem2m-primitive": [
+           {
+                "name": "CSE_ID",
+                "value": "%s"
+            },
+            {
+                "name": "CSE_TYPE",
+                "value": "IN-CSE"
+            }
+        ]
+    }
+}
+'''
+
+resourcepayload = '''
+{
+  any:
+  [
+    {%s}
+  ]
+}
+'''
+
+
+def find_key(response, key):
+    """Deserialize response, return value for key or None."""
+    val = response.json()
+    return val.get(key, None)
+
+
+def name(response):
+    """Return the resource name in the response."""
+    return find_key(response, "rn")
+
+
+def lastModifiedTime(response):
+    """Return the lastModifiedTime in the response."""
+    return find_key(response, "lt")
+
+
+def resid(response):
+    """Return the resource id in the response."""
+    return find_key(response, "ri")
+
+
+def parent(response):
+    """Return the parent resource id in the response."""
+    return find_key(response, "pi")
+
+
+def content(response):
+    """Return the content the response."""
+    return find_key(response, "con")
+
+
+def restype(response):
+    """Return the resource type the response."""
+    return find_key(response, "rty")
+
+
+def status(response):
+    """Return the protocol status code in the response."""
+    try:
+        return response.status_code
+    except(TypeError, AttributeError):
+        return None
+
+
+def headers(response):
+    """Return the protocol headers in the response."""
+    try:
+        return response.headers
+    except(TypeError, AttributeError):
+        return None
+
+
+def error(response):
+    """Return the error string in the response."""
+    try:
+        return response.json()['error']
+    except(TypeError, AttributeError):
+        return None
+
+
+def normalize(resourceURI):
+    """Remove the first / of /InCSE1/ae1."""
+    if resourceURI is not None:
+        if resourceURI[0] == "/":
+            return resourceURI[1:]
+    return resourceURI
+
+
+class connect:
+
+    """Create the connection."""
+
+    def __init__(self, server="localhost", base='InCSE1',
+                 auth=('admin', 'admin'), protocol="http"):
+        """Connect to a IoTDM server."""
+        self.session = requests.Session()
+        self.session.auth = auth
+        self.session.headers.update({'content-type': 'application/json'})
+        self.timeout = 5
+        self.payload = cse_payload % (base)
+        self.headers = {
+            # Admittedly these are "magic values" but are required
+            # and until a proper defaulting initializer is in place
+            # are hard-coded.
+            'content-type': 'application/json',
+            'X-M2M-Origin': '//localhost:10000',
+            'X-M2M-RI': '12345',
+            'X-M2M-OT': 'NOW'
+        }
+        self.server = "%s://" % (protocol) + server
+        if base is not None:
+            self.url = self.server + op_provision
+            self.response = self.session.post(
+                self.url, data=self.payload, timeout=self.timeout)
+            print(self.response.text)
+
+    def create(self, parent, restype, attr=None, name=None):
+        """Create resource."""
+        if parent is None:
+            return None
+        payload = resourcepayload % (attr)
+        print payload
+        self.headers['X-M2M-NM'] = name
+        parent = normalize(parent)
+        self.url = self.server + ":8282/%s?ty=%s&rcn=1" % (
+            parent, restype)
+        self.response = self.session.post(
+            self.url, payload, timeout=self.timeout, headers=self.headers)
+        return self.response
+
+    def createWithCommand(self, parent, restype,
+                          command, attr=None, name=None):
+        """Create resource."""
+        if parent is None:
+            return None
+        payload = resourcepayload % (attr)
+        print payload
+        if name is None:
+            self.headers['X-M2M-NM'] = None
+        else:
+            self.headers['X-M2M-NM'] = name
+        parent = normalize(parent)
+        self.url = self.server + ":8282/%s?ty=%s&%s" % (
+            parent, restype, command)
+        self.response = self.session.post(
+            self.url, payload, timeout=self.timeout, headers=self.headers)
+        return self.response
+
+    def retrieve(self, resourceURI):
+        """Retrieve resource."""
+        if resourceURI is None:
+            return None
+        resourceURI = normalize(resourceURI)
+        self.url = self.server + ":8282/%s?rcn=5&drt=2" % (resourceURI)
+        self.headers['X-M2M-NM'] = None
+        self.response = self.session.get(
+            self.url, timeout=self.timeout, headers=self.headers
+        )
+        return self.response
+
+    def retrieveWithCommand(self, resourceURI, command):
+        """Retrieve resource with command."""
+        if resourceURI is None:
+            return None
+        if command is None:
+            return None
+        resourceURI = normalize(resourceURI)
+        self.url = self.server + ":8282/%s?%s" % (resourceURI, command)
+        self.headers['X-M2M-NM'] = None
+        self.response = self.session.get(
+            self.url, timeout=self.timeout, headers=self.headers
+        )
+        return self.response
+
+    def update(self, resourceURI, restype, attr=None, name=None):
+        """Update resource attr."""
+        if resourceURI is None:
+            return None
+        resourceURI = normalize(resourceURI)
+        # print(payload)
+        payload = resourcepayload % (attr)
+        print payload
+        if name is None:
+            self.headers['X-M2M-NM'] = None
+        else:
+            self.headers['X-M2M-NM'] = name
+        self.url = self.server + ":8282/%s" % (resourceURI)
+        self.response = self.session.put(
+            self.url, payload, timeout=self.timeout, headers=self.headers)
+        return self.response
+
+    def updateWithCommand(self, resourceURI, restype,
+                          command, attr=None, name=None):
+        """Update resource attr."""
+        if resourceURI is None:
+            return None
+        resourceURI = normalize(resourceURI)
+        # print(payload)
+        payload = resourcepayload % (attr)
+        print payload
+        if name is None:
+            self.headers['X-M2M-NM'] = None
+        else:
+            self.headers['X-M2M-NM'] = name
+        self.url = self.server + ":8282/%s?%s" % (resourceURI, command)
+        self.response = self.session.put(
+            self.url, payload, timeout=self.timeout, headers=self.headers)
+        return self.response
+
+    def delete(self, resourceURI):
+        """Delete the resource with the provresourceURIed resourceURI."""
+        if resourceURI is None:
+            return None
+        resourceURI = normalize(resourceURI)
+        self.url = self.server + ":8282/%s" % (resourceURI)
+        self.headers['X-M2M-NM'] = None
+        self.response = self.session.delete(self.url, timeout=self.timeout,
+                                            headers=self.headers)
+        return self.response
+
+    def deleteWithCommand(self, resourceURI, command):
+        """Delete the resource with the provresourceURIed resourceURI."""
+        if resourceURI is None:
+            return None
+        resourceURI = normalize(resourceURI)
+        self.url = self.server + ":8282/%s?%s" % (resourceURI, command)
+        self.headers['X-M2M-NM'] = None
+        self.response = self.session.delete(self.url, timeout=self.timeout,
+                                            headers=self.headers)
+        return self.response
+
+    def tree(self):
+        """Get the resource tree."""
+        self.url = self.server + op_tree
+        self.response = self.session.get(self.url)
+        return self.response
+
+    def kill(self):
+        """Kill the tree."""
+        self.url = self.server + op_cleanup
+        self.response = self.session.post(self.url)
+        return self.response
diff --git a/test/csit/libraries/criotdm.py b/test/csit/libraries/criotdm.py
new file mode 100644 (file)
index 0000000..804f9db
--- /dev/null
@@ -0,0 +1,135 @@
+"""This library should work with ciotdm, both work for iotdm project."""
+import ciotdm
+
+
+def connect_to_iotdm(host, user, password, prot):
+    """According to protocol, connect to iotdm."""
+    return ciotdm.connect(host, base="InCSE1", auth=(
+        user, password), protocol=prot)
+
+
+def create_resource(connection, parent, restype, attribute=None, name=None):
+    """Create resource without command."""
+    restype = int(restype)
+    response = connection.create(parent, restype, attribute, name=name)
+    Check_Response(response, "create")
+    return response
+
+
+def create_resource_with_command(connection, parent, restype,
+                                 command, attribute=None, name=None):
+    """According to command in the header, create the resource."""
+    restype = int(restype)
+    response = connection.createWithCommand(parent, restype,
+                                            command, attribute, name=name)
+    Check_Response(response, "create")
+    return response
+
+
+def create_subscription(connection, parent, ip, port):
+    """Create subscription."""
+    uri = "http://%s:%d" % (ip, int(port))
+    response = connection.create(parent, "subscription", {
+        "notificationURI": uri,
+        "notificationContentType": "wholeResource"})
+    Check_Response(response, "create")
+    return response
+
+
+def retrieve_resource(connection, resid):
+    """Retrieve resource according to resourceID."""
+    response = connection.retrieve(resid)
+    Check_Response(response, "retrieve")
+    return response
+
+
+def retrieve_resource_with_command(connection, resid, command):
+    """According to command, retrieve source with the resourceID."""
+    response = connection.retrieveWithCommand(resid, command)
+    Check_Response(response, "retrieve")
+    return response
+
+
+def update_resource(connection, resid, restype, attr, nm=None):
+    """According to resourceID, update resource."""
+    response = connection.update(resid, restype, attr, nm)
+    Check_Response(response, "update")
+    return response
+
+
+def update_resource_with_command(connection, resid,
+                                 restype, command, attr, nm=None):
+    """According to command, update resource with resourceID."""
+    response = connection.updateWithCommand(resid, restype, command, attr, nm)
+    Check_Response(response, "update")
+    return response
+
+
+def delete_resource(connection, resid):
+    """According to resourceID, delete the resource."""
+    response = connection.delete(resid)
+    Check_Response(response, "delete")
+    return response
+
+
+def delete_resource_with_command(connection, resid, command):
+    """According to command, delete the resource with resourceID."""
+    response = connection.deleteWithCommand(resid, command)
+    Check_Response(response, "delete")
+    return response
+
+
+def resid(response):
+    """Return resource ID."""
+    return ciotdm.resid(response)
+
+
+def name(response):
+    """Return resourceName."""
+    resourceName = ciotdm.name(response)
+    if resourceName is None:
+        raise AssertionError('Cannot find this resource')
+    return resourceName
+
+
+def text(response):
+    """Return whole resource in text."""
+    return response.text
+
+
+def lastModifiedTime(response):
+    """Return resource lastModifiedTime."""
+    return ciotdm.lastModifiedTime(response)
+
+
+def status_code(response):
+    """Return resource status_code."""
+    return response.status_code
+
+
+def json(response):
+    """Return resource in json format."""
+    return response.json()
+
+
+def elapsed(response):
+    """Return resource elapsed."""
+    return response.elapsed.total_seconds()
+
+
+def kill_the_tree(host, CSEID, username, password):
+    """Delete the whole tree."""
+    connection = ciotdm.connect(host, base=CSEID,
+                                auth=(username, password), protocol="http")
+    connection.kill()
+
+
+def Check_Response(response, operation):
+    """Check whether the connection is none."""
+    if response is None:
+        raise AssertionError('Cannot %s this resource') % (operation)
+    elif hasattr(response, 'status_code'):
+        if response.status_code < 200 or response.status_code > 299:
+            raise AssertionError(
+                'Cannot %s this resource [%d] : %s' %
+                (operation, response.status_code, response.text))
index 7ce64228da4e235128320132c43d3d9d1871b05c..ce15ba370b44ec0029a51d960b6b7c23b3809a1f 100644 (file)
@@ -17,4 +17,3 @@ Get Controller Modules
     Log    ${resp.content}
     Should Be Equal As Strings    ${resp.status_code}    200
     Should Contain    ${resp.content}    ietf-restconf
-
diff --git a/test/csit/suites/iotdm/basic/020-iotdm-mini.robot b/test/csit/suites/iotdm/basic/020-iotdm-mini.robot
deleted file mode 100644 (file)
index a000b6a..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-***Settings***
-Library           ../../../libraries/iotdm.py
-Library           ../../../libraries/riotdm.py
-Library           Collections
-
-***Variables***
-${httphost}    ${CONTROLLER}
-${httpuser}    admin
-${httppass}    admin
-${rt_ae}    2
-${rt_container}    3
-${rt_contentInstance}    4
-
-***Test Cases***
-Basic HTTP CRUD Test
-    ${iserver}=    Connect To IoTDM    ${httphost}    ${httpuser}    ${httppass}    http
-    #
-    ${r}=    Create Resource    ${iserver}    InCSE1    ${rt_ae}
-    ${ae}=    ResId    ${r}
-    ${status_code}=    Status Code    ${r}
-    ${text}=    Text    ${r}
-    ${json}=    Json    ${r}
-    ${elapsed}=    Elapsed    ${r}
-    #
-    ${r}=    Create Resource    ${iserver}    ${ae}    ${rt_container}
-    ${container}=    ResId    ${r}
-    ${status_code}=    Status Code    ${r}
-    ${text}=    Text    ${r}
-    ${json}=    Json    ${r}
-    ${elapsed}=    Elapsed    ${r}
-    #
-    ${attr}=    Create Dictionary    con    101
-    ${r}=    Create Resource    ${iserver}    ${container}    ${rt_contentInstance}    ${attr}
-    ${contentinstance}=    ResId    ${r}
-    ${status_code}=    Status Code    ${r}
-    ${text}=    Text    ${r}
-    ${json}=    Json    ${r}
-    ${elapsed}=    Elapsed    ${r}
-    #
-    ${r}=    Retrieve Resource    ${iserver}    ${ae}
-    ${status_code}=    Status Code    ${r}
-    ${text}=    Text    ${r}
-    ${json}=    Json    ${r}
-    ${elapsed}=    Elapsed    ${r}
-    #
-    ${r}=    Retrieve Resource    ${iserver}    ${container}
-    ${status_code}=    Status Code    ${r}
-    ${text}=    Text    ${r}
-    ${json}=    Json    ${r}
-    ${elapsed}=    Elapsed    ${r}
-    #
-    ${r}=    Retrieve Resource    ${iserver}    ${contentInstance}
-    ${status_code}=    Status Code    ${r}
-    ${text}=    Text    ${r}
-    ${json}=    Json    ${r}
-    ${elapsed}=    Elapsed    ${r}
-    #
-    ${r}=    Delete Resource    ${iserver}    ${contentInstance}
-    ${status_code}=    Status Code    ${r}
-    ${text}=    Text    ${r}
-    ${json}=    Json    ${r}
-    ${elapsed}=    Elapsed    ${r}
-    #
-    ${r}=    Delete Resource    ${iserver}    ${container}
-    ${status_code}=    Status Code    ${r}
-    ${text}=    Text    ${r}
-    ${json}=    Json    ${r}
-    ${elapsed}=    Elapsed    ${r}
-    #
-    ${r}=    Delete Resource    ${iserver}    ${ae}
-    ${status_code}=    Status Code    ${r}
-    ${text}=    Text    ${r}
-    ${json}=    Json    ${r}
-    ${elapsed}=    Elapsed    ${r}
diff --git a/test/csit/suites/iotdm/basic/030_LayerTest.robot b/test/csit/suites/iotdm/basic/030_LayerTest.robot
new file mode 100644 (file)
index 0000000..1dbe6a5
--- /dev/null
@@ -0,0 +1,285 @@
+*** Settings ***
+Documentation     Test for layers AE/CONTAINER/CONTENTINSTANCE
+Suite Teardown    Kill The Tree    ${CONTROLLER}    InCSE1    admin    admin
+Library           ../../../libraries/criotdm.py
+Library           Collections
+
+*** Variables ***
+${httphost}       ${CONTROLLER}
+${httpuser}       admin
+${httppass}       admin
+${rt_ae}          2
+${rt_container}    3
+${rt_contentInstance}    4
+
+*** Test Cases ***
+Set Suite Variable
+    [Documentation]    set a suite variable ${iserver}
+    #==================================================
+    #    AE Test
+    #==================================================
+    ${iserver} =    Connect To Iotdm    ${httphost}    ${httpuser}    ${httppass}    http
+    Set Suite Variable    ${iserver}
+
+1.11 Valid Input for AE without name
+    [Documentation]    Valid Input for AE without name
+    ${attr} =    Set Variable    "aei":"ODL","api":"jb","apn":"jb2","or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    InCSE1    ${rt_ae}    ${attr}
+    Response Is Correct    ${r}
+
+1.12 Valid Input for AE with name
+    ${attr} =    Set Variable    "aei":"ODL","api":"jb","apn":"jb2","or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    InCSE1    ${rt_ae}    ${attr}    ODL3
+    Response Is Correct    ${r}
+
+1.13 Invalid Input for AE with name Already Exist, should return error
+    [Documentation]    Invalid Input for AE with name Already Exist, should return error
+    ${attr} =    Set Variable    "aei":"ODL","api":"jb","apn":"jb2","or":"http://hey/you"
+    ${error} =    Run Keyword And Expect Error    *    Create Resource    ${iserver}    InCSE1    ${rt_ae}
+    ...    ${attr}    ODL3
+    Should Start with    ${error}    Cannot create this resource [409]
+
+1.14 Invalid Input for AE (AE cannot be created under AE)
+    [Documentation]    Invalid Input for AE (AE cannot be created under AE), expect error
+    ${attr} =    Set Variable    "aei":"ODL","api":"jb","apn":"jb2","or":"http://hey/you"
+    ${error} =    Run Keyword And Expect Error    *    Create Resource    ${iserver}    InCSE1/ODL3    ${rt_ae}
+    ...    ${attr}    ODL4
+    Should Start with    ${error}    Cannot create this resource [405]
+    # -----------------    Update and Retrieve -------------
+
+1.15 Valid Update AE's label
+    [Documentation]    Valid Update AE's label
+    ${attr} =    Set Variable    "lbl":["aaa","bbb","ccc"]
+    ${r} =    Update Resource    ${iserver}    InCSE1/ODL3    2    ${attr}
+    ${ae} =    Name    ${r}
+    Response Is Correct    ${r}
+    # Retrieve and test the lbl
+    ${r} =    Retrieve Resource    ${iserver}    ${ae}
+    ${Json} =    Text    ${r}
+    Should Contain    ${Json}    "aaa"    "bbb"    "ccc"
+    Should Contain    ${r.json()['lbl']}    aaa    bbb    ccc
+    #==================================================
+    #    Container Test
+    #==================================================
+
+2.11 Create Container under AE without name
+    [Documentation]    Create Container under AE without name
+    ${attr} =    Set Variable    "cr":null,"mni":1,"mbs":15,"or":"http://hey/you"
+    Connect And Create Resource    InCSE1/ODL3    ${rt_container}    ${attr}
+
+2.12 Create Container under AE with name
+    [Documentation]    Invalid Input for Container Under AE with name (Already exist)
+    ${attr} =    Set Variable    "cr":null,"mni":1,"mbs":15,"or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    InCSE1/ODL3    ${rt_container}    ${attr}    containerUnderAE
+    ${container} =    Name    ${r}
+    Response Is Correct    ${r}
+    # retrieve it
+    ${result} =    Retrieve Resource    ${iserver}    ${container}
+    ${text} =    Text    ${result}
+    Should Contain    ${text}    "containerUnderAE"
+
+2.13 Invalid Input for Container Under AE with name (Already exist)
+    [Documentation]    Invalid Input for Container Under AE with name (Already exist)
+    ${attr} =    Set Variable    "cr":null,"mni":1,"mbs":15,"or":"http://hey/you"
+    ${error} =    Run Keyword And Expect Error    *    Connect And Create Resource    InCSE1/ODL3    ${rt_container}    ${attr}
+    ...    containerUnderAE
+    Should Start with    ${error}    Cannot create this resource [409]
+
+2.14 Update Container Label
+    [Documentation]    Update Label to ["aaa","bbb","ccc"]
+    ${attr} =    Set Variable    "lbl":["aaa","bbb","ccc"]
+    ${r} =    Update Resource    ${iserver}    InCSE1/ODL3/containerUnderAE    ${rt_container}    ${attr}
+    ${container} =    Name    ${r}
+    Response Is Correct    ${r}
+    # Retrieve and test the lbl
+    ${r} =    Retrieve Resource    ${iserver}    ${container}
+    ${Json} =    Text    ${r}
+    Should Contain    ${Json}    "aaa"    "bbb"    "ccc"
+    Should Contain    ${r.json()['lbl']}    aaa    bbb    ccc
+    #----------------------------------------------------------------------
+
+2.21 Create Container under InCSE1 without name
+    [Documentation]    Create Container under InCSE1 without name
+    ${attr} =    Set Variable    "cr":null,"mni":1,"mbs":15,"or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    InCSE1    ${rt_container}    ${attr}
+    Response Is Correct    ${r}
+
+2.22 Create Container under CSE with name
+    [Documentation]    Create Container under CSE with name
+    ${attr} =    Set Variable    "cr":null,"mni":1,"mbs":15,"or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    InCSE1    ${rt_container}    ${attr}    containerUnderCSE
+    Response Is Correct    ${r}
+    # retrieve it
+    ${result} =    Retrieve Resource    ${iserver}    InCSE1/containerUnderCSE
+    ${text} =    Text    ${result}
+    Should Contain    ${text}    "contaienrUnderCSE"
+
+2.23 Invalid Input for Container Under CSE with name (Already exist)
+    [Documentation]    Invalid Input for Container Under CSE with name (Already exist)
+    ${attr} =    Set Variable    "cr":null,"mni":1,"mbs":15,"or":"http://hey/you"
+    ${error} =    Run Keyword And Expect Error    *    Create Resource    ${iserver}    InCSE1    ${rt_container}
+    ...    ${attr}    containerUnderCSE
+    Should Start with    ${error}    Cannot create this resource [409]
+
+2.24 Update Container Label
+    [Documentation]    Update Container Label
+    ${attr} =    Set Variable    "lbl":["aaa","bbb","ccc"]
+    ${r} =    Update Resource    ${iserver}    InCSE1/containerUnderCSE    ${rt_container}    ${attr}
+    ${container} =    Name    ${r}
+    Response Is Correct    ${r}
+    # Retrieve and test the lbl
+    ${r} =    Retrieve Resource    ${iserver}    ${container}
+    ${Json} =    Text    ${r}
+    Should Contain    ${Json}    "aaa"    "bbb"    "ccc"
+    Should Contain    ${r.json()['lbl']}    aaa    bbb    ccc
+    #----------------------------------------------------------------------
+
+2.31 Create Container under Container without name
+    [Documentation]    Create Container under Container without name
+    ${attr} =    Set Variable    "cr":null,"mni":1,"mbs":15,"or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    InCSE1/containerUnderCSE    ${rt_container}    ${attr}
+    Response Is Correct    ${r}
+
+2.32 Create Container under Container with name
+    [Documentation]    Create Container under Container with name
+    ${attr} =    Set Variable    "cr":null,"mni":1,"mbs":15,"or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    InCSE1/containerUnderCSE    ${rt_container}    ${attr}    containerUnderContainer
+    ${container} =    Name    ${r}
+    Response Is Correct    ${r}
+    # retrieve it
+    ${result} =    Retrieve Resource    ${iserver}    ${container}
+    ${text} =    Text    ${result}
+    Should Contain    ${text}    "containerUnderContainer"
+
+2.33 Invalid Input for Container Under Container with name (Already exist)
+    [Documentation]    Invalid Input for Container Under Container with name (Already exist)
+    ${attr} =    Set Variable    "cr":null,"mni":1,"mbs":15,"or":"http://hey/you"
+    ${error} =    Run Keyword And Expect Error    *    Create Resource    ${iserver}    InCSE1/containerUnderCSE    ${rt_container}
+    ...    ${attr}    containerUnderContainer
+    Should Start with    ${error}    Cannot create this resource [409]
+
+2.34 Update Container Label
+    [Documentation]    Update Container Label to ["aaa","bbb","ccc"]
+    ${attr} =    Set Variable    "lbl":["aaa","bbb","ccc"]
+    ${r} =    Update Resource    ${iserver}    InCSE1/containerUnderCSE/containerUnderContainer    ${rt_container}    ${attr}
+    Response Is Correct    ${r}
+    # Retrieve and test the lbl
+    ${r} =    Retrieve Resource    ${iserver}    InCSE1/containerUnderCSE/containerUnderContainer
+    ${Json} =    Text    ${r}
+    Should Contain    ${Json}    "aaa"    "bbb"    "ccc"
+    Should Contain    ${r.json()['lbl']}    aaa    bbb    ccc
+
+2.41 Invalid Input for AE under container withoutname(mess up layer)
+    [Documentation]    Invalid Input for AE under container withoutname(mess up layer)
+    ${attr} =    Set Variable    "aei":"ODL","api":"jb","apn":"jb2","or":"http://hey/you"
+    ${error} =    Run Keyword And Expect Error    *    Create Resource    ${iserver}    InCSE1/containerUnderCSE    ${rt_ae}
+    ...    ${attr}    ODL4
+    Should Start with    ${error}    Cannot create this resource [405]
+    Should Contain    ${error}    Cannot create AE under this resource type: 3
+    #==================================================
+    #    ContentInstance Test
+    #==================================================
+
+3.11 Valid contentInstance under CSEBase/container without name
+    [Documentation]    Valid contentInstance under CSEBase/container without name
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"101"
+    ${r} =    Create Resource    ${iserver}    InCSE1/containerUnderCSE    ${rt_contentInstance}    ${attr}
+    Response Is Correct    ${r}
+
+3.12 Valid contentInstance under CSEBase/container with name
+    [Documentation]    Valid contentInstance under CSEBase/container with name
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"102"
+    ${r} =    Create Resource    ${iserver}    InCSE1/containerUnderCSE    ${rt_contentInstance}    ${attr}    conIn1
+    Response Is Correct    ${r}
+
+3.13 Invalid contentInstance under CSEBase
+    [Documentation]    Invalid contentInstance under CSEBase
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"101"
+    ${error} =    Run Keyword And Expect Error    *    Create Resource    ${iserver}    InCSE1    ${rt_contentInstance}
+    ...    ${attr}
+    Should Start with    ${error}    Cannot create this resource [405]
+    Should Contain    ${error}    Cannot create ContentInstance under this resource type: 5
+
+3.14 Invalid contentInstance under AE
+    [Documentation]    Invalid contentInstance under AE
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"101"
+    ${error} =    Run Keyword And Expect Error    *    Create Resource    ${iserver}    InCSE1/ODL3    ${rt_contentInstance}
+    ...    ${attr}
+    Should Start with    ${error}    Cannot create this resource [405]
+    Should Contain    ${error}    Cannot create ContentInstance under this resource type: 2
+
+3.15 Invalid contentInstance under contentInstance
+    [Documentation]    Invalid contentInstance under contentInstance
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"101"
+    ${error} =    Run Keyword And Expect Error    *    Create Resource    ${iserver}    InCSE1/containerUnderCSE/conIn1    ${rt_contentInstance}
+    ...    ${attr}
+    Should Start with    ${error}    Cannot create this resource [405]
+    Should Contain    ${error}    Cannot create ContentInstance under this resource type: 4
+
+3.16 Invalid AE under contentInstance
+    [Documentation]    Invalid AE under contentInstance
+    ${attr} =    Set Variable    "aei":"ODL","api":"jb","apn":"jb2","or":"http://hey/you"
+    ${error} =    Run Keyword And Expect Error    *    Create Resource    ${iserver}    InCSE1/containerUnderCSE/conIn1    ${rt_ae}
+    ...    ${attr}
+    Should Start with    ${error}    Cannot create this resource [405]
+    Should Contain    ${error}    Cannot create AE under this resource type: 4
+
+3.17 Invalid container under contentInstance
+    [Documentation]    Invalid container under contentInstance
+    ${attr} =    Set Variable    "cr":null,"lbl":["aaa","bbb","ccc"]
+    ${error} =    Run Keyword And Expect Error    *    Create Resource    ${iserver}    InCSE1/containerUnderCSE/conIn1    ${rt_container}
+    ...    ${attr}
+    Should Start with    ${error}    Cannot create this resource [405]
+    Should Contain    ${error}    Cannot create Container under this resource type: 4
+    #==================================================
+    #    Delete Test
+    #==================================================
+
+4.11 Delete AE without child resource
+    [Documentation]    Delete AE without child resource
+    ${attr} =    Set Variable    "aei":"ODL","api":"jb","apn":"jb2","or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    InCSE1    ${rt_ae}    ${attr}
+    ${ae} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${deleteRes} =    Delete Resource    ${iserver}    ${ae}
+    ${status_code} =    Status Code    ${deleteRes}
+    Should Be Equal As Integers    ${status_code}    200
+    # Delete AE that does not exist/has been deleted should return error
+    ${error} =    Run Keyword And Expect Error    *    Delete Resource    ${iserver}    ${ae}
+    Should Start with    ${error}    Cannot delete this resource [404]
+
+4.12 Delete Container without child resource
+    [Documentation]    Delete Container without child resource
+    ${attr} =    Set Variable    "cr":null,"mni":1,"mbs":15,"or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    InCSE1/ODL3    ${rt_container}    ${attr}
+    ${container} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${deleteRes} =    Delete Resource    ${iserver}    ${container}
+    ${status_code} =    Status Code    ${deleteRes}
+    Should Be Equal As Integers    ${status_code}    200
+    # Delete container that does not exist/has been deleted should return error
+    ${error} =    Run Keyword And Expect Error    *    Delete Resource    ${iserver}    ${container}
+    Should Start with    ${error}    Cannot delete this resource [404]
+
+Delete the Container Under CSEBase
+    [Documentation]    Delete the Container and AE Under CSEBase
+    ${deleteRes} =    Delete Resource    ${iserver}    InCSE1/containerUnderCSE
+    ${deleteRes} =    Delete Resource    ${iserver}    InCSE1/ODL3
+
+*** Keywords ***
+Connect And Create Resource
+    [Arguments]    ${targetURI}    ${resoutceType}    ${attr}    ${resourceName}=${EMPTY}
+    ${iserver} =    Connect To Iotdm    ${httphost}    ${httpuser}    ${httppass}    http
+    ${r} =    Create Resource    ${iserver}    ${targetURI}    ${resoutceType}    ${attr}    ${resourceName}
+    ${container} =    Name    ${r}
+    ${status_code} =    Status Code    ${r}
+    Should Be Equal As Integers    ${status_code}    201
+
+Response Is Correct
+    [Arguments]    ${r}
+    ${status_code} =    Status Code    ${r}
+    Should Be True    199 < ${status_code} < 299
+    ${text} =    Text    ${r}
+    LOG    ${text}
+    ${json} =    Json    ${r}
+    LOG    ${json}
diff --git a/test/csit/suites/iotdm/basic/040_AEAttributeTest.robot b/test/csit/suites/iotdm/basic/040_AEAttributeTest.robot
new file mode 100644 (file)
index 0000000..0260055
--- /dev/null
@@ -0,0 +1,293 @@
+*** Settings ***
+Suite Teardown    Kill The Tree    ${CONTROLLER}    InCSE1    admin    admin
+Library           ../../../libraries/criotdm.py
+Library           Collections
+
+*** Variables ***
+${httphost}       ${CONTROLLER}
+${httpuser}       admin
+${httppass}       admin
+${rt_ae}          2
+${rt_container}    3
+${rt_contentInstance}    4
+
+*** Test Cases ***
+Set Suite Variable
+    [Documentation]    set a suite variable ${iserver}
+    ${iserver} =    Connect To Iotdm    ${httphost}    ${httpuser}    ${httppass}    http
+    Set Suite Variable    ${iserver}
+    #==================================================
+    #    AE Mandatory Attribute Test
+    #==================================================
+    # For Creation, there are only 2 mandatory attribute: App-ID(api), AE-ID(aei)
+
+1.11 Missing App-ID should return error
+    [Documentation]    when create AE, Missing App-ID should return error
+    ${attr} =    Set Variable    "aei":"ODL"
+    ${error} =    Run Keyword And Expect Error    *    Create Resource    ${iserver}    InCSE1    ${rt_ae}
+    ...    ${attr}
+    Should Start with    ${error}    Cannot create this resource [400]
+    Should Contain    ${error}    APP_ID missing parameter
+
+1.21 Missing AE-ID should return error
+    [Documentation]    when creete AE, Missing AE-ID should return error
+    ${attr} =    Set Variable    "api":"ODL"
+    ${error} =    Run Keyword And Expect Error    *    Create Resource    ${iserver}    InCSE1    ${rt_ae}
+    ...    ${attr}
+    Should Start with    ${error}    Cannot create this resource [400]
+    Should Contain    ${error}    AE_ID missing parameter
+
+1.3 After Created, test whether all the mandatory attribtues are exist.
+    [Documentation]    mandatory attributes should be there after created
+    ${attr} =    Set Variable    "api":"ODL","aei":"ODL"
+    ${r}=    Create Resource    ${iserver}    InCSE1    ${rt_ae}    ${attr}    AE1
+    ${status_code} =    Status Code    ${r}
+    Should Be Equal As Integers    ${status_code}    201
+    ${text} =    Text    ${r}
+    Should Contain    ${text}    "ri":    "rn":    "api":"ODL"
+    Should Contain    ${text}    "aei":"ODL"    "lt":    "pi":
+    Should Contain    ${text}    "ct":    "rty":2
+    Should Not Contain    S{text}    "lbl"    "apn"    "or"
+    # 1.13    if Child Container updated, parent Last Modified time will be updated?
+    # 1.14    if Child Container's child updated, parent Last Modified time will not be updated?
+    # support rcn(support change URI in python library)
+    #==================================================
+    #    AE Optional Attribute Test (Allowed)
+    #==================================================
+    #    update(create)--> update(modified)-->update (delete)
+
+2.11 appName can be created through update (0-1)
+    [Documentation]    appName can be created through update (0-1)
+    ${attr} =    Set Variable    "apn":"abcd"
+    ${text} =    Update And Retrieve AE    ${attr}
+    Should Contain    ${text}    apn    abcd
+
+2.12 appName can be modified (1-1)
+    [Documentation]    appName can be modified (1-1)
+    ${attr} =    Set Variable    "apn":"dbac"
+    ${text} =    Update And Retrieve AE    ${attr}
+    Should Not Contain    ${text}    abcd
+    Should Contain    ${text}    apn    dbac
+
+2.13 if set to null, appName should be deleted
+    [Documentation]    if set to null, appName should be deleted
+    ${attr} =    Set Variable    "apn":null
+    ${text} =    Update And Retrieve AE    ${attr}
+    Should Not Contain    ${text}    apn    abcd    dbac
+
+2.21 ontologyRef can be created through update (0-1)
+    [Documentation]    ontologyRef can be created through update (0-1)
+    ${attr} =    Set Variable    "or":"abcd"
+    ${text} =    Update And Retrieve AE    ${attr}
+    Should Contain    ${text}    or    abcd
+
+2.22 ontologyRef can be modified (1-1)
+    [Documentation]    ontologyRef can be modified (1-1)
+    ${attr} =    Set Variable    "or":"dbac"
+    ${text} =    Update And Retrieve AE    ${attr}
+    Should Not Contain    ${text}    abcd
+    Should Contain    ${text}    or    dbac
+
+2.23 if set to null, ontologyRef should be deleted
+    [Documentation]    if set to null, ontologyRef should be deleted
+    ${attr} =    Set Variable    "or":null
+    ${text} =    Update And Retrieve AE    ${attr}
+    Should Not Contain    ${text}    or    abcd    dbac
+
+2.31 labels can be created through update (0-1)
+    [Documentation]    labels can be created through update (0-1)
+    ${attr} =    Set Variable    "lbl":["label1"]
+    ${text} =    Update And Retrieve AE    ${attr}
+    Should Contain    ${text}    lbl    label1
+
+2.32 labels can be modified (1-1)
+    [Documentation]    labels can be modified (1-1)
+    ${attr} =    Set Variable    "lbl":["label2"]
+    ${text} =    Update And Retrieve AE    ${attr}
+    Should Not Contain    ${text}    label1
+    Should Contain    ${text}    lbl    label2
+
+2.33 if set to null, labels should be deleted(1-0)
+    [Documentation]    if set to null, labels should be deleted(1-0)
+    ${attr} =    Set Variable    "lbl":null
+    ${text} =    Update And Retrieve AE    ${attr}
+    Should Not Contain    ${text}    lbl    label1    label2
+
+2.34 labels can be created through update (0-n)
+    [Documentation]    labels can be created through update (0-n)
+    ${attr} =    Set Variable    "lbl":["label3","label4","label5"]
+    ${text} =    Update And Retrieve AE    ${attr}
+    Should Contain    ${text}    lbl    label3    label4
+    Should Contain    ${text}    label5
+
+2.35 labels can be modified (n-n)(across)
+    [Documentation]    labels can be modified (n-n)(across)
+    ${attr} =    Set Variable    "lbl":["label4","label5","label6"]
+    ${text} =    Update And Retrieve AE    ${attr}
+    Should Not Contain    ${text}    label1    label2    label3
+    Should Contain    ${text}    lbl    label4    label5
+    Should Contain    ${text}    label6
+
+2.36 labels can be modified (n-n)(not across)
+    [Documentation]    labels can be modified (n-n)(not across)
+    ${attr} =    Set Variable    "lbl":["label7","label8","label9"]
+    ${text} =    Update And Retrieve AE    ${attr}
+    Should Not Contain    ${text}    label1    label2    label3
+    Should Not Contain    ${text}    label6    label4    label5
+    Should Contain    ${text}    lbl    label7    label8
+    Should Contain    ${text}    label9
+
+2.37 if set to null, labels should be deleted(n-0)
+    [Documentation]    if set to null, labels should be deleted(n-0)
+    ${attr} =    Set Variable    "lbl":null
+    ${text} =    Update And Retrieve AE    ${attr}
+    Should Not Contain    ${text}    label1    label2    label3
+    Should Not Contain    ${text}    label6    label4    label5
+    Should Not Contain    ${text}    label7    label8    label9
+    Should Not Contain    ${text}    lbl
+    #======================================================
+    #    AE Disturbing Attribute Test, Not Allowed Update
+    #======================================================
+    # using non-valid attribtue to create then expext error
+
+3.11 Mulitiple App-ID should return error
+    [Documentation]    Mulitiple App-ID should return error
+    ${attr} =    Set Variable    "aei":"ODL","api":"ODL","api":"ODL2"
+    ${error} =    Cannot Update AE Error    ${attr}
+    Should Contain    ${error}    Duplicate key    api
+
+3.12 Mulitiple AE-ID should return error
+    [Documentation]    Mulitiple AE-ID should return error
+    ${attr} =    Set Variable    "aei":"ODL","api":"ODL","aei":"ODL1"
+    ${error} =    Cannot Update AE Error    ${attr}
+    Should Contain    ${error}    Duplicate key    aei
+
+3.13 Multiple app-name should return error
+    [Documentation]    Multiple app-name should return error
+    ${attr} =    Set Variable    "aei":"ODL","api":"ODL","apn":"ODL1","apn":"ODL1"
+    ${error} =    Cannot Update AE Error    ${attr}
+    Should Contain    ${error}    Duplicate key    apn
+
+3.14 Multiple label attribute should return error(multiple array)
+    [Documentation]    Multiple label attribute should return error(multiple array)
+    ${attr} =    Set Variable    "aei":"ODL","api":"ODL","lbl":["ODL1"], "lbl":["dsdsd"]
+    ${error} =    Cannot Update AE Error    ${attr}
+    Should Contain    ${error}    Duplicate key    lbl
+
+3.15 Multiple ontologyRef attribute should return error
+    [Documentation]    Multiple ontologyRef attribute should return error
+    ${attr} =    Set Variable    "aei":"ODL","api":"ODL","or":"http://hey/you", "or":"http://hey/you"
+    ${error} =    Cannot Update AE Error    ${attr}
+    Should Contain    ${error}    Duplicate key    or
+
+3.21 Using Container's M attribute to create
+    [Documentation]    Using Container's M attribute to create
+    ${attr} =    Set Variable    "cr":null,"mni":1,"mbs":15,"or":"http://hey/you"
+    ${error} =    Cannot Update AE Error    ${attr}
+    Should Contain    ${error}    CONTENT(pc)
+
+3.22 Using ContentInstance's M attribute to create
+    [Documentation]    Using ContentInstance's M attribute to create
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"101"
+    ${error} =    Cannot Update AE Error    ${attr}
+    Should Contain    ${error}    CONTENT(pc)
+    #------------------------------------------------------
+    # using non-valid attribute to update then expect error
+
+3.31 resourceType cannot be update.
+    [Documentation]    when update resourceType expext error
+    ${attr} =    Set Variable    "ty":3
+    ${error} =    Cannot Update AE Error    ${attr}
+    Should Contain    ${error}    error
+
+3.32 resoureceID cannot be update.
+    [Documentation]    when update resourceId expect error
+    ${attr} =    Set Variable    "ri":"aaa"
+    ${error} =    Cannot Update AE Error    ${attr}
+    Should Contain    ${error}    error    ri
+
+3.33 resouceNme cannot be update.(write once)
+    [Documentation]    when update resourceName expect error
+    ${attr} =    Set Variable    "rn":"aaa"
+    ${error} =    Cannot Update AE Error    ${attr}
+    Should Contain    ${error}    error    rn
+
+3.34 parentID cannot be update.
+    [Documentation]    when update parentID expect error
+    ${attr} =    Set Variable    "pi":"aaa"
+    ${error} =    Cannot Update AE Error    ${attr}
+    Should Contain    ${error}    error    pi
+
+3.35 createTime cannot be update.
+    [Documentation]    when update createTime expect error
+    ${attr} =    Set Variable    "ct":"aaa"
+    ${error} =    Cannot Update AE Error    ${attr}
+    Should Contain    ${error}    error    ct
+
+3.36 app-id cannot be update
+    [Documentation]    when update app-id expect error
+    ${attr} =    Set Variable    "api":"aaa"
+    ${error} =    Cannot Update AE Error    ${attr}
+    Should Contain    ${error}    error    api
+
+3.37 ae-id cannot be updated
+    [Documentation]    when update ae-id epxect error
+    ${attr} =    Set Variable    "aei":"aaa"
+    ${error} =    Cannot Update AE Error    ${attr}
+    Should Contain    ${error}    error    aei
+
+3.38 LastMoifiedTime --- Special, cannot be modified by the user
+    [Documentation]    LastMoifiedTime --- Special, cannot be modified by the user
+    ${attr} =    Set Variable    "lt":"aaa"
+    ${error} =    Cannot Update AE Error    ${attr}
+    Should Contain    ${error}    error    lt
+    #==================================================
+    #    Functional Attribute Test
+    #==================================================
+    # 1. lastModifiedTime
+    # 2. parentID
+
+4.1 if updated seccessfully, lastModifiedTime must be modified.
+    [Documentation]    if updated seccessfully, lastModifiedTime must be modified.
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1/AE1
+    ${text} =    Text    ${oldr}
+    LOG    ${text}
+    ${lt1} =    LastModifiedTime    ${oldr}
+    ${attr} =    Set Variable    "lbl":["aaa"]
+    Sleep    1s
+    # We know Beryllium is going to be get rid of all sleep.
+    # But as lastModifiedTime has precision in seconds,
+    # we need to wait 1 second to see different value on update.
+    ${r} =    update Resource    ${iserver}    InCSE1/AE1    ${rt_ae}    ${attr}
+    ${text} =    Text    ${r}
+    LOG    ${text}
+    ${lt2} =    LastModifiedTime    ${r}
+    Should Not Be Equal    ${oldr.json()['lt']}    ${lt2}
+
+4.2 Check parentID
+    [Documentation]    check parentID whether it is correct
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1
+    ${CSEID} =    Set Variable    ${oldr.json()['ri']}
+    ${r} =    Retrieve Resource    ${iserver}    InCSE1/AE1
+    Should Be Equal    ${oldr.json()['ri']}    ${r.json()['pi']}
+    #==================================================
+    #    Finish
+    #==================================================
+
+*** Keywords ***
+Update And Retrieve AE
+    [Arguments]    ${attr}
+    ${r} =    update Resource    ${iserver}    InCSE1/AE1    ${rt_ae}    ${attr}
+    ${text} =    Text    ${r}
+    LOG    ${text}
+    ${rr} =    Retrieve Resource    ${iserver}    InCSE1/AE1
+    ${text} =    Text    ${rr}
+    LOG    ${text}
+    [Return]    ${text}
+
+Cannot Update AE Error
+    [Arguments]    ${attr}
+    ${error} =    Run Keyword And Expect Error    *    Update Resource    ${iserver}    InCSE1/AE1    ${rt_ae}
+    ...    ${attr}
+    Should Start with    ${error}    Cannot update this resource [400]
+    [Return]    ${error}
diff --git a/test/csit/suites/iotdm/basic/050_ContainerAttributeTest.robot b/test/csit/suites/iotdm/basic/050_ContainerAttributeTest.robot
new file mode 100644 (file)
index 0000000..d8ade1d
--- /dev/null
@@ -0,0 +1,776 @@
+*** Settings ***
+Suite Teardown    Kill The Tree    ${CONTROLLER}    InCSE1    admin    admin
+Library           ../../../libraries/criotdm.py
+Library           Collections
+
+*** Variables ***
+${httphost}       ${CONTROLLER}
+${httpuser}       admin
+${httppass}       admin
+${rt_ae}          2
+${rt_container}    3
+${rt_contentInstance}    4
+
+*** Test Cases ***
+Set Suite Variable
+    [Documentation]    set a suite variable ${iserver}
+    ${iserver} =    Connect To Iotdm    ${httphost}    ${httpuser}    ${httppass}    http
+    Set Suite Variable    ${iserver}
+    #==================================================
+    #    Container Mandatory Attribute Test
+    #==================================================
+    # For Creation, there are no mandatory input attribute
+
+1.1 After Created, test whether all the mandatory attribtues are exist.
+    [Documentation]    After Created, test whether all the mandatory attribtues are exist.
+    ${attr} =    Set Variable
+    ${r}=    Create Resource    ${iserver}    InCSE1    ${rt_container}    ${attr}    Container1
+    ${container} =    Name    ${r}
+    ${status_code} =    Status Code    ${r}
+    Should Be Equal As Integers    ${status_code}    201
+    ${text} =    Text    ${r}
+    Should Contain    ${text}    "ri":    "rn":    "cni"
+    Should Contain    ${text}    "lt":    "pi":    "st":
+    Should Contain    ${text}    "ct":    "rty":3    "cbs"
+    Should Not Contain    S{text}    "lbl"    "creator"    "or"
+    #==================================================
+    #    Container Optional Attribute Test (Allowed)
+    #==================================================
+    #    create--> delete
+    #    update(create)--> update(modified)-->update (delete)
+
+2.11 maxNumberofInstance (mni) can be added when create
+    [Documentation]    maxNumberofInstance (mni) can be added when create
+    ${attr} =    Set Variable    "mni":3
+    ${r}=    Create Resource    ${iserver}    InCSE1    ${rt_container}    ${attr}    Container2
+    ${text} =    Check Response and Retrieve Resource    ${r}
+    Should Contain    ${text}    "mni"
+
+Delete the Container2-2.1
+    ${deleteRes} =    Delete Resource    ${iserver}    InCSE1/Container2
+
+2.12 maxNumberofInstance (mni) can be added through update (0-1)
+    [Documentation]    maxNumberofInstance (mni) can be added through update (0-1)
+    ${attr} =    Set Variable    "mni":3
+    ${r} =    update Resource    ${iserver}    InCSE1/Container1    ${rt_container}    ${attr}
+    ${text} =    Check Response and Retrieve Resource    ${r}
+    Should Contain    ${text}    "mni"
+
+2.13 maxNumberofInstance (mni) can be modified through update (1-1)
+    [Documentation]    maxNumberofInstance (mni) can be modified through update (1-1)
+    ${attr} =    Set Variable    "mni":5
+    ${r} =    update Resource    ${iserver}    InCSE1/Container1    ${rt_container}    ${attr}
+    ${text} =    Check Response and Retrieve Resource    ${r}
+    Should Contain    ${text}    "mni":5
+    Should Not Contain    ${text}    "mni":3
+
+2.14 if set to null, maxnumberofInstance (mni) can be deleted through delete(1-0)
+    [Documentation]    if set to null, maxnumberofInstance (mni) can be deleted through delete(1-0)
+    ${attr} =    Set Variable    "mni":null
+    ${r} =    update Resource    ${iserver}    InCSE1/Container1    ${rt_container}    ${attr}
+    ${text} =    Check Response and Retrieve Resource    ${r}
+    Should Not Contain    ${text}    "mni"
+
+2.21 maxByteSize (mbs) can be added when create
+    [Documentation]    maxByteSize (mbs) can be added when create
+    ${attr} =    Set Variable    "mbs":20
+    ${r}=    Create Resource    ${iserver}    InCSE1    ${rt_container}    ${attr}    Container2
+    ${text} =    Check Response and Retrieve Resource    ${r}
+    Should Contain    ${text}    "mbs"
+
+Delete the Container2-2.2
+    ${deleteRes} =    Delete Resource    ${iserver}    InCSE1/Container2
+
+2.22 maxByteSize (mbs) can be added through update (0-1)
+    [Documentation]    maxByteSize (mbs) can be added through update (0-1)
+    ${attr} =    Set Variable    "mbs":20
+    ${r} =    update Resource    ${iserver}    InCSE1/Container1    ${rt_container}    ${attr}
+    ${text} =    Check Response and Retrieve Resource    ${r}
+    Should Contain    ${text}    "mbs"
+
+2.23 maxByteSize (mbs) can be modified through update (1-1)
+    [Documentation]    maxByteSize (mbs) can be modified through update (1-1)
+    ${attr} =    Set Variable    "mbs":25
+    ${r} =    update Resource    ${iserver}    InCSE1/Container1    ${rt_container}    ${attr}
+    ${text} =    Check Response and Retrieve Resource    ${r}
+    Should Contain    ${text}    "mbs":25
+    Should Not Contain    ${text}    "mbs":20
+
+2.24 if set to null, maxByteSize (mbs) can be deleted through delete(1-0)
+    [Documentation]    if set to null, maxByteSize (mbs) can be deleted through delete(1-0)
+    ${attr} =    Set Variable    "mbs":null
+    ${r} =    update Resource    ${iserver}    InCSE1/Container1    ${rt_container}    ${attr}
+    ${text} =    Check Response and Retrieve Resource    ${r}
+    Should Not Contain    ${text}    "mbs"
+
+2.31 ontologyRef(or) can be added when create
+    [Documentation]    ontologyRef(or) can be added when create
+    ${attr} =    Set Variable    "or":"http://cisco.com"
+    ${r}=    Create Resource    ${iserver}    InCSE1    ${rt_container}    ${attr}    Container2
+    ${text} =    Check Response and Retrieve Resource    ${r}
+    Should Contain    ${text}    "or"
+
+Delete the Container2-2.3
+    ${deleteRes} =    Delete Resource    ${iserver}    InCSE1/Container2
+
+2.32 ontologyRef(or) can be added through update (0-1)
+    [Documentation]    ontologyRef(or) can be added through update (0-1)
+    ${attr} =    Set Variable    "or":"http://cisco.com"
+    ${r} =    update Resource    ${iserver}    InCSE1/Container1    ${rt_container}    ${attr}
+    ${text} =    Check Response and Retrieve Resource    ${r}
+    Should Contain    ${text}    "or"
+
+2.33 ontologyRef(or) can be modified through update (1-1)
+    [Documentation]    ontologyRef(or) can be modified through update (1-1)
+    ${attr} =    Set Variable    "or":"http://iotdm.com"
+    ${r} =    update Resource    ${iserver}    InCSE1/Container1    ${rt_container}    ${attr}
+    ${text} =    Check Response and Retrieve Resource    ${r}
+    Should Contain    ${text}    "or":"http://iotdm.com"
+    Should Not Contain    ${text}    "or":"http://cisco.com"
+
+2.34 if set to null, ontologyRef(or) can be deleted through delete(1-0)
+    [Documentation]    if set to null, ontologyRef(or) can be deleted through delete(1-0)
+    ${attr} =    Set Variable    "or":null
+    ${r} =    update Resource    ${iserver}    InCSE1/Container1    ${rt_container}    ${attr}
+    ${text} =    Check Response and Retrieve Resource    ${r}
+    Should Not Contain    ${text}    "or"
+
+2.41 labels can be created through update (0-1)
+    [Documentation]    labels can be created through update (0-1)
+    ${attr} =    Set Variable    "lbl":["label1"]
+    ${r} =    update Resource    ${iserver}    InCSE1/Container1    ${rt_container}    ${attr}
+    ${text} =    Check Response and Retrieve Resource    ${r}
+    Should Contain    ${text}    lbl    label1
+
+2.42 labels can be modified (1-1)
+    [Documentation]    labels can be modified (1-1)
+    ${attr} =    Set Variable    "lbl":["label2"]
+    ${r} =    update Resource    ${iserver}    InCSE1/Container1    ${rt_container}    ${attr}
+    ${text} =    Check Response and Retrieve Resource    ${r}
+    Should Not Contain    ${text}    label1
+    Should Contain    ${text}    lbl    label2
+
+2.43 if set to null, labels should be deleted(1-0)
+    [Documentation]    if set to null, labels should be deleted(1-0)
+    ${attr} =    Set Variable    "lbl":null
+    ${r} =    update Resource    ${iserver}    InCSE1/Container1    ${rt_container}    ${attr}
+    ${text} =    Check Response and Retrieve Resource    ${r}
+    Should Not Contain    ${text}    lbl    label1    label2
+
+2.44 labels can be created through update (0-n)
+    [Documentation]    labels can be created through update (0-n)
+    ${attr} =    Set Variable    "lbl":["label3","label4","label5"]
+    ${r} =    update Resource    ${iserver}    InCSE1/Container1    ${rt_container}    ${attr}
+    ${text} =    Check Response and Retrieve Resource    ${r}
+    Should Contain    ${text}    lbl    label3    label4
+    Should Contain    ${text}    label5
+
+2.45 labels can be modified (n-n)(across)
+    [Documentation]    labels can be modified (n-n)(across)
+    ${attr} =    Set Variable    "lbl":["label4","label5","label6"]
+    ${r} =    update Resource    ${iserver}    InCSE1/Container1    ${rt_container}    ${attr}
+    ${text} =    Check Response and Retrieve Resource    ${r}
+    Should Not Contain    ${text}    label1    label2    label3
+    Should Contain    ${text}    lbl    label4    label5
+    Should Contain    ${text}    label6
+
+2.46 labels can be modified (n-n)(not across)
+    [Documentation]    labels can be modified (n-n)(not across)
+    ${attr} =    Set Variable    "lbl":["label7","label8","label9"]
+    ${r} =    update Resource    ${iserver}    InCSE1/Container1    ${rt_container}    ${attr}
+    ${text} =    Check Response and Retrieve Resource    ${r}
+    Should Not Contain    ${text}    label1    label2    label3
+    Should Not Contain    ${text}    label6    label4    label5
+    Should Contain    ${text}    lbl    label7    label8
+    Should Contain    ${text}    label9
+
+2.47 if set to null, labels should be deleted(n-0)
+    [Documentation]    if set to null, labels should be deleted(n-0)
+    ${attr} =    Set Variable    "lbl":null
+    ${r} =    update Resource    ${iserver}    InCSE1/Container1    ${rt_container}    ${attr}
+    ${text} =    Check Response and Retrieve Resource    ${r}
+    Should Not Contain    ${text}    label1    label2    label3
+    Should Not Contain    ${text}    label6    label4    label5
+    Should Not Contain    ${text}    label7    label8    label9
+    Should Not Contain    ${text}    lbl
+    #======================================================
+    #    Container Disturbing Attribute Test, Not Allowed Update
+    #======================================================
+    # using non-valid attribtue to create then expext error
+
+3.11 Mulitiple maxNrofInstance should return error
+    [Documentation]    Mulitiple maxNrofInstance should return error
+    ${attr} =    Set Variable    "mni":33,"mni":33
+    ${error} =    Cannot Create Container Error    ${attr}
+    Should Contain    ${error}    Duplicate key    mni
+
+3.12 Mulitiple maxByteSize should return error
+    [Documentation]    Mulitiple maxByteSize should return error
+    ${attr} =    Set Variable    "mbs":44,"mbs":44
+    ${error} =    Cannot Create Container Error    ${attr}
+    Should Contain    ${error}    Duplicate key    mbs
+
+3.13 Multiple creator should return error
+    [Documentation]    Multiple creator should return error
+    ${attr} =    Set Variable    "cr":null,"cr":null
+    ${error} =    Cannot Create Container Error    ${attr}
+    Should Contain    ${error}    Duplicate key    cr
+
+3.14 Multiple ontologyRef should return error
+    [Documentation]    Multiple ontologyRef should return error
+    ${attr} =    Set Variable    "or":"http://cisco.com","or":"http://cisco.com"
+    ${error} =    Cannot Create Container Error    ${attr}
+    Should Contain    ${error}    Duplicate key    or
+
+3.14 Multiple label attribute should return error(multiple array)
+    [Documentation]    Multiple label attribute should return error(multiple array)
+    ${attr} =    Set Variable    "lbl":["ODL1"], "lbl":["dsdsd"]
+    ${error} =    Cannot Create Container Error    ${attr}
+    Should Contain    ${error}    Duplicate key    lbl
+    #    3.2 Input of Integer using String should return error    [Should checked by wenxin]
+    #------------------------------------------------------
+    # using non-valid attribute to update then expect error
+
+3.31 resourceType cannot be update.
+    [Documentation]    when update resourceType, expect error
+    ${attr} =    Set Variable    "ty":2
+    ${error} =    Cannot Update Container Error    ${attr}
+    Should Contain    ${error}    error
+
+3.32 resoureceID cannot be update.
+    [Documentation]    update resoureceID then expect error
+    ${attr} =    Set Variable    "ri":"aaa"
+    ${error} =    Cannot Update Container Error    ${attr}
+    Should Contain    ${error}    error    ri
+
+3.33 resouceNme cannot be update.(write once)
+    [Documentation]    update resourceName and expect error
+    ${attr} =    Set Variable    "rn":"aaa"
+    ${error} =    Cannot Update Container Error    ${attr}
+    Should Contain    ${error}    error    rn
+
+3.34 parentID cannot be update.
+    [Documentation]    update parentID and expect error
+    ${attr} =    Set Variable    "pi":"aaa"
+    ${error} =    Cannot Update Container Error    ${attr}
+    Should Contain    ${error}    error    pi
+
+3.35 createTime cannot be update.
+    [Documentation]    update createTime and expect error
+    ${attr} =    Set Variable    "ct":"aaa"
+    ${error} =    Cannot Update Container Error    ${attr}
+    Should Contain    ${error}    error    ct
+
+3.36 curerntByteSize cannot be update --- Special, cannot be modified by the user
+    [Documentation]    update currentByteSize and expect error
+    ${attr} =    Set Variable    "cbs":123
+    ${error} =    Cannot Update Container Error    ${attr}
+    Should Contain    ${error}    error    api
+
+3.37 currentNrofInstance cannot be updated --- Special, cannot be modified by the user
+    [Documentation]    update cni and expect error
+    ${attr} =    Set Variable    "cni":3
+    ${error} =    Cannot Update Container Error    ${attr}
+    Should Contain    ${error}    error    aei
+
+3.38 LastMoifiedTime --- Special, cannot be modified by the user
+    [Documentation]    update lt and expect error
+    ${attr} =    Set Variable    "lt":"aaa"
+    ${error} =    Cannot Update Container Error    ${attr}
+    Should Contain    ${error}    error    lt
+
+3.39 stateTag --- Special, cannot be modified by the user
+    [Documentation]    update st and expect error
+    ${attr} =    Set Variable    "st":3
+    ${error} =    Cannot Update Container Error    ${attr}
+    Should Contain    ${error}    error    st
+
+3.310 creator -- cannot be modified
+    [Documentation]    update cr and expect error
+    ${attr} =    Set Variable    "cr":null
+    ${error} =    Cannot Update Container Error    ${attr}
+    Should Contain    ${error}    error    cr
+
+3.41 Using AE's M attribute to create
+    [Documentation]    use AE attribtue to create Container then expect error
+    ${attr} =    Set Variable    "api":"ODL","aei":"ODL"
+    ${error} =    Cannot Update Container Error    ${attr}
+    Should Contain    ${error}    CONTENT(pc)
+
+3.42 Using ContentInstance's M attribute to create
+    [Documentation]    use contentInstance attribtue to create Container then expect error
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"101"
+    ${error} =    Cannot Update Container Error    ${attr}
+    Should Contain    ${error}    CONTENT(pc)
+    #==================================================
+    #    Functional Attribute Test
+    #==================================================
+    # 1. lastModifiedTime
+    # 2. parentID
+    # 3. stateTag
+    # 4. currentNrOfInstances
+    # 5. currentByteSize
+    # 6. maxNrOfInstances
+    # 7. maxByteSize
+    # 8. creator
+    # 9. contentSize
+    # 10. childresource
+    #-------------- 1.    lastModifiedTime    -----------
+
+4.11 if updated seccessfully, lastModifiedTime must be modified.
+    [Documentation]    if updated seccessfully, lastModifiedTime must be modified.
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1/Container1
+    ${text} =    Text    ${oldr}
+    LOG    ${text}
+    ${lt1} =    LastModifiedTime    ${oldr}
+    ${attr} =    Set Variable    "lbl":["aaa"]
+    Sleep    1s
+    # We know Beryllium is going to be get rid of all sleep.
+    # But as lastModifiedTime has precision in seconds,
+    # we need to wait 1 second to see different value on update.
+    ${r} =    update Resource    ${iserver}    InCSE1/Container1    ${rt_container}    ${attr}
+    ${lt2} =    LastModifiedTime    ${r}
+    Should Not Be Equal    ${oldr.json()['lt']}    ${lt2}
+
+4.12 childResources create , parent's lastmodifiedTime update
+    [Documentation]    childResources create , parent's lastmodifiedTime update
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1/Container1
+    ${text} =    Text    ${oldr}
+    LOG    ${text}
+    ${lt1} =    LastModifiedTime    ${oldr}
+    Sleep    1s
+    # We know Beryllium is going to be get rid of all sleep.
+    # But as lastModifiedTime has precision in seconds,
+    # we need to wait 1 second to see different value on update.
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"102"
+    ${r} =    Create Resource    ${iserver}    InCSE1/Container1    ${rt_contentInstance}    ${attr}    conIn1
+    ${lt2} =    LastModifiedTime    ${r}
+    Should Not Be Equal    ${oldr.json()['lt']}    ${lt2}
+    #-------------- 2 parentID ------------
+
+4.21 Check parentID(cse-container)
+    [Documentation]    parentID should be InCSE1
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1
+    ${CSEID} =    Set Variable    ${oldr.json()['ri']}
+    ${r} =    Retrieve Resource    ${iserver}    InCSE1/Container1
+    Should Be Equal    ${oldr.json()['ri']}    ${r.json()['pi']}
+
+4.22 Check parentID(cse-container-container)
+    [Documentation]    parentID should be correct
+    # CSE
+    #    |--Contianer1
+    #    |--Container2
+    ${attr} =    Set Variable
+    ${r}=    Create Resource    ${iserver}    InCSE1/Container1    ${rt_container}    ${attr}    Container2
+    ${container} =    Name    ${r}
+    ${status_code} =    Status Code    ${r}
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1/Container1
+    ${CSEID} =    Set Variable    ${oldr.json()['ri']}
+    ${r} =    Retrieve Resource    ${iserver}    InCSE1/Container1/Container2
+    Should Be Equal    ${oldr.json()['ri']}    ${r.json()['pi']}
+
+4.23 Check parentID(cse-AE-container)
+    [Documentation]    parentID should be correct
+    # CSE
+    #    |--AE1
+    #    |--Container2
+    ${attr} =    Set Variable    "api":"ODL","aei":"ODL"
+    ${r}=    Create Resource    ${iserver}    InCSE1    ${rt_ae}    ${attr}    AE1
+    ${attr} =    Set Variable
+    ${r}=    Create Resource    ${iserver}    InCSE1/AE1    ${rt_container}    ${attr}    Container2
+    ${container} =    Name    ${r}
+    ${status_code} =    Status Code    ${r}
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1/AE1
+    ${CSEID} =    Set Variable    ${oldr.json()['ri']}
+    ${r} =    Retrieve Resource    ${iserver}    InCSE1/AE1/Container2
+    Should Be Equal    ${oldr.json()['ri']}    ${r.json()['pi']}
+
+4.24 Check parentID(cse-AE-container-container)
+    [Documentation]    parentID should be correct
+    # CSE
+    #    |--AE1
+    #    |--Container2
+    #    |--- Container3
+    ${attr} =    Set Variable
+    ${r}=    Create Resource    ${iserver}    InCSE1/AE1/Container2    ${rt_container}    ${attr}    Container3
+    ${container} =    Name    ${r}
+    ${status_code} =    Status Code    ${r}
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1/AE1/Container2
+    ${CSEID} =    Set Variable    ${oldr.json()['ri']}
+    ${r} =    Retrieve Resource    ${iserver}    InCSE1/AE1/Container2/Container3
+    Should Be Equal    ${oldr.json()['ri']}    ${r.json()['pi']}
+
+Delete the test AE-4.2
+    ${deleteRes} =    Delete Resource    ${iserver}    InCSE1/AE1
+    #--------------3. stateTag------------
+
+4.31 stateTag (when create, check if 0)
+    [Documentation]    when create, st should be 0
+    # CSE
+    #    |--Container2
+    ${attr} =    Set Variable
+    ${r}=    Create Resource    ${iserver}    InCSE1    ${rt_container}    ${attr}    Container2
+    ${container} =    Name    ${r}
+    ${status_code} =    Status Code    ${r}
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${st} =    Set Variable    ${oldr.json()['st']}
+    Should Be Equal As Integers    0    ${st}
+    # 4.32 stateTag (when update expirationTime)
+    # 4.33 stateTag (when update accessControlPolicyIDs)
+
+4.34 stateTag (when update labels) + lastModifiedTime
+    [Documentation]    st and lt should be changed
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${oldst} =    Set Variable    ${oldr.json()['st']}
+    ${attr} =    Set Variable    "lbl":["label1"]
+    Sleep    1s
+    # We know Beryllium is going to be get rid of all sleep.
+    # But as lastModifiedTime has precision in seconds,
+    # we need to wait 1 second to see different value on update.
+    Update Resource    ${iserver}    InCSE1/Container2    ${rt_container}    ${attr}
+    ${r} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    Should Be Equal As Integers    ${oldst+1}    ${r.json()['st']}
+    Should Not Be Equal    ${oldr.json()['lt']}    ${r.json()['lt']}
+    # 4.35 stateTag (when update announceTo)
+    # 4.36 stateTag (when update announceAttribute)
+
+4.37 stateTag (when update MaxNrOfInstances) + lastModifiedTime
+    [Documentation]    st and lt should be changed
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${oldst} =    Set Variable    ${oldr.json()['st']}
+    ${attr} =    Set Variable    "mni":5
+    Sleep    1s
+    # We know Beryllium is going to be get rid of all sleep.
+    # But as lastModifiedTime has precision in seconds,
+    # we need to wait 1 second to see different value on update.
+    Update Resource    ${iserver}    InCSE1/Container2    ${rt_container}    ${attr}
+    ${r} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    Should Be Equal As Integers    ${oldst+1}    ${r.json()['st']}
+    Should Not Be Equal    ${oldr.json()['lt']}    ${r.json()['lt']}
+
+4.38 stateTag (when update MaxByteSize) + lastModifiedTime
+    [Documentation]    st and lt should be changed
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${oldst} =    Set Variable    ${oldr.json()['st']}
+    ${attr} =    Set Variable    "mbs":30
+    Sleep    1s
+    # We know Beryllium is going to be get rid of all sleep.
+    # But as lastModifiedTime has precision in seconds,
+    # we need to wait 1 second to see different value on update.
+    Update Resource    ${iserver}    InCSE1/Container2    ${rt_container}    ${attr}
+    ${r} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    Should Be Equal As Integers    ${oldst+1}    ${r.json()['st']}
+    Should Not Be Equal    ${oldr.json()['lt']}    ${r.json()['lt']}
+    # 4.39 stateTag (when update maxInstanceAge)
+    # 4.310 stateTag (when update locationID)
+
+4.311 stateTag (when update ontologyRef) + lastModifiedTime
+    [Documentation]    st and lt should be changed
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${oldst} =    Set Variable    ${oldr.json()['st']}
+    ${attr} =    Set Variable    "or":"http://google.com"
+    Sleep    1s
+    # We know Beryllium is going to be get rid of all sleep.
+    # But as lastModifiedTime has precision in seconds,
+    # we need to wait 1 second to see different value on update.
+    Update Resource    ${iserver}    InCSE1/Container2    ${rt_container}    ${attr}
+    ${r} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    Should Be Equal As Integers    ${oldst+1}    ${r.json()['st']}
+    Should Not Be Equal    ${oldr.json()['lt']}    ${r.json()['lt']}
+
+4.312 when create child container, stateTag will not increase + lastModifiedTime should change
+    [Documentation]    when create child container, stateTag will not increase + lastModifiedTime should not change
+    # CSE
+    #    |--Contianer2
+    #    |--Container3
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${oldst} =    Set Variable    ${oldr.json()['st']}
+    ${attr} =    Set Variable    "lbl":["label1"]
+    Sleep    1s
+    # We know Beryllium is going to be get rid of all sleep.
+    # But as lastModifiedTime has precision in seconds,
+    # we need to wait 1 second to see different value on update.
+    Create Resource    ${iserver}    InCSE1/Container2    ${rt_container}    ${attr}    Container3
+    ${r} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${text} =    Text    ${r}
+    LOG    ${text}
+    Should Be Equal As Integers    ${oldst}    ${r.json()['st']}
+    Should Not Be Equal    ${oldr.json()['lt']}    ${r.json()['lt']}
+
+4.313 * when create child contentInsntance, state should increase + lastModifiedTime shold change
+    [Documentation]    when create child contentInsntance, state should increase + lastModifiedTime shold not change
+    # CSE
+    #    |--Contianer2
+    #    |--ContentInstance
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${oldst} =    Set Variable    ${oldr.json()['st']}
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"102"
+    Sleep    1s
+    # We know Beryllium is going to be get rid of all sleep.
+    # But as lastModifiedTime has precision in seconds,
+    # we need to wait 1 second to see different value on update.
+    Create Resource    ${iserver}    InCSE1/Container2    ${rt_contentInstance}    ${attr}
+    ${r} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${text} =    Text    ${r}
+    LOG    ${text}
+    Should Be Equal As Integers    ${oldst+1}    ${r.json()['st']}
+    Should Not Be Equal    ${oldr.json()['lt']}    ${r.json()['lt']}
+
+4.314 stateTag should not be updated when update child container
+    [Documentation]    stateTag should not be updated when update child container
+    # CSE
+    #    |--Contianer2
+    #    |--Container3
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${oldst} =    Set Variable    ${oldr.json()['st']}
+    ${attr} =    Set Variable    "lbl":["label45"]
+    Sleep    1s
+    # We know Beryllium is going to be get rid of all sleep.
+    # But as lastModifiedTime has precision in seconds,
+    # we need to wait 1 second to see different value on update.
+    Update Resource    ${iserver}    InCSE1/Container2/Container3    ${rt_container}    ${attr}
+    ${r} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${text} =    Text    ${r}
+    LOG    ${text}
+    Should Be Equal As Integers    ${oldst}    ${r.json()['st']}
+    ${lt2} =    LastModifiedTime    ${r}
+    Should Be Equal    ${oldr.json()['lt']}    ${r.json()['lt']}
+
+Delete the Container2-4.3
+    ${deleteRes} =    Delete Resource    ${iserver}    InCSE1/Container2
+    #------------    4.    currentNrofInstance ------
+
+4.41 when container create, cni should be 0
+    [Documentation]    when container create, cni should be 0
+    ${attr} =    Set Variable
+    ${r}=    Create Resource    ${iserver}    InCSE1    ${rt_container}    ${attr}    Container2
+    ${container} =    Name    ${r}
+    ${status_code} =    Status Code    ${r}
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${cni} =    Set Variable    ${oldr.json()['cni']}
+    Should Be Equal As Integers    0    ${cni}
+
+4.42 when conInstance create, parent container's cni should + 1
+    [Documentation]    when conInstance create, parent container's cni should + 1
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${oldcni} =    Set Variable    ${oldr.json()['cni']}
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"102"
+    Create Resource    ${iserver}    InCSE1/Container2    ${rt_contentInstance}    ${attr}
+    ${r} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${text} =    Text    ${r}
+    LOG    ${text}
+    Should Be Equal As Integers    ${oldcni+1}    ${r.json()['cni']}
+    # Test again
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${oldcni} =    Set Variable    ${oldr.json()['cni']}
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"102"
+    Create Resource    ${iserver}    InCSE1/Container2    ${rt_contentInstance}    ${attr}    contentIn1
+    ${r} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${text} =    Text    ${r}
+    LOG    ${text}
+    Should Be Equal As Integers    ${oldcni+1}    ${r.json()['cni']}
+
+4.43 when conInstance delete, parent container's cni should - 1
+    [Documentation]    Delete the conIn created in 4.42, when conInstance delete, parent container's cni should - 1
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${oldcni} =    Set Variable    ${oldr.json()['cni']}
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"102"
+    Delete Resource    ${iserver}    InCSE1/Container2/contentIn1
+    ${r} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${text} =    Text    ${r}
+    LOG    ${text}
+    Should Be Equal As Integers    ${oldcni-1}    ${r.json()['cni']}
+
+Delete the Container2-4.4
+    ${deleteRes} =    Delete Resource    ${iserver}    InCSE1/Container2
+    # -------------    5. currentByteSize    -----------
+
+4.51 when container create, cbs should be 0
+    [Documentation]    when container create, cbs should be 0
+    ${attr} =    Set Variable
+    ${r}=    Create Resource    ${iserver}    InCSE1    ${rt_container}    ${attr}    Container2
+    ${container} =    Name    ${r}
+    ${status_code} =    Status Code    ${r}
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${cbs} =    Set Variable    ${oldr.json()['cbs']}
+    Should Be Equal As Integers    0    ${cbs}
+
+4.52 when conInstance create, parent container's cbs should + cs
+    [Documentation]    when conInstance create, parent container's cbs should + cs
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${oldcbs} =    Set Variable    ${oldr.json()['cbs']}
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"102CSS"
+    Create Resource    ${iserver}    InCSE1/Container2    ${rt_contentInstance}    ${attr}
+    ${r} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${text} =    Text    ${r}
+    LOG    ${text}
+    Should Be Equal As Integers    ${oldcbs+6}    ${r.json()['cbs']}
+    # Test again
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${oldcbs} =    Set Variable    ${oldr.json()['cbs']}
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"xxx%%!@"
+    Create Resource    ${iserver}    InCSE1/Container2    ${rt_contentInstance}    ${attr}    contentIn1
+    ${r} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${text} =    Text    ${r}
+    LOG    ${text}
+    Should Be Equal As Integers    ${oldcbs+7}    ${r.json()['cbs']}
+
+4.53 when conInstance delete, parent container's cbs should - cs
+    [Documentation]    Delete the conIn created in 4.52, when conInstance delete, parent container's cbs should - cs
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${oldcbs} =    Set Variable    ${oldr.json()['cbs']}
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"102"
+    Delete Resource    ${iserver}    InCSE1/Container2/contentIn1
+    ${r} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${text} =    Text    ${r}
+    LOG    ${text}
+    Should Be Equal As Integers    ${oldcbs-7}    ${r.json()['cbs']}
+
+Delete the Container2-4.5
+    ${deleteRes} =    Delete Resource    ${iserver}    InCSE1/Container2
+    # -------------    6. maxNrOfInstances    ----------
+
+4.61 if maxNrOfInstance = 1 , can create 1 contentInstance
+    [Documentation]    if maxNrOfInstance = 1 , can create 1 contentInstance
+    ${attr} =    Set Variable    "mni":1
+    ${r}=    Create Resource    ${iserver}    InCSE1    ${rt_container}    ${attr}    Container2
+    ${container} =    Name    ${r}
+    ${status_code} =    Status Code    ${r}
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${mni} =    Set Variable    ${oldr.json()['mni']}
+    Should Be Equal As Integers    1    ${mni}
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"102CSS"
+    Create Resource    ${iserver}    InCSE1/Container2    ${rt_contentInstance}    ${attr}
+
+4.62 if maxNrOfInstance = 1 , cannot create 2 contentInstance
+    [Documentation]    if maxNrOfInstance = 1 , cannot create 2 contentInstance
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"102CSS"
+    # cannot create 2
+    ${error} =    Run Keyword And Expect Error    *    Create Resource    ${iserver}    InCSE1/Container2    ${rt_contentInstance}
+    ...    ${attr}
+    Should Start with    ${error}    Cannot create this resource [400]
+
+4.63 if update to 3 , cannot create 4 contentInstance
+    [Documentation]    if update to 3 , cannot create 4 contentInstance
+    ${attr} =    Set Variable    "mni":3
+    ${r}=    Update Resource    ${iserver}    InCSE1/Container2    ${rt_container}    ${attr}
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"102CSS"
+    # create 3
+    Create Resource    ${iserver}    InCSE1/Container2    ${rt_contentInstance}    ${attr}    cin1
+    Create Resource    ${iserver}    InCSE1/Container2    ${rt_contentInstance}    ${attr}    cin2
+    #Create Resource    ${iserver}    InCSE1/Container2    ${rt_contentInstance}    ${attr}
+    ${rr}=    Retrieve resource    ${iserver}    InCSE1/Container2
+    ${mni} =    Set Variable    ${rr.json()['mni']}
+    ${chr} =    Set Variable    ${rr.json()['ch']}
+    ${text} =    Text    ${rr}
+    LOG    ${text}
+    # cannot create 4
+    ${error} =    Run Keyword And Expect Error    *    Create Resource    ${iserver}    InCSE1/Container2    ${rt_contentInstance}
+    ...    ${attr}
+    Should Start with    ${error}    Cannot create this resource [400]
+
+4.64 what if alread have 4, then set mni to 1 ?
+    [Documentation]    what if alread have 4, then set mni to 1 ?
+    ${attr} =    Set Variable    "mni":1
+    ${r}=    Update Resource    ${iserver}    InCSE1/Container2    ${rt_container}    ${attr}
+    ${rr}=    Retrieve resource    ${iserver}    InCSE1/Container2
+    ${chr} =    Set Variable    ${rr.json()['ch']}
+    ${mni} =    Set Variable    ${rr.json()['mni']}
+    Should Be Equal As Integers    ${rr.json()['cni']}    1
+
+Delete the Container2-4.6
+    ${deleteRes} =    Delete Resource    ${iserver}    InCSE1/Container2
+    # -------------    7. maxByteSize -------
+
+4.71 if maxByteSize = 5 , can create contentInstance with contentSize 5
+    [Documentation]    if maxByteSize = 5 , can create contentInstance with contentSize 5
+    ${attr} =    Set Variable    "mbs":5
+    ${r}=    Create Resource    ${iserver}    InCSE1    ${rt_container}    ${attr}    Container2
+    ${container} =    Name    ${r}
+    ${status_code} =    Status Code    ${r}
+    ${oldr} =    Retrieve Resource    ${iserver}    InCSE1/Container2
+    ${mbs} =    Set Variable    ${oldr.json()['mbs']}
+    Should Be Equal As Integers    5    ${mbs}
+
+4.72 if maxByteSize = 5 , cannot create contentInstance with contenSize 8
+    [Documentation]    if maxByteSize = 5 , cannot create contentInstance with contenSize 8
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"102C"
+    # create 1 (6 bytes)
+    Create Resource    ${iserver}    InCSE1/Container2    ${rt_contentInstance}    ${attr}
+    # cannot create 2
+    ${error} =    Run Keyword And Expect Error    *    Create Resource    ${iserver}    InCSE1/Container2    ${rt_contentInstance}
+    ...    ${attr}
+    Should Start with    ${error}    Cannot create this resource [400]
+
+4.73 if update to 20 , cannot create another contentInstance
+    [Documentation]    if update to 20 , cannot create another contentInstance
+    ${attr} =    Set Variable    "mbs":20
+    ${r}=    Update Resource    ${iserver}    InCSE1/Container2    ${rt_container}    ${attr}
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"102CS"
+    # create 3
+    Create Resource    ${iserver}    InCSE1/Container2    ${rt_contentInstance}    ${attr}    cin1
+    Create Resource    ${iserver}    InCSE1/Container2    ${rt_contentInstance}    ${attr}    cin2
+    Create Resource    ${iserver}    InCSE1/Container2    ${rt_contentInstance}    ${attr}    cin3
+    Create Resource    ${iserver}    InCSE1/Container2    ${rt_contentInstance}    ${attr}    cin4
+    ${rr}=    Retrieve resource    ${iserver}    InCSE1/Container2
+    ${cbs} =    Set Variable    ${rr.json()['cbs']}
+    ${chr} =    Set Variable    ${rr.json()['ch']}
+    ${text} =    Text    ${rr}
+    LOG    ${text}
+    # cannot create 4
+    ${error} =    Run Keyword And Expect Error    *    Create Resource    ${iserver}    InCSE1/Container2    ${rt_contentInstance}
+    ...    ${attr}
+    Should Start with    ${error}    Cannot create this resource [400]
+
+4.74 what if alread have 20, then set mbs to 5 ?
+    [Documentation]    what if alread have 20, then set mbs to 5 ?
+    ${attr} =    Set Variable    "mbs":5
+    ${r}=    Update Resource    ${iserver}    InCSE1/Container2    ${rt_container}    ${attr}
+    ${rr}=    Retrieve resource    ${iserver}    InCSE1/Container2
+    ${chr} =    Set Variable    ${rr.json()['ch']}
+    ${cbs} =    Set Variable    ${rr.json()['cbs']}
+    Should Be Equal As Integers    ${rr.json()['cni']}    1
+
+Delete the Container2-4.7
+    ${deleteRes} =    Delete Resource    ${iserver}    InCSE1/Container2
+
+4.81 creator -- value must be null
+    [Documentation]    creator -- value must be null
+    ${attr} =    Set Variable    "cr":"VALUE"
+    ${error} =    Run Keyword And Expect Error    *    Create Resource    ${iserver}    InCSE1/Container1    ${rt_container}
+    ...    ${attr}
+    Should Start with    ${error}    Cannot create this resource [400]
+    Should Contain    ${error}    error    cr
+    #==================================================
+    #    Finish
+    #==================================================
+
+Delete the test Container1
+    [Documentation]    Delete the test Container1
+    ${deleteRes} =    Delete Resource    ${iserver}    InCSE1/Container1
+
+*** Keywords ***
+Check Response and Retrieve Resource
+    [Arguments]    ${r}
+    ${con} =    Name    ${r}
+    ${status_code} =    Status Code    ${r}
+    Should Be True    199 < ${status_code} < 299
+    ${rr} =    Retrieve Resource    ${iserver}    ${con}
+    ${text} =    Text    ${rr}
+    [Return]    ${text}
+
+Cannot Create Container Error
+    [Arguments]    ${attr}
+    [Documentation]    create Container Under InCSE1 and expect error
+    ${error} =    Run Keyword And Expect Error    *    Create Resource    ${iserver}    InCSE1    ${rt_container}
+    ...    ${attr}
+    Should Start with    ${error}    Cannot create this resource [400]
+    [Return]    ${error}
+
+Cannot Update Container Error
+    [Arguments]    ${attr}
+    [Documentation]    update Container Under InCSE1 and expect error
+    ${error} =    Run Keyword And Expect Error    *    Update Resource    ${iserver}    InCSE1/Container1    ${rt_container}
+    ...    ${attr}
+    Should Start with    ${error}    Cannot update this resource [400]
+    [Return]    ${error}
diff --git a/test/csit/suites/iotdm/basic/060_ConInAttributeTest.robot b/test/csit/suites/iotdm/basic/060_ConInAttributeTest.robot
new file mode 100644 (file)
index 0000000..39d7a4d
--- /dev/null
@@ -0,0 +1,245 @@
+*** Settings ***
+Suite Teardown    Kill The Tree    ${CONTROLLER}    InCSE1    admin    admin
+Library           ../../../libraries/criotdm.py
+Library           Collections
+
+*** Variables ***
+${httphost}       ${CONTROLLER}
+${httpuser}       admin
+${httppass}       admin
+${rt_ae}          2
+${rt_container}    3
+${rt_contentInstance}    4
+
+*** Test Cases ***
+Set Suite Variable
+    [Documentation]    set a suite variable ${iserver}
+    #==================================================
+    #    Container Mandatory Attribute Test
+    #==================================================
+    # mandatory attribute: content
+    # cse
+    #    |
+    #    ---Container1
+    #    |
+    #    ----conIn1
+    ${iserver} =    Connect To Iotdm    ${httphost}    ${httpuser}    ${httppass}    http
+    Set Suite Variable    ${iserver}
+
+1.1 After Created, test whether all the mandatory attribtues are exist.
+    [Documentation]    create 1 conIn test whether all the mandatory attribtues are exist
+    ${attr} =    Set Variable
+    ${r}=    Create Resource    ${iserver}    InCSE1    ${rt_container}    ${attr}    Container1
+    ${container} =    Name    ${r}
+    ${status_code} =    Status Code    ${r}
+    Should Be Equal As Integers    ${status_code}    201
+    ${attr} =    Set Variable    "con":"102CSS"
+    Create Resource    ${iserver}    InCSE1/Container1    ${rt_contentInstance}    ${attr}    conIn1
+    ${text} =    Text    ${r}
+    Should Contain    ${text}    "ri":    "rn":    "cs":
+    Should Contain    ${text}    "lt":    "pi":    "con":
+    Should Contain    ${text}    "ct":    "rty":4
+    Should Not Contain    S{text}    "lbl"    "creator"    "or"
+
+1.21 Missing content should return error
+    [Documentation]    Missing content should return error
+    ${attr} =    Set Variable
+    ${error} =    Run Keyword And Expect Error    *    Create Resource    ${iserver}    InCSE1/Container1    ${rt_contentInstance}
+    ...    ${attr}
+    Should Start with    ${error}    Cannot create this resource [400]
+    Should Contain    ${error}    CONTENT    missing
+    #===========================================================
+    #    ContentInstance Optional Attribute Test (Allowed)
+    #===========================================================
+    #    create--> delete
+    #    Cannot be updated
+    # Optional attribute: [aa,at],contentInfo, ontologyRef, label, creator
+
+2.11 ContentInfo (cnf) can be added when create
+    [Documentation]    ContentInfo (cnf) can be added when create
+    ${attr} =    Set Variable    "cnf": "1","con":"102CSS"
+    # create conIn under Container1
+    ${r}=    Create Resource    ${iserver}    InCSE1/Container1    ${rt_contentInstance}    ${attr}    conIn2
+    ${text} =    Check Create and Retrieve ContentInstance    ${r}
+    Should Contain    ${text}    cnf
+
+Delete the ContenInstance 2.1
+    ${deleteRes} =    Delete Resource    ${iserver}    InCSE1/Container1/conIn2
+
+2.12 ContentInfo (cnf) cannot be updated
+    [Documentation]    ContentInfo (cnf) cannot be updated
+    ${attr} =    Set Variable    "cnf": "1"
+    ${error} =    Cannot Update ContentInstance Error    ${attr}
+    Should Contain    ${error}    Not permitted to update content
+
+2.21 OntologyRef (or) can be added when create
+    [Documentation]    OntologyRef (or) can be added when create
+    ${attr} =    Set Variable    "or": "http://cisco.com","con":"102CSS"
+    # create conIn under Container1
+    ${r}=    Create Resource    ${iserver}    InCSE1/Container1    ${rt_contentInstance}    ${attr}    conIn2
+    ${text} =    Check Create and Retrieve ContentInstance    ${r}
+    Should Contain    ${text}    or
+
+Delete the ContenInstance 2.2
+    ${deleteRes} =    Delete Resource    ${iserver}    InCSE1/Container1/conIn2
+
+2.22 OntologyRef (or) cannot be updated
+    [Documentation]    OntologyRef (or) cannot be updated
+    ${attr} =    Set Variable    "or": "1"
+    ${error} =    Cannot Update ContentInstance Error    ${attr}
+    Should Contain    ${error}    Not permitted to update content
+
+2.31 labels[single] can be added when create
+    [Documentation]    create conIn under Container1, labels[single] can be added when create
+    ${attr} =    Set Variable    "lbl":["ds"],"con":"102CSS"
+    ${r}=    Create Resource    ${iserver}    InCSE1/Container1    ${rt_contentInstance}    ${attr}    conIn2
+    ${text} =    Check Create and Retrieve ContentInstance    ${r}
+    Should Contain    ${text}    lbl
+
+Delete the ContenInstance 2.31
+    ${deleteRes} =    Delete Resource    ${iserver}    InCSE1/Container1/conIn2
+
+2.32 labels (single) cannot be updated
+    [Documentation]    update labels then expect error
+    ${attr} =    Set Variable    "lbl":["1"]
+    ${error} =    Cannot Update ContentInstance Error    ${attr}
+    Should Contain    ${error}    Not permitted to update content
+
+2.33 labels (multiple) can be added when create
+    [Documentation]    labels (multiple) can be added when create
+    ${attr} =    Set Variable    "lbl":["http://cisco.com","dsds"],"con":"102CSS"
+    # create conIn under Container1
+    ${r}=    Create Resource    ${iserver}    InCSE1/Container1    ${rt_contentInstance}    ${attr}    conIn2
+    ${text} =    Check Create and Retrieve ContentInstance    ${r}
+    Should Contain    ${text}    lbl
+
+Delete the ContenInstance 2.33
+    ${deleteRes} =    Delete Resource    ${iserver}    InCSE1/Container1/conIn2
+
+2.34 labels (multiple) cannot be updated
+    [Documentation]    labels (multiple) cannot be updated
+    ${attr} =    Set Variable    "lbl":["1"]
+    ${error} =    Cannot Update ContentInstance Error    ${attr}
+    Should Contain    ${error}    Not permitted to update content
+    #=================================================================
+    #    contentInstance Disturbing Attribute Test, Not Allowed Update
+    #=================================================================
+    # using non-valid attribtue to create then expext error
+
+3.11 Mulitiple labels should return error
+    [Documentation]    Mulitiple labels should return error
+    ${attr} =    Set Variable    "con": "1", "lbl":["label1"],"lbl":["label2"]
+    ${error} =    Cannot Craete ContentInstance Error    ${attr}
+    Should Contain    ${error}    Duplicate    lbl
+
+3.12 Multiple creator should return error
+    [Documentation]    Multiple creator should return error
+    ${attr} =    Set Variable    "con": "1", "cr":null, "cr":null
+    ${error} =    Cannot Craete ContentInstance Error    ${attr}
+    Should Contain    ${error}    Duplicate    cr
+
+3.13 Multiple contentInfo should return error
+    [Documentation]    Multiple contentInfo should return error
+    ${attr} =    Set Variable    "con": "1", "cnf":"1","cnf":"2"
+    ${error} =    Cannot Craete ContentInstance Error    ${attr}
+    Should Contain    ${error}    Duplicate    cnf
+
+3.14 Multiple ontologyRef should return error
+    [Documentation]    Multiple ontologyRef should return error
+    ${attr} =    Set Variable    "con": "1", "or":"http://cisco.com","or":"http://google.com"
+    ${error} =    Cannot Craete ContentInstance Error    ${attr}
+    Should Contain    ${error}    Duplicate    or
+
+3.15 Mulptiple content should return error
+    [Documentation]    Mulptiple content should return error
+    ${attr} =    Set Variable    "con": "1", "con":"2313"
+    ${error} =    Cannot Craete ContentInstance Error    ${attr}
+    Should Contain    ${error}    Duplicate    con
+    #----------------All attributes cannot be updated----------
+
+3.21 resourceType cannot be updated.
+    [Documentation]    update resourceType and expect error
+    ${attr} =    Set Variable    "rt": 3
+    ${error} =    Cannot Update ContentInstance Error    ${attr}
+    Should Contain    ${error}    Not permitted to update content
+
+3.22 resourceId cannot be updated.
+    [Documentation]    update resourceId and expect error
+    ${attr} =    Set Variable    "ri": "e4e43"
+    ${error} =    Cannot Update ContentInstance Error    ${attr}
+    Should Contain    ${error}    Not permitted to update content
+
+3.23 resourceName cannot be updated.
+    [Documentation]    update resourceName and expect error
+    ${attr} =    Set Variable    "rn": "4343"
+    ${error} =    Cannot Update ContentInstance Error    ${attr}
+    Should Contain    ${error}    Not permitted to update content
+
+3.24 parentId cannot be updated.
+    [Documentation]    update parentID and expect error
+    ${attr} =    Set Variable    "pi": "InCSE2/ERE"
+    ${error} =    Cannot Update ContentInstance Error    ${attr}
+    Should Contain    ${error}    Not permitted to update content
+
+3.25 cretionTime cannot be updated.
+    [Documentation]    update createTime and expect error
+    ${attr} =    Set Variable    "ct": "343434T34322"
+    ${error} =    Cannot Update ContentInstance Error    ${attr}
+    Should Contain    ${error}    Not permitted to update content
+
+3.26 lastmodifiedTime cannot be updated.
+    [Documentation]    update lt then expect error
+    ${attr} =    Set Variable    "lt": "434343T23232"
+    ${error} =    Cannot Update ContentInstance Error    ${attr}
+    Should Contain    ${error}    Not permitted to update content
+
+3.27 contentSize cannot be updated.
+    [Documentation]    update contentSize then expect error
+    ${attr} =    Set Variable    "cs": 232
+    ${error} =    Cannot Update ContentInstance Error    ${attr}
+    Should Contain    ${error}    Not permitted to update content
+
+3.28 content cannot be updated
+    [Documentation]    update content then expect error
+    ${attr} =    Set Variable    "con": "1"
+    ${error} =    Cannot Update ContentInstance Error    ${attr}
+    Should Contain    ${error}    Not permitted to update content
+    #==================================================
+    #    Functional Attribute Test
+    #==================================================
+    # Next step:
+    # creator
+    # contentSzie
+    # contentInfo
+    # content
+    #==================================================
+    #    Finish
+    #==================================================
+
+Delete the test Container1
+    [Documentation]    Delete the test Container1
+    ${deleteRes} =    Delete Resource    ${iserver}    InCSE1/Container1
+
+*** Keywords ***
+Cannot Update ContentInstance Error
+    [Arguments]    ${attr}
+    ${error} =    Run Keyword And Expect Error    *    update Resource    ${iserver}    InCSE1/Container1/conIn1    ${rt_contentInstance}
+    ...    ${attr}
+    Should Start with    ${error}    Cannot update this resource [405]
+    [Return]    ${error}
+
+Cannot Craete ContentInstance Error
+    [Arguments]    ${attr}
+    ${error} =    Run Keyword And Expect Error    *    create Resource    ${iserver}    InCSE1/Container1/conIn1    ${rt_contentInstance}
+    ...    ${attr}
+    Should Start with    ${error}    Cannot create this resource [400]
+    [Return]    ${error}
+
+Check Create and Retrieve ContentInstance
+    [Arguments]    ${r}
+    ${con} =    Name    ${r}
+    ${status_code} =    Status Code    ${r}
+    Should Be Equal As Integers    ${status_code}    201
+    ${rr} =    Retrieve Resource    ${iserver}    ${con}
+    ${text} =    Text    ${rr}
+    [Return]    ${text}
diff --git a/test/csit/suites/iotdm/basic/070_DeleteTest.robot b/test/csit/suites/iotdm/basic/070_DeleteTest.robot
new file mode 100644 (file)
index 0000000..5b14d06
--- /dev/null
@@ -0,0 +1,419 @@
+*** Settings ***
+Suite Teardown    Kill The Tree    ${CONTROLLER}    InCSE1    admin    admin
+Library           ../../../libraries/criotdm.py
+Library           Collections
+
+*** Variables ***
+${httphost}       ${CONTROLLER}
+${httpuser}       admin
+${httppass}       admin
+${rt_ae}          2
+${rt_container}    3
+${rt_contentInstance}    4
+
+*** Test Cases ***
+Set Suite Variable
+    [Documentation]    set a suite variable ${iserver}
+    #==================================================
+    #    Delete Test
+    #==================================================
+    ${iserver} =    Connect To Iotdm    ${httphost}    ${httpuser}    ${httppass}    http
+    Set Suite Variable    ${iserver}
+
+4.11 Delete AE without child resource
+    [Documentation]    Create AE then delete it
+    ${attr} =    Set Variable    "aei":"ODL","api":"jb","apn":"jb2","or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    InCSE1    ${rt_ae}    ${attr}
+    ${ae} =    Name    ${r}
+    Response Is Correct    ${r}
+    #------------- Delete -----------------------------
+    ${deleteRes} =    Delete Resource    ${iserver}    ${ae}
+    ${status_code} =    Status Code    ${deleteRes}
+    Should Be Equal As Integers    ${status_code}    200
+    # Delete AE that does not exist/has been deleted should return error
+    ${error} =    Run Keyword And Expect Error    *    Delete Resource    ${iserver}    ${ae}
+    Should Start with    ${error}    Cannot delete this resource [404]
+
+4.12 Delete Container without child resource
+    [Documentation]    create container then delete it
+    ${attr} =    Set Variable    "cr":null,"mni":5,"mbs":15,"or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    InCSE1    ${rt_container}    ${attr}
+    ${container} =    Name    ${r}
+    Response Is Correct    ${r}
+    #------------- Delete -----------------------------
+    ${deleteRes} =    Delete Resource    ${iserver}    ${container}
+    ${status_code} =    Status Code    ${deleteRes}
+    Should Be Equal As Integers    ${status_code}    200
+    # Delete container that does not exist/has been deleted should return error
+    ${error} =    Run Keyword And Expect Error    *    Delete Resource    ${iserver}    ${container}
+    Should Start with    ${error}    Cannot delete this resource [404]
+
+4.13 Delete contentInstance under InCSE1/AE/container/
+    [Documentation]    Delete contentInstance under InCSE1/AE/container/
+    ${attr} =    Set Variable    "aei":"ODL","api":"jb","apn":"jb2","or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    InCSE1    ${rt_ae}    ${attr}    AE1
+    ${ae} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${attr} =    Set Variable    "cr":null,"mni":5,"mbs":15,"or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    ${ae}    ${rt_container}    ${attr}    Con1
+    ${container} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"101"
+    ${r} =    Create Resource    ${iserver}    ${container}    ${rt_contentInstance}    ${attr}
+    ${conIn} =    Name    ${r}
+    Response Is Correct    ${r}
+    #------------- Delete -----------------------------
+    ${deleteRes} =    Delete Resource    ${iserver}    ${conIn}
+    ${status_code} =    Status Code    ${deleteRes}
+    Should Be Equal As Integers    ${status_code}    200
+    # Delete container that does not exist/has been deleted should return error
+    ${error} =    Run Keyword And Expect Error    *    Delete Resource    ${iserver}    ${conIn}
+    Should Start with    ${error}    Cannot delete this resource [404]
+
+4.14 Delete contentInstance under InCSE1/Container/
+    [Documentation]    Delete contentInstance under InCSE1/Container/
+    ${attr} =    Set Variable    "cr":null,"mni":5,"mbs":15,"or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    InCSE1    ${rt_container}    ${attr}    Con2
+    ${container} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"101"
+    ${r} =    Create Resource    ${iserver}    ${container}    ${rt_contentInstance}    ${attr}
+    ${conIn} =    Name    ${r}
+    Response Is Correct    ${r}
+    #------------- Delete -----------------------------
+    ${deleteRes} =    Delete Resource    ${iserver}    ${conIn}
+    ${status_code} =    Status Code    ${deleteRes}
+    Should Be Equal As Integers    ${status_code}    200
+    # Delete container that does not exist/has been deleted should return error
+    ${error} =    Run Keyword And Expect Error    *    Delete Resource    ${iserver}    ${conIn}
+    Should Start with    ${error}    Cannot delete this resource [404]
+
+4.15 Delete contentIsntance under InCSE1/Container/container/
+    [Documentation]    Delete contentIsntance under InCSE1/Container/container/
+    ${attr} =    Set Variable    "cr":null,"mni":5,"mbs":15,"or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    InCSE1/Con2    ${rt_container}    ${attr}    Con3
+    ${container} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"101"
+    ${r} =    Create Resource    ${iserver}    ${container}    ${rt_contentInstance}    ${attr}
+    ${conIn} =    Name    ${r}
+    Response Is Correct    ${r}
+    #------------- Delete -----------------------------
+    ${deleteRes} =    Delete Resource    ${iserver}    ${conIn}
+    ${status_code} =    Status Code    ${deleteRes}
+    Should Be Equal As Integers    ${status_code}    200
+    # Delete container that does not exist/has been deleted should return error
+    ${error} =    Run Keyword And Expect Error    *    Delete Resource    ${iserver}    ${conIn}
+    Should Start with    ${error}    Cannot delete this resource [404]
+    # ============== AE with child container ==================
+
+4.21 Delete AE with 1 child Container
+    [Documentation]    Delete the AE nmaed AE1 which contains Con1 in the above test
+    ${r} =    Delete Resource    ${iserver}    InCSE1/AE1
+    Response Is Correct    ${r}
+    # Delete container that does not exist/has been deleted should return error
+    ${error} =    Run Keyword And Expect Error    *    Delete Resource    ${iserver}    InCSE1/AE1
+    Should Start with    ${error}    Cannot delete this resource [404]
+    #----------- Make sure cannot retrieve them -----------
+    Cannot Retrieve Error    InCSE1/AE1
+    Cannot Retrieve Error    InCSE1/AE1/Con1
+
+4.22 Delete AE with 3 child Container
+    [Documentation]    Delete AE with 3 child Container
+    ${attr} =    Set Variable    "aei":"ODL","api":"jb","apn":"jb2","or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    InCSE1    ${rt_ae}    ${attr}    AE1
+    ${ae} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${attr} =    Set Variable    "cr":null,"mni":5,"mbs":15,"or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    ${ae}    ${rt_container}    ${attr}    Con2
+    ${container} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${attr} =    Set Variable    "cr":null,"mni":5,"mbs":15,"or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    ${ae}    ${rt_container}    ${attr}    Con3
+    ${container} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${attr} =    Set Variable    "cr":null,"mni":5,"mbs":15,"or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    ${ae}    ${rt_container}    ${attr}    Con4
+    ${container} =    Name    ${r}
+    Response Is Correct    ${r}
+    # ----------- Delete the parent AE --------------
+    ${r} =    Delete Resource    ${iserver}    InCSE1/AE1
+    ${status_code} =    Status Code    ${r}
+    Should Be Equal As Integers    ${status_code}    200
+    ${text} =    Text    ${r}
+    LOG    ${text}
+    ${json} =    Json    ${r}
+    LOG    ${json}
+    # Delete the resource that does not exist/has been deleted should return error
+    ${error} =    Run Keyword And Expect Error    *    Delete Resource    ${iserver}    InCSE1/AE1
+    Should Start with    ${error}    Cannot delete this resource [404]
+    #----------- Make sure cannot retrieve them -----------
+    Cannot Retrieve Error    InCSE1/AE1
+    Cannot Retrieve Error    InCSE1/AE1/Con2
+    Cannot Retrieve Error    InCSE1/AE1/Con3
+    Cannot Retrieve Error    InCSE1/AE1/Con4
+
+4.23 Delete AE with 1 child Container/1 contentInstance
+    [Documentation]    Delete AE with 1 child Container/1 contentInstance
+    ${attr} =    Set Variable    "aei":"ODL","api":"jb","apn":"jb2","or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    InCSE1    ${rt_ae}    ${attr}    AE1
+    ${ae} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${attr} =    Set Variable    "cr":null,"mni":5,"mbs":15,"or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    ${ae}    ${rt_container}    ${attr}    Con2
+    ${container} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"101"
+    ${r} =    Create Resource    ${iserver}    ${container}    ${rt_contentInstance}    ${attr}    conIn1
+    ${name} =    Name    ${r}
+    Response Is Correct    ${r}
+    # ----------- Delete the parent AE --------------
+    ${r} =    Delete Resource    ${iserver}    InCSE1/AE1
+    Response Is Correct    ${r}
+    # Delete the resource that does not exist/has been deleted should return error
+    ${error} =    Run Keyword And Expect Error    *    Delete Resource    ${iserver}    InCSE1/AE1
+    Should Start with    ${error}    Cannot delete this resource [404]
+    #----------- Make sure cannot retrieve all of them -----------
+    Cannot Retrieve Error    InCSE1/AE1
+    Cannot Retrieve Error    InCSE1/AE1/Con2
+    Cannot Retrieve Error    InCSE1/AE1/Con2/conIn1
+
+4.24 Delete AE with 1 child Container/3 contentInsntace
+    [Documentation]    Delete AE with 1 child Container/3 contentInsntace
+    ${attr} =    Set Variable    "aei":"ODL","api":"jb","apn":"jb2","or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    InCSE1    ${rt_ae}    ${attr}    AE1
+    ${ae} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${attr} =    Set Variable    "cr":null,"mni":5,"mbs":15,"or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    ${ae}    ${rt_container}    ${attr}    Con2
+    ${container} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"101"
+    ${r} =    Create Resource    ${iserver}    ${container}    ${rt_contentInstance}    ${attr}    conIn1
+    Response Is Correct    ${r}
+    ${r} =    Create Resource    ${iserver}    ${container}    ${rt_contentInstance}    ${attr}    conIn2
+    Response Is Correct    ${r}
+    ${r} =    Create Resource    ${iserver}    ${container}    ${rt_contentInstance}    ${attr}    conIn3
+    Response Is Correct    ${r}
+    # ----------- Delete the parent AE --------------
+    ${r} =    Delete Resource    ${iserver}    InCSE1/AE1
+    Response Is Correct    ${r}
+    # Delete the resource that does not exist/has been deleted should return error
+    ${error} =    Run Keyword And Expect Error    *    Delete Resource    ${iserver}    InCSE1/AE1
+    Should Start with    ${error}    Cannot delete this resource [404]
+    #----------- Make sure cannot retrieve all of them -----------
+    Cannot Retrieve Error    InCSE1/AE1
+    Cannot Retrieve Error    InCSE1/AE1/Con2
+    Cannot Retrieve Error    InCSE1/AE1/Con2/conIn1
+    Cannot Retrieve Error    InCSE1/AE1/Con2/conIn2
+    Cannot Retrieve Error    InCSE1/AE1/Con2/conIn3
+
+4.25 Delete AE with 3 child Container/9 contentInstance
+    [Documentation]    Delete AE with 3 child Container/9 contentInstance
+    ${attr} =    Set Variable    "aei":"ODL","api":"jb","apn":"jb2","or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    InCSE1    ${rt_ae}    ${attr}    AE1
+    ${ae} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${attr} =    Set Variable    "cr":null,"mni":5,"mbs":15,"or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    ${ae}    ${rt_container}    ${attr}    Con1
+    ${container1} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${attr} =    Set Variable    "cr":null,"mni":5,"mbs":15,"or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    ${ae}    ${rt_container}    ${attr}    Con2
+    ${container2} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${attr} =    Set Variable    "cr":null,"mni":5,"mbs":15,"or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    ${ae}    ${rt_container}    ${attr}    Con3
+    ${container3} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"101"
+    : FOR    ${conName}    IN    conIn1    conIn2    conIn3
+    \    ${r} =    Create Resource    ${iserver}    ${container1}    ${rt_contentInstance}    ${attr}
+    \    ...    ${conName}
+    \    Response Is Correct    ${r}
+    : FOR    ${conName}    IN    conIn1    conIn2    conIn3
+    \    ${r} =    Create Resource    ${iserver}    ${container2}    ${rt_contentInstance}    ${attr}
+    \    ...    ${conName}
+    \    Response Is Correct    ${r}
+    : FOR    ${conName}    IN    conIn1    conIn2    conIn3
+    \    ${r} =    Create Resource    ${iserver}    ${container3}    ${rt_contentInstance}    ${attr}
+    \    ...    ${conName}
+    \    Response Is Correct    ${r}
+    # ----------- Delete the parent AE --------------
+    ${r} =    Delete Resource    ${iserver}    InCSE1/AE1
+    Response Is Correct    ${r}
+    # Delete the resource that does not exist/has been deleted should return error
+    ${error} =    Run Keyword And Expect Error    *    Delete Resource    ${iserver}    InCSE1/AE1
+    Should Start with    ${error}    Cannot delete this resource [404]
+    #----------- Make sure cannot retrieve them -----------
+    Cannot Retrieve Error    InCSE1/AE1
+    Cannot Retrieve Error    InCSE1/AE1/Con1
+    Cannot Retrieve Error    InCSE1/AE1/Con2
+    Cannot Retrieve Error    InCSE1/AE1/Con3
+    Cannot Retrieve Error    InCSE1/AE1/Con1/conIn1
+    Cannot Retrieve Error    InCSE1/AE1/Con1/conIn2
+    Cannot Retrieve Error    InCSE1/AE1/Con1/conIn3
+    Cannot Retrieve Error    InCSE1/AE1/Con2/conIn1
+    Cannot Retrieve Error    InCSE1/AE1/Con2/conIn2
+    Cannot Retrieve Error    InCSE1/AE1/Con2/conIn3
+    Cannot Retrieve Error    InCSE1/AE1/Con3/conIn1
+    Cannot Retrieve Error    InCSE1/AE1/Con3/conIn2
+    Cannot Retrieve Error    InCSE1/AE1/Con3/conIn3
+    # ================ Container with child container ==================
+
+4.31 Delete Container with 1 child Container
+    [Documentation]    Delete the Container nmaed Con2 which contains Con3 in the above test
+    ${r} =    Delete Resource    ${iserver}    InCSE1/Con2
+    Response Is Correct    ${r}
+    # Delete container that does not exist/has been deleted should return error
+    ${error} =    Run Keyword And Expect Error    *    Delete Resource    ${iserver}    InCSE1/Con2
+    Should Start with    ${error}    Cannot delete this resource [404]
+    #----------- Make sure cannot retrieve them -----------
+    Cannot Retrieve Error    InCSE1/Con2
+    Cannot Retrieve Error    InCSE1/Con2/Con3
+
+4.32 Delete Container with 3 child Container
+    [Documentation]    Delete Container with 3 child Container
+    ${attr} =    Set Variable    "cr":null,"mni":5,"mbs":15,"or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    InCSE1    ${rt_container}    ${attr}    ConTop1
+    ${container} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${r} =    Create Resource    ${iserver}    ${container}    ${rt_container}    ${attr}    Con1
+    ${container1} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${r} =    Create Resource    ${iserver}    ${container}    ${rt_container}    ${attr}    Con2
+    ${container2} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${r} =    Create Resource    ${iserver}    ${container}    ${rt_container}    ${attr}    Con3
+    ${container3} =    Name    ${r}
+    Response Is Correct    ${r}
+    # ----------- Delete the parent Container --------------
+    ${r} =    Delete Resource    ${iserver}    InCSE1/ConTop1
+    Response Is Correct    ${r}
+    # Delete the resource that does not exist/has been deleted should return error
+    ${error} =    Run Keyword And Expect Error    *    Delete Resource    ${iserver}    InCSE1/Contop1
+    Should Start with    ${error}    Cannot delete this resource [404]
+    #----------- Make sure cannot retrieve them -----------
+    Cannot Retrieve Error    InCSE1/Contop1
+    Cannot Retrieve Error    InCSE1/Contop1/Con1
+    Cannot Retrieve Error    InCSE1/Contop1/Con2
+    Cannot Retrieve Error    InCSE1/Contop1/Con3
+
+4.33 Delete Container with 1 child Container/1 contentInstance
+    [Documentation]    Delete Container with 1 child Container/1 contentInstance
+    ${attr} =    Set Variable    "cr":null,"mni":5,"mbs":15,"or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    InCSE1    ${rt_container}    ${attr}    Con1
+    ${con} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${attr} =    Set Variable    "cr":null,"mni":5,"mbs":15,"or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    ${con}    ${rt_container}    ${attr}    Con2
+    ${container} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"101"
+    ${r} =    Create Resource    ${iserver}    ${container}    ${rt_contentInstance}    ${attr}    conIn1
+    ${name} =    Name    ${r}
+    Response Is Correct    ${r}
+    # ----------- Delete the parent Container --------------
+    ${r} =    Delete Resource    ${iserver}    InCSE1/Con1
+    Response Is Correct    ${r}
+    # Delete the resource that does not exist/has been deleted should return error
+    ${error} =    Run Keyword And Expect Error    *    Delete Resource    ${iserver}    InCSE1/Con1
+    Should Start with    ${error}    Cannot delete this resource [404]
+    #----------- Make sure cannot retrieve all of them -----------
+    Cannot Retrieve Error    InCSE1/Con1
+    Cannot Retrieve Error    InCSE1/Con1/Con2
+    Cannot Retrieve Error    InCSE1/Con1/Con2/conIn1
+
+4.34 Delete Container with 1 child Container/3 contentInsntace
+    [Documentation]    Delete Container with 1 child Container/3 contentInsntace
+    ${attr} =    Set Variable    "cr":null,"mni":5,"mbs":15,"or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    InCSE1    ${rt_container}    ${attr}    Con1
+    ${con} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${attr} =    Set Variable    "cr":null,"mni":5,"mbs":15,"or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    ${con}    ${rt_container}    ${attr}    Con2
+    ${container} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"101"
+    ${r} =    Create Resource    ${iserver}    ${container}    ${rt_contentInstance}    ${attr}    conIn1
+    Response Is Correct    ${r}
+    ${r} =    Create Resource    ${iserver}    ${container}    ${rt_contentInstance}    ${attr}    conIn2
+    Response Is Correct    ${r}
+    ${r} =    Create Resource    ${iserver}    ${container}    ${rt_contentInstance}    ${attr}    conIn3
+    Response Is Correct    ${r}
+    # ----------- Delete the parent Container --------------
+    ${r} =    Delete Resource    ${iserver}    InCSE1/Con1
+    Response Is Correct    ${r}
+    # Delete the resource that does not exist/has been deleted should return error
+    ${error} =    Run Keyword And Expect Error    *    Delete Resource    ${iserver}    InCSE1/Con1
+    Should Start with    ${error}    Cannot delete this resource [404]
+    #----------- Make sure cannot retrieve all of them -----------
+    Cannot Retrieve Error    InCSE1/Con1
+    Cannot Retrieve Error    InCSE1/Con1/Con1/conIn2
+    Cannot Retrieve Error    InCSE1/Con1/Con2/conIn1
+    Cannot Retrieve Error    InCSE1/Con1/Con2/conIn2
+    Cannot Retrieve Error    InCSE1/Con1/Con2/conIn3
+
+4.35 Delete Container with 3 child Container/9 contentInstance
+    [Documentation]    Delete Container with 3 child Container/9 contentInstance
+    ${attr} =    Set Variable    "cr":null,"mni":5,"mbs":15,"or":"http://hey/you"
+    ${r} =    Create Resource    ${iserver}    InCSE1    ${rt_container}    ${attr}    Con1
+    ${con} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${r} =    Create Resource    ${iserver}    ${con}    ${rt_container}    ${attr}    Con2
+    ${container1} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${r} =    Create Resource    ${iserver}    ${con}    ${rt_container}    ${attr}    Con3
+    ${container2} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${r} =    Create Resource    ${iserver}    ${con}    ${rt_container}    ${attr}    Con4
+    ${container3} =    Name    ${r}
+    Response Is Correct    ${r}
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"101"
+    : FOR    ${conName}    IN    conIn1    conIn2    conIn3
+    \    ${r} =    Create Resource    ${iserver}    ${container1}    ${rt_contentInstance}    ${attr}
+    \    ...    ${conName}
+    \    Response Is Correct    ${r}
+    : FOR    ${conName}    IN    conIn1    conIn2    conIn3
+    \    ${r} =    Create Resource    ${iserver}    ${container2}    ${rt_contentInstance}    ${attr}
+    \    ...    ${conName}
+    \    Response Is Correct    ${r}
+    : FOR    ${conName}    IN    conIn1    conIn2    conIn3
+    \    ${r} =    Create Resource    ${iserver}    ${container3}    ${rt_contentInstance}    ${attr}
+    \    ...    ${conName}
+    \    Response Is Correct    ${r}
+    # ----------- Delete the parent Container --------------
+    ${r} =    Delete Resource    ${iserver}    InCSE1/Con1
+    Response Is Correct    ${r}
+    # Delete the resource that does not exist/has been deleted should return error
+    ${error} =    Run Keyword And Expect Error    *    Delete Resource    ${iserver}    InCSE1/Con1
+    Should Start with    ${error}    Cannot delete this resource [404]
+    #----------- Make sure cannot retrieve them -----------
+    Cannot Retrieve Error    InCSE1/Con1
+    Cannot Retrieve Error    InCSE1/Con1/Con2
+    Cannot Retrieve Error    InCSE1/Con1/Con3
+    Cannot Retrieve Error    InCSE1/Con1/Con4
+    Cannot Retrieve Error    InCSE1/Con1/Con2/conIn1
+    Cannot Retrieve Error    InCSE1/Con1/Con2/conIn2
+    Cannot Retrieve Error    InCSE1/Con1/Con2/conIn3
+    Cannot Retrieve Error    InCSE1/Con1/Con3/conIn1
+    Cannot Retrieve Error    InCSE1/Con1/Con3/conIn2
+    Cannot Retrieve Error    InCSE1/Con1/Con3/conIn3
+    Cannot Retrieve Error    InCSE1/Con1/Con4/conIn1
+    Cannot Retrieve Error    InCSE1/Con1/Con4/conIn2
+    Cannot Retrieve Error    InCSE1/Con1/Con4/conIn3
+
+*** Keywords ***
+Response Is Correct
+    [Arguments]    ${r}
+    ${status_code} =    Status Code    ${r}
+    Should Be True    199 < ${status_code} < 299
+    ${text} =    Text    ${r}
+    LOG    ${text}
+    ${json} =    Json    ${r}
+    LOG    ${json}
+
+Cannot Retrieve Error
+    [Arguments]    ${uri}
+    ${error} =    Run Keyword And Expect Error    *    Retrieve Resource    ${iserver}    ${uri}
+    Should Start with    ${error}    Cannot retrieve this resource [404]
diff --git a/test/csit/suites/iotdm/basic/080_FilterCriteriaTest.robot b/test/csit/suites/iotdm/basic/080_FilterCriteriaTest.robot
new file mode 100644 (file)
index 0000000..f93ee8b
--- /dev/null
@@ -0,0 +1,185 @@
+*** Settings ***
+Suite Setup       Connect And Create The Tree
+Suite Teardown    Kill The Tree    ${CONTROLLER}    InCSE1    admin    admin
+Library           ../../../libraries/criotdm.py
+Library           Collections
+
+*** Variables ***
+${httphost}       ${CONTROLLER}
+${httpuser}       admin
+${httppass}       admin
+${rt_ae}          2
+${rt_container}    3
+${rt_contentInstance}    4
+
+*** Test Cases ***
+Set Suite Variable
+    ${iserver} =    Connect To Iotdm    ${httphost}    ${httpuser}    ${httppass}    http
+    Set Suite Variable    ${iserver}
+    #==================================================
+    #    ResultContent(rcn) Test
+    #==================================================
+
+1.1 rcn is legal in create
+    [Documentation]    rcn=1, 2, 3, 0 is legal
+    ${attr} =    Set Variable    "aei":"ODL","api":"jb","apn":"jb2","or":"http://hey/you"
+    : FOR    ${rcn}    IN    \    1    2    3
+    ...    0
+    \    ${r} =    Create Resource With Command    ${iserver}    InCSE1    ${rt_ae}    rcn=${rcn}
+    \    ...    ${attr}
+    #add check reponse here in the next step, seperate them
+
+1.2 rcn is illegal in create
+    [Documentation]    rcn=4, 5, 6, 7 is illegal
+    ${attr} =    Set Variable    "aei":"ODL","api":"jb","apn":"jb2","or":"http://hey/you"
+    : FOR    ${rcn}    IN    4    5    6    7
+    \    ${error} =    Run Keyword And Expect Error    *    Create Resource With Command    ${iserver}    InCSE1
+    \    ...    ${rt_ae}    rcn=${rcn}    ${attr}
+    \    Should Start with    ${error}    Cannot create this resource [400]
+    \    Should Contain    ${error}    rcn
+
+2.1 rcn is legal in update
+    [Documentation]    rcn=1, 4, 0/ null is legal
+    ${attr} =    Set Variable    "or":"http://hey/you"
+    : FOR    ${rcn}    IN    \    0    1    4
+    \    ${r} =    Update Resource With Command    ${iserver}    InCSE1/AE1    ${rt_ae}    rcn=${rcn}
+    \    ...    ${attr}
+
+2.2 rcn is illegal in update
+    [Documentation]    rcn=2, 3, 5, 6, 7 is illegal
+    ${attr} =    Set Variable    "or":"http://hey/you"
+    : FOR    ${rcn}    IN    2    3    4    7
+    \    ${error} =    Run Keyword And Expect Error    *    Update Resource With Command    ${iserver}    InCSE1/AE1
+    \    ...    ${rt_ae}    rcn=${rcn}    ${attr}
+    \    Should Start with    ${error}    Cannot update this resource [400]
+    \    Should Contain    ${error}    rcn
+
+3.1 rcn is legal in retrieve
+    [Documentation]    rcn=1, 4, 5, 6 null is legal
+    : FOR    ${rcn}    IN    \    1    4    5
+    ...    6
+    \    ${r} =    Retrieve Resource With Command    ${iserver}    InCSE1/AE1    rcn=${rcn}
+    # when rcn=7 can be retrieved
+
+3.2 rcn is illegal in retrieve
+    [Documentation]    rcn=0, 2, 3 is illegal
+    : FOR    ${rcn}    IN    0    2    3
+    \    ${error} =    Run Keyword And Expect Error    *    Retrieve Resource With Command    ${iserver}    InCSE1/AE1
+    \    ...    rcn=${rcn}
+    \    Should Start with    ${error}    Cannot retrieve this resource [400]
+    \    Should Contain    ${error}    rcn
+
+4.2 rcn is illegal in delete
+    [Documentation]    rcn=4, 5, 6, 7 is illegal
+    ${attr} =    Set Variable    "or":"http://hey/you"
+    : FOR    ${rcn}    IN    2    3    4    5
+    ...    6    7
+    \    ${error} =    Run Keyword And Expect Error    *    Delete Resource With Command    ${iserver}    InCSE1/AE1
+    \    ...    rcn=${rcn}
+    \    Should Start with    ${error}    Cannot delete this resource [400]
+    \    Should Contain    ${error}    rcn
+
+Delete the tree
+    Kill The Tree    ${CONTROLLER}    InCSE1    admin    admin
+    #==================================================
+    #    FilterCriteria Test
+    #==================================================
+
+Create the tree
+    Connect And Create The Tree
+
+1. createdBefore
+    ${r} =    Retrieve Resource With Command    ${iserver}    InCSE1/AE1    rcn=4&crb=20160612T033748Z
+    ${count} =    Get Length    ${r.json()['ch']}
+    Should Be Equal As Integers    ${count}    2
+
+2. createdAfter
+    ${r} =    Retrieve Resource With Command    ${iserver}    InCSE1/AE1    rcn=4&cra=20150612T033748Z
+    ${count} =    Get Length    ${r.json()['ch']}
+    Should Be Equal As Integers    ${count}    2
+
+3. modifiedSince
+    ${r} =    Retrieve Resource With Command    ${iserver}    InCSE1/AE1    rcn=4&ms=20150612T033748Z
+    ${count} =    Get Length    ${r.json()['ch']}
+    Should Be Equal As Integers    ${count}    2
+
+4. unmodifiedSince
+    ${r} =    Retrieve Resource With Command    ${iserver}    InCSE1/AE1    rcn=4&us=20160612T033748Z
+    ${count} =    Get Length    ${r.json()['ch']}
+    Should Be Equal As Integers    ${count}    2
+
+5. stateTagSmaller
+    ${r} =    Retrieve Resource With Command    ${iserver}    InCSE1/Container3    rcn=4&sts=3
+    ${count} =    Get Length    ${r.json()['ch']}
+    ${s} =    Set Variable    ${r.json()['ch']}
+    Should Be Equal As Integers    ${count}    5
+
+6. stateTagBigger
+    ${r} =    Retrieve Resource With Command    ${iserver}    InCSE1/Container3    rcn=4&stb=1
+    ${count} =    Get Length    ${r.json()['ch']}
+    Should Be Equal As Integers    ${count}    2
+    # 7. expireBefore
+    # 8. expireAfter
+
+9. labels
+    ${r} =    Retrieve Resource With Command    ${iserver}    InCSE1/Container3    rcn=4&sts=3&lbl=contentInstanceUnderContainerContainer
+    ${count} =    Get Length    ${r.json()['ch']}
+    Should Be Equal As Integers    ${count}    2
+    # 2 labels test
+
+10. resourceType
+    ${r} =    Retrieve Resource With Command    ${iserver}    InCSE1    rcn=4&rty=3
+    ${count} =    Get Length    ${r.json()['ch']}
+    Should Be Equal As Integers    ${count}    3
+
+11. sizeAbove
+    ${r} =    Retrieve Resource With Command    ${iserver}    InCSE1    rcn=4&rty=3&sza=5
+    ${count} =    Get Length    ${r.json()['ch']}
+    Should Be Equal As Integers    ${count}    2
+
+12. sizeBelow
+    ${r} =    Retrieve Resource With Command    ${iserver}    InCSE1    rcn=4&rty=3&szb=5
+    ${count} =    Get Length    ${r.json()['ch']}
+    Should Be Equal As Integers    ${count}    1
+    # 13. contentType
+    # 14. limit
+    #    ${r} =    Retrieve Resource With Command    ${iserver}    InCSE1    rcn=4&rty=3&lim=2
+    #    ${count} =    Get Length    ${r.json()['ch']}
+    #    Should Be Equal As Integers    ${count}    2
+    #15. attribute
+    #16. filterUsage
+    # different conditions shall use the "AND" logical operation;
+    # same conditions shall use the "OR" logical operation.
+
+*** Keywords ***
+Connect And Create The Tree
+    [Documentation]    Create a tree that contain AE/ container / contentInstance in different layers
+    ${iserver} =    Connect To Iotdm    ${httphost}    ${httpuser}    ${httppass}    http
+    ${attr} =    Set Variable    "aei":"ODL","api":"jb","apn":"jb2","or":"http://hey/you"
+    Create Resource    ${iserver}    InCSE1    ${rt_ae}    ${attr}    AE1
+    Create Resource    ${iserver}    InCSE1    ${rt_ae}    ${attr}    AE2
+    Create Resource    ${iserver}    InCSE1    ${rt_ae}    ${attr}    AE3
+    ${attr} =    Set Variable
+    Create Resource    ${iserver}    InCSE1/AE1    ${rt_container}    ${attr}    Container1
+    Create Resource    ${iserver}    InCSE1/AE1    ${rt_container}    ${attr}    Container2
+    ${attr} =    Set Variable    "cr":null,"mni":5,"mbs":150,"or":"http://hey/you","lbl":["underCSE"]
+    Create Resource    ${iserver}    InCSE1    ${rt_container}    ${attr}    Container3
+    Create Resource    ${iserver}    InCSE1    ${rt_container}    ${attr}    Container4
+    Create Resource    ${iserver}    InCSE1    ${rt_container}    ${attr}    Container5
+    ${attr} =    Set Variable    "cr":null,"mni":5,"mbs":150,"or":"http://hey/you","lbl":["underAEContainer"]
+    Create Resource    ${iserver}    InCSE1/AE1/Container1    ${rt_container}    ${attr}    Container6
+    ${attr} =    Set Variable    "cr":null,"mni":5,"mbs":150,"or":"http://hey/you","lbl":["underCSEContainer"]
+    Create Resource    ${iserver}    InCSE1/Container3    ${rt_container}    ${attr}    Container7
+    Create Resource    ${iserver}    InCSE1/Container3    ${rt_container}    ${attr}    Container8
+    Create Resource    ${iserver}    InCSE1/Container3    ${rt_container}    ${attr}    Container9
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"102","lbl":["contentInstanceUnderAEContainer"]
+    Create Resource    ${iserver}    InCSE1/AE1/Container1    ${rt_contentInstance}    ${attr}    conIn1
+    Create Resource    ${iserver}    InCSE1/AE1/Container1    ${rt_contentInstance}    ${attr}    conIn2
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"102","lbl":["contentInstanceUnderContainerContainer"]
+    Create Resource    ${iserver}    InCSE1/Container3    ${rt_contentInstance}    ${attr}    conIn3
+    Create Resource    ${iserver}    InCSE1/Container3    ${rt_contentInstance}    ${attr}    conIn4
+    Create Resource    ${iserver}    InCSE1/Container3    ${rt_contentInstance}    ${attr}    conIn5
+    ${attr} =    Set Variable    "cnf": "1","or": "http://hey/you","con":"102","lbl":["contentInstanceUnderContainer"]
+    Create Resource    ${iserver}    InCSE1/Container4    ${rt_contentInstance}    ${attr}    conIn6
+    Create Resource    ${iserver}    InCSE1/Container4    ${rt_contentInstance}    ${attr}    conIn7
+    Create Resource    ${iserver}    InCSE1/Container4    ${rt_contentInstance}    ${attr}    conIn8