From 3aedf53f582cfe2cc1df8dc990b885760da28518 Mon Sep 17 00:00:00 2001
From: Marco Mornati <mmornati@byte-code.com>
Date: Thu, 6 Nov 2008 09:47:41 +0100
Subject: [PATCH] Updated Func-Java Binding to support func latest version functions

---
 bindings/func-java/pom.xml                         |   43 +++-
 .../src/main/groovy/org/func/FuncFactory.groovy    |   26 ++
 .../src/main/groovy/org/func/FuncImpl.groovy       |  289 +++++++++++++++++---
 .../func-java/src/main/java/org/func/Func.java     |   83 ++++++-
 .../func-java/src/main/resources/log4j.properties  |    5 +
 .../src/test/groovy/FuncFactoryTest.groovy         |   32 ---
 .../src/test/groovy/org/func/FuncImplTest.groovy   |  127 ++++++++-
 7 files changed, 526 insertions(+), 79 deletions(-)
 create mode 100644 bindings/func-java/src/main/resources/log4j.properties
 delete mode 100644 bindings/func-java/src/test/groovy/FuncFactoryTest.groovy

diff --git a/bindings/func-java/pom.xml b/bindings/func-java/pom.xml
index 01668a4..4655661 100644
--- a/bindings/func-java/pom.xml
+++ b/bindings/func-java/pom.xml
@@ -5,7 +5,7 @@
     <groupId>org.func</groupId>
     <artifactId>func-java</artifactId>
     <packaging>jar</packaging>
-    <version>1.0-SNAPSHOT</version>
+    <version>1.7</version>
     <name>Func-Java Bindings</name>
     <url>https://fedorahosted.org/func</url>
 
@@ -13,9 +13,9 @@
     <dependencies>
 
         <dependency>
-            <groupId>org.jvyaml</groupId>
-            <artifactId>jvyaml</artifactId>
-            <version>1.1</version>
+            <groupId>org.json</groupId>
+            <artifactId>json</artifactId>
+            <version>20070829</version>
         </dependency>
 
         <dependency>
@@ -25,6 +25,12 @@
         </dependency>
 
         <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+            <version>1.2.14</version>
+        </dependency>
+
+        <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <version>3.8.1</version>
@@ -85,6 +91,35 @@
                     </execution>
                 </executions>
             </plugin>
+            <plugin>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <addClasspath>true</addClasspath>
+                            <classpathPrefix>lib</classpathPrefix>
+                        </manifest>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>funcjava</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>directory</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                <descriptor>${basedir}/assembly.xml</descriptor>
+                            </descriptors>
+                            <finalName>executable</finalName>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
         </plugins>
     </build>
 
diff --git a/bindings/func-java/src/main/groovy/org/func/FuncFactory.groovy b/bindings/func-java/src/main/groovy/org/func/FuncFactory.groovy
index 84d3d7b..078ca40 100644
--- a/bindings/func-java/src/main/groovy/org/func/FuncFactory.groovy
+++ b/bindings/func-java/src/main/groovy/org/func/FuncFactory.groovy
@@ -34,6 +34,19 @@ class FuncFactory {
         return funcImplementation
     }
 
+
+    /**
+     * Factory class method. You need to call this method to obtain an instance of Func classes
+     * @param aSync boolean to set how you want to call func (true=async, false=normal)
+     * @param nForks number of threads you want to use for your func call
+     * @return Func instances. To use for func invokation.
+     */
+    public static Func getFunc(boolean aSync, int nForks) {
+        Func funcImplementation = new FuncImpl(aSync, nForks)
+
+        return funcImplementation
+    }
+
     /**
      * Factory class method. You need to call this method to obtain an instance of Func classes
      * @param funcTransmit You can specify folder where your func-transmit is located. By default it must be in your path.
@@ -45,4 +58,17 @@ class FuncFactory {
         return funcImplementation
     }
 
+    /**
+     * Factory class method. You need to call this method to obtain an instance of Func classes
+     * @param funcTransmit You can specify folder where your func-transmit is located. By default it must be in your path.
+     * @param aSync boolean to set how you want to call func (true=async, false=normal)
+     * @param nForks number of threads you want to use for your func call
+     * @return Func instances. To use for func invokation. 
+     */
+    public static Func getFunc(String funcTransmit, boolean aSync, int nForks) {
+        Func funcImplementation = new FuncImpl(funcTransmit, aSync, nForks)
+
+        return funcImplementation
+    }
+
 }
