Beispiel #1
0
class Start(opencog.cogserver.Request):
    """
    Implements a CogServer Module to load upon startup that will load the REST
    API defined in apimain.py

    See examples @ github.com/opencog/opencog/tree/master/examples/restapi
    """

    summary = "Start the OpenCog REST API"
    description = "Usage: restapi.Start\n\nStarts the OpenCog REST API. " \
                  "This will provide a REST interface to the Atomspace,\n" \
                  "allowing you to create, read, update and delete atoms " \
                  "across the network using\nHTTP requests/responses with " \
                  "JSON-formatted data.\n\nDefault endpoint: " \
                  "http://127.0.0.1:5000/api/v1.1/\nExample request: " \
                  "http://127.0.0.1:5000/api/v1.1/atoms?type=ConceptNode"

    def __init__(self):
        self.atomspace = None  # Will be passed as argument in run method

    def run(self, args, atomspace):
        self.atomspace = atomspace
        '''
        make a daemon thread so that it can be interrupted
        '''
        thread = Thread(target=self.invoke)
        thread.setDaemon(True)
        thread.start()
        print "REST API is now running in a separate daemon thread."

    def invoke(self):
        self.api = RESTAPI(self.atomspace)
        self.api.run(host=IP_ADDRESS, port=PORT)
Beispiel #2
0
    def setUp(self):
        self.uri = '/api/v1.1/'
        self.headers = {'content-type': 'application/json'}

        # Populate a test AtomSpace
        self.atomspace = AtomSpace()
        self.animal = self.atomspace.add_node(
            types.ConceptNode, 'animal', TruthValue(.1, 0.0011860914528369904))
        self.bird = self.atomspace.add_node(
            types.ConceptNode, 'bird', TruthValue(.01, 0.0011237357975915074))
        self.swan = self.atomspace.add_node(
            types.ConceptNode, 'swan', TruthValue(.001, 0.0011237357975915074))
        self.frog = self.atomspace.add_node(
            types.ConceptNode, 'frog', TruthValue(.001, 0.7142857313156128))
        self.swan_bird = self.atomspace.add_link(
            types.InheritanceLink, [self.swan, self.bird],
            TruthValue(1, 0.0011237357975915074))
        self.bird_animal = self.atomspace.add_link(
            types.InheritanceLink, [self.bird, self.animal],
            TruthValue(1, 0.0011237357975915074))
        self.bird.sti = 9
        self.swan.sti = 9

        self.api = RESTAPI(self.atomspace)
        self.client = self.api.test()
Beispiel #3
0
    def setUp(self):
        self.uri = '/api/v1.1/'
        self.headers = {'content-type': 'application/json'}

        # Populate a test AtomSpace
        self.atomspace = AtomSpace()
        self.animal = self.atomspace.add_node(types.ConceptNode, 'animal',
                                              TruthValue(.1, .95))
        self.bird = self.atomspace.add_node(types.ConceptNode, 'bird',
                                            TruthValue(.01, .9))
        self.swan = self.atomspace.add_node(types.ConceptNode, 'swan',
                                            TruthValue(.001, .9))
        self.frog = self.atomspace.add_node(types.ConceptNode, 'frog',
                                            TruthValue(.001, 2000))
        self.swan_bird = self.atomspace.add_link(types.InheritanceLink,
                                                 [self.swan, self.bird],
                                                 TruthValue(1, .9))
        self.bird_animal = self.atomspace.add_link(types.InheritanceLink,
                                                   [self.bird, self.animal],
                                                   TruthValue(1, .9))
        self.bird.av = {'sti': 9}
        self.swan.av = {'sti': 9}

        self.api = RESTAPI(self.atomspace)
        self.client = self.api.test()
Beispiel #4
0
class Start(opencog.cogserver.Request):
    """
    Implements a CogServer Module to load upon startup that will load the REST
    API defined in apimain.py

    Prerequisites:
        1) Requires installation of the Python dependencies by running:
            sudo ./install_dependencies.sh

        2) Requires the configuration file (opencog.conf) to contain the
           following parameters:
            - PYTHON_EXTENSION_DIRS must specify the relative location of the
              API scripts
                Example: PYTHON_EXTENSION_DIRS = ../opencog/python/web/api
            - PYTHON_PRELOAD must specify the restapi module
                Example: PYTHON_PRELOAD = restapi

    To start the REST API, type restapi.Start at the CogServer shell
    """

    summary = "Start the OpenCog REST API"
    description = "Usage: restapi.Start\n\nStarts the OpenCog REST API. " \
                  "This will provide a REST interface to the Atomspace,\n" \
                  "allowing you to create, read, update and delete atoms " \
                  "across the network using\nHTTP requests/responses with " \
                  "JSON-formatted data.\n\nDefault endpoint: " \
                  "http://127.0.0.1:5000/api/v1.1/\nExample request: " \
                  "http://127.0.0.1:5000/api/v1.1/atoms?type=ConceptNode"

    def __init__(self):
        self.process = Process(target=self.invoke)
        self.atomspace = None  # Will be passed as argument in run method

    def run(self, args, atomspace):
        """
        Loads the REST API into a separate process and invokes it, so that it
        will continue serving requests in the background after the Request
        that loads it has returned control to the CogServer
        """
        self.atomspace = atomspace

        '''
        By using multiprocessing and setting the daemon attribute of the
        process serving background REST API requests to True, when the
        parent process exits, it will attempt to terminate the daemonic
        child process (https://docs.python.org/2/library/multiprocessing.html#multiprocessing.Process.daemon)
        '''
        self.process.daemon = True
        self.process.start()

        print "REST API is now running in a separate process."

    def invoke(self):
        self.api = RESTAPI(self.atomspace)
        self.api.run(host=IP_ADDRESS, port=PORT)
Beispiel #5
0
class Start(opencog.cogserver.Request):
    """
    Implements a CogServer Module to load upon startup that will load the REST
    API defined in apimain.py

    Prerequisites:
        1) Requires installation of the Python dependencies by running:
            sudo ./install_dependencies.sh

        2) Requires the configuration file (opencog.conf) to contain the
           following parameters:
            - PYTHON_EXTENSION_DIRS must specify the relative location of the
              API scripts
                Example: PYTHON_EXTENSION_DIRS = ../opencog/python/web/api
            - PYTHON_PRELOAD must specify the restapi module
                Example: PYTHON_PRELOAD = restapi

    To start the REST API, type restapi.Start at the CogServer shell
    """

    summary = "Start the OpenCog REST API"
    description = "Usage: restapi.Start\n\nStarts the OpenCog REST API. " \
                  "This will provide a REST interface to the Atomspace,\n" \
                  "allowing you to create, read, update and delete atoms " \
                  "across the network using\nHTTP requests/responses with " \
                  "JSON-formatted data.\n\nDefault endpoint: " \
                  "http://127.0.0.1:5000/api/v1.1/\nExample request: " \
                  "http://127.0.0.1:5000/api/v1.1/atoms?type=ConceptNode"

    def __init__(self):
        self.process = Process(target=self.invoke)
        self.atomspace = None  # Will be passed as argument in run method

    def run(self, args, atomspace):
        """
        Loads the REST API into a separate process and invokes it, so that it
        will continue serving requests in the background after the Request
        that loads it has returned control to the CogServer
        """
        self.atomspace = atomspace
        '''
        By using multiprocessing and setting the daemon attribute of the
        process serving background REST API requests to True, when the
        parent process exits, it will attempt to terminate the daemonic
        child process (https://docs.python.org/2/library/multiprocessing.html#multiprocessing.Process.daemon)
        '''
        self.process.daemon = True
        self.process.start()

        print "REST API is now running in a separate process."

    def invoke(self):
        self.api = RESTAPI(self.atomspace)
        self.api.run(host=IP_ADDRESS, port=PORT)
Beispiel #6
0
    def invoke(self):
        self.api = RESTAPI(self.atomspace)

        # OK, so if the remote end closes the pipe, we get a SIGPIPE
        # error, and the server dies.  So just restart the server in
        # that situation. See bug opencog/ros-behavior-scripting/issues/108
        try_again = True
        while try_again:
            try_again = False
            try:
                self.api.run(host=IP_ADDRESS, port=PORT)
            except socket.error, e:
                try_again = True
Beispiel #7
0
class Start(opencog.cogserver.Request):
    """
    Implements a CogServer Module to load upon startup that will load the REST
    API defined in apimain.py

    Prerequisites:
        1) Requires installation of the Python dependencies by running:
            sudo ./install_dependencies.sh

        2) Requires the configuration file (opencog.conf) to contain the
           following parameters:
            - PYTHON_EXTENSION_DIRS must specify the relative location of the
              API scripts
                Example: PYTHON_EXTENSION_DIRS = ../opencog/python/web/api
            - PYTHON_PRELOAD must specify the restapi module
                Example: PYTHON_PRELOAD = restapi

    To start the REST API, type restapi.Start at the CogServer shell
    """

    summary = "Start the OpenCog REST API"
    description = "Usage: restapi.Start\n\nStarts the OpenCog REST API. " \
                  "This will provide a REST interface to the Atomspace,\n" \
                  "allowing you to create, read, update and delete atoms " \
                  "across the network using\nHTTP requests/responses with " \
                  "JSON-formatted data.\n\nDefault endpoint: " \
                  "http://127.0.0.1:5000/api/v1.1/\nExample request: " \
                  "http://127.0.0.1:5000/api/v1.1/atoms?type=ConceptNode"

    def __init__(self):
        self.atomspace = None  # Will be passed as argument in run method

    def run(self, args, atomspace):        
        self.atomspace = atomspace
        '''
        make a daemon thread so that it can be interrupted
        '''
        thread = Thread(target=self.invoke)
        thread.setDaemon(True)
        thread.start()
        print "REST API is now running in a separate daemon thread."        

    def invoke(self):
        self.api = RESTAPI(self.atomspace)
        self.api.run(host=IP_ADDRESS, port=PORT)
Beispiel #8
0
class Start(opencog.cogserver.Request):
    """
    Implements a CogServer Module to load upon startup that will load the REST
    API defined in apimain.py

    Prerequisites:
        1) Requires installation of the Python dependencies by running:
            sudo ./install_dependencies.sh

        2) Requires the configuration file (opencog.conf) to contain the
           following parameters:
            - PYTHON_EXTENSION_DIRS must specify the relative location of the
              API scripts
                Example: PYTHON_EXTENSION_DIRS = ../opencog/python/web/api
            - PYTHON_PRELOAD must specify the restapi module
                Example: PYTHON_PRELOAD = restapi

    To start the REST API, type restapi.Start at the CogServer shell
    """

    summary = "Start the OpenCog REST API"
    description = "Usage: restapi.Start\n\nStarts the OpenCog REST API. " \
                  "This will provide a REST interface to the Atomspace,\n" \
                  "allowing you to create, read, update and delete atoms " \
                  "across the network using\nHTTP requests/responses with " \
                  "JSON-formatted data.\n\nDefault endpoint: " \
                  "http://127.0.0.1:5000/api/v1.1/\nExample request: " \
                  "http://127.0.0.1:5000/api/v1.1/atoms?type=ConceptNode"

    def __init__(self):
        self.atomspace = None  # Will be passed as argument in run method

    def run(self, args, atomspace):
        self.atomspace = atomspace
        '''
        make a daemon thread so that it can be interrupted
        '''
        thread = Thread(target=self.invoke)
        thread.setDaemon(True)
        thread.start()
        print "REST API is now running in a separate daemon thread."

    def invoke(self):
        self.api = RESTAPI(self.atomspace)
        self.api.run(host=IP_ADDRESS, port=PORT)
Beispiel #9
0
	def run (self):

		atomspace=AtomSpace()
		scheme_clear=\
			"""
			(clear)
			"""
		scheme_code=\
				"""
				(load-scm-from-file "/home/mahlet/webCodes/moses_result.scm")
				"""
		scheme_eval(atomspace,scheme_clear)
		scheme_eval(atomspace,scheme_code)

		#start the REST API
		IP_ADDRESS = '0.0.0.0'
		PORT = 5000
		api = RESTAPI(atomspace)
		api.run(host=IP_ADDRESS, port=PORT)
Beispiel #10
0
class Start(opencog.cogserver.Request):
    """
    Implements a CogServer Module to load upon startup that will load the REST
    API defined in apimain.py

    See examples @ github.com/opencog/opencog/tree/master/examples/restapi
    """

    summary = "Start the OpenCog REST API"
    description = "Usage: restapi.Start\n\nStarts the OpenCog REST API. " \
                  "This will provide a REST interface to the Atomspace,\n" \
                  "allowing you to create, read, update and delete atoms " \
                  "across the network using\nHTTP requests/responses with " \
                  "JSON-formatted data.\n\nDefault endpoint: " \
                  "http://127.0.0.1:5000/api/v1.1/\nExample request: " \
                  "http://127.0.0.1:5000/api/v1.1/atoms?type=ConceptNode"

    def __init__(self):
        self.atomspace = None  # Will be passed as argument in run method

    def run(self, args, atomspace):
        self.atomspace = atomspace
        '''
        make a daemon thread so that it can be interrupted
        '''
        thread = Thread(target=self.invoke)
        thread.setDaemon(True)
        thread.start()
        print "REST API is now running in a separate daemon thread."

    def invoke(self):
        self.api = RESTAPI(self.atomspace)

        # OK, so if the remote end closes the pipe, we get a SIGPIPE
        # error, and the server dies.  So just restart the server in
        # that situation. See bug opencog/ros-behavior-scripting/issues/108
        try_again = True
        while try_again:
            try_again = False
            try:
                self.api.run(host=IP_ADDRESS, port=PORT)
            except socket.error, e:
                try_again = True
Beispiel #11
0
    def run(self):

        atomspace = AtomSpace()
        scheme_clear=\
         """
			(clear)
			"""
        scheme_code=\
          """
				(load-scm-from-file "/home/mahlet/webCodes/moses_result.scm")
				"""
        scheme_eval(atomspace, scheme_clear)
        scheme_eval(atomspace, scheme_code)

        #start the REST API
        IP_ADDRESS = '0.0.0.0'
        PORT = 5000
        api = RESTAPI(atomspace)
        api.run(host=IP_ADDRESS, port=PORT)
Beispiel #12
0
class Start(opencog.cogserver.Request):
    """
    Implements a CogServer Module to load upon startup that will load the REST API defined in apimain.py

    Prerequisites:
        1) Requires installation of the Python dependencies by running:
            sudo ./install_dependencies.sh

        2) Requires the configuration file (opencog.conf) to contain the following parameters:
            - PYTHON_EXTENSION_DIRS must specify the relative location of the API scripts
                Example: PYTHON_EXTENSION_DIRS = ../opencog/python/web/api
            - PYTHON_PRELOAD must specify the restapi module
                Example: PYTHON_PRELOAD = restapi

    To start the REST API, type restapi.Start at the CogServer shell
    """

    summary = "Start the OpenCog REST API"
    description = "Usage: restapi.Start\n\n" \
    "Starts the OpenCog REST API. This will provide a REST interface to the Atomspace,\n" \
    "allowing you to create, read, update and delete atoms across the network using\n" \
    "HTTP requests/responses with JSON-formatted data.\n\n" \
    "Default endpoint: http://127.0.0.1:5000/api/v1.0/\n" \
    "Example request: http://127.0.0.1:5000/api/v1.0/atoms?type=ConceptNode"

    def run(self, args, atomspace):
        """
        Loads the REST API into a separate thread and invokes it, so that it will continue serving requests in the
        background after the Request that loads it has returned control to the CogServer
        """
        self.atomspace = atomspace
        thread = Thread(target=self.invoke)
        thread.start()
        print "REST API is now running in a separate thread."
        # @todo: detect Control-C to end the thread

    def invoke(self):
        self.api = RESTAPI(self.atomspace)
        self.api.run(host=IP_ADDRESS, port=PORT)
    def setUp(self):
        self.uri = '/api/v1.0/'
        self.headers = {'content-type': 'application/json'}

        # Populate a test AtomSpace
        self.atomspace = AtomSpace()
        self.animal = self.atomspace.add_node(types.ConceptNode, 'animal', TruthValue(.1, .9))
        self.bird = self.atomspace.add_node(types.ConceptNode, 'bird', TruthValue(.01, .9))
        self.swan = self.atomspace.add_node(types.ConceptNode, 'swan', TruthValue(.001, .9))
        self.swan_bird = self.atomspace.add_link(types.InheritanceLink, [self.swan, self.bird], TruthValue(1, .9))
        self.bird_animal = self.atomspace.add_link(types.InheritanceLink, [self.bird, self.animal], TruthValue(1, .9))
        self.bird.av = {'sti': 9}

        self.api = RESTAPI(self.atomspace)
        self.client = self.api.test()
Beispiel #14
0
    def setUp(self):
        self.uri = '/api/v1.1/'
        self.headers = {'content-type': 'application/json'}

        # Populate a test AtomSpace
        self.atomspace = AtomSpace()
        self.animal = self.atomspace.add_node(
            types.ConceptNode, 'animal', TruthValue(.1, 0.0011860914528369904))
        self.bird = self.atomspace.add_node(
            types.ConceptNode, 'bird', TruthValue(.01, 0.0011237357975915074))
        self.swan = self.atomspace.add_node(
            types.ConceptNode, 'swan', TruthValue(.001, 0.0011237357975915074))
        self.frog = self.atomspace.add_node(
            types.ConceptNode, 'frog', TruthValue(.001, 0.7142857313156128))
        self.swan_bird = self.atomspace.add_link(
            types.InheritanceLink, [self.swan, self.bird], TruthValue(1, 0.0011237357975915074))
        self.bird_animal = self.atomspace.add_link(
            types.InheritanceLink, [self.bird, self.animal], TruthValue(1, 0.0011237357975915074))
        self.bird.sti = 9
        self.swan.sti = 9

        self.api = RESTAPI(self.atomspace)
        self.client = self.api.test()