\ No newline at end of file
diff --git a/bindings/func-java/src/main/groovy/org/func/FuncImpl.groovy b/bindings/func-java/src/main/groovy/org/func/FuncImpl.groovy
index 332f72c..420a27b 100644
--- a/bindings/func-java/src/main/groovy/org/func/FuncImpl.groovy
+++ b/bindings/func-java/src/main/groovy/org/func/FuncImpl.groovy
@@ -1,8 +1,11 @@
 package org.func
 
 import org.func.exceptions.FuncCommunicationException
-import org.jvyaml.YAML
 import org.func.exceptions.CertmasterException
+import org.apache.log4j.Logger
+import org.json.JSONObject
+import org.json.JSONArray
+import org.json.JSONString
 
 /**
  *  Copyright (C) 2008, Byte-Code srl <http://www.byte-code.com>
@@ -29,83 +32,237 @@ import org.func.exceptions.CertmasterException
  */
 class FuncImpl implements Func {
 
-    private funcTransmit = "func-transmit"
-    private func = "func"
+    private static Logger log = Logger.getLogger(Func.class.getName());
+
+    public static int JOB_ID_RUNNING = 0
+    public static int JOB_ID_FINISHED = 1
+    public static int JOB_ID_LOST_IN_SPACE = 2
+    public static int JOB_ID_PARTIAL = 3
+    public static int JOB_ID_REMOTE_ERROR = 4
+
+    private String funcTransmit = "func-transmit"
+    private String func = "func"
+    private boolean async = false
+    private int nforks = 1
 
     public FuncImpl() {
 
     }
 
+    public FuncImpl(boolean async, int nforks) {
+        this.async = async
+        this.nforks = nforks
+    }
+
+    public FuncImpl(String transmit, boolean async, int nforks) {
+        this.funcTransmit = transmit
+        this.async = async
+        this.nforks = nforks
+    }
+
     public FuncImpl(String transmit) {
         this.funcTransmit = transmit
     }
 
+    /* TODO: sistemare rendendo più snella e flessibile l'API */
+
     public Map call(String client, String module, String method) throws FuncCommunicationException {
-        this.call([client], module, method, null)
+        this.funcCall([client], module, method, null)
+    }
+
+    public Map call(String client, String module, String method, boolean async) throws FuncCommunicationException {
+        this.funcCall([client], module, method, null, async)
     }
 
     public Map call(List clients, String module, String method) throws FuncCommunicationException {
-        this.call(clients, module, method, null)
+        this.funcCall(clients, module, method, null)
+    }
+
+    public Map call(List clients, String module, String method, boolean async) throws FuncCommunicationException {
+        this.funcCall(clients, module, method, null, async)
     }
 
+
     public Map call(String client, String module, String method, String parameter) throws FuncCommunicationException {
-        this.call([client], module, method, [parameter])
+        this.funcCall([client], module, method, [parameter])
+    }
+
+    public Map call(String client, String module, String method, String parameter, boolean async) throws FuncCommunicationException {
+        this.funcCall([client], module, method, [parameter], async)
+    }
+
+    public Map call(List clients, String module, String method, String parameter) throws FuncCommunicationException {
+        this.funcCall(clients, module, method, [parameter])
+    }
+
+    public Map call(List clients, String module, String method, String parameter, boolean async) throws FuncCommunicationException {
+        this.funcCall(client, module, method, [parameter], async)
+    }
+
+
+    public Map call(String client, String module, String method, List parameters) throws FuncCommunicationException {
+        return funcCall([client], module, method, parameters)
+    }
+
+    public Map call(String client, String module, String method, List parameters, boolean async) throws FuncCommunicationException {
+        return funcCall([client], module, method, parameters, async)
     }
 
     public Map call(List clients, String module, String method, List parameters) throws FuncCommunicationException {
-        return funcCall(clients, module, method, parameters)
+        this.funcCall(clients, module, method, parameters)
     }
 
+    public Map call(List clients, String module, String method, List parameters, boolean async) throws FuncCommunicationException {
+        this.funcCall(clients, module, method, parameters, async)
+    }
+    
     public Map listModules(String client) {
-        return this.listModules([client])
+        return this.listModules([client], this.async)
+    }
+
+    public Map listModules(String client, boolean async) {
+        return this.listModules([client], async)
     }
 
     public Map listModuleMethods(String client, String method) {
-        return this.listModuleMethods([client], method)
+        return this.listModuleMethods([client], method, this.async)
+    }
+
+    public Map listModuleMethods(String client, String method, boolean async) {
+        return this.listModuleMethods([client], method, async)
     }
 
     public Map listModules(List clients) {
-        return funcCall(clients, "system", "list_modules", null)
+        return this.listModules(clients, this.async)
+    }
+
+    public Map listModules(List clients, boolean async) {
+        log.debug("Calling func module list")
+        return funcCall(clients, "system", "list_modules", null, async)
     }
 
     public Map listModuleMethods(List clients, String module) {
-        return funcCall(clients, module, "list_methods", null)
+        return this.listModuleMethods(clients, module, this.async)
     }
 
+    public Map listModuleMethods(List clients, String module, boolean async) {
+        log.debug("Calling func method list for module ${module}")
+        return funcCall(clients, module, "list_methods", null, async)
+    }
 
-    public List listMinions() {
-        def minions = []
-        def commandToExecute = [func, "*", "list_minions"]
-        def proc = commandToExecute.execute()
-        proc.waitFor()
-        def procAnswer = proc.text
-        if (procAnswer) {
-            minions = procAnswer.split("\n")
+
+    public List listMinions() throws FuncCommunicationException {
+        log.debug("Calling list minions")
+        def minions = funcCall(["*"], null, 'list_minions', null, false, nforks)
+        def parsed = generateListFromJSON(minions)
+        if (parsed instanceof List) {
+            return (List)parsed
         } else {
-            throw new CertmasterException("Error communicating with certmaster")
+            return []
         }
-        return minions;
     }
 
+    public Map getProcessResponse(String pid) throws FuncCommunicationException {
+        log.debug("Getting status for pid ${pid}")
+        def funcResponse = this.funcCall(["*"], null, "job_status", ["${pid}"], false, 1)
+        log.debug("Process Response: ${funcResponse}")
+        def serialized = generateListFromJSON(funcResponse)
+        def response = ["status": serialized[0]]
+        if (serialized[1] instanceof JSONObject) {
+            response["result"] = generateMapFromJSON((JSONObject)serialized[1])
+        } else if (serialized[1] instanceof JSONArray) {
+            response["result"] = generateListFromJSON((JSONArray)serialized[1])
+        } else {
+            response["result"] = serialized[1]
+        }
+        response
+    }
+
+
+    public Map getMethodArguments(String client, String module, String method) {
+        log.debug("Getting list of arguments for module ${module} and method ${method}")
+        def funcResponse = this.funcCall([client], module, "get_method_args", null, false)
+        def returnedMap = [:]
+        if (funcResponse) {
+            log.debug "List of arguments returned from func: ${funcResponse}"
+            if (funcResponse[funcResponse.keySet().iterator().next()][method]!=null) {
+                returnedMap = funcResponse[funcResponse.keySet().iterator().next()][method]
+            }
+        }
+        log.debug("Map to return: ${returnedMap}")
+        return returnedMap;  
+    }
 
     private Map funcCall(List clients, String module, String method, List parameters) throws FuncCommunicationException {
-        def values = [clients: clientsCallPatch(clients), module: module, method: method, parameters: parameters]
-        def yamlDump = YAML.dump(values)
-        def commandToExecute = [funcTransmit]
+        return this.funcCall(clients, module, method, parameters, this.async)
+    }
+
+    private Map funcCall(List clients, String module, String method, List parameters, boolean async) throws FuncCommunicationException {
+        def funcResponse = funcCall(clients, module, method, parameters, async, nforks)
+        def response = [:]
+        if (funcResponse) {
+            if (async) {
+                if (funcResponse) {
+                    response['processid'] = funcResponse[1..-3]
+                } else {
+                    //TODO: Verify if there's any case
+                    throw new FuncCommunicationException("Error with the response for async call: ${funcResponse}")
+                }
+            } else {
+                if (funcResponse instanceof JSONArray) {
+                    response = generateListFromJSON(funcResponse)
+                } else if (funcResponse instanceof JSONObject) {
+                    response = generateMapFromJSON(funcResponse)
+                }
+            }
+        } else {
+            throw new FuncCommunicationException("Error communicating with func: ${funcResponse}")
+        }
+
+        return response
+    }
+
+    private Object funcCall(List clients, String module, String method, List parameters, boolean async, int nforks) throws FuncCommunicationException {
+        def values = [:]
+        if (clients != null && clients.size() > 0) {
+            values['clients'] = clientsCallPatch(clients)
+        }
+        if (module) {
+            values['module'] = module
+        }
+        if (method) {
+            values['method'] = method
+        }
+        if (parameters != null && parameters.size() > 0) {
+            values['parameters'] = parameters
+        }
+
+        if (async) {
+            values['async'] = true
+        } else {
+            values['async'] = 0
+        }
+        values['nforks'] = this.nforks
+        JSONObject jsonObj = new JSONObject(values)
+        log.debug("Calling JSon Values: ${jsonObj.toString()}")
+        def commandToExecute = [funcTransmit, "-j"]
+        log.debug "Command to execute: ${commandToExecute}"
         def proc = commandToExecute.execute()
-        proc.withWriter {writer -> writer << yamlDump }
+        proc.withWriter {writer -> writer << jsonObj.toString()}
         proc.waitFor()
         def procAnswer = proc.text
-        Map funcResponse = null
-        if (procAnswer) {
-            def response = YAML.load(procAnswer)
-            if (response instanceof Map) {
-                funcResponse = (Map) response
-            }
-        } else {
+        if (!procAnswer) {
             throw new FuncCommunicationException(procAnswer + " - Error reading answer from Func-Transmit Process!")
         }
-        return funcResponse
+        def response = null
+        if (procAnswer[0].equals("[")) {
+            response = new JSONArray(procAnswer)
+        } else if (procAnswer[0].equals("\"")) {
+            response = procAnswer
+        } else {
+            response = new JSONObject(procAnswer)
+        }
+        return response
     }
 
 
@@ -124,6 +281,47 @@ class FuncImpl implements Func {
         //===== PATCH ENDS
     }
 
+    private String parametersPatch(List parameters) {
+        String params = ""
+        parameters?.each {
+            if (!params.equals("")) {
+                params += " "
+            }
+            params += "${it}"
+        }
+        params
+    }
+
+    private Map generateMapFromJSON(JSONObject jsonObj) {
+        def map = [:]
+        jsonObj.keys()?.each {
+            def content = jsonObj.get(it)
+            if (content instanceof JSONObject) {
+                map[it] = generateMapFromJSON((JSONObject) content)
+            } else if (content instanceof JSONArray) {
+                map[it] = generateListFromJSON((JSONArray) content)
+            } else {
+                map[it] = content
+            }
+        }
+        map
+    }
+
+    private List generateListFromJSON(JSONArray jsonArray) {
+        def list = []
+        for (int i = 0; i < jsonArray.length(); i++) {
+            def content = jsonArray.get(i)
+            if (content instanceof JSONArray) {
+                list << generateListFromJSON((JSONArray) content)
+            } else if (content instanceof JSONObject) {
+                list << generateMapFromJSON((JSONObject) content)
+            } else {
+                list << content
+            }
+        }
+        list
+    }
+
     public void setFuncTransmit(String funcTransmit) {
         this.funcTransmit = funcTransmit
     }
@@ -132,4 +330,29 @@ class FuncImpl implements Func {
         return funcTransmit
     }
 
+    public void setFunc(String func) {
+        this.func = func
+    }
+
+    public String getFunc() {
+        return this.func
+    }
+
+    public void setAsync(boolean async) {
+        this.async = async
+    }
+
+    public boolean getAsync() {
+        return this.async
+    }
+
+    public void setNforks(int nforks) {
+        this.nforks = nforks
+    }
+
+    public int getNforks() {
+        return this.nforks
+    }
+
+
 }
\ No newline at end of file
diff --git a/bindings/func-java/src/main/java/org/func/Func.java b/bindings/func-java/src/main/java/org/func/Func.java
index d0d09a2..ea30188 100644
--- a/bindings/func-java/src/main/java/org/func/Func.java
+++ b/bindings/func-java/src/main/java/org/func/Func.java
@@ -33,8 +33,9 @@ public interface Func {
     /**
      * Function invoked to optain the list of func client (machine that you can control in your java application using this API).
      * @return List of String with machine hostname
+     * @throws FuncCommunicationException thrown if there is any kind of error in func invokation
      */
-    public List listMinions();
+    public List listMinions() throws FuncCommunicationException;
 
     /**
      * Caller for func-transmit with single client and no parameter
@@ -47,6 +48,17 @@ public interface Func {
     public Map call (String client, String module, String method) throws FuncCommunicationException;
 
     /**
+     * 
+     * @param client
+     * @param module
+     * @param method
+     * @param async
+     * @return
+     * @throws FuncCommunicationException
+     */
+    public Map call (String client, String module, String method, boolean async) throws FuncCommunicationException;
+
+    /**
      * Caller for func-transmit with list of clients and no parameter
      * @param clients List of Func clients.
      * @param module Name of func module (use listModules to obtain the available modules)
@@ -86,6 +98,18 @@ public interface Func {
     public Map call (List clients, String module, String method, List parameters) throws FuncCommunicationException;
 
     /**
+     * 
+     * @param clients
+     * @param module
+     * @param method
+     * @param parameters
+     * @param async
+     * @return
+     * @throws FuncCommunicationException
+     */
+    public Map call (List clients, String module, String method, List parameters, boolean async) throws FuncCommunicationException;
+
+    /**
      * Invoked to obtain for specified client the list of func module installed
      * 
      * @param client Name of the client to use with func. To invoke all defined clients use "*"
@@ -95,6 +119,16 @@ public interface Func {
     public Map listModules (String client) throws FuncCommunicationException;
 
     /**
+     * Invoked to obtain for specified client the list of func module installed
+     *
+     * @param client Name of the client to use with func. To invoke all defined clients use "*"
+     * @param async decide if you call will be sync or async
+     * @return Map with clientName as key and list of all installed func module as object
+     * @throws FuncCommunicationException thrown if there is any kind of error in func invokation
+     */
+    public Map listModules (String client, boolean async) throws FuncCommunicationException;
+
+    /**
      * Invoked to obtain for specified list of clients, the list of func module installed
      * @param clients List of func clients names.
      * @return Map with response divided for each client: clientName as key and list of all installed func module as value
@@ -103,6 +137,15 @@ public interface Func {
     public Map listModules (List clients) throws FuncCommunicationException;
 
     /**
+     * Invoked to obtain for specified list of clients, the list of func module installed
+     * @param clients List of func clients names.
+     * @param async decide if you call will be sync or async
+     * @return Map with response divided for each client: clientName as key and list of all installed func module as value
+     * @throws FuncCommunicationException thrown if there is any kind of error in func invokation
+     */
+    public Map listModules (List clients, boolean async) throws FuncCommunicationException;
+
+    /**
      * Invoked to obtain the list of methods for provided module and client
      * @param client client Name of the client to use with func. To invoke all defined clients use "*"
      * @param module name of func module for which you need a list of methods
@@ -112,6 +155,16 @@ public interface Func {
     public Map listModuleMethods (String client, String module) throws FuncCommunicationException;
 
     /**
+     * Invoked to obtain the list of methods for provided module and client
+     * @param client client Name of the client to use with func. To invoke all defined clients use "*"
+     * @param module name of func module for which you need a list of methods
+     * @param async decide if you call will be sync or async
+     * @return Map with client name as key and list of module's methods as value
+     * @throws FuncCommunicationException thrown if there is any kind of error in func invokation
+     */
+    public Map listModuleMethods (String client, String module, boolean async) throws FuncCommunicationException;
+
+    /**
      * Invoked to obtain the list of methods for provided module and list of clients
      * @param clients List of func clients names.
      * @param module name of func module for which you need a list of methods
@@ -119,5 +172,33 @@ public interface Func {
      * @throws FuncCommunicationException thrown if there is any kind of error in func invokation
      */
     public Map listModuleMethods (List clients, String module) throws FuncCommunicationException;
+
+    /**
+     * Invoked to obtain the list of methods for provided module and list of clients
+     * @param clients List of func clients names.
+     * @param module name of func module for which you need a list of methods
+     * @param async decide if you call will be sync or async
+     * @return Map with response divided for each client: clientName as key and list of all module's methods as value
+     * @throws FuncCommunicationException thrown if there is any kind of error in func invokation
+     */
+    public Map listModuleMethods (List clients, String module, boolean async) throws FuncCommunicationException;
+
+    /**
+     * Invoked to get results for run async processes 
+     * @param pid Process ID to get results
+     * @return Map with machines divided in relative process status
+     * @throws FuncCommunicationException thrown if there is any kind of error in func invokation
+     */
+    public Map getProcessResponse(String pid) throws FuncCommunicationException;
+
+    /**
+     * 
+     * @param client A func minion hostname
+     * @param module Func module name
+     * @param method Module method name
+     * @return Map with list of arguments required from method
+     * @throws FuncCommunicationException thrown if there is any kind of error in func invokation
+     */
+    public Map getMethodArguments(String client, String module, String method) throws FuncCommunicationException; 
     
 }
diff --git a/bindings/func-java/src/main/resources/log4j.properties b/bindings/func-java/src/main/resources/log4j.properties
new file mode 100644
index 0000000..6e71f59
--- /dev/null
+++ b/bindings/func-java/src/main/resources/log4j.properties
@@ -0,0 +1,5 @@
+#log4j.rootLogger = WARN, funcjava
+log4j.logger.org.func=DEBUG, funcjava
+log4j.appender.funcjava=org.apache.log4j.ConsoleAppender
+log4j.appender.funcjava.layout=org.apache.log4j.PatternLayout
+log4j.appender.funcjava.layout.ConversionPattern=%d{HH:mm:ss.SSS} %X{user} %5p %m%n
diff --git a/bindings/func-java/src/test/groovy/FuncFactoryTest.groovy b/bindings/func-java/src/test/groovy/FuncFactoryTest.groovy
deleted file mode 100644
index fd0ab86..0000000
--- a/bindings/func-java/src/test/groovy/FuncFactoryTest.groovy
+++ /dev/null
@@ -1,32 +0,0 @@
-import org.func.FuncFactory
-import org.func.Func
-
-/**
- *  Copyright (C) 2008, Byte-Code srl <http://www.byte-code.com>
- *
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * Date: Jul 11, 2008
- * Time: 10:06:03 AM
- */
-class FuncFactoryTest extends GroovyTestCase {
-
-    void testFuncFactory() {
-        def func = FuncFactory.getFunc()
-
-        assertNotNull ("Func Factory returns a null Func Implementation", func)
-        assertTrue ("Func Factory does not return a correct Func object", func instanceof Func)
-    }
-
-}
\ No newline at end of file
diff --git a/bindings/func-java/src/test/groovy/org/func/FuncImplTest.groovy b/bindings/func-java/src/test/groovy/org/func/FuncImplTest.groovy
index cd9ce60..eec6e2b 100644
--- a/bindings/func-java/src/test/groovy/org/func/FuncImplTest.groovy
+++ b/bindings/func-java/src/test/groovy/org/func/FuncImplTest.groovy
@@ -1,7 +1,5 @@
 package org.func
 
-import org.jvyaml.YAML
-
 /**
  *  Copyright (C) 2008, Byte-Code srl <http://www.byte-code.com>
  *
@@ -28,27 +26,58 @@ import org.jvyaml.YAML
  */
 class FuncImplTest extends GroovyTestCase {
 
-    void testCall() {
-        Func func = FuncFactory.getFunc("/home/mmornati/projects/func/scripts/func-transmit")
+    void testSyncCallOneClientNoParameters() {
+        Func func = FuncFactory.getFunc()
         def response = func.call ("*", "hardware", "info")
         assertTrue ("Func Response is not a Map", response instanceof Map)
     }
 
+    void testSyncCallOneClientOneParameter() {
+        Func func = FuncFactory.getFunc()
+        def response = func.call ("*", "hardware", "info", "")
+        assertTrue ("Func Response is not a Map", response instanceof Map)
+    }
+
+    void testSyncCallOneClientManyParameters() {
+        Func func = FuncFactory.getFunc()
+        def response = func.call ("*", "hardware", "info", [""])
+        assertTrue ("Func Response is not a Map", response instanceof Map)
+    }
+
+    void testSyncCallManyClientsNoParameters() {
+        Func func = FuncFactory.getFunc()
+        def response = func.call (["*"], "hardware", "info")
+        assertTrue ("Func Response is not a Map", response instanceof Map)
+    }
+
+    void testSyncCallManyClientsOneParameter() {
+        Func func = FuncFactory.getFunc()
+        def response = func.call (["*"], "hardware", "info", "")
+        assertTrue ("Func Response is not a Map", response instanceof Map)
+    }
+
+    void testSyncCallManyClientsManyParameters() {
+        Func func = FuncFactory.getFunc()
+        def response = func.call (["*"], "hardware", "info", [""])
+        assertTrue ("Func Response is not a Map", response instanceof Map)
+    }
+
+
     void testListModules() {
-        Func func = FuncFactory.getFunc("/home/mmornati/projects/func/scripts/func-transmit")
-        def response = func.listModules("bcmmornati")
+        Func func = FuncFactory.getFunc()
+        def response = func.listModules("*")
         assertTrue ("Func Response is not a Map", response instanceof Map)
     }
 
     void testListModuleMethods() {
-        Func func = FuncFactory.getFunc("/home/mmornati/projects/func/scripts/func-transmit")
-        def response = func.listModuleMethods("bcmmornati", "hardware")
+        Func func = FuncFactory.getFunc()
+        def response = func.listModuleMethods("*", "hardware")
         assertTrue ("Func Response is not a Map", response instanceof Map)
     }
 
     void testClientPatch() {
         def clients = ["client1", "client2"]
-        FuncImpl func = FuncFactory.getFunc()
+        Func func = FuncFactory.getFunc()
         def returned = func.clientsCallPatch(clients)
         assertEquals ("Error in ClientsPatch generation", returned, "client1;client2")
     }
@@ -59,4 +88,84 @@ class FuncImplTest extends GroovyTestCase {
         assertTrue ("Error in calling listMinions", response instanceof List)
     }
 
+    void testAsyncCallOneClientNoParameter() {
+        Func func = FuncFactory.getFunc(true, 1)
+        def response = func.call("*", "hardware", "info")
+        def pid = response['processid']
+        assertNotNull ("Error in reading process ID", pid)
+        def result = ["status":3]
+        while (result["status"].equals(FuncImpl.JOB_ID_PARTIAL)) {
+            result =  func.getProcessResponse(pid)
+        }
+        assertNotNull ("Error. Null objet in async response", result["result"])
+    }
+
+    void testAsyncCallOneClientOneParameter() {
+        Func func = FuncFactory.getFunc(true, 1)
+        def response = func.call("*", "hardware", "info", "")
+        def pid = response['processid']
+        assertNotNull ("Error in reading process ID", pid)
+        def result = ["status":3]
+        while (result["status"].equals(FuncImpl.JOB_ID_PARTIAL)) {
+            result =  func.getProcessResponse(pid)
+        }
+        assertNotNull ("Error. Null objet in async response", result["result"])
+    }
+
+    void testAsyncCallOneClientManyParameters() {
+        Func func = FuncFactory.getFunc(true, 1)
+        def response = func.call("*", "hardware", "info", [""])
+        def pid = response['processid']
+        assertNotNull ("Error in reading process ID", pid)
+        def result = ["status":3]
+        while (result["status"].equals(FuncImpl.JOB_ID_PARTIAL)) {
+            result =  func.getProcessResponse(pid)
+        }
+        assertNotNull ("Error. Null objet in async response", result["result"])
+    }
+
+    void testAsyncCallManyClientsNoParameter() {
+        Func func = FuncFactory.getFunc(true, 1)
+        def response = func.call(["*"], "hardware", "info")
+        def pid = response['processid']
+        assertNotNull ("Error in reading process ID", pid)
+        def result = ["status":3]
+        while (result["status"].equals(FuncImpl.JOB_ID_PARTIAL)) {
+            result =  func.getProcessResponse(pid)
+        }
+        assertNotNull ("Error. Null objet in async response", result["result"])
+    }
+
+    void testAsyncCallManyClientsOneParameter() {
+        Func func = FuncFactory.getFunc(true, 1)
+        def response = func.call(["*"], "hardware", "info", "")
+        def pid = response['processid']
+        assertNotNull ("Error in reading process ID", pid)
+        def result = ["status":3]
+        while (result["status"].equals(FuncImpl.JOB_ID_PARTIAL)) {
+            result =  func.getProcessResponse(pid)
+        }
+        assertNotNull ("Error. Null objet in async response", result["result"])
+    }
+
+    void testAsyncCallManyClientsManyParameters() {
+        Func func = FuncFactory.getFunc(true, 1)
+        def response = func.call(["*"], "hardware", "info", [""])
+        def pid = response['processid']
+        assertNotNull ("Error in reading process ID", pid)
+        def result = ["status":3]
+        while (result["status"].equals(FuncImpl.JOB_ID_PARTIAL)) {
+            result =  func.getProcessResponse(pid)
+        }
+        assertNotNull ("Error. Null objet in async response", result["result"])
+    }
+
+    void testGetMethodArguments() {
+        Func func = FuncFactory.getFunc()
+        def response = func.getMethodArguments("*", "command", "run")
+        assertNotNull ("Error calling func to retrieve arguments.", response)
+        assertTrue ("Func Response is not a Map", response instanceof Map)
+        println "Mappa tornata: ${response}"
+    }
+
 }
\ No newline at end of file
-- 
1.5.6.5