class TestRESTApi():
    """
    Unit tests for the OpenCog REST API.

    See: opencog/python/web/api/apimain.py for the class definitions
    Documentation: http://wiki.opencog.org/w/REST_API
    """

    def setUp(self):
        self.uri = '/api/v1.0/'
        self.headers = {'content-type': 'application/json'}

        # Populate a test AtomSpace
        self.atomspace = AtomSpace()
        self.animal = self.atomspace.add_node(types.ConceptNode, 'animal', TruthValue(.1, .9))
        self.bird = self.atomspace.add_node(types.ConceptNode, 'bird', TruthValue(.01, .9))
        self.swan = self.atomspace.add_node(types.ConceptNode, 'swan', TruthValue(.001, .9))
        self.swan_bird = self.atomspace.add_link(types.InheritanceLink, [self.swan, self.bird], TruthValue(1, .9))
        self.bird_animal = self.atomspace.add_link(types.InheritanceLink, [self.bird, self.animal], TruthValue(1, .9))
        self.bird.av = {'sti': 9}

        self.api = RESTAPI(self.atomspace)
        self.client = self.api.test()

    def tearDown(self):
        del self.api
        del self.client

    def test_post_and_get_node(self):
        # Create a test node
        truthvalue = {'type': 'simple', 'details': {'strength': 0.08, 'count': 0.2}}
        atom = {'type': 'ConceptNode', 'name': 'giant_frog', 'truthvalue': truthvalue}

        post_response = self.client.post(self.uri + 'atoms', data=json.dumps(atom), headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']

        # Verify values returned by the POST request
        assert post_result['type'] == atom['type']
        assert post_result['name'] == atom['name']
        assert post_result['truthvalue']['type'] == truthvalue['type']
        assert_almost_equals(
            float(post_result['truthvalue']['details']['strength']), truthvalue['details']['strength'], places=5)
        assert_almost_equals(
            float(post_result['truthvalue']['details']['count']), truthvalue['details']['count'], places=5)

        # Compare to the values created in the AtomSpace
        atomspace_result = self.atomspace[Handle(post_result['handle'])]
        assert Handle(post_result['handle']) == atomspace_result.h
        assert post_result['name'] == atomspace_result.name
        assert types.__dict__.get(post_result['type']) == atomspace_result.type
        assert TruthValue(float(post_result['truthvalue']['details']['strength']),
                          float(post_result['truthvalue']['details']['count'])) == atomspace_result.tv

        # Get by handle and compare
        handle = post_result['handle']
        get_response_handle = self.client.get(self.uri + 'atoms/' + str(handle))
        get_result_handle = json.loads(get_response_handle.data)['atoms']
        assert post_result == get_result_handle

        # Get by name and compare
        name = post_result['name']
        get_response_name = self.client.get(self.uri + 'atoms?name=' + name)
        get_result_name = json.loads(get_response_name.data)['result']['atoms'][0]
        assert post_result == get_result_name

        # Get by name and type and compare
        type = post_result['type']
        get_response_name_type = self.client.get(self.uri + 'atoms?name=' + name + '&type=' + type)
        get_result_name_type = json.loads(get_response_name_type.data)['result']['atoms'][0]
        assert post_result == get_result_name_type

    def test_post_and_get_link(self):
        # Create a test link between swan and animal
        truthvalue = {'type': 'simple', 'details': {'strength': 0.5, 'count': 0.4}}
        atom = {'type': 'InheritanceLink', 'truthvalue': truthvalue, 'outgoing':
            [self.swan.h.value(), self.animal.h.value()]}

        post_response = self.client.post(self.uri + 'atoms', data=json.dumps(atom), headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']

        # Verify values returned by the POST request
        assert post_result['type'] == atom['type']
        assert post_result['truthvalue']['type'] == truthvalue['type']
        assert_almost_equals(
            float(post_result['truthvalue']['details']['strength']), truthvalue['details']['strength'], places=5)
        assert_almost_equals(
            float(post_result['truthvalue']['details']['count']), truthvalue['details']['count'], places=5)
        assert self.swan.h.value() in post_result['outgoing']
        assert self.animal.h.value() in post_result['outgoing']

        # Compare to the values created in the AtomSpace
        atomspace_result = self.atomspace[Handle(post_result['handle'])]
        assert Handle(post_result['handle']) == atomspace_result.h
        assert types.__dict__.get(post_result['type']) == atomspace_result.type
        assert TruthValue(float(post_result['truthvalue']['details']['strength']),
                          float(post_result['truthvalue']['details']['count'])) == atomspace_result.tv

        # Get by handle and compare
        handle = post_result['handle']
        get_response_handle = self.client.get(self.uri + 'atoms/' + str(handle))
        get_result_handle = json.loads(get_response_handle.data)['atoms']
        assert post_result == get_result_handle

        # Check if the link is in the incoming set of each of the nodes
        for h in post_result['outgoing']:
            assert Handle(post_result['handle']) in [atom.h for atom in self.atomspace[Handle(h)].incoming]

    def test_put_and_get_tv_av_node(self):
        atom = self.swan
        truthvalue = {'type': 'simple', 'details': {'strength': 0.005, 'count': 0.8}}
        attentionvalue = {'sti': 9, 'lti': 2, 'vlti': True}
        atom_update = {'truthvalue': truthvalue, 'attentionvalue': attentionvalue}
        put_response = self.client.put(self.uri + 'atoms/' + str(atom.h.value()), data=json.dumps(atom_update), headers=self.headers)
        put_result = json.loads(put_response.data)['atoms']

        # Verify values returned by the PUT request
        assert put_result['handle'] == atom.h.value()
        assert_almost_equals(
            float(put_result['truthvalue']['details']['strength']), truthvalue['details']['strength'], places=5)
        assert_almost_equals(
            float(put_result['truthvalue']['details']['count']), truthvalue['details']['count'], places=5)
        assert put_result['attentionvalue']['sti'] == attentionvalue['sti']
        assert put_result['attentionvalue']['lti'] == attentionvalue['lti']
        assert put_result['attentionvalue']['vlti'] == attentionvalue['vlti']

        # Compare to the values updated in the AtomSpace
        atomspace_result = self.atomspace[Handle(put_result['handle'])]
        assert Handle(put_result['handle']) == atomspace_result.h
        assert types.__dict__.get(put_result['type']) == atomspace_result.type
        assert TruthValue(float(put_result['truthvalue']['details']['strength']),
                          float(put_result['truthvalue']['details']['count'])) == atomspace_result.tv
        assert put_result['attentionvalue'] == atomspace_result.av

        # Get by handle and compare
        get_response = self.client.get(self.uri + 'atoms/' + str(atom.h.value()))
        get_result = json.loads(get_response.data)['atoms']
        assert put_result == get_result

    def test_put_and_get_tv_av_link(self):
        atom = self.bird_animal
        truthvalue = {'type': 'simple', 'details': {'strength': 0.9, 'count': 0.95}}
        attentionvalue = {'sti': 6, 'lti': 3, 'vlti': True}
        atom_update = {'truthvalue': truthvalue, 'attentionvalue': attentionvalue}
        put_response =\
            self.client.put(self.uri + 'atoms/' + str(atom.h.value()), data=json.dumps(atom_update), headers=self.headers)
        put_result = json.loads(put_response.data)['atoms']

        # Verify values returned by the PUT request
        assert put_result['handle'] == atom.h.value()
        assert_almost_equals(
            float(put_result['truthvalue']['details']['strength']), truthvalue['details']['strength'], places=5)
        assert_almost_equals(
            float(put_result['truthvalue']['details']['count']), truthvalue['details']['count'], places=5)
        assert put_result['attentionvalue']['sti'] == attentionvalue['sti']
        assert put_result['attentionvalue']['lti'] == attentionvalue['lti']
        assert put_result['attentionvalue']['vlti'] == attentionvalue['vlti']

        # Compare to the values updated in the AtomSpace
        atomspace_result = self.atomspace[Handle(put_result['handle'])]
        assert Handle(put_result['handle']) == atomspace_result.h
        assert types.__dict__.get(put_result['type']) == atomspace_result.type
        assert TruthValue(float(put_result['truthvalue']['details']['strength']),
                          float(put_result['truthvalue']['details']['count'])) == atomspace_result.tv
        assert put_result['attentionvalue'] == atomspace_result.av

        # Get by handle and compare
        get_response = self.client.get(self.uri + 'atoms/' + str(atom.h.value()))
        get_result = json.loads(get_response.data)['atoms']
        assert put_result == get_result

    def test_post_revise_existing_node(self):
        # Attempt to create a node, where a node already exists with that name and type. Should revise existing node.
        existing_atom = self.bird

        truthvalue = {'type': 'simple', 'details': {'strength': 0.1, 'count': 0.95}}
        atom = {'type': 'ConceptNode', 'name': 'bird', 'truthvalue': truthvalue}

        post_response = self.client.post(self.uri + 'atoms', data=json.dumps(atom), headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']

        # Verify values returned by the POST request
        assert_almost_equals(
            float(post_result['truthvalue']['details']['strength']), truthvalue['details']['strength'], places=5)
        assert_almost_equals(
            float(post_result['truthvalue']['details']['count']), truthvalue['details']['count'], places=5)

        # Compare to the values updated in the AtomSpace
        assert post_result['handle'] == existing_atom.h.value()
        assert TruthValue(float(post_result['truthvalue']['details']['strength']),
                          float(post_result['truthvalue']['details']['count'])) == existing_atom.tv

    def test_post_revise_existing_link(self):
        # Attempt to create a link, where a link already exists with that name and outgoing set.
        # Should revise existing link.
        existing_atom = self.bird_animal
        truthvalue = {'type': 'simple', 'details': {'strength': 0.1, 'count': 0.95}}
        outgoing = [a.h.value() for a in existing_atom.out]
        atom = {'type': 'InheritanceLink', 'truthvalue': truthvalue, 'outgoing': outgoing}

        post_response = self.client.post(self.uri + 'atoms', data=json.dumps(atom), headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']

        # Verify values returned by the POST request
        assert post_result['outgoing'] == outgoing
        assert_almost_equals(
            float(post_result['truthvalue']['details']['strength']), truthvalue['details']['strength'], places=5)
        assert_almost_equals(
            float(post_result['truthvalue']['details']['count']), truthvalue['details']['count'], places=5)

        # Compare to the values updated in the AtomSpace
        assert post_result['handle'] == existing_atom.h.value()
        assert TruthValue(float(post_result['truthvalue']['details']['strength']),
                          float(post_result['truthvalue']['details']['count'])) == existing_atom.tv

    @raises(IndexError)
    def test_delete_node(self):
        atom = self.swan
        handle = atom.h.value()
        get_response = self.client.get(self.uri + 'atoms/' + str(handle))
        get_result = json.loads(get_response.data)['atoms']

        delete_response = self.client.delete(self.uri + 'atoms/' + str(atom.h.value()))
        delete_result = json.loads(delete_response.data)['result']

        assert delete_result['success']
        assert delete_result['handle'] == get_result['handle']

        # Confirm the atom isn't contained in the AtomSpace anymore
        assert_raises(self.atomspace[atom.h], IndexError)

    @raises(IndexError)
    def test_delete_link(self):
        atom = self.bird_animal
        handle = atom.h.value()
        get_response = self.client.get(self.uri + 'atoms/' + str(handle))
        get_result = json.loads(get_response.data)['atoms']

        delete_response = self.client.delete(self.uri + 'atoms/' + str(atom.h.value()))
        delete_result = json.loads(delete_response.data)['result']

        assert delete_result['success']
        assert delete_result['handle'] == get_result['handle']

        # Confirm the atom isn't contained in the AtomSpace anymore
        assert_raises(self.atomspace[atom.h], IndexError)

    def test_get_atoms_by_av(self):
        # Assign some STI values
        self.atomspace.set_av(h=self.bird.h, sti=9)
        self.atomspace.set_av(h=self.swan.h, sti=20)
        self.atomspace.set_av(h=self.bird_animal.h, sti=15)
        self.atomspace.set_av(h=self.animal.h, sti=0)

        get_response = self.client.get(self.uri + 'atoms?filterby=attentionalfocus')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 3
        assert set([atom['handle'] for atom in get_result]) == set([self.bird.h.value(), self.swan.h.value(), self.bird_animal.h.value()])

        get_response = self.client.get(self.uri + 'atoms?filterby=stirange&stimin=15')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 2
        assert set([atom['handle'] for atom in get_result]) == set([self.swan.h.value(), self.bird_animal.h.value()])

        get_response = self.client.get(self.uri + 'atoms?filterby=stirange&stimin=15&stimax=18')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 1
        assert set([atom['handle'] for atom in get_result]) == set([self.bird_animal.h.value()])
Beispiel #16
0
 def invoke(self):
     self.api = RESTAPI(self.atomspace)
     self.api.run(host=IP_ADDRESS, port=PORT)
from web.api.apimain import RESTAPI
from opencog.atomspace import AtomSpace, types
from opencog.utilities import initialize_opencog
from opencog.type_constructors import *

# Endpoint configuration
# To allow public access, set to 0.0.0.0; for local access, set to 127.0.0.1
IP_ADDRESS = '0.0.0.0'
PORT = 5000

atomspace = AtomSpace()
initialize_opencog(atomspace)

Link(ConceptNode("Test Concept"), ConceptNode("another one"))

api = RESTAPI(atomspace)
api.run(host=IP_ADDRESS, port=PORT)
Beispiel #18
0
class TestRESTApi():
    """
    Unit tests for the OpenCog REST API.

    See: opencog/python/web/api/apimain.py for the class definitions
    Documentation: http://wiki.opencog.org/w/REST_API
    """
    def setUp(self):
        self.uri = '/api/v1.1/'
        self.headers = {'content-type': 'application/json'}

        # Populate a test AtomSpace
        self.atomspace = AtomSpace()
        self.animal = self.atomspace.add_node(types.ConceptNode, 'animal',
                                              TruthValue(.1, .95))
        self.bird = self.atomspace.add_node(types.ConceptNode, 'bird',
                                            TruthValue(.01, .9))
        self.swan = self.atomspace.add_node(types.ConceptNode, 'swan',
                                            TruthValue(.001, .9))
        self.frog = self.atomspace.add_node(types.ConceptNode, 'frog',
                                            TruthValue(.001, 2000))
        self.swan_bird = self.atomspace.add_link(types.InheritanceLink,
                                                 [self.swan, self.bird],
                                                 TruthValue(1, .9))
        self.bird_animal = self.atomspace.add_link(types.InheritanceLink,
                                                   [self.bird, self.animal],
                                                   TruthValue(1, .9))
        self.bird.av = {'sti': 9}
        self.swan.av = {'sti': 9}

        self.api = RESTAPI(self.atomspace)
        self.client = self.api.test()

    def tearDown(self):
        del self.api
        del self.client

    def test_post_and_get_node(self):
        # Create a test node
        truthvalue = {
            'type': 'simple',
            'details': {
                'strength': 0.08,
                'count': 0.2
            }
        }
        atom = {
            'type': 'ConceptNode',
            'name': 'giant_frog',
            'truthvalue': truthvalue
        }

        post_response = self.client.post(self.uri + 'atoms',
                                         data=json.dumps(atom),
                                         headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']

        # Verify values returned by the POST request
        assert post_result['type'] == atom['type']
        assert post_result['name'] == atom['name']
        assert post_result['truthvalue']['type'] == truthvalue['type']
        assert_almost_equals(float(
            post_result['truthvalue']['details']['strength']),
                             truthvalue['details']['strength'],
                             places=5)
        assert_almost_equals(float(
            post_result['truthvalue']['details']['count']),
                             truthvalue['details']['count'],
                             places=5)

        # Compare to the values created in the AtomSpace
        atomspace_result = self.atomspace[Handle(post_result['handle'])]
        assert Handle(post_result['handle']) == atomspace_result.h
        assert post_result['name'] == atomspace_result.name
        assert types.__dict__.get(post_result['type']) == atomspace_result.type
        assert TruthValue(
            float(post_result['truthvalue']['details']['strength']),
            float(post_result['truthvalue']['details']['count'])) \
            == atomspace_result.tv

        # Get by handle and compare
        handle = post_result['handle']
        get_response_handle = \
            self.client.get(self.uri + 'atoms/' + str(handle))
        get_result_handle = \
            json.loads(get_response_handle.data)['result']['atoms'][0]
        assert post_result == get_result_handle

        # Get by name and compare
        name = post_result['name']
        get_response_name = self.client.get(self.uri + 'atoms?name=' + name)
        get_result_name = \
            json.loads(get_response_name.data)['result']['atoms'][0]
        assert post_result == get_result_name

        # Get by name and type and compare
        type = post_result['type']
        get_response_name_type = \
            self.client.get(self.uri + 'atoms?name=' + name + '&type=' + type)
        get_result_name_type = \
            json.loads(get_response_name_type.data)['result']['atoms'][0]
        assert post_result == get_result_name_type

    def test_post_and_get_link(self):
        # Create a test link between swan and animal
        truthvalue = \
            {'type': 'simple', 'details': {'strength': 0.5, 'count': 0.4}}
        atom = {
            'type': 'InheritanceLink',
            'truthvalue': truthvalue,
            'outgoing': [self.swan.h.value(),
                         self.animal.h.value()]
        }

        post_response = self.client.post(self.uri + 'atoms',
                                         data=json.dumps(atom),
                                         headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']

        # Verify values returned by the POST request
        assert post_result['type'] == atom['type']
        assert post_result['truthvalue']['type'] == truthvalue['type']
        assert_almost_equals(float(
            post_result['truthvalue']['details']['strength']),
                             truthvalue['details']['strength'],
                             places=5)
        assert_almost_equals(float(
            post_result['truthvalue']['details']['count']),
                             truthvalue['details']['count'],
                             places=5)
        assert self.swan.h.value() in post_result['outgoing']
        assert self.animal.h.value() in post_result['outgoing']

        # Compare to the values created in the AtomSpace
        atomspace_result = self.atomspace[Handle(post_result['handle'])]
        assert Handle(post_result['handle']) == atomspace_result.h
        assert types.__dict__.get(post_result['type']) == atomspace_result.type
        assert TruthValue(
            float(post_result['truthvalue']['details']['strength']),
            float(post_result['truthvalue']['details']['count'])) \
            == atomspace_result.tv

        # Get by handle and compare
        handle = post_result['handle']
        get_response_handle = \
            self.client.get(self.uri + 'atoms/' + str(handle))
        get_result_handle = \
            json.loads(get_response_handle.data)['result']['atoms'][0]
        assert post_result == get_result_handle

        # Check if the link is in the incoming set of each of the nodes
        for h in post_result['outgoing']:
            assert Handle(post_result['handle']) \
                in [atom.h for atom in self.atomspace[Handle(h)].incoming]

    def test_put_and_get_tv_av_node(self):
        atom = self.swan
        truthvalue = \
            {'type': 'simple', 'details': {'strength': 0.005, 'count': 0.8}}
        attentionvalue = {'sti': 9, 'lti': 2, 'vlti': True}
        atom_update = \
            {'truthvalue': truthvalue, 'attentionvalue': attentionvalue}
        put_response = self.client.put(self.uri + 'atoms/' +
                                       str(atom.h.value()),
                                       data=json.dumps(atom_update),
                                       headers=self.headers)
        put_result = json.loads(put_response.data)['atoms']

        # Verify values returned by the PUT request
        assert put_result['handle'] == atom.h.value()
        assert_almost_equals(float(
            put_result['truthvalue']['details']['strength']),
                             truthvalue['details']['strength'],
                             places=5)
        assert_almost_equals(float(
            put_result['truthvalue']['details']['count']),
                             truthvalue['details']['count'],
                             places=5)
        assert put_result['attentionvalue']['sti'] == attentionvalue['sti']
        assert put_result['attentionvalue']['lti'] == attentionvalue['lti']
        assert put_result['attentionvalue']['vlti'] == attentionvalue['vlti']

        # Compare to the values updated in the AtomSpace
        atomspace_result = self.atomspace[Handle(put_result['handle'])]
        assert Handle(put_result['handle']) == atomspace_result.h
        assert types.__dict__.get(put_result['type']) == atomspace_result.type
        assert TruthValue(
            float(put_result['truthvalue']['details']['strength']),
            float(put_result['truthvalue']['details']['count'])) \
            == atomspace_result.tv
        assert put_result['attentionvalue'] == atomspace_result.av

        # Get by handle and compare
        get_response = \
            self.client.get(self.uri + 'atoms/' + str(atom.h.value()))
        get_result = json.loads(get_response.data)['result']['atoms'][0]
        assert put_result == get_result

    def test_put_and_get_tv_av_link(self):
        atom = self.bird_animal
        truthvalue = \
            {'type': 'simple', 'details': {'strength': 0.9, 'count': 0.95}}
        attentionvalue = {'sti': 6, 'lti': 3, 'vlti': True}
        atom_update = \
            {'truthvalue': truthvalue, 'attentionvalue': attentionvalue}
        put_response =\
            self.client.put(
                self.uri + 'atoms/' + str(atom.h.value()),
                data=json.dumps(atom_update),
                headers=self.headers)
        put_result = json.loads(put_response.data)['atoms']

        # Verify values returned by the PUT request
        assert put_result['handle'] == atom.h.value()
        assert_almost_equals(float(
            put_result['truthvalue']['details']['strength']),
                             truthvalue['details']['strength'],
                             places=5)
        assert_almost_equals(float(
            put_result['truthvalue']['details']['count']),
                             truthvalue['details']['count'],
                             places=5)
        assert put_result['attentionvalue']['sti'] == attentionvalue['sti']
        assert put_result['attentionvalue']['lti'] == attentionvalue['lti']
        assert put_result['attentionvalue']['vlti'] == attentionvalue['vlti']

        # Compare to the values updated in the AtomSpace
        atomspace_result = self.atomspace[Handle(put_result['handle'])]
        assert Handle(put_result['handle']) == atomspace_result.h
        assert types.__dict__.get(put_result['type']) == atomspace_result.type
        assert TruthValue(
            float(put_result['truthvalue']['details']['strength']),
            float(put_result['truthvalue']['details']['count'])) \
            == atomspace_result.tv
        assert put_result['attentionvalue'] == atomspace_result.av

        # Get by handle and compare
        get_response = \
            self.client.get(self.uri + 'atoms/' + str(atom.h.value()))
        get_result = json.loads(get_response.data)['result']['atoms'][0]
        assert put_result == get_result

    def test_post_revise_existing_node(self):
        # Attempt to create a node, where a node already exists with that name
        # and type. Should revise existing node.
        existing_atom = self.bird

        truthvalue = \
            {'type': 'simple', 'details': {'strength': 0.1, 'count': 0.95}}
        atom = \
            {'type': 'ConceptNode', 'name': 'bird', 'truthvalue': truthvalue}

        post_response = self.client.post(self.uri + 'atoms',
                                         data=json.dumps(atom),
                                         headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']

        # Verify values returned by the POST request
        assert_almost_equals(float(
            post_result['truthvalue']['details']['strength']),
                             truthvalue['details']['strength'],
                             places=5)
        assert_almost_equals(float(
            post_result['truthvalue']['details']['count']),
                             truthvalue['details']['count'],
                             places=5)

        # Compare to the values updated in the AtomSpace
        assert post_result['handle'] == existing_atom.h.value()
        assert TruthValue(
            float(post_result['truthvalue']['details']['strength']),
            float(post_result['truthvalue']['details']['count'])) \
               == existing_atom.tv

    def test_post_revise_existing_link(self):
        # Attempt to create a link, where a link already exists with that name
        # and outgoing set.
        # Should revise existing link.
        existing_atom = self.bird_animal
        truthvalue = \
            {'type': 'simple', 'details': {'strength': 0.1, 'count': 0.95}}
        outgoing = [a.h.value() for a in existing_atom.out]
        atom = {
            'type': 'InheritanceLink',
            'truthvalue': truthvalue,
            'outgoing': outgoing
        }

        post_response = self.client.post(self.uri + 'atoms',
                                         data=json.dumps(atom),
                                         headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']

        # Verify values returned by the POST request
        assert post_result['outgoing'] == outgoing
        assert_almost_equals(float(
            post_result['truthvalue']['details']['strength']),
                             truthvalue['details']['strength'],
                             places=5)
        assert_almost_equals(float(
            post_result['truthvalue']['details']['count']),
                             truthvalue['details']['count'],
                             places=5)

        # Compare to the values updated in the AtomSpace
        assert post_result['handle'] == existing_atom.h.value()
        assert TruthValue(
            float(post_result['truthvalue']['details']['strength']),
            float(post_result['truthvalue']['details']['count'])) \
               == existing_atom.tv

    @raises(IndexError)
    def test_delete_node(self):
        atom = self.swan
        handle = atom.h.value()
        get_response = self.client.get(self.uri + 'atoms/' + str(handle))
        get_result = json.loads(get_response.data)['result']['atoms'][0]

        delete_response = \
            self.client.delete(self.uri + 'atoms/' + str(atom.h.value()))
        delete_result = json.loads(delete_response.data)['result']

        assert delete_result['success']
        assert delete_result['handle'] == get_result['handle']

        # Confirm the atom isn't contained in the AtomSpace anymore
        assert_raises(self.atomspace[atom.h], IndexError)

    @raises(IndexError)
    def test_delete_link(self):
        atom = self.bird_animal
        handle = atom.h.value()
        get_response = self.client.get(self.uri + 'atoms/' + str(handle))
        get_result = json.loads(get_response.data)['result']['atoms'][0]

        delete_response = \
            self.client.delete(self.uri + 'atoms/' + str(atom.h.value()))
        delete_result = json.loads(delete_response.data)['result']

        assert delete_result['success']
        assert delete_result['handle'] == get_result['handle']

        # Confirm the atom isn't contained in the AtomSpace anymore
        assert_raises(self.atomspace[atom.h], IndexError)

    def test_get_atoms_by_av(self):
        # Assign some STI values
        self.atomspace.set_av(h=self.bird.h, sti=9)
        self.atomspace.set_av(h=self.swan.h, sti=20)
        self.atomspace.set_av(h=self.bird_animal.h, sti=15)
        self.atomspace.set_av(h=self.animal.h, sti=0)

        get_response = \
            self.client.get(self.uri + 'atoms?filterby=attentionalfocus')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 3
        assert set([atom['handle'] for atom in get_result]) \
            == {self.bird.h.value(),
                self.swan.h.value(),
                self.bird_animal.h.value()}

        get_response = \
            self.client.get(self.uri + 'atoms?filterby=stirange&stimin=15')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 2
        assert set([atom['handle'] for atom in get_result]) \
            == {self.swan.h.value(), self.bird_animal.h.value()}

        get_response = self.client.get(
            self.uri + 'atoms?filterby=stirange&stimin=15&stimax=18')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 1
        assert set([atom['handle'] for atom in get_result]) \
            == {self.bird_animal.h.value()}

    def test_get_types(self):
        # Verify that a list of valid atom types was returned
        get_response = self.client.get(self.uri + 'types')
        get_result = json.loads(get_response.data)['types']
        assert len(get_result) > 0
        assert get_result.__contains__('ConceptNode')

    def test_tv_filter(self):
        # Should return animal, swan_bird, bird_animal (3 atoms)
        get_response = self.client.get(self.uri + 'atoms?tvStrengthMin=0.1')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 3

        # Should return frog (1 atom)
        get_response = self.client.get(self.uri + 'atoms?tvConfidenceMin=0.7')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 1

        # Should return frog (1 atom)
        get_response = self.client.get(self.uri + 'atoms?tvCountMin=2000')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 1

    def test_include_incoming_outgoing(self):
        # Should return bird and swan (2 atoms)
        get_response = self.client.get(
            self.uri +
            'atoms?filterby=stirange&stimin=1&includeIncoming=false')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 2

        # Should additionally return swan_bird and bird_animal (4 atoms)
        get_response = self.client.get(
            self.uri + 'atoms?filterby=stirange&stimin=1&includeIncoming=true')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 4

        # Should additionally return animal (5 atoms)
        get_response = \
            self.client.get(
                self.uri + 'atoms?filterby=stirange&stimin=1&'
                           'includeIncoming=true&includeOutgoing=true')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 5

    def test_scheme_command(self):
        # Test an arbitrary Scheme command to ensure the binding is working
        # properly

        # Set the AttentionalFocus Boundary
        command = {'command': '(cog-set-af-boundary! 5)'}

        post_response = self.client.post(self.uri + 'scheme',
                                         data=json.dumps(command),
                                         headers=self.headers)
        post_result = json.loads(post_response.data)['response']

        # Verify that the value returned by the POST request is the new
        # value of the AttentionalFocus Boundary
        assert post_result == "5\n"

        # Get the AttentionalFocus Boundary
        command = {'command': '(cog-af-boundary)'}

        post_response = self.client.post(self.uri + 'scheme',
                                         data=json.dumps(command),
                                         headers=self.headers)
        post_result = json.loads(post_response.data)['response']

        # Verify that it matches the previous response
        assert post_result == "5\n"

    def test_dot_export(self):
        # Export the atomspace to DOT format and ensure that there is a
        # properly defined DOT header created and the correct atoms are
        # included in the description

        # TODO: The Python module "graphviz" needs to be added to ocpkg, so
        # that this dependency will be available for the continuous integration
        # system
        try:
            from graph_description import dot

            get_response = self.client.get(
                self.uri + 'atoms?filterby=attentionalfocus&dot=True')
            get_result = json.loads(get_response.data)['result']
            assert get_result.startswith("// OpenCog Graph")
            assert "digraph" in get_result
            assert "swan" in get_result
            assert "bird" in get_result
            assert get_result.count("label") == 2
        except ImportError:
            pass
Beispiel #19
0
class TestRESTApi():
    """
    Unit tests for the OpenCog REST API.

    See: opencog/python/web/api/apimain.py for the class definitions
    Documentation: http://wiki.opencog.org/w/REST_API
    """
    def setUp(self):
        self.uri = '/api/v1.1/'
        self.headers = {'content-type': 'application/json'}

        # Populate a test AtomSpace
        self.atomspace = AtomSpace()
        self.animal = self.atomspace.add_node(
            types.ConceptNode, 'animal', TruthValue(.1, 0.0011860914528369904))
        self.bird = self.atomspace.add_node(
            types.ConceptNode, 'bird', TruthValue(.01, 0.0011237357975915074))
        self.swan = self.atomspace.add_node(
            types.ConceptNode, 'swan', TruthValue(.001, 0.0011237357975915074))
        self.frog = self.atomspace.add_node(
            types.ConceptNode, 'frog', TruthValue(.001, 0.7142857313156128))
        self.swan_bird = self.atomspace.add_link(
            types.InheritanceLink, [self.swan, self.bird],
            TruthValue(1, 0.0011237357975915074))
        self.bird_animal = self.atomspace.add_link(
            types.InheritanceLink, [self.bird, self.animal],
            TruthValue(1, 0.0011237357975915074))
        self.bird.sti = 9
        self.swan.sti = 9

        self.api = RESTAPI(self.atomspace)
        self.client = self.api.test()

    def tearDown(self):
        del self.api
        del self.client

    def mkatom(self, json_atom):
        post_response = self.client.post(self.uri + 'atoms',
                                         data=json.dumps(json_atom),
                                         headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']
        return post_result

    def mkswan(self):
        return self.mkatom({
            'type': 'ConceptNode',
            'name': 'swan',
            'truthvalue': {
                'type': 'simple',
                'details': {
                    'strength': 0.001,
                    'count': 0.9
                }
            }
        })

    def mkbird(self):
        return self.mkatom({
            'type': 'ConceptNode',
            'name': 'bird',
            'truthvalue': {
                'type': 'simple',
                'details': {
                    'strength': 0.01,
                    'count': 0.9
                }
            }
        })

    def mkanimal(self):
        return self.mkatom({
            'type': 'ConceptNode',
            'name': 'animal',
            'truthvalue': {
                'type': 'simple',
                'details': {
                    'strength': 0.1,
                    'count': 0.95
                }
            }
        })

    def mkbird_animal(self):
        jbird = self.mkbird()
        janimal = self.mkanimal()
        return self.mkatom({
            'type': 'InheritanceLink',
            'truthvalue': {
                'type': 'simple',
                'details': {
                    'strength': 1.0,
                    'count': 0.9
                }
            },
            'outgoing': [jbird['handle'], janimal['handle']]
        })

    def get_atom(self, handle):
        get_response_handle = \
            self.client.get(self.uri + 'atoms/' + str(handle))
        get_result_handle = \
            json.loads(get_response_handle.data)['result']['atoms'][0]
        return get_result_handle

    def test_a_post_and_get_node(self):
        # Create a test node
        truthvalue = {
            'type': 'simple',
            'details': {
                'strength': 0.08,
                'count': 0.2
            }
        }
        jatom = {
            'type': 'ConceptNode',
            'name': 'giant_frog',
            'truthvalue': truthvalue
        }

        post_response = self.client.post(self.uri + 'atoms',
                                         data=json.dumps(jatom),
                                         headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']

        # Verify values returned by the POST request
        assert post_result['type'] == jatom['type']
        assert post_result['name'] == jatom['name']
        assert post_result['truthvalue']['type'] == truthvalue['type']
        assert_almost_equals(float(
            post_result['truthvalue']['details']['strength']),
                             truthvalue['details']['strength'],
                             places=5)
        assert_almost_equals(float(
            post_result['truthvalue']['details']['count']),
                             truthvalue['details']['count'],
                             places=5)

        # Compare to the values created in the AtomSpace
        frog = self.atomspace.add_node(
            types.ConceptNode, 'giant_frog',
            TruthValue(.08, count_to_confidence(0.2)))
        atomspace_result = frog
        assert post_result['name'] == atomspace_result.name
        assert types.__dict__.get(post_result['type']) == atomspace_result.type
        assert TruthValue(
            float(post_result['truthvalue']['details']['strength']),
            count_to_confidence(
                float(post_result['truthvalue']['details']['count']))) \
            == atomspace_result.tv

        # Get by handle and compare
        handle = post_result['handle']
        get_response_handle = \
            self.client.get(self.uri + 'atoms/' + str(handle))
        get_result_handle = \
            json.loads(get_response_handle.data)['result']['atoms'][0]
        assert post_result == get_result_handle

        # Get by name and compare
        name = post_result['name']
        get_response_name = self.client.get(self.uri + 'atoms?name=' + name)
        get_result_name = \
            json.loads(get_response_name.data)['result']['atoms'][0]
        assert post_result == get_result_name

        # Get by name and type and compare
        type = post_result['type']
        get_response_name_type = \
            self.client.get(self.uri + 'atoms?name=' + name + '&type=' + type)
        get_result_name_type = \
            json.loads(get_response_name_type.data)['result']['atoms'][0]
        assert post_result == get_result_name_type

    def test_b_post_and_get_link(self):
        jswan = self.mkswan()
        janimal = self.mkanimal()

        # Create a test link between swan and animal
        truthvalue = \
            {'type': 'simple', 'details': {'strength': 0.5, 'count': 0.4}}
        atom = {
            'type': 'InheritanceLink',
            'truthvalue': truthvalue,
            'outgoing': [jswan['handle'], janimal['handle']]
        }

        post_response = self.client.post(self.uri + 'atoms',
                                         data=json.dumps(atom),
                                         headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']

        # Verify values returned by the POST request
        assert post_result['type'] == atom['type']
        assert post_result['truthvalue']['type'] == truthvalue['type']
        assert_almost_equals(float(
            post_result['truthvalue']['details']['strength']),
                             truthvalue['details']['strength'],
                             places=5)
        assert_almost_equals(float(
            post_result['truthvalue']['details']['count']),
                             truthvalue['details']['count'],
                             places=5)
        assert jswan['handle'] in post_result['outgoing']
        assert janimal['handle'] in post_result['outgoing']

        # Compare to the values created in the AtomSpace
        swan_animal = self.atomspace.add_link(
            types.InheritanceLink, [self.swan, self.animal],
            TruthValue(0.5, count_to_confidence(0.4)))

        atomspace_result = swan_animal
        assert types.__dict__.get(post_result['type']) == atomspace_result.type
        assert TruthValue(
            float(post_result['truthvalue']['details']['strength']),
            count_to_confidence(
                float(post_result['truthvalue']['details']['count']))) \
            == atomspace_result.tv

        # Get by handle and compare
        handle = post_result['handle']
        get_response_handle = \
            self.client.get(self.uri + 'atoms/' + str(handle))
        get_result_handle = \
            json.loads(get_response_handle.data)['result']['atoms'][0]
        assert post_result == get_result_handle

        # Check if the link is in the incoming set of each of the nodes
        jswan = self.get_atom(jswan['handle'])
        janimal = self.get_atom(janimal['handle'])
        for h in post_result['outgoing']:
            assert post_result['handle'] in jswan['incoming']
            assert post_result['handle'] in janimal['incoming']

    def test_c_put_and_get_tv_av_node(self):
        jswan = self.mkswan()

        truthvalue = \
            {'type': 'simple', 'details': {'strength': 0.005, 'count': 0.8}}
        attentionvalue = {'sti': 9, 'lti': 2, 'vlti': True}
        atom_update = \
            {'truthvalue': truthvalue, 'attentionvalue': attentionvalue}
        put_response = self.client.put(self.uri + 'atoms/' +
                                       str(jswan['handle']),
                                       data=json.dumps(atom_update),
                                       headers=self.headers)
        put_result = json.loads(put_response.data)['atoms']

        # Verify values returned by the PUT request
        assert put_result['handle'] == jswan['handle']
        assert_almost_equals(float(
            put_result['truthvalue']['details']['strength']),
                             truthvalue['details']['strength'],
                             places=5)
        assert_almost_equals(float(
            put_result['truthvalue']['details']['count']),
                             truthvalue['details']['count'],
                             places=5)
        assert put_result['attentionvalue']['sti'] == attentionvalue['sti']
        assert put_result['attentionvalue']['lti'] == attentionvalue['lti']
        assert put_result['attentionvalue']['vlti'] == attentionvalue['vlti']

        # Compare to the values updated in the AtomSpace
        atomspace_result = self.swan
        assert types.__dict__.get(put_result['type']) == atomspace_result.type
        assert TruthValue(
            float(put_result['truthvalue']['details']['strength']),
            count_to_confidence(
                float(put_result['truthvalue']['details']['count']))) \
            == atomspace_result.tv
        assert put_result['attentionvalue'] == atomspace_result.av

        # Get by handle and compare
        get_response = \
            self.client.get(self.uri + 'atoms/' + str(jswan['handle']))
        get_result = json.loads(get_response.data)['result']['atoms'][0]
        assert put_result == get_result

    def test_d_put_and_get_tv_av_link(self):
        jatom = self.mkbird_animal()
        truthvalue = \
            {'type': 'simple', 'details': {'strength': 0.9, 'count': 0.95}}
        attentionvalue = {'sti': 6, 'lti': 3, 'vlti': True}
        atom_update = \
            {'truthvalue': truthvalue, 'attentionvalue': attentionvalue}
        put_response =\
            self.client.put(
                self.uri + 'atoms/' + str(jatom['handle']),
                data=json.dumps(atom_update),
                headers=self.headers)
        put_result = json.loads(put_response.data)['atoms']

        # Verify values returned by the PUT request
        assert put_result['handle'] == jatom['handle']
        assert_almost_equals(float(
            put_result['truthvalue']['details']['strength']),
                             truthvalue['details']['strength'],
                             places=5)
        assert_almost_equals(float(
            put_result['truthvalue']['details']['count']),
                             truthvalue['details']['count'],
                             places=5)
        assert put_result['attentionvalue']['sti'] == attentionvalue['sti']
        assert put_result['attentionvalue']['lti'] == attentionvalue['lti']
        assert put_result['attentionvalue']['vlti'] == attentionvalue['vlti']

        # Compare to the values updated in the AtomSpace
        atomspace_result = self.bird_animal
        assert types.__dict__.get(put_result['type']) == atomspace_result.type
        assert TruthValue(
            float(put_result['truthvalue']['details']['strength']),
            count_to_confidence(
                float(put_result['truthvalue']['details']['count']))) \
            == atomspace_result.tv
        assert put_result['attentionvalue'] == atomspace_result.av

        # Get by handle and compare
        get_response = \
            self.client.get(self.uri + 'atoms/' + str(jatom['handle']))
        get_result = json.loads(get_response.data)['result']['atoms'][0]
        assert put_result == get_result

    def test_e_post_revise_existing_node(self):
        # Attempt to create a node, where a node already exists with that name
        # and type. Should revise existing node.
        existing_atom = self.bird

        truthvalue = \
            {'type': 'simple', 'details': {'strength': 0.1, 'count': 0.95}}
        atom = \
            {'type': 'ConceptNode', 'name': 'bird', 'truthvalue': truthvalue}

        post_response = self.client.post(self.uri + 'atoms',
                                         data=json.dumps(atom),
                                         headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']

        # Verify values returned by the POST request
        assert_almost_equals(float(
            post_result['truthvalue']['details']['strength']),
                             truthvalue['details']['strength'],
                             places=5)
        assert_almost_equals(float(
            post_result['truthvalue']['details']['count']),
                             truthvalue['details']['count'],
                             places=5)

        # Compare to the values updated in the AtomSpace
        assert TruthValue(
            float(post_result['truthvalue']['details']['strength']),
            count_to_confidence(
                float(post_result['truthvalue']['details']['count']))) \
               == existing_atom.tv

    def test_f_post_revise_existing_link(self):
        # Attempt to create a link, where a link already exists with that name
        # and outgoing set.
        # Should revise existing link.
        existing_atom = self.bird_animal
        jbird_animal = self.mkbird_animal()
        truthvalue = \
            {'type': 'simple', 'details': {'strength': 0.1, 'count': 0.95}}
        outgoing = jbird_animal['outgoing']
        atom = {
            'type': 'InheritanceLink',
            'truthvalue': truthvalue,
            'outgoing': outgoing
        }

        post_response = self.client.post(self.uri + 'atoms',
                                         data=json.dumps(atom),
                                         headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']

        # Verify values returned by the POST request
        assert post_result['outgoing'] == outgoing
        assert_almost_equals(float(
            post_result['truthvalue']['details']['strength']),
                             truthvalue['details']['strength'],
                             places=5)
        assert_almost_equals(float(
            post_result['truthvalue']['details']['count']),
                             truthvalue['details']['count'],
                             places=5)

        # Compare to the values updated in the AtomSpace
        assert TruthValue(
            float(post_result['truthvalue']['details']['strength']),
            count_to_confidence(
                float(post_result['truthvalue']['details']['count']))) \
               == existing_atom.tv

    # @raises(IndexError)
    def test_g_delete_node(self):
        jswan = self.mkswan()
        handle = jswan['handle']
        get_response = self.client.get(self.uri + 'atoms/' + str(handle))
        get_result = json.loads(get_response.data)['result']['atoms'][0]

        old_size = self.atomspace.size()
        delete_response = \
            self.client.delete(self.uri + 'atoms/' + str(handle))
        delete_result = json.loads(delete_response.data)['result']

        assert delete_result['success']
        assert delete_result['handle'] == get_result['handle']

        # Confirm the atom isn't contained in the AtomSpace anymore
        # Actually, the python bindings don't provide a way to ask
        # this question. So we check the size, instead.  Should shrink
        # by 2, since both the swan, and the inhertance link get
        # deleted.
        new_size = self.atomspace.size()
        assert new_size + 2 == old_size

    # @raises(IndexError)
    def test_h_delete_link(self):
        jatom = self.mkbird_animal()
        handle = jatom['handle']
        get_response = self.client.get(self.uri + 'atoms/' + str(handle))
        get_result = json.loads(get_response.data)['result']['atoms'][0]

        old_size = self.atomspace.size()
        delete_response = \
            self.client.delete(self.uri + 'atoms/' + str(handle))
        delete_result = json.loads(delete_response.data)['result']

        assert delete_result['success']
        assert delete_result['handle'] == get_result['handle']

        # Confirm the atom isn't contained in the AtomSpace anymore
        # Actually, the python bindings don't provide a way to ask
        # this question. So we check the size, instead.  Should shrink
        # by 1, since only the inhertance link gets deleted.
        new_size = self.atomspace.size()
        assert new_size + 1 == old_size

    def test_i_get_atoms_by_av(self):
        # Assign some STI values
        self.bird.sti = 9
        self.swan.sti = 20
        self.bird_animal.sti = 15
        self.animal.sti = 0

        jswan = self.mkswan()
        jbird = self.mkbird()
        jbird_animal = self.mkbird_animal()
        get_response = \
            self.client.get(self.uri + 'atoms?filterby=attentionalfocus')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 3
        assert set([atom['handle'] for atom in get_result]) \
            == {jbird['handle'],
                jswan['handle'],
                jbird_animal['handle']}

        get_response = \
            self.client.get(self.uri + 'atoms?filterby=stirange&stimin=15')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 2
        assert set([atom['handle'] for atom in get_result]) \
            == {jswan['handle'], jbird_animal['handle']}

        get_response = self.client.get(
            self.uri + 'atoms?filterby=stirange&stimin=15&stimax=18')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 1
        assert set([atom['handle'] for atom in get_result]) \
            == {jbird_animal['handle']}

    def test_j_get_types(self):
        # Verify that a list of valid atom types was returned
        get_response = self.client.get(self.uri + 'types')
        get_result = json.loads(get_response.data)['types']
        assert len(get_result) > 0
        assert get_result.__contains__('ConceptNode')

    def test_k_tv_filter(self):
        # Should return animal, swan_bird, bird_animal (3 atoms)
        get_response = self.client.get(self.uri + 'atoms?tvStrengthMin=0.1')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 3

        # Should return frog (1 atom)
        get_response = self.client.get(self.uri + 'atoms?tvConfidenceMin=0.7')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 1

        # Should return frog (1 atom)
        get_response = self.client.get(self.uri + 'atoms?tvCountMin=2000')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 1

    def test_l_include_incoming_outgoing(self):
        # Should return bird and swan (2 atoms)
        get_response = self.client.get(
            self.uri +
            'atoms?filterby=stirange&stimin=1&includeIncoming=false')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 2

        # Should additionally return swan_bird and bird_animal (4 atoms)
        get_response = self.client.get(
            self.uri + 'atoms?filterby=stirange&stimin=1&includeIncoming=true')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 4

        # Should additionally return animal (5 atoms)
        get_response = \
            self.client.get(
                self.uri + 'atoms?filterby=stirange&stimin=1&'
                           'includeIncoming=true&includeOutgoing=true')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 5

    def test_m_scheme_command(self):
        # Test an arbitrary Scheme command to ensure the binding is working
        # properly

        # Set the AttentionalFocus Boundary
        command = {'command': '(cog-set-af-boundary! 5)'}

        post_response = self.client.post(self.uri + 'scheme',
                                         data=json.dumps(command),
                                         headers=self.headers)
        post_result = json.loads(post_response.data)['response']

        # Verify that the value returned by the POST request is the new
        # value of the AttentionalFocus Boundary
        assert post_result == "5\n"

        # Get the AttentionalFocus Boundary
        command = {'command': '(cog-af-boundary)'}

        post_response = self.client.post(self.uri + 'scheme',
                                         data=json.dumps(command),
                                         headers=self.headers)
        post_result = json.loads(post_response.data)['response']

        # Verify that it matches the previous response
        assert post_result == "5\n"

    def test_n_dot_export(self):
        # Export the atomspace to DOT format and ensure that there is a
        # properly defined DOT header created and the correct atoms are
        # included in the description

        # TODO: The Python module "graphviz" needs to be added to ocpkg, so
        # that this dependency will be available for the continuous integration
        # system
        try:
            from graph_description import dot

            get_response = self.client.get(
                self.uri + 'atoms?filterby=attentionalfocus&dot=True')
            get_result = json.loads(get_response.data)['result']
            assert get_result.startswith("// OpenCog Graph")
            assert "digraph" in get_result
            assert "swan" in get_result
            assert "bird" in get_result
            assert get_result.count("label") == 2
        except ImportError:
            pass
Beispiel #20
0
from web.api.apimain import RESTAPI
from opencog.atomspace import AtomSpace, types
from opencog.utilities import initialize_opencog
from opencog.type_constructors import *

# Endpoint configuration
# To allow public access, set to 0.0.0.0; for local access, set to 127.0.0.1
IP_ADDRESS = '0.0.0.0'
PORT = 5000

atomspace = AtomSpace()
initialize_opencog(atomspace)

Link(
    ConceptNode("Test Concept"),
    ConceptNode("another one")
)

api = RESTAPI(atomspace)
api.run(host=IP_ADDRESS, port=PORT)
Beispiel #21
0
class TestRESTApi():
    """
    Unit tests for the OpenCog REST API.

    See: opencog/python/web/api/apimain.py for the class definitions
    Documentation: http://wiki.opencog.org/w/REST_API
    """

    def setUp(self):
        self.uri = '/api/v1.1/'
        self.headers = {'content-type': 'application/json'}

        # Populate a test AtomSpace
        self.atomspace = AtomSpace()
        self.animal = self.atomspace.add_node(
            types.ConceptNode, 'animal', TruthValue(.1, .95))
        self.bird = self.atomspace.add_node(
            types.ConceptNode, 'bird', TruthValue(.01, .9))
        self.swan = self.atomspace.add_node(
            types.ConceptNode, 'swan', TruthValue(.001, .9))
        self.frog = self.atomspace.add_node(
            types.ConceptNode, 'frog', TruthValue(.001, 2000))
        self.swan_bird = self.atomspace.add_link(
            types.InheritanceLink, [self.swan, self.bird], TruthValue(1, .9))
        self.bird_animal = self.atomspace.add_link(
            types.InheritanceLink, [self.bird, self.animal], TruthValue(1, .9))
        self.bird.av = {'sti': 9}
        self.swan.av = {'sti': 9}

        self.api = RESTAPI(self.atomspace)
        self.client = self.api.test()

    def tearDown(self):
        del self.api
        del self.client

    def test_post_and_get_node(self):
        # Create a test node
        truthvalue = {'type': 'simple',
                      'details': {'strength': 0.08, 'count': 0.2}}
        atom = {'type': 'ConceptNode',
                'name': 'giant_frog',
                'truthvalue': truthvalue}

        post_response = self.client.post(self.uri + 'atoms',
                                         data=json.dumps(atom),
                                         headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']

        # Verify values returned by the POST request
        assert post_result['type'] == atom['type']
        assert post_result['name'] == atom['name']
        assert post_result['truthvalue']['type'] == truthvalue['type']
        assert_almost_equals(
            float(post_result['truthvalue']['details']['strength']),
            truthvalue['details']['strength'], places=5)
        assert_almost_equals(
            float(post_result['truthvalue']['details']['count']),
            truthvalue['details']['count'], places=5)

        # Compare to the values created in the AtomSpace
        atomspace_result = self.atomspace[Handle(post_result['handle'])]
        assert Handle(post_result['handle']) == atomspace_result.h
        assert post_result['name'] == atomspace_result.name
        assert types.__dict__.get(post_result['type']) == atomspace_result.type
        assert TruthValue(
            float(post_result['truthvalue']['details']['strength']),
            float(post_result['truthvalue']['details']['count'])) \
            == atomspace_result.tv

        # Get by handle and compare
        handle = post_result['handle']
        get_response_handle = \
            self.client.get(self.uri + 'atoms/' + str(handle))
        get_result_handle = \
            json.loads(get_response_handle.data)['result']['atoms'][0]
        assert post_result == get_result_handle

        # Get by name and compare
        name = post_result['name']
        get_response_name = self.client.get(self.uri + 'atoms?name=' + name)
        get_result_name = \
            json.loads(get_response_name.data)['result']['atoms'][0]
        assert post_result == get_result_name

        # Get by name and type and compare
        type = post_result['type']
        get_response_name_type = \
            self.client.get(self.uri + 'atoms?name=' + name + '&type=' + type)
        get_result_name_type = \
            json.loads(get_response_name_type.data)['result']['atoms'][0]
        assert post_result == get_result_name_type

    def test_post_and_get_link(self):
        # Create a test link between swan and animal
        truthvalue = \
            {'type': 'simple', 'details': {'strength': 0.5, 'count': 0.4}}
        atom = {'type': 'InheritanceLink', 'truthvalue': truthvalue,
                'outgoing': [self.swan.h.value(), self.animal.h.value()]}

        post_response = self.client.post(
            self.uri + 'atoms', data=json.dumps(atom), headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']

        # Verify values returned by the POST request
        assert post_result['type'] == atom['type']
        assert post_result['truthvalue']['type'] == truthvalue['type']
        assert_almost_equals(
            float(post_result['truthvalue']['details']['strength']),
            truthvalue['details']['strength'], places=5)
        assert_almost_equals(
            float(post_result['truthvalue']['details']['count']),
            truthvalue['details']['count'], places=5)
        assert self.swan.h.value() in post_result['outgoing']
        assert self.animal.h.value() in post_result['outgoing']

        # Compare to the values created in the AtomSpace
        atomspace_result = self.atomspace[Handle(post_result['handle'])]
        assert Handle(post_result['handle']) == atomspace_result.h
        assert types.__dict__.get(post_result['type']) == atomspace_result.type
        assert TruthValue(
            float(post_result['truthvalue']['details']['strength']),
            float(post_result['truthvalue']['details']['count'])) \
            == atomspace_result.tv

        # Get by handle and compare
        handle = post_result['handle']
        get_response_handle = \
            self.client.get(self.uri + 'atoms/' + str(handle))
        get_result_handle = \
            json.loads(get_response_handle.data)['result']['atoms'][0]
        assert post_result == get_result_handle

        # Check if the link is in the incoming set of each of the nodes
        for h in post_result['outgoing']:
            assert Handle(post_result['handle']) \
                in [atom.h for atom in self.atomspace[Handle(h)].incoming]

    def test_put_and_get_tv_av_node(self):
        atom = self.swan
        truthvalue = \
            {'type': 'simple', 'details': {'strength': 0.005, 'count': 0.8}}
        attentionvalue = {'sti': 9, 'lti': 2, 'vlti': True}
        atom_update = \
            {'truthvalue': truthvalue, 'attentionvalue': attentionvalue}
        put_response = self.client.put(
            self.uri + 'atoms/' + str(atom.h.value()),
            data=json.dumps(atom_update),
            headers=self.headers)
        put_result = json.loads(put_response.data)['atoms']

        # Verify values returned by the PUT request
        assert put_result['handle'] == atom.h.value()
        assert_almost_equals(
            float(put_result['truthvalue']['details']['strength']),
            truthvalue['details']['strength'], places=5)
        assert_almost_equals(
            float(put_result['truthvalue']['details']['count']),
            truthvalue['details']['count'], places=5)
        assert put_result['attentionvalue']['sti'] == attentionvalue['sti']
        assert put_result['attentionvalue']['lti'] == attentionvalue['lti']
        assert put_result['attentionvalue']['vlti'] == attentionvalue['vlti']

        # Compare to the values updated in the AtomSpace
        atomspace_result = self.atomspace[Handle(put_result['handle'])]
        assert Handle(put_result['handle']) == atomspace_result.h
        assert types.__dict__.get(put_result['type']) == atomspace_result.type
        assert TruthValue(
            float(put_result['truthvalue']['details']['strength']),
            float(put_result['truthvalue']['details']['count'])) \
            == atomspace_result.tv
        assert put_result['attentionvalue'] == atomspace_result.av

        # Get by handle and compare
        get_response = \
            self.client.get(self.uri + 'atoms/' + str(atom.h.value()))
        get_result = json.loads(get_response.data)['result']['atoms'][0]
        assert put_result == get_result

    def test_put_and_get_tv_av_link(self):
        atom = self.bird_animal
        truthvalue = \
            {'type': 'simple', 'details': {'strength': 0.9, 'count': 0.95}}
        attentionvalue = {'sti': 6, 'lti': 3, 'vlti': True}
        atom_update = \
            {'truthvalue': truthvalue, 'attentionvalue': attentionvalue}
        put_response =\
            self.client.put(
                self.uri + 'atoms/' + str(atom.h.value()),
                data=json.dumps(atom_update),
                headers=self.headers)
        put_result = json.loads(put_response.data)['atoms']

        # Verify values returned by the PUT request
        assert put_result['handle'] == atom.h.value()
        assert_almost_equals(
            float(put_result['truthvalue']['details']['strength']),
            truthvalue['details']['strength'], places=5)
        assert_almost_equals(
            float(put_result['truthvalue']['details']['count']),
            truthvalue['details']['count'], places=5)
        assert put_result['attentionvalue']['sti'] == attentionvalue['sti']
        assert put_result['attentionvalue']['lti'] == attentionvalue['lti']
        assert put_result['attentionvalue']['vlti'] == attentionvalue['vlti']

        # Compare to the values updated in the AtomSpace
        atomspace_result = self.atomspace[Handle(put_result['handle'])]
        assert Handle(put_result['handle']) == atomspace_result.h
        assert types.__dict__.get(put_result['type']) == atomspace_result.type
        assert TruthValue(
            float(put_result['truthvalue']['details']['strength']),
            float(put_result['truthvalue']['details']['count'])) \
            == atomspace_result.tv
        assert put_result['attentionvalue'] == atomspace_result.av

        # Get by handle and compare
        get_response = \
            self.client.get(self.uri + 'atoms/' + str(atom.h.value()))
        get_result = json.loads(get_response.data)['result']['atoms'][0]
        assert put_result == get_result

    def test_post_revise_existing_node(self):
        # Attempt to create a node, where a node already exists with that name
        # and type. Should revise existing node.
        existing_atom = self.bird

        truthvalue = \
            {'type': 'simple', 'details': {'strength': 0.1, 'count': 0.95}}
        atom = \
            {'type': 'ConceptNode', 'name': 'bird', 'truthvalue': truthvalue}

        post_response = self.client.post(self.uri + 'atoms',
                                         data=json.dumps(atom),
                                         headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']

        # Verify values returned by the POST request
        assert_almost_equals(
            float(post_result['truthvalue']['details']['strength']),
            truthvalue['details']['strength'], places=5)
        assert_almost_equals(
            float(post_result['truthvalue']['details']['count']),
            truthvalue['details']['count'], places=5)

        # Compare to the values updated in the AtomSpace
        assert post_result['handle'] == existing_atom.h.value()
        assert TruthValue(
            float(post_result['truthvalue']['details']['strength']),
            float(post_result['truthvalue']['details']['count'])) \
               == existing_atom.tv

    def test_post_revise_existing_link(self):
        # Attempt to create a link, where a link already exists with that name
        # and outgoing set.
        # Should revise existing link.
        existing_atom = self.bird_animal
        truthvalue = \
            {'type': 'simple', 'details': {'strength': 0.1, 'count': 0.95}}
        outgoing = [a.h.value() for a in existing_atom.out]
        atom = {'type': 'InheritanceLink',
                'truthvalue': truthvalue,
                'outgoing': outgoing}

        post_response = self.client.post(
            self.uri + 'atoms', data=json.dumps(atom), headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']

        # Verify values returned by the POST request
        assert post_result['outgoing'] == outgoing
        assert_almost_equals(
            float(post_result['truthvalue']['details']['strength']),
            truthvalue['details']['strength'], places=5)
        assert_almost_equals(
            float(post_result['truthvalue']['details']['count']),
            truthvalue['details']['count'], places=5)

        # Compare to the values updated in the AtomSpace
        assert post_result['handle'] == existing_atom.h.value()
        assert TruthValue(
            float(post_result['truthvalue']['details']['strength']),
            float(post_result['truthvalue']['details']['count'])) \
               == existing_atom.tv

    @raises(IndexError)
    def test_delete_node(self):
        atom = self.swan
        handle = atom.h.value()
        get_response = self.client.get(self.uri + 'atoms/' + str(handle))
        get_result = json.loads(get_response.data)['result']['atoms'][0]

        delete_response = \
            self.client.delete(self.uri + 'atoms/' + str(atom.h.value()))
        delete_result = json.loads(delete_response.data)['result']

        assert delete_result['success']
        assert delete_result['handle'] == get_result['handle']

        # Confirm the atom isn't contained in the AtomSpace anymore
        assert_raises(self.atomspace[atom.h], IndexError)

    @raises(IndexError)
    def test_delete_link(self):
        atom = self.bird_animal
        handle = atom.h.value()
        get_response = self.client.get(self.uri + 'atoms/' + str(handle))
        get_result = json.loads(get_response.data)['result']['atoms'][0]

        delete_response = \
            self.client.delete(self.uri + 'atoms/' + str(atom.h.value()))
        delete_result = json.loads(delete_response.data)['result']

        assert delete_result['success']
        assert delete_result['handle'] == get_result['handle']

        # Confirm the atom isn't contained in the AtomSpace anymore
        assert_raises(self.atomspace[atom.h], IndexError)

    def test_get_atoms_by_av(self):
        # Assign some STI values
        self.atomspace.set_av(h=self.bird.h, sti=9)
        self.atomspace.set_av(h=self.swan.h, sti=20)
        self.atomspace.set_av(h=self.bird_animal.h, sti=15)
        self.atomspace.set_av(h=self.animal.h, sti=0)

        get_response = \
            self.client.get(self.uri + 'atoms?filterby=attentionalfocus')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 3
        assert set([atom['handle'] for atom in get_result]) \
            == {self.bird.h.value(),
                self.swan.h.value(),
                self.bird_animal.h.value()}

        get_response = \
            self.client.get(self.uri + 'atoms?filterby=stirange&stimin=15')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 2
        assert set([atom['handle'] for atom in get_result]) \
            == {self.swan.h.value(), self.bird_animal.h.value()}

        get_response = self.client.get(
            self.uri + 'atoms?filterby=stirange&stimin=15&stimax=18')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 1
        assert set([atom['handle'] for atom in get_result]) \
            == {self.bird_animal.h.value()}

    def test_get_types(self):
        # Verify that a list of valid atom types was returned
        get_response = self.client.get(self.uri + 'types')
        get_result = json.loads(get_response.data)['types']
        assert len(get_result) > 0
        assert get_result.__contains__('ConceptNode')

    def test_tv_filter(self):
        # Should return animal, swan_bird, bird_animal (3 atoms)
        get_response = self.client.get(self.uri + 'atoms?tvStrengthMin=0.1')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 3

        # Should return frog (1 atom)
        get_response = self.client.get(self.uri + 'atoms?tvConfidenceMin=0.7')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 1

        # Should return frog (1 atom)
        get_response = self.client.get(self.uri + 'atoms?tvCountMin=2000')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 1

    def test_include_incoming_outgoing(self):
        # Should return bird and swan (2 atoms)
        get_response = self.client.get(
            self.uri +
            'atoms?filterby=stirange&stimin=1&includeIncoming=false')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 2

        # Should additionally return swan_bird and bird_animal (4 atoms)
        get_response = self.client.get(
            self.uri + 'atoms?filterby=stirange&stimin=1&includeIncoming=true')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 4

        # Should additionally return animal (5 atoms)
        get_response = \
            self.client.get(
                self.uri + 'atoms?filterby=stirange&stimin=1&'
                           'includeIncoming=true&includeOutgoing=true')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 5

    def test_scheme_command(self):
        # Test an arbitrary Scheme command to ensure the binding is working
        # properly

        # Set the AttentionalFocus Boundary
        command = {'command': '(cog-set-af-boundary! 5)'}

        post_response = self.client.post(
            self.uri + 'scheme',
            data=json.dumps(command),
            headers=self.headers)
        post_result = json.loads(post_response.data)['response']

        # Verify that the value returned by the POST request is the new
        # value of the AttentionalFocus Boundary
        assert post_result == "5\n"

        # Get the AttentionalFocus Boundary
        command = {'command': '(cog-af-boundary)'}

        post_response = self.client.post(
            self.uri + 'scheme',
            data=json.dumps(command),
            headers=self.headers)
        post_result = json.loads(post_response.data)['response']

        # Verify that it matches the previous response
        assert post_result == "5\n"
Beispiel #22
0
class TestRESTApi():
    """
    Unit tests for the OpenCog REST API.

    See: opencog/python/web/api/apimain.py for the class definitions
    Documentation: http://wiki.opencog.org/w/REST_API
    """

    def setUp(self):
        self.uri = '/api/v1.1/'
        self.headers = {'content-type': 'application/json'}

        # Populate a test AtomSpace
        self.atomspace = AtomSpace()
        self.animal = self.atomspace.add_node(
            types.ConceptNode, 'animal', TruthValue(.1, 0.0011860914528369904))
        self.bird = self.atomspace.add_node(
            types.ConceptNode, 'bird', TruthValue(.01, 0.0011237357975915074))
        self.swan = self.atomspace.add_node(
            types.ConceptNode, 'swan', TruthValue(.001, 0.0011237357975915074))
        self.frog = self.atomspace.add_node(
            types.ConceptNode, 'frog', TruthValue(.001, 0.7142857313156128))
        self.swan_bird = self.atomspace.add_link(
            types.InheritanceLink, [self.swan, self.bird], TruthValue(1, 0.0011237357975915074))
        self.bird_animal = self.atomspace.add_link(
            types.InheritanceLink, [self.bird, self.animal], TruthValue(1, 0.0011237357975915074))
        self.bird.sti = 9
        self.swan.sti = 9

        self.api = RESTAPI(self.atomspace)
        self.client = self.api.test()

    def tearDown(self):
        del self.api
        del self.client


    def mkatom(self, json_atom):
        post_response = self.client.post(self.uri + 'atoms',
                                         data=json.dumps(json_atom),
                                         headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']
        return post_result

    def mkswan(self):
        return self.mkatom(
                {'type': 'ConceptNode', 'name': 'swan',
                'truthvalue': {'type': 'simple',
                'details': {'strength': 0.001, 'count': 0.9}}})

    def mkbird(self):
        return self.mkatom(
                {'type': 'ConceptNode', 'name': 'bird',
                'truthvalue': {'type': 'simple',
                'details': {'strength': 0.01, 'count': 0.9}}})

    def mkanimal(self):
        return self.mkatom(
                {'type': 'ConceptNode', 'name': 'animal',
                'truthvalue': {'type': 'simple',
                'details': {'strength': 0.1, 'count': 0.95}}})

    def mkbird_animal(self):
        jbird = self.mkbird()
        janimal = self.mkanimal()
        return self.mkatom(
            {'type': 'InheritanceLink', 'truthvalue':
            {'type': 'simple', 'details': {'strength': 1.0, 'count': 0.9}},
             'outgoing': [jbird['handle'], janimal['handle']]})

    def get_atom(self, handle):
        get_response_handle = \
            self.client.get(self.uri + 'atoms/' + str(handle))
        get_result_handle = \
            json.loads(get_response_handle.data)['result']['atoms'][0]
        return get_result_handle

    def test_a_post_and_get_node(self):
        # Create a test node
        truthvalue = {'type': 'simple',
                      'details': {'strength': 0.08, 'count': 0.2}}
        jatom = {'type': 'ConceptNode',
                'name': 'giant_frog',
                'truthvalue': truthvalue}

        post_response = self.client.post(self.uri + 'atoms',
                                         data=json.dumps(jatom),
                                         headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']

        # Verify values returned by the POST request
        assert post_result['type'] == jatom['type']
        assert post_result['name'] == jatom['name']
        assert post_result['truthvalue']['type'] == truthvalue['type']
        assert_almost_equals(
            float(post_result['truthvalue']['details']['strength']),
            truthvalue['details']['strength'], places=5)
        assert_almost_equals(
            float(post_result['truthvalue']['details']['count']),
            truthvalue['details']['count'], places=5)

        # Compare to the values created in the AtomSpace
        frog = self.atomspace.add_node(
            types.ConceptNode, 'giant_frog',
            TruthValue(.08, count_to_confidence(0.2)))
        atomspace_result = frog
        assert post_result['name'] == atomspace_result.name
        assert types.__dict__.get(post_result['type']) == atomspace_result.type
        assert TruthValue(
            float(post_result['truthvalue']['details']['strength']),
            count_to_confidence(
                float(post_result['truthvalue']['details']['count']))) \
            == atomspace_result.tv

        # Get by handle and compare
        handle = post_result['handle']
        get_response_handle = \
            self.client.get(self.uri + 'atoms/' + str(handle))
        get_result_handle = \
            json.loads(get_response_handle.data)['result']['atoms'][0]
        assert post_result == get_result_handle

        # Get by name and compare
        name = post_result['name']
        get_response_name = self.client.get(self.uri + 'atoms?name=' + name)
        get_result_name = \
            json.loads(get_response_name.data)['result']['atoms'][0]
        assert post_result == get_result_name

        # Get by name and type and compare
        type = post_result['type']
        get_response_name_type = \
            self.client.get(self.uri + 'atoms?name=' + name + '&type=' + type)
        get_result_name_type = \
            json.loads(get_response_name_type.data)['result']['atoms'][0]
        assert post_result == get_result_name_type

    def test_b_post_and_get_link(self):
        jswan = self.mkswan()
        janimal = self.mkanimal()

        # Create a test link between swan and animal
        truthvalue = \
            {'type': 'simple', 'details': {'strength': 0.5, 'count': 0.4}}
        atom = {'type': 'InheritanceLink', 'truthvalue': truthvalue,
                'outgoing': [jswan['handle'], janimal['handle']]}

        post_response = self.client.post(
            self.uri + 'atoms', data=json.dumps(atom), headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']

        # Verify values returned by the POST request
        assert post_result['type'] == atom['type']
        assert post_result['truthvalue']['type'] == truthvalue['type']
        assert_almost_equals(
            float(post_result['truthvalue']['details']['strength']),
            truthvalue['details']['strength'], places=5)
        assert_almost_equals(
            float(post_result['truthvalue']['details']['count']),
            truthvalue['details']['count'], places=5)
        assert jswan['handle'] in post_result['outgoing']
        assert janimal['handle'] in post_result['outgoing']

        # Compare to the values created in the AtomSpace
        swan_animal = self.atomspace.add_link(
            types.InheritanceLink, [self.swan, self.animal],
            TruthValue(0.5, count_to_confidence(0.4)))

        atomspace_result = swan_animal
        assert types.__dict__.get(post_result['type']) == atomspace_result.type
        assert TruthValue(
            float(post_result['truthvalue']['details']['strength']),
            count_to_confidence(
                float(post_result['truthvalue']['details']['count']))) \
            == atomspace_result.tv

        # Get by handle and compare
        handle = post_result['handle']
        get_response_handle = \
            self.client.get(self.uri + 'atoms/' + str(handle))
        get_result_handle = \
            json.loads(get_response_handle.data)['result']['atoms'][0]
        assert post_result == get_result_handle

        # Check if the link is in the incoming set of each of the nodes
        jswan = self.get_atom(jswan['handle'])
        janimal = self.get_atom(janimal['handle'])
        for h in post_result['outgoing']:
            assert post_result['handle'] in jswan['incoming']
            assert post_result['handle'] in janimal['incoming']

    def test_c_put_and_get_tv_av_node(self):
        jswan = self.mkswan()

        truthvalue = \
            {'type': 'simple', 'details': {'strength': 0.005, 'count': 0.8}}
        attentionvalue = {'sti': 9, 'lti': 2, 'vlti': True}
        atom_update = \
            {'truthvalue': truthvalue, 'attentionvalue': attentionvalue}
        put_response = self.client.put(
            self.uri + 'atoms/' + str(jswan['handle']),
            data=json.dumps(atom_update),
            headers=self.headers)
        put_result = json.loads(put_response.data)['atoms']

        # Verify values returned by the PUT request
        assert put_result['handle'] == jswan['handle']
        assert_almost_equals(
            float(put_result['truthvalue']['details']['strength']),
            truthvalue['details']['strength'], places=5)
        assert_almost_equals(
            float(put_result['truthvalue']['details']['count']),
            truthvalue['details']['count'], places=5)
        assert put_result['attentionvalue']['sti'] == attentionvalue['sti']
        assert put_result['attentionvalue']['lti'] == attentionvalue['lti']
        assert put_result['attentionvalue']['vlti'] == attentionvalue['vlti']

        # Compare to the values updated in the AtomSpace
        atomspace_result = self.swan
        assert types.__dict__.get(put_result['type']) == atomspace_result.type
        assert TruthValue(
            float(put_result['truthvalue']['details']['strength']),
            count_to_confidence(
                float(put_result['truthvalue']['details']['count']))) \
            == atomspace_result.tv
        assert put_result['attentionvalue'] == atomspace_result.av

        # Get by handle and compare
        get_response = \
            self.client.get(self.uri + 'atoms/' + str(jswan['handle']))
        get_result = json.loads(get_response.data)['result']['atoms'][0]
        assert put_result == get_result

    def test_d_put_and_get_tv_av_link(self):
        jatom = self.mkbird_animal()
        truthvalue = \
            {'type': 'simple', 'details': {'strength': 0.9, 'count': 0.95}}
        attentionvalue = {'sti': 6, 'lti': 3, 'vlti': True}
        atom_update = \
            {'truthvalue': truthvalue, 'attentionvalue': attentionvalue}
        put_response =\
            self.client.put(
                self.uri + 'atoms/' + str(jatom['handle']),
                data=json.dumps(atom_update),
                headers=self.headers)
        put_result = json.loads(put_response.data)['atoms']

        # Verify values returned by the PUT request
        assert put_result['handle'] == jatom['handle']
        assert_almost_equals(
            float(put_result['truthvalue']['details']['strength']),
            truthvalue['details']['strength'], places=5)
        assert_almost_equals(
            float(put_result['truthvalue']['details']['count']),
            truthvalue['details']['count'], places=5)
        assert put_result['attentionvalue']['sti'] == attentionvalue['sti']
        assert put_result['attentionvalue']['lti'] == attentionvalue['lti']
        assert put_result['attentionvalue']['vlti'] == attentionvalue['vlti']

        # Compare to the values updated in the AtomSpace
        atomspace_result = self.bird_animal
        assert types.__dict__.get(put_result['type']) == atomspace_result.type
        assert TruthValue(
            float(put_result['truthvalue']['details']['strength']),
            count_to_confidence(
                float(put_result['truthvalue']['details']['count']))) \
            == atomspace_result.tv
        assert put_result['attentionvalue'] == atomspace_result.av

        # Get by handle and compare
        get_response = \
            self.client.get(self.uri + 'atoms/' + str(jatom['handle']))
        get_result = json.loads(get_response.data)['result']['atoms'][0]
        assert put_result == get_result

    def test_e_post_revise_existing_node(self):
        # Attempt to create a node, where a node already exists with that name
        # and type. Should revise existing node.
        existing_atom = self.bird

        truthvalue = \
            {'type': 'simple', 'details': {'strength': 0.1, 'count': 0.95}}
        atom = \
            {'type': 'ConceptNode', 'name': 'bird', 'truthvalue': truthvalue}

        post_response = self.client.post(self.uri + 'atoms',
                                         data=json.dumps(atom),
                                         headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']

        # Verify values returned by the POST request
        assert_almost_equals(
            float(post_result['truthvalue']['details']['strength']),
            truthvalue['details']['strength'], places=5)
        assert_almost_equals(
            float(post_result['truthvalue']['details']['count']),
            truthvalue['details']['count'], places=5)

        # Compare to the values updated in the AtomSpace
        assert TruthValue(
            float(post_result['truthvalue']['details']['strength']),
            count_to_confidence(
                float(post_result['truthvalue']['details']['count']))) \
               == existing_atom.tv

    def test_f_post_revise_existing_link(self):
        # Attempt to create a link, where a link already exists with that name
        # and outgoing set.
        # Should revise existing link.
        existing_atom = self.bird_animal
        jbird_animal = self.mkbird_animal()
        truthvalue = \
            {'type': 'simple', 'details': {'strength': 0.1, 'count': 0.95}}
        outgoing = jbird_animal['outgoing']
        atom = {'type': 'InheritanceLink',
                'truthvalue': truthvalue,
                'outgoing': outgoing}

        post_response = self.client.post(
            self.uri + 'atoms', data=json.dumps(atom), headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']

        # Verify values returned by the POST request
        assert post_result['outgoing'] == outgoing
        assert_almost_equals(
            float(post_result['truthvalue']['details']['strength']),
            truthvalue['details']['strength'], places=5)
        assert_almost_equals(
            float(post_result['truthvalue']['details']['count']),
            truthvalue['details']['count'], places=5)

        # Compare to the values updated in the AtomSpace
        assert TruthValue(
            float(post_result['truthvalue']['details']['strength']),
            count_to_confidence(
                float(post_result['truthvalue']['details']['count']))) \
               == existing_atom.tv

    # @raises(IndexError)
    def test_g_delete_node(self):
        jswan = self.mkswan()
        handle = jswan['handle']
        get_response = self.client.get(self.uri + 'atoms/' + str(handle))
        get_result = json.loads(get_response.data)['result']['atoms'][0]

        old_size = self.atomspace.size()
        delete_response = \
            self.client.delete(self.uri + 'atoms/' + str(handle))
        delete_result = json.loads(delete_response.data)['result']

        assert delete_result['success']
        assert delete_result['handle'] == get_result['handle']

        # Confirm the atom isn't contained in the AtomSpace anymore
        # Actually, the python bindings don't provide a way to ask
        # this question. So we check the size, instead.  Should shrink
        # by 2, since both the swan, and the inhertance link get
        # deleted.
        new_size = self.atomspace.size()
        assert new_size + 2 == old_size

    # @raises(IndexError)
    def test_h_delete_link(self):
        jatom = self.mkbird_animal()
        handle = jatom['handle']
        get_response = self.client.get(self.uri + 'atoms/' + str(handle))
        get_result = json.loads(get_response.data)['result']['atoms'][0]

        old_size = self.atomspace.size()
        delete_response = \
            self.client.delete(self.uri + 'atoms/' + str(handle))
        delete_result = json.loads(delete_response.data)['result']

        assert delete_result['success']
        assert delete_result['handle'] == get_result['handle']

        # Confirm the atom isn't contained in the AtomSpace anymore
        # Actually, the python bindings don't provide a way to ask
        # this question. So we check the size, instead.  Should shrink
        # by 1, since only the inhertance link gets deleted.
        new_size = self.atomspace.size()
        assert new_size + 1 == old_size

    def test_j_get_types(self):
        # Verify that a list of valid atom types was returned
        get_response = self.client.get(self.uri + 'types')
        get_result = json.loads(get_response.data)['types']
        assert len(get_result) > 0
        assert get_result.__contains__('ConceptNode')

    def test_k_tv_filter(self):
        # Should return animal, swan_bird, bird_animal (3 atoms)
        get_response = self.client.get(self.uri + 'atoms?tvStrengthMin=0.1')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 3

        # Should return frog (1 atom)
        get_response = self.client.get(self.uri + 'atoms?tvConfidenceMin=0.7')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 1

        # Should return frog (1 atom)
        get_response = self.client.get(self.uri + 'atoms?tvCountMin=2000')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 1

    def test_l_include_incoming_outgoing(self):
        # Should return bird and swan (2 atoms)
        get_response = self.client.get(
            self.uri +
            'atoms?filterby=stirange&stimin=1&includeIncoming=false')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 2

        # Should additionally return swan_bird and bird_animal (4 atoms)
        get_response = self.client.get(
            self.uri + 'atoms?filterby=stirange&stimin=1&includeIncoming=true')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 4

        # Should additionally return animal (5 atoms)
        get_response = \
            self.client.get(
                self.uri + 'atoms?filterby=stirange&stimin=1&'
                           'includeIncoming=true&includeOutgoing=true')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 5

    def test_m_scheme_command(self):
        # Test an arbitrary Scheme command to ensure the binding is working
        # properly
        # XXX Emptied because the scheme command (i.e cog-af-boundary) has been removed.
        pass 
    def test_n_dot_export(self):
        # Export the atomspace to DOT format and ensure that there is a
        # properly defined DOT header created and the correct atoms are
        # included in the description

        # TODO: The Python module "graphviz" needs to be added to ocpkg, so
        # that this dependency will be available for the continuous integration
        # system
        try:
            from graph_description import dot

            get_response = self.client.get(
                self.uri +
                'atoms?filterby=attentionalfocus&dot=True')
            get_result = json.loads(get_response.data)['result']
            assert get_result.startswith("// OpenCog Graph")
            assert "digraph" in get_result
            assert "swan" in get_result
            assert "bird" in get_result
            assert get_result.count("label") == 2
        except ImportError:
            pass
Beispiel #23
0
class TestRESTApi():
    """
    Unit tests for the OpenCog REST API.

    See: opencog/python/web/api/apimain.py for the class definitions
    Documentation: http://wiki.opencog.org/w/REST_API
    """
    def setUp(self):
        self.uri = '/api/v1.1/'
        self.headers = {'content-type': 'application/json'}

        # Populate a test AtomSpace
        self.atomspace = AtomSpace()
        self.animal = self.atomspace.add_node(types.ConceptNode, 'animal',
                                              TruthValue(.1, .95))
        self.bird = self.atomspace.add_node(types.ConceptNode, 'bird',
                                            TruthValue(.01, .9))
        self.swan = self.atomspace.add_node(types.ConceptNode, 'swan',
                                            TruthValue(.001, .9))
        self.frog = self.atomspace.add_node(types.ConceptNode, 'frog',
                                            TruthValue(.001, 2000))
        self.swan_bird = self.atomspace.add_link(types.InheritanceLink,
                                                 [self.swan, self.bird],
                                                 TruthValue(1, .9))
        self.bird_animal = self.atomspace.add_link(types.InheritanceLink,
                                                   [self.bird, self.animal],
                                                   TruthValue(1, .9))
        self.bird.av = {'sti': 9}
        self.swan.av = {'sti': 9}

        self.api = RESTAPI(self.atomspace)
        self.client = self.api.test()

    def tearDown(self):
        del self.api
        del self.client

    def test_post_and_get_node(self):
        # Create a test node
        truthvalue = {
            'type': 'simple',
            'details': {
                'strength': 0.08,
                'count': 0.2
            }
        }
        atom = {
            'type': 'ConceptNode',
            'name': 'giant_frog',
            'truthvalue': truthvalue
        }

        post_response = self.client.post(self.uri + 'atoms',
                                         data=json.dumps(atom),
                                         headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']

        # Verify values returned by the POST request
        assert post_result['type'] == atom['type']
        assert post_result['name'] == atom['name']
        assert post_result['truthvalue']['type'] == truthvalue['type']
        assert_almost_equals(float(
            post_result['truthvalue']['details']['strength']),
                             truthvalue['details']['strength'],
                             places=5)
        assert_almost_equals(float(
            post_result['truthvalue']['details']['count']),
                             truthvalue['details']['count'],
                             places=5)

        # Compare to the values created in the AtomSpace
        atomspace_result = self.atomspace[Handle(post_result['handle'])]
        assert Handle(post_result['handle']) == atomspace_result.h
        assert post_result['name'] == atomspace_result.name
        assert types.__dict__.get(post_result['type']) == atomspace_result.type
        assert TruthValue(
            float(post_result['truthvalue']['details']['strength']),
            float(post_result['truthvalue']['details']
                  ['count'])) == atomspace_result.tv

        # Get by handle and compare
        handle = post_result['handle']
        get_response_handle = self.client.get(self.uri + 'atoms/' +
                                              str(handle))
        get_result_handle = json.loads(
            get_response_handle.data)['result']['atoms'][0]
        assert post_result == get_result_handle

        # Get by name and compare
        name = post_result['name']
        get_response_name = self.client.get(self.uri + 'atoms?name=' + name)
        get_result_name = json.loads(
            get_response_name.data)['result']['atoms'][0]
        assert post_result == get_result_name

        # Get by name and type and compare
        type = post_result['type']
        get_response_name_type = self.client.get(self.uri + 'atoms?name=' +
                                                 name + '&type=' + type)
        get_result_name_type = json.loads(
            get_response_name_type.data)['result']['atoms'][0]
        assert post_result == get_result_name_type

    def test_post_and_get_link(self):
        # Create a test link between swan and animal
        truthvalue = {
            'type': 'simple',
            'details': {
                'strength': 0.5,
                'count': 0.4
            }
        }
        atom = {
            'type': 'InheritanceLink',
            'truthvalue': truthvalue,
            'outgoing': [self.swan.h.value(),
                         self.animal.h.value()]
        }

        post_response = self.client.post(self.uri + 'atoms',
                                         data=json.dumps(atom),
                                         headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']

        # Verify values returned by the POST request
        assert post_result['type'] == atom['type']
        assert post_result['truthvalue']['type'] == truthvalue['type']
        assert_almost_equals(float(
            post_result['truthvalue']['details']['strength']),
                             truthvalue['details']['strength'],
                             places=5)
        assert_almost_equals(float(
            post_result['truthvalue']['details']['count']),
                             truthvalue['details']['count'],
                             places=5)
        assert self.swan.h.value() in post_result['outgoing']
        assert self.animal.h.value() in post_result['outgoing']

        # Compare to the values created in the AtomSpace
        atomspace_result = self.atomspace[Handle(post_result['handle'])]
        assert Handle(post_result['handle']) == atomspace_result.h
        assert types.__dict__.get(post_result['type']) == atomspace_result.type
        assert TruthValue(
            float(post_result['truthvalue']['details']['strength']),
            float(post_result['truthvalue']['details']
                  ['count'])) == atomspace_result.tv

        # Get by handle and compare
        handle = post_result['handle']
        get_response_handle = self.client.get(self.uri + 'atoms/' +
                                              str(handle))
        get_result_handle = json.loads(
            get_response_handle.data)['result']['atoms'][0]
        assert post_result == get_result_handle

        # Check if the link is in the incoming set of each of the nodes
        for h in post_result['outgoing']:
            assert Handle(post_result['handle']) in [
                atom.h for atom in self.atomspace[Handle(h)].incoming
            ]

    def test_put_and_get_tv_av_node(self):
        atom = self.swan
        truthvalue = {
            'type': 'simple',
            'details': {
                'strength': 0.005,
                'count': 0.8
            }
        }
        attentionvalue = {'sti': 9, 'lti': 2, 'vlti': True}
        atom_update = {
            'truthvalue': truthvalue,
            'attentionvalue': attentionvalue
        }
        put_response = self.client.put(self.uri + 'atoms/' +
                                       str(atom.h.value()),
                                       data=json.dumps(atom_update),
                                       headers=self.headers)
        put_result = json.loads(put_response.data)['atoms']

        # Verify values returned by the PUT request
        assert put_result['handle'] == atom.h.value()
        assert_almost_equals(float(
            put_result['truthvalue']['details']['strength']),
                             truthvalue['details']['strength'],
                             places=5)
        assert_almost_equals(float(
            put_result['truthvalue']['details']['count']),
                             truthvalue['details']['count'],
                             places=5)
        assert put_result['attentionvalue']['sti'] == attentionvalue['sti']
        assert put_result['attentionvalue']['lti'] == attentionvalue['lti']
        assert put_result['attentionvalue']['vlti'] == attentionvalue['vlti']

        # Compare to the values updated in the AtomSpace
        atomspace_result = self.atomspace[Handle(put_result['handle'])]
        assert Handle(put_result['handle']) == atomspace_result.h
        assert types.__dict__.get(put_result['type']) == atomspace_result.type
        assert TruthValue(
            float(put_result['truthvalue']['details']['strength']),
            float(put_result['truthvalue']['details']
                  ['count'])) == atomspace_result.tv
        assert put_result['attentionvalue'] == atomspace_result.av

        # Get by handle and compare
        get_response = self.client.get(self.uri + 'atoms/' +
                                       str(atom.h.value()))
        get_result = json.loads(get_response.data)['result']['atoms'][0]
        assert put_result == get_result

    def test_put_and_get_tv_av_link(self):
        atom = self.bird_animal
        truthvalue = {
            'type': 'simple',
            'details': {
                'strength': 0.9,
                'count': 0.95
            }
        }
        attentionvalue = {'sti': 6, 'lti': 3, 'vlti': True}
        atom_update = {
            'truthvalue': truthvalue,
            'attentionvalue': attentionvalue
        }
        put_response =\
            self.client.put(self.uri + 'atoms/' + str(atom.h.value()), data=json.dumps(atom_update), headers=self.headers)
        put_result = json.loads(put_response.data)['atoms']

        # Verify values returned by the PUT request
        assert put_result['handle'] == atom.h.value()
        assert_almost_equals(float(
            put_result['truthvalue']['details']['strength']),
                             truthvalue['details']['strength'],
                             places=5)
        assert_almost_equals(float(
            put_result['truthvalue']['details']['count']),
                             truthvalue['details']['count'],
                             places=5)
        assert put_result['attentionvalue']['sti'] == attentionvalue['sti']
        assert put_result['attentionvalue']['lti'] == attentionvalue['lti']
        assert put_result['attentionvalue']['vlti'] == attentionvalue['vlti']

        # Compare to the values updated in the AtomSpace
        atomspace_result = self.atomspace[Handle(put_result['handle'])]
        assert Handle(put_result['handle']) == atomspace_result.h
        assert types.__dict__.get(put_result['type']) == atomspace_result.type
        assert TruthValue(
            float(put_result['truthvalue']['details']['strength']),
            float(put_result['truthvalue']['details']
                  ['count'])) == atomspace_result.tv
        assert put_result['attentionvalue'] == atomspace_result.av

        # Get by handle and compare
        get_response = self.client.get(self.uri + 'atoms/' +
                                       str(atom.h.value()))
        get_result = json.loads(get_response.data)['result']['atoms'][0]
        assert put_result == get_result

    def test_post_revise_existing_node(self):
        # Attempt to create a node, where a node already exists with that name and type. Should revise existing node.
        existing_atom = self.bird

        truthvalue = {
            'type': 'simple',
            'details': {
                'strength': 0.1,
                'count': 0.95
            }
        }
        atom = {
            'type': 'ConceptNode',
            'name': 'bird',
            'truthvalue': truthvalue
        }

        post_response = self.client.post(self.uri + 'atoms',
                                         data=json.dumps(atom),
                                         headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']

        # Verify values returned by the POST request
        assert_almost_equals(float(
            post_result['truthvalue']['details']['strength']),
                             truthvalue['details']['strength'],
                             places=5)
        assert_almost_equals(float(
            post_result['truthvalue']['details']['count']),
                             truthvalue['details']['count'],
                             places=5)

        # Compare to the values updated in the AtomSpace
        assert post_result['handle'] == existing_atom.h.value()
        assert TruthValue(
            float(post_result['truthvalue']['details']['strength']),
            float(post_result['truthvalue']['details']
                  ['count'])) == existing_atom.tv

    def test_post_revise_existing_link(self):
        # Attempt to create a link, where a link already exists with that name and outgoing set.
        # Should revise existing link.
        existing_atom = self.bird_animal
        truthvalue = {
            'type': 'simple',
            'details': {
                'strength': 0.1,
                'count': 0.95
            }
        }
        outgoing = [a.h.value() for a in existing_atom.out]
        atom = {
            'type': 'InheritanceLink',
            'truthvalue': truthvalue,
            'outgoing': outgoing
        }

        post_response = self.client.post(self.uri + 'atoms',
                                         data=json.dumps(atom),
                                         headers=self.headers)
        post_result = json.loads(post_response.data)['atoms']

        # Verify values returned by the POST request
        assert post_result['outgoing'] == outgoing
        assert_almost_equals(float(
            post_result['truthvalue']['details']['strength']),
                             truthvalue['details']['strength'],
                             places=5)
        assert_almost_equals(float(
            post_result['truthvalue']['details']['count']),
                             truthvalue['details']['count'],
                             places=5)

        # Compare to the values updated in the AtomSpace
        assert post_result['handle'] == existing_atom.h.value()
        assert TruthValue(
            float(post_result['truthvalue']['details']['strength']),
            float(post_result['truthvalue']['details']
                  ['count'])) == existing_atom.tv

    @raises(IndexError)
    def test_delete_node(self):
        atom = self.swan
        handle = atom.h.value()
        get_response = self.client.get(self.uri + 'atoms/' + str(handle))
        get_result = json.loads(get_response.data)['result']['atoms'][0]

        delete_response = self.client.delete(self.uri + 'atoms/' +
                                             str(atom.h.value()))
        delete_result = json.loads(delete_response.data)['result']

        assert delete_result['success']
        assert delete_result['handle'] == get_result['handle']

        # Confirm the atom isn't contained in the AtomSpace anymore
        assert_raises(self.atomspace[atom.h], IndexError)

    @raises(IndexError)
    def test_delete_link(self):
        atom = self.bird_animal
        handle = atom.h.value()
        get_response = self.client.get(self.uri + 'atoms/' + str(handle))
        get_result = json.loads(get_response.data)['result']['atoms'][0]

        delete_response = self.client.delete(self.uri + 'atoms/' +
                                             str(atom.h.value()))
        delete_result = json.loads(delete_response.data)['result']

        assert delete_result['success']
        assert delete_result['handle'] == get_result['handle']

        # Confirm the atom isn't contained in the AtomSpace anymore
        assert_raises(self.atomspace[atom.h], IndexError)

    def test_get_atoms_by_av(self):
        # Assign some STI values
        self.atomspace.set_av(h=self.bird.h, sti=9)
        self.atomspace.set_av(h=self.swan.h, sti=20)
        self.atomspace.set_av(h=self.bird_animal.h, sti=15)
        self.atomspace.set_av(h=self.animal.h, sti=0)

        get_response = self.client.get(self.uri +
                                       'atoms?filterby=attentionalfocus')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 3
        assert set([atom['handle'] for atom in get_result]) == set([
            self.bird.h.value(),
            self.swan.h.value(),
            self.bird_animal.h.value()
        ])

        get_response = self.client.get(self.uri +
                                       'atoms?filterby=stirange&stimin=15')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 2
        assert set([atom['handle'] for atom in get_result]) == set(
            [self.swan.h.value(),
             self.bird_animal.h.value()])

        get_response = self.client.get(
            self.uri + 'atoms?filterby=stirange&stimin=15&stimax=18')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 1
        assert set([atom['handle'] for atom in get_result
                    ]) == set([self.bird_animal.h.value()])

    def test_get_types(self):
        # Verify that a list of valid atom types was returned
        get_response = self.client.get(self.uri + 'types')
        get_result = json.loads(get_response.data)['types']
        assert len(get_result) > 0
        assert get_result.__contains__('ConceptNode')

    def test_tv_filter(self):
        # Should return animal, swan_bird, bird_animal (3 atoms)
        get_response = self.client.get(self.uri + 'atoms?tvStrengthMin=0.1')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 3

        # Should return frog (1 atom)
        get_response = self.client.get(self.uri + 'atoms?tvConfidenceMin=0.7')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 1

        # Should return frog (1 atom)
        get_response = self.client.get(self.uri + 'atoms?tvCountMin=2000')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 1

    def test_include_incoming_outgoing(self):
        # Should return bird and swan (2 atoms)
        get_response = self.client.get(
            self.uri +
            'atoms?filterby=stirange&stimin=1&includeIncoming=false')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 2

        # Should additionally return swan_bird and bird_animal (4 atoms)
        get_response = self.client.get(
            self.uri + 'atoms?filterby=stirange&stimin=1&includeIncoming=true')
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 4

        # Should additionally return animal (5 atoms)
        get_response = self.client.get(
            self.uri +
            'atoms?filterby=stirange&stimin=1&includeIncoming=true&includeOutgoing=true'
        )
        get_result = json.loads(get_response.data)['result']['atoms']
        assert len(get_result) == 5