diff --git a/src/common/test/SConstruct b/src/common/test/SConstruct new file mode 100644 index 0000000000..f5945c6847 --- /dev/null +++ b/src/common/test/SConstruct @@ -0,0 +1,64 @@ +# -------------------------------------------------------------------------- # +# Copyright 2002-2009, Distributed Systems Architecture Group, Universidad # +# Complutense de Madrid (dsa-research.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +import os +import sys +import shutil +sys.path.append("../../../share/scons") +from lex_bison import * + +# This is the absolute path where the project is located +cwd="../../../" + +# Environment that will be applied to each scons child +main_env=Environment() +main_env['ENV']['PATH']=os.environ['PATH'] + +# Add builders for flex and bison +add_lex(main_env) +add_bison(main_env) + +# Include dirs +main_env.Append(CPPPATH=[ + cwd + '/include', + '/usr/include/cppunit/' +]) + +# Library dirs +main_env.Append(LIBPATH=[ + cwd + '/src/common', +]) + +main_env.Append(LIBS=[ + 'nebula_common', + 'cppunit', + 'dl', + 'pthread' +]) + +# Compile flags +main_env.Append(CPPFLAGS=[ + "-g", + "-Wall" +]) + +# Linking flags +main_env.Append(LDFLAGS=["-g"]) + +main_env.Program('single_attribute.cc') +main_env.Program('vector_attribute.cc') +main_env.Program('action_manager.cc') diff --git a/src/common/test/action_manager.cc b/src/common/test/action_manager.cc new file mode 100644 index 0000000000..134c30e899 --- /dev/null +++ b/src/common/test/action_manager.cc @@ -0,0 +1,183 @@ +#include "ActionManager.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace std; + +extern "C" void * addsub_loop(void *arg); + +class AddSub : public ActionListener +{ +public: + AddSub(int i):am(),counter(i) + { + am.addListener(this); + }; + + ~AddSub(){}; + + void add(int i) + { + int * p; + + p = new int(i); + + am.trigger("ADD",(void *) p); + } + + void sub(int i) + { + int * p; + + p = new int(i); + + am.trigger("SUB",(void *) p); + } + + int value() + { + return counter; + } + + pthread_t id() + { + return pid; + } + + void start() + { + pthread_attr_t pattr; + + pthread_attr_init (&pattr); + pthread_attr_setdetachstate (&pattr, PTHREAD_CREATE_JOINABLE); + + pthread_create(&pid,&pattr,addsub_loop,(void *) this); + } + + void end() + { + am.trigger(ActionListener::ACTION_FINALIZE,0); + } + +private: + ActionManager am; + + int counter; + pthread_t pid; + + friend void * addsub_loop(void *arg); + + void do_action(const string &action, void * arg) + { + int * i = static_cast(arg); + + if ( i == 0 ) + { + return; + } + else if ( action == "ADD" ) + { + counter = counter + *i; + } + else if ( action == "SUB" ) + { + counter = counter - *i; + } + + delete i; + } +}; + +extern "C" void * addsub_loop(void *arg) +{ + AddSub *as; + + as = static_cast(arg); + + as->am.loop(0,0); + + return 0; +}; + +class ActionManagerTest : public CppUnit::TestFixture +{ +private: + AddSub *as; + +public: + void setUp() + { + as = new AddSub(10); + as->start(); + } + + void tearDown() + { + delete as; + } + + void test_add() + { + as->add(23); + as->add(5); + + sleep(1); + + CPPUNIT_ASSERT(as->value() == 38); + + as->end(); + + pthread_join(as->id(),0); + + CPPUNIT_ASSERT(as->value() == 38); + } + + void test_sub() + { + as->sub(3); + as->sub(15); + + sleep(1); + + CPPUNIT_ASSERT(as->value() == -8); + + as->end(); + + pthread_join(as->id(),0); + + CPPUNIT_ASSERT(as->value() == -8); + } + + static CppUnit::TestSuite * suite() + { + CppUnit::TestSuite *ts=new CppUnit::TestSuite("ActionManager Tests"); + + ts->addTest(new CppUnit::TestCaller( + "add() Test", + &ActionManagerTest::test_add)); + + ts->addTest(new CppUnit::TestCaller( + "sub() Test", + &ActionManagerTest::test_sub)); + return ts; + } +}; + +int main(int argc, char ** argv) +{ + + CppUnit::TextUi::TestRunner tr; + + tr.addTest(ActionManagerTest::suite()); + tr.run(); + + return 0; +} diff --git a/src/common/test/single_attribute.cc b/src/common/test/single_attribute.cc new file mode 100644 index 0000000000..4da4a0daed --- /dev/null +++ b/src/common/test/single_attribute.cc @@ -0,0 +1,131 @@ +#include "Attribute.h" + +#include +#include + +#include +#include +#include +#include +#include + +using namespace std; + +class SingleAttributeTest : public CppUnit::TestFixture +{ +private: + SingleAttribute *a, *b; + +public: + void setUp() + { + string a_name = "single_a"; + + string b_name = "single_b"; + string b_value= "value_b"; + + a = new SingleAttribute(a_name); + b = new SingleAttribute(b_name, b_value); + } + + void tearDown() + { + delete a; + delete b; + } + + void test_type() + { + CPPUNIT_ASSERT(a->type() == Attribute::SIMPLE); + CPPUNIT_ASSERT(b->type() == Attribute::SIMPLE); + } + + void test_name() + { + CPPUNIT_ASSERT(a->name() == "SINGLE_A"); + CPPUNIT_ASSERT(b->name() == "SINGLE_B"); + } + + void test_value() + { + CPPUNIT_ASSERT(a->value().empty() == true); + CPPUNIT_ASSERT(b->value() == "value_b"); + } + + void test_marshall() + { + string *am, *bm; + + am = a->marshall(); + bm = b->marshall(); + + CPPUNIT_ASSERT(am->empty() == true); + CPPUNIT_ASSERT(*bm == "value_b"); + + delete am; + delete bm; + } + + void test_xml() + { + string *am, *bm; + + am = a->to_xml(); + bm = b->to_xml(); + + CPPUNIT_ASSERT(*am == ""); + CPPUNIT_ASSERT(*bm == "value_b"); + + delete am; + delete bm; + } + + void test_replace() + { + string nv = "new_value_b"; + + b->replace(nv); + + CPPUNIT_ASSERT(b->value() == "new_value_b"); + } + + static CppUnit::TestSuite * suite() + { + CppUnit::TestSuite *ts=new CppUnit::TestSuite("SingleAttribute Tests"); + + ts->addTest(new CppUnit::TestCaller( + "type() Test", + &SingleAttributeTest::test_type)); + + ts->addTest(new CppUnit::TestCaller( + "name() Test", + &SingleAttributeTest::test_name)); + + ts->addTest(new CppUnit::TestCaller( + "value() Test", + &SingleAttributeTest::test_value)); + + ts->addTest(new CppUnit::TestCaller( + "marshall() Test", + &SingleAttributeTest::test_marshall)); + + ts->addTest(new CppUnit::TestCaller( + "to_xml() Test", + &SingleAttributeTest::test_xml)); + + ts->addTest(new CppUnit::TestCaller( + "replace() Test", + &SingleAttributeTest::test_replace)); + return ts; + } +}; + +int main(int argc, char ** argv) +{ + CppUnit::TextUi::TestRunner tr; + + tr.addTest(SingleAttributeTest::suite()); + tr.run(); + + return 0; +} diff --git a/src/common/test/vector_attribute.cc b/src/common/test/vector_attribute.cc new file mode 100644 index 0000000000..aa41b7c6c9 --- /dev/null +++ b/src/common/test/vector_attribute.cc @@ -0,0 +1,163 @@ +#include "Attribute.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace std; + +class VectorAttributeTest : public CppUnit::TestFixture +{ +private: + VectorAttribute *a, *b; + map b_value; + +public: + void setUp() + { + string a_name = "vector_a"; + string b_name = "vector_b"; + + b_value.insert(make_pair("attr1","val1")); + b_value.insert(make_pair("attr2","val2")); + b_value.insert(make_pair("attr3","val3")); + + a = new VectorAttribute(a_name); + b = new VectorAttribute(b_name, b_value); + } + + void tearDown() + { + delete a; + delete b; + } + + void test_type() + { + CPPUNIT_ASSERT(a->type() == Attribute::VECTOR); + CPPUNIT_ASSERT(b->type() == Attribute::VECTOR); + } + + void test_name() + { + CPPUNIT_ASSERT(a->name() == "VECTOR_A"); + CPPUNIT_ASSERT(b->name() == "VECTOR_B"); + } + + void test_value() + { + CPPUNIT_ASSERT(a->value().empty() == true); + CPPUNIT_ASSERT(b->value() == b_value); + + CPPUNIT_ASSERT(a->vector_value("NAME").empty() == true); + CPPUNIT_ASSERT(b->vector_value("NAME").empty() == true); + + CPPUNIT_ASSERT(b->vector_value("attr1") == "val1"); + CPPUNIT_ASSERT(b->vector_value("attr2") == "val2"); + CPPUNIT_ASSERT(b->vector_value("attr3") == "val3"); + } + + void test_marshall() + { + string *am, *bm; + + am = a->marshall(); + bm = b->marshall(); + + CPPUNIT_ASSERT(am == 0); + CPPUNIT_ASSERT(*bm == "attr1=val1@^_^@attr2=val2@^_^@attr3=val3"); + + VectorAttribute c("vector_c"); + c.unmarshall(*bm); + + CPPUNIT_ASSERT(c.vector_value("attr1") == "val1"); + CPPUNIT_ASSERT(c.vector_value("attr2") == "val2"); + CPPUNIT_ASSERT(c.vector_value("attr3") == "val3"); + + delete am; + delete bm; + } + + void test_xml() + { + string *am, *bm; + + am = a->to_xml(); + bm = b->to_xml(); + + CPPUNIT_ASSERT(*am == ""); + CPPUNIT_ASSERT(*bm == "val1val2" + "val3"); + delete am; + delete bm; + } + + void test_replace() + { + map nm; + string nv = "new_val1"; + + b->replace("attr1",nv); + + CPPUNIT_ASSERT(b->vector_value("attr1") == "new_val1"); + + nm.insert(make_pair("other_attr1","other_val1")); + nm.insert(make_pair("other_attr2","other_val2")); + + b->replace(nm); + + CPPUNIT_ASSERT(b->vector_value("other_attr1") == "other_val1"); + CPPUNIT_ASSERT(b->vector_value("other_attr2") == "other_val2"); + CPPUNIT_ASSERT(b->vector_value("attr3").empty() == true); + CPPUNIT_ASSERT(b->value() == nm); + } + + static CppUnit::TestSuite * suite() + { + CppUnit::TestSuite *ts=new CppUnit::TestSuite("VectorAttribute Tests"); + + ts->addTest(new CppUnit::TestCaller( + "type() Test", + &VectorAttributeTest::test_type)); + + ts->addTest(new CppUnit::TestCaller( + "name() Test", + &VectorAttributeTest::test_name)); + + ts->addTest(new CppUnit::TestCaller( + "value() Test", + &VectorAttributeTest::test_value)); + + ts->addTest(new CppUnit::TestCaller( + "marshall() Test", + &VectorAttributeTest::test_marshall)); + + ts->addTest(new CppUnit::TestCaller( + "to_xml() Test", + &VectorAttributeTest::test_xml)); + + ts->addTest(new CppUnit::TestCaller( + "replace() Test", + &VectorAttributeTest::test_replace)); + + return ts; + } + +}; + +int main(int argc, char ** argv) +{ + + CppUnit::TextUi::TestRunner tr; + + tr.addTest(VectorAttributeTest::suite()); + tr.run(); + + return 0; +} diff --git a/src/host/HostPool.cc b/src/host/HostPool.cc index 1416f6b0ba..fa832ddeb3 100644 --- a/src/host/HostPool.cc +++ b/src/host/HostPool.cc @@ -72,7 +72,6 @@ int HostPool::discover_cb(void * _map, int num, char **values, char **names) int HostPool::discover(map * discovered_hosts) { - ostringstream sql; int rc; @@ -82,7 +81,8 @@ int HostPool::discover(map * discovered_hosts) static_cast(discovered_hosts)); sql << "SELECT oid, im_mad FROM " - << Host::table << " ORDER BY last_mon_time LIMIT 10"; + << Host::table << " WHERE state != " + << Host::DISABLED << " ORDER BY last_mon_time LIMIT 10"; rc = db->exec(sql,this); diff --git a/src/oca/java/src/org/opennebula/client/virtualMachine/VirtualMachine.java b/src/oca/java/src/org/opennebula/client/virtualMachine/VirtualMachine.java deleted file mode 100644 index 2a416f54e8..0000000000 --- a/src/oca/java/src/org/opennebula/client/virtualMachine/VirtualMachine.java +++ /dev/null @@ -1,395 +0,0 @@ -/******************************************************************************* - * Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************/ -package org.opennebula.client.virtualMachine; - - -import org.opennebula.client.Client; -import org.opennebula.client.OneResponse; -import org.opennebula.client.PoolElement; -import org.w3c.dom.Node; - -/** - * This class represents an OpenNebula VM. - * It also offers static XML-RPC call wrappers. - */ -public class VirtualMachine extends PoolElement{ - - private static final String METHOD_PREFIX = "vm."; - private static final String ALLOCATE = METHOD_PREFIX + "allocate"; - private static final String INFO = METHOD_PREFIX + "info"; - private static final String DEPLOY = METHOD_PREFIX + "deploy"; - private static final String ACTION = METHOD_PREFIX + "action"; - private static final String MIGRATE = METHOD_PREFIX + "migrate"; - - private static final String[] VM_STATES = - { - "INIT", - "PENDING", - "HOLD", - "ACTIVE", - "STOPPED", - "SUSPENDED", - "DONE", - "FAILED" }; - - private static final String[] SHORT_VM_STATES = - { - "init", - "pend", - "hold", - "actv", - "stop", - "susp", - "done", - "fail" }; - - private static final String[] LCM_STATE = - { - "LCM_INIT", - "PROLOG", - "BOOT", - "RUNNING", - "MIGRATE", - "SAVE_STOP", - "SAVE_SUSPEND", - "SAVE_MIGRATE", - "PROLOG_MIGRATE", - "PROLOG_RESUME", - "EPILOG_STOP", - "EPILOG", - "SHUTDOWN", - "CANCEL", - "FAILURE", - "DELETE", - "UNKNOWN" }; - - private static final String[] SHORT_LCM_STATES = - { - null, - "prol", - "boot", - "runn", - "migr", - "save", - "save", - "save", - "migr", - "prol", - "epil", - "epil", - "shut", - "shut", - "fail", - "dele", - "unkn" }; - - /** - * Creates a new VM representation. - * - * @param id The virtual machine Id (vid). - * @param client XML-RPC Client. - */ - public VirtualMachine(int id, Client client) - { - super(id, client); - } - - /** - * @see PoolElement - */ - protected VirtualMachine(Node xmlElement, Client client) - { - super(xmlElement, client); - } - - - // ================================= - // Static XML-RPC methods - // ================================= - - /** - * Allocates a new VM in OpenNebula. - * - * @param client XML-RPC Client. - * @param description A string containing the template of the vm. - * @return If successful the message contains the associated - * id generated for this VM. - */ - public static OneResponse allocate(Client client, String description) - { - return client.call(ALLOCATE, description); - } - - /** - * Retrieves the information of the given VM. - * - * @param client XML-RPC Client. - * @param id The virtual machine id (vid) of the target instance. - * @return If successful the message contains the string - * with the information returned by OpenNebula. - */ - public static OneResponse info(Client client, int id) - { - return client.call(INFO, id); - } - - - // ================================= - // Instanced object XML-RPC methods - // ================================= - - /** - * Loads the xml representation of the virtual machine. - * The info is also stored internally. - * - * @see VirtualMachine#info(Client, int) - */ - public OneResponse info() - { - OneResponse response = info(client, id); - super.processInfo(response); - return response; - } - - /** - * Initiates the instance of the VM on the target host. - * - * @param hostId The host id (hid) of the target host where - * the VM will be instantiated. - * @return If an error occurs the error message contains the reason. - */ - public OneResponse deploy(int hostId) - { - return client.call(DEPLOY, id, hostId); - } - - /** - * Submits an action to be performed on the virtual machine. - *
- * It is recommended to use the helper methods instead: - *
    - *
  • {@link VirtualMachine#shutdown()}
  • - *
  • {@link VirtualMachine#cancel()}
  • - *
  • {@link VirtualMachine#hold()}
  • - *
  • {@link VirtualMachine#release()}
  • - *
  • {@link VirtualMachine#stop()}
  • - *
  • {@link VirtualMachine#suspend()}
  • - *
  • {@link VirtualMachine#resume()}
  • - *
  • {@link VirtualMachine#finalizeVM()}
  • - *
  • {@link VirtualMachine#restart()}
  • - *
- * - * @param action The action name to be performed, can be:
- * "shutdown", "hold", "release", "stop", "cancel", "suspend", - * "resume", "restart", "finalize". - * @return If an error occurs the error message contains the reason. - */ - protected OneResponse action(String action) - { - return client.call(ACTION, action, id); - } - - /** - * Migrates the virtual machine to the target host (hid). - * - * @param hostId The target host id (hid) where we want to migrate - * the vm. - * @param live If true we are indicating that we want livemigration, - * otherwise false. - * @return If an error occurs the error message contains the reason. - */ - public OneResponse migrate(int hostId, boolean live) - { - return client.call(MIGRATE, id, hostId, live); - } - - - // ================================= - // Helpers - // ================================= - - /** - * Shuts down the already deployed VM. - * @return If an error occurs the error message contains the reason. - */ - public OneResponse shutdown() - { - return action("shutdown"); - } - - /** - * Cancels the running VM. - * @return If an error occurs the error message contains the reason. - */ - public OneResponse cancel() - { - return action("cancel"); - } - - /** - * Sets the VM to hold state. The VM will not be scheduled until it is - * released. - * @return If an error occurs the error message contains the reason. - */ - public OneResponse hold() - { - return action("hold"); - } - - /** - * Releases a virtual machine from hold state. - * @return If an error occurs the error message contains the reason. - */ - public OneResponse release() - { - return action("release"); - } - - /** - * Stops the virtual machine. The virtual machine state is transferred back - * to OpenNebula for a possible reschedule. - * @return If an error occurs the error message contains the reason. - */ - public OneResponse stop() - { - return action("stop"); - } - - /** - * Suspends the virtual machine. The virtual machine state is left in the - * cluster node for resuming. - * @return If an error occurs the error message contains the reason. - */ - public OneResponse suspend() - { - return action("suspend"); - } - - /** - * Resumes the execution of a saved VM. - * @return If an error occurs the error message contains the reason. - */ - public OneResponse resume() - { - return action("resume"); - } - - /** - * Deletes the VM from the pool and database. - * @return If an error occurs the error message contains the reason. - */ - public OneResponse finalizeVM() - { - return action("finalize"); - } - - /** - * Resubmits the virtual machine after failure. - * @return If an error occurs the error message contains the reason. - */ - public OneResponse restart() - { - return action("shutdown"); - } - - - /** - * Migrates the virtual machine to the target host (hid). - *
- * It does the same as {@link VirtualMachine#migrate(int, boolean)} - * with live set to false. - * - * @param hostId The target host id (hid) where we want to migrate - * the vm. - * @return If an error occurs the error message contains the reason. - */ - public OneResponse migrate(int hostId) - { - return migrate(hostId, false); - } - - /** - * Performs a live migration of the virtual machine to the - * target host (hid). - *
- * It does the same as {@link VirtualMachine#migrate(int, boolean)} - * with live set to true. - * - * @param hostId The target host id (hid) where we want to migrate - * the vm. - * @return If an error occurs the error message contains the reason. - */ - public OneResponse liveMigrate(int hostId) - { - return migrate(hostId, true); - } - - public int state() - { - return super.state(); - } - - /** - * Returns the VM state of the VirtualMachine (string value). - * @return The VM state of the VirtualMachine (string value). - */ - public String stateStr() - { - int state = state(); - return state != -1 ? VM_STATES[state()] : null; - } - - /** - * Returns the LCM state of the VirtualMachine (numeric value). - * @return The LCM state of the VirtualMachine (numeric value). - */ - public int lcmState() - { - String state = xpath("LCM_STATE"); - return state != null ? Integer.parseInt(state) : -1; - } - - /** - * Returns the LCM state of the VirtualMachine (string value). - * @return The LCM state of the VirtualMachine (string value). - */ - public String lcmStateStr() - { - int state = lcmState(); - return state != -1 ? LCM_STATE[state] : null; - } - - /** - * Returns the short status string for the VirtualMachine. - * @return The short status string for the VirtualMachine. - */ - public String status() - { - int state = state(); - String shortStateStr = null; - if(state != -1) - { - shortStateStr = SHORT_VM_STATES[state]; - if(shortStateStr.equals("actv")) - { - int lcmState = lcmState(); - if(lcmState != -1) - shortStateStr = SHORT_LCM_STATES[lcmState]; - } - } - return shortStateStr; - } -} diff --git a/src/oca/java/src/org/opennebula/client/virtualMachine/VirtualMachinePool.java b/src/oca/java/src/org/opennebula/client/virtualMachine/VirtualMachinePool.java deleted file mode 100644 index 5b0f3d5f9e..0000000000 --- a/src/oca/java/src/org/opennebula/client/virtualMachine/VirtualMachinePool.java +++ /dev/null @@ -1,129 +0,0 @@ -/******************************************************************************* - * Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************/ -package org.opennebula.client.virtualMachine; - -import java.util.AbstractList; -import java.util.Iterator; - - -import org.opennebula.client.Client; -import org.opennebula.client.OneResponse; -import org.opennebula.client.Pool; -import org.opennebula.client.PoolElement; -import org.w3c.dom.Node; - -/** - * This class represents an OpenNebula VM pool. - * It also offers static XML-RPC call wrappers. - */ -public class VirtualMachinePool extends Pool implements Iterable{ - - private static final String ELEMENT_NAME = "VM"; - private static final String INFO_METHOD = "vmpool.info"; - - private int filter; - - /** - * Creates a new VM pool with the default filter flag value - * set to 0 (VMs belonging to user with UID 0) - * - * @param client XML-RPC Client. - * - * @see VirtualMachinePool#VirtualMachinePool(Client, int) - */ - public VirtualMachinePool(Client client) - { - super(ELEMENT_NAME, client); - this.filter = 0; - } - - /** - * Creates a new VM pool. - * - * @param client XML-RPC Client. - * @param filter Filter flag used by default in the method - * {@link VirtualMachinePool#info()}. Possible values: - *
    - *
  • <= -2: All VMs
  • - *
  • -1: Connected user's VMs
  • - *
  • >= 0: UID User's VMs
  • - *
- */ - public VirtualMachinePool(Client client, int filter) - { - super(ELEMENT_NAME, client); - this.filter = filter; - } - - @Override - public PoolElement factory(Node node) - { - return new VirtualMachine(node, client); - } - - /** - * Retrieves all or part of the VMs in the pool. - * - * @param client XML-RPC Client. - * @param filter Filter flag. Possible values: - *
    - *
  • <= -2: All VMs
  • - *
  • -1: Connected user's VMs
  • - *
  • >= 0: UID User's VMs
  • - *
- * @return If successful the message contains the string - * with the information returned by OpenNebula. - */ - public static OneResponse info(Client client, int filter) - { - return client.call(INFO_METHOD, filter); - } - - /** - * Loads the xml representation of all or part of the - * VMs in the pool. The filter used is the one set in - * the constructor. - * - * @see VirtualMachinePool#info(Client, int) - * - * @return If successful the message contains the string - * with the information returned by OpenNebula. - */ - public OneResponse info() - { - OneResponse response = info(client, filter); - super.processInfo(response); - return response; - } - - public Iterator iterator() - { - AbstractList ab = new AbstractList() - { - public int size() - { - return getLength(); - } - - public VirtualMachine get(int index) - { - return (VirtualMachine) item(index); - } - }; - - return ab.iterator(); - } -} diff --git a/src/oca/java/src/org/opennebula/client/virtualNetwork/VirtualNetwork.java b/src/oca/java/src/org/opennebula/client/virtualNetwork/VirtualNetwork.java deleted file mode 100644 index 6982498eb4..0000000000 --- a/src/oca/java/src/org/opennebula/client/virtualNetwork/VirtualNetwork.java +++ /dev/null @@ -1,126 +0,0 @@ -/******************************************************************************* - * Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************/ -package org.opennebula.client.virtualNetwork; - - -import org.opennebula.client.Client; -import org.opennebula.client.OneResponse; -import org.opennebula.client.PoolElement; -import org.w3c.dom.Node; - -/** - * This class represents an OpenNebula virtual network. - * It also offers static XML-RPC call wrappers. - */ -public class VirtualNetwork extends PoolElement{ - - private static final String METHOD_PREFIX = "vn."; - private static final String ALLOCATE = METHOD_PREFIX + "allocate"; - private static final String INFO = METHOD_PREFIX + "info"; - private static final String DELETE = METHOD_PREFIX + "delete"; - - - /** - * Creates a new virtual network representation. - * - * @param id The virtual network id (nid) . - * @param client XML-RPC Client. - */ - public VirtualNetwork(int id, Client client) - { - super(id, client); - } - - /** - * @see PoolElement - */ - protected VirtualNetwork(Node xmlElement, Client client) - { - super(xmlElement, client); - } - - // ================================= - // Static XML-RPC methods - // ================================= - - /** - * Allocates a new virtual network in OpenNebula. - * - * @param client XML-RPC Client. - * @param description A string containing the template - * of the virtual network. - * @return If successful the message contains the associated - * id generated for this virtual network. - */ - public static OneResponse allocate(Client client, String description) - { - return client.call(ALLOCATE, description); - } - - /** - * Retrieves the information of the given virtual network - * - * @param client XML-RPC Client. - * @param id the virtual network id (nid) for the network to - * retrieve the information from. - * @return If successful the message contains the string - * with the information returned by OpenNebula. - */ - public static OneResponse info(Client client, int id) - { - return client.call(INFO, id); - } - - /** - * Deletes a network from OpenNebula. - * - * @param client XML-RPC Client. - * @param id The virtual network id (nid) of the target network. - * @return A encapsulated response. - */ - public static OneResponse delete(Client client, int id) - { - return client.call(DELETE, id); - } - - - // ================================= - // Instanced object XML-RPC methods - // ================================= - - /** - * Loads the xml representation of the virtual network. - * The info is also stored internally. - * - * @see VirtualNetwork#info(Client, int) - */ - public OneResponse info() - { - OneResponse response = info(client, id); - super.processInfo(response); - return response; - } - - /** - * Deletes the network from OpenNebula. - * - * @return A encapsulated response. - */ - public OneResponse delete() - { - return delete(client, id); - } -} diff --git a/src/oca/java/src/org/opennebula/client/virtualNetwork/VirtualNetworkPool.java b/src/oca/java/src/org/opennebula/client/virtualNetwork/VirtualNetworkPool.java deleted file mode 100644 index cfc0dfd2d9..0000000000 --- a/src/oca/java/src/org/opennebula/client/virtualNetwork/VirtualNetworkPool.java +++ /dev/null @@ -1,128 +0,0 @@ -/******************************************************************************* - * Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - ******************************************************************************/ -package org.opennebula.client.virtualNetwork; - -import java.util.AbstractList; -import java.util.Iterator; - - -import org.opennebula.client.Client; -import org.opennebula.client.OneResponse; -import org.opennebula.client.Pool; -import org.opennebula.client.PoolElement; -import org.w3c.dom.Node; - -/** - * This class represents an OpenNebula Virtual Network pool. - * It also offers static XML-RPC call wrappers. - */ -public class VirtualNetworkPool extends Pool implements Iterable{ - - private static final String ELEMENT_NAME = "VNET"; - private static final String INFO_METHOD = "vnpool.info"; - - private int filter; - - /** - * Creates a new VN pool with the default filter flag value - * set to 0 (VNs belonging to user with UID 0) - * - * @param client XML-RPC Client. - * - * @see VirtualNetworkPool#VirtualNetworkPool(Client, int) - */ - public VirtualNetworkPool(Client client) - { - super(ELEMENT_NAME, client); - this.filter = 0; - } - - /** - * Creates a new VN pool. - * - * @param client XML-RPC Client. - * @param filter Filter flag used by default in the method - * {@link VirtualNetworkPool#info()}. Possible values: - *
    - *
  • <= -2: All VNs
  • - *
  • -1: Connected user's VNs
  • - *
  • >= 0: UID User's VNs
  • - *
- */ - public VirtualNetworkPool(Client client, int filter) - { - super(ELEMENT_NAME, client); - this.filter = filter; - } - - @Override - public PoolElement factory(Node node) - { - return new VirtualNetwork(node, client); - } - - /** - * Retrieves all or part of the VNs in the pool. - * - * @param client XML-RPC Client. - * @param filter Filter flag. Possible values: - *
    - *
  • <= -2: All VNs
  • - *
  • -1: Connected user's VNs
  • - *
  • >= 0: UID User's VNs
  • - *
- * @return If successful the message contains the string - * with the information returned by OpenNebula. - */ - public static OneResponse info(Client client, int filter) - { - return client.call(INFO_METHOD, filter); - } - - /** - * Loads the xml representation of all or part of the - * VNs in the pool. The filter used is the one set in - * the constructor. - * - * @see VirtualNetworkPool#info(Client, int) - * @return If successful the message contains the string - * with the information returned by OpenNebula. - */ - public OneResponse info() - { - OneResponse response = info(client, filter); - super.processInfo(response); - return response; - } - - public Iterator iterator() - { - AbstractList ab = new AbstractList() - { - public int size() - { - return getLength(); - } - - public VirtualNetwork get(int index) - { - return (VirtualNetwork) item(index); - } - }; - - return ab.iterator(); - } -} diff --git a/src/pool/test/SConstruct b/src/pool/test/SConstruct new file mode 100644 index 0000000000..7f10456439 --- /dev/null +++ b/src/pool/test/SConstruct @@ -0,0 +1,68 @@ +# -------------------------------------------------------------------------- +# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# -------------------------------------------------------------------------- + +import os +import sys +import shutil +sys.path.append("../../../share/scons") +from lex_bison import * + +# This is the absolute path where the project is located +cwd="../../../" + +# Environment that will be applied to each scons child +main_env=Environment() +main_env['ENV']['PATH']=os.environ['PATH'] + +# Add builders for flex and bison +add_lex(main_env) +add_bison(main_env) + +# Include dirs +main_env.Append(CPPPATH=[ + cwd + '/include', + '/usr/include/cppunit/', +]) + +# Library dirs +main_env.Append(LIBPATH=[ + cwd + '/src/common', + cwd + '/src/pool', + cwd + '/src/pool/test', +]) + +main_env.Append(LIBS=[ + 'nebula_pool', + 'nebula_common', + 'cppunit', + 'dl', + 'pthread', + 'sqlite3', + 'test_object' +]) + +# Compile flags +main_env.Append(CPPFLAGS=[ + "-g", + "-Wall" +]) + +# Linking flags +main_env.Append(LDFLAGS=["-g "]) + +main_env.StaticLibrary('test_object', ['TestPoolSQL.cc', 'TestPoolSQL.h']) +main_env.Program('pool.cc') +# diff --git a/src/pool/test/TestPoolSQL.cc b/src/pool/test/TestPoolSQL.cc new file mode 100644 index 0000000000..de33632352 --- /dev/null +++ b/src/pool/test/TestPoolSQL.cc @@ -0,0 +1,131 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); you may */ +/* not use this file except in compliance with the License. You may obtain */ +/* a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ +/* -------------------------------------------------------------------------- */ + +#include +#include +#include + +#include +#include + +#include +#include + +#include "TestPoolSQL.h" + +/* ************************************************************************** */ +/* Database Access Functions */ +/* ************************************************************************** */ + +const char * TestObjectSQL::table = "test_pool"; + +const char * TestObjectSQL::db_names = "(oid,number,text)"; + +const char * TestObjectSQL::db_bootstrap = "CREATE TABLE test_pool (" + "oid INTEGER, number INTEGER, text TEXT, PRIMARY KEY(oid))"; + +/* -------------------------------------------------------------------------- */ + +int TestObjectSQL::unmarshall(void * nil, int num, char **values, char **names) +{ + if ((!values[OID]) || + (!values[NUMBER]) || + (!values[TEXT]) || + (num != LIMIT )) + { + return -1; + } + + oid = atoi(values[OID]); + number = atoi(values[NUMBER]); + text = values[TEXT]; + + return 0; +} + +/* -------------------------------------------------------------------------- */ + +int TestObjectSQL::select(SqlDB *db) +{ + ostringstream oss; + int rc; + int boid; + + set_callback( + static_cast(&TestObjectSQL::unmarshall),0); + oss << "SELECT * FROM " << table << " WHERE oid = " << oid; + + boid = oid; + oid = -1; + + rc = db->exec(oss, this); + + if ((rc != 0) || (oid != boid )) + { + return -1; + } + + return 0; +} + +/* -------------------------------------------------------------------------- */ + +int TestObjectSQL::insert(SqlDB *db) +{ + return update(db); +} + +/* -------------------------------------------------------------------------- */ + +int TestObjectSQL::update(SqlDB *db) +{ + ostringstream oss; + + int rc; + char * sql_text; + + sql_text = db->escape_str(text.c_str()); + + oss << "INSERT OR REPLACE INTO " << table << " "<< db_names <<" VALUES (" + << oid << "," + << number << "," + << "'" << sql_text << "')"; + + rc = db->exec(oss); + + db->free_str(sql_text); + + return rc; +} + +/* -------------------------------------------------------------------------- */ + +int TestObjectSQL::drop(SqlDB * db) +{ + ostringstream oss; + int rc; + + oss << "DELETE FROM " << table << " WHERE oid=" << oid; + + rc = db->exec(oss); + + if ( rc == 0 ) + { + set_valid(false); + } + + return rc; +} \ No newline at end of file diff --git a/src/pool/test/TestPoolSQL.h b/src/pool/test/TestPoolSQL.h new file mode 100644 index 0000000000..8e8c2f1732 --- /dev/null +++ b/src/pool/test/TestPoolSQL.h @@ -0,0 +1,100 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); you may */ +/* not use this file except in compliance with the License. You may obtain */ +/* a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ +/* -------------------------------------------------------------------------- */ + +#ifndef TESTSQL_H_ +#define TESTSQL_H_ + +#include +#include "PoolSQL.h" + +using namespace std; + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +// THE OBJECT +class TestObjectSQL : public PoolObjectSQL +{ +public: + //OBJECT ATTRIBUTES + TestObjectSQL(int n=-1, string t="default"):number(n),text(t){}; + + ~TestObjectSQL(){}; + + int number; + + string text; + + // OBJECTSQL INTERFACE + int unmarshall(void * nil, int num, char **names, char ** values); + + int select(SqlDB *db); + + int insert(SqlDB *db); + + int update(SqlDB *db); + + int drop(SqlDB *db); + + // DATABASE IMPLEMENTATION + enum ColNames + { + OID = 0, + NUMBER = 1, + TEXT = 2, + LIMIT = 3 + }; + + static const char * db_names; + + static const char * db_bootstrap; + + static const char * table; + + static void bootstrap(SqlDB * db) + { + ostringstream oss; + oss.str(TestObjectSQL::db_bootstrap); + + db->exec(oss,0); + }; +}; + +// THE POOL +class TestPool : public PoolSQL +{ + +public: + TestPool(SqlDB *db):PoolSQL(db,"test_pool"){}; + ~TestPool(){}; + + TestObjectSQL * get( + int oid, + bool lock) + { + return static_cast(PoolSQL::get(oid,lock));; + } + +private: + + TestObjectSQL * create() + { + return new TestObjectSQL; + }; + +}; + +#endif \ No newline at end of file diff --git a/src/pool/test/pool.cc b/src/pool/test/pool.cc new file mode 100644 index 0000000000..8bffae3e14 --- /dev/null +++ b/src/pool/test/pool.cc @@ -0,0 +1,220 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); you may */ +/* not use this file except in compliance with the License. You may obtain */ +/* a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ +/* -------------------------------------------------------------------------- */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "PoolSQL.h" +#include "TestPoolSQL.h" +#include "SqliteDB.h" + +using namespace std; + +/* ************************************************************************* */ +/* ************************************************************************* */ + +class PoolTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE (PoolTest); + CPPUNIT_TEST (allocate_get); + CPPUNIT_TEST (wrong_get); + CPPUNIT_TEST (search); + CPPUNIT_TEST (cache_test); + CPPUNIT_TEST_SUITE_END (); + +private: + TestPool * pool; + SqliteDB * db; + + int create_allocate(int n, string st) + { + TestObjectSQL *obj = new TestObjectSQL(n,st); + + return pool->allocate(obj); + }; + +public: + PoolTest(){}; + + ~PoolTest(){}; + + void setUp() + { + string db_name = "test.db"; + unlink("test.db"); + + db = new SqliteDB(db_name); + + TestObjectSQL::bootstrap(db); + + pool = new TestPool(db); + }; + + void tearDown() + { + delete db; + delete pool; + }; + + /* ********************************************************************* */ + /* ********************************************************************* */ + + // Try to allocate two objects, and retrieve them + void allocate_get() + { + int n1 = 3; + int n2 = 7; + string st1 = "text number one"; + string st2 = "another text"; + + TestObjectSQL *obj; + int oid; + + oid = create_allocate(n1,st1); + // first element in the pool should have oid=0 + CPPUNIT_ASSERT(oid == 0); + + oid = create_allocate(n2,st2); + // second element in the pool should have oid=1 + CPPUNIT_ASSERT(oid == 1); + + // --------------------------------- + obj = pool->get(0, false); + CPPUNIT_ASSERT(obj != 0); + + CPPUNIT_ASSERT(obj->number == n1); + CPPUNIT_ASSERT(obj->text == st1); + + // --------------------------------- + obj = pool->get(1, true); + CPPUNIT_ASSERT(obj != 0); + + CPPUNIT_ASSERT(obj->number == n2); + CPPUNIT_ASSERT(obj->text == st2); + obj->unlock(); + }; + + void wrong_get() + { + int n1 = 2; + string st1 = "object 2"; + + TestObjectSQL *obj; + int oid; + + oid = create_allocate(n1,st1); + + obj = pool->get(oid,true); + CPPUNIT_ASSERT(obj != 0); + + obj->drop(db); + obj->unlock(); + + obj = pool->get(oid,true); + CPPUNIT_ASSERT(obj == 0); + + pool->clean(); + obj = pool->get(oid,true); + CPPUNIT_ASSERT(obj == 0); + }; + + void search() + { + int nA = 13; + int nB = 17; + string stA = "String value for number 13"; + string stB = "String value for number 17"; + + int oidA = create_allocate(nA, stA); + int oidB = create_allocate(nB, stB); + + vector results; + const char * table = "test_pool"; + string where = "text = '" + stB + "'"; + int ret; + + ret = pool->search(results, table, where); + CPPUNIT_ASSERT(ret == 0); + CPPUNIT_ASSERT(results.size() == 1); + CPPUNIT_ASSERT(results.at(0) == oidB); + + results.erase(results.begin(), results.end()); + + where = "number < 18"; + + ret = pool->search(results, table, where); + CPPUNIT_ASSERT(ret == 0); + CPPUNIT_ASSERT(results.size() == 2); + CPPUNIT_ASSERT(results.at(0) == oidA); + CPPUNIT_ASSERT(results.at(1) == oidB); + }; + + void cache_test() + { + TestObjectSQL *obj; + TestObjectSQL *obj_lock; + + //pin object in the cache, it can't be removed - + for (int i=0 ; i < 499 ; i++) + { + create_allocate(i,"A Test object"); + + obj_lock = pool->get(i, true); + CPPUNIT_ASSERT(obj_lock != 0); + } + + for (int i=499 ; i < 2000 ; i++) + { + create_allocate(i,"A Test object"); + } + + for (int i=499; i < 2000 ; i++) + { + obj = pool->get(i, true); + CPPUNIT_ASSERT(obj != 0); + + CPPUNIT_ASSERT(obj->number == i); + CPPUNIT_ASSERT(obj->text == "A Test object"); + obj->unlock(); + } + + for (int i=0 ; i < 499 ; i++) + { + obj_lock = pool->get(i, false);//pin object in the cache, it can't be removed + obj_lock->unlock(); + } + }; +}; + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + +int main(int argc, char ** argv) +{ + CppUnit::TextUi::TestRunner runner; + runner.addTest( PoolTest::suite() ); + runner.run(); + return 0; +} diff --git a/src/template/test/SConstruct b/src/template/test/SConstruct new file mode 100644 index 0000000000..77a572f3e1 --- /dev/null +++ b/src/template/test/SConstruct @@ -0,0 +1,67 @@ +# -------------------------------------------------------------------------- # +# Copyright 2002-2009, Distributed Systems Architecture Group, Universidad # +# Complutense de Madrid (dsa-research.org) # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +import os +import sys +import shutil +sys.path.append("../../../share/scons") +from lex_bison import * + +# This is the absolute path where the project is located +cwd="../../../" + +# Environment that will be applied to each scons child +main_env=Environment() +main_env['ENV']['PATH']=os.environ['PATH'] + +# Add builders for flex and bison +add_lex(main_env) +add_bison(main_env) + +# Include dirs +main_env.Append(CPPPATH=[ + cwd + '/include', + '/usr/include/cppunit/' +]) + +# Library dirs +main_env.Append(LIBPATH=[ + cwd + '/src/common', + cwd + '/src/template', +]) + +main_env.Append(LIBS=[ + 'nebula_template', + 'nebula_common', + 'cppunit', + 'dl', + 'pthread', + 'sqlite3' +]) + +# Compile flags +main_env.Append(CPPFLAGS=[ + "-g", + "-Wall" +]) + +# Linking flags +main_env.Append(LDFLAGS=["-g "]) + +main_env.Program('template.cc') +main_env.Program('template_sql.cc') +# diff --git a/src/template/test/template.cc b/src/template/test/template.cc new file mode 100644 index 0000000000..15fdcf9574 --- /dev/null +++ b/src/template/test/template.cc @@ -0,0 +1,319 @@ +#include "Template.h" + +#include +#include + +#include +#include +#include +#include +#include + +using namespace std; + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + +class TemplateTest : public CppUnit::TestFixture +{ +private: + Template *t, *tr, *t1; + + string test_ok; + string test_ok_marshall; + string test_ok_xml; + string test_ok_str; + +public: + + /* --------------------------------------------------------------------- */ + /* --------------------------------------------------------------------- */ + + TemplateTest() + { + test_ok = + "#This line is a comment\n" + " # Other comment\n" + "MEMORY=345 # more comments behind an attribute\n" + " CPU = 4\n" + "#------------------------------\n" + "#Comments in the middle\n" + "#------------------------------\n" + " empty_var = \n" + "REQUIREMENTS = \"HOSTNAME = \\\"host*.com\\\"\"\n" + " DISK= [file = path1, extra = \"disk attribute \"]\n" + "DISK =[ FILE = \"path2\", EXTRA = str, TYPE=disk]\n" + " graphics = [\n" + " VNC = \"127.0.0.1\",\n" + " PORT = 12\n" + " ]\n"; + + test_ok_marshall="CPU=4\nDISK=EXTRA=disk attribute @^_^@FILE=path1\n" + "DISK=EXTRA=str@^_^@FILE=path2@^_^@TYPE=disk\nEMPTY_VAR=\n" + "GRAPHICS=PORT=12@^_^@VNC=127.0.0.1\nMEMORY=345\n" + "REQUIREMENTS=HOSTNAME = \"host*.com\"\n"; + + test_ok_xml=""; + + test_ok_str= + "\n\tCPU=4" + "\n\tDISK=EXTRA=disk attribute ,FILE=path1" + "\n\tDISK=EXTRA=str,FILE=path2,TYPE=disk" + "\n\tEMPTY_VAR=" + "\n\tGRAPHICS=PORT=12,VNC=127.0.0.1" + "\n\tMEMORY=345" + "\n\tREQUIREMENTS=HOSTNAME = \"host*.com\""; + } + + ~TemplateTest(){}; + + /* --------------------------------------------------------------------- */ + /* --------------------------------------------------------------------- */ + + void setUp() + { + char *error = 0; + + t = new Template(); + + tr= new Template(true); + tr->parse(test_ok,&error); + + t1= new Template(); + t1->parse(test_ok,&error); + } + + void tearDown() + { + delete t; + delete tr; + delete t1; + } + + /* ********************************************************************* */ + /* ********************************************************************* */ + + void test_parser() + { + char * error = 0; + int rc; + string tmp; + + rc = t->parse(test_ok,&error); + + if ( error != 0 ) + { + cerr << error << endl; + free(error); + } + + CPPUNIT_ASSERT( rc == 0); + } + + /* --------------------------------------------------------------------- */ + + void test_marshall() + { + string tmp; + + t1->marshall(tmp); + + CPPUNIT_ASSERT(test_ok_marshall == tmp); + } + + /* --------------------------------------------------------------------- */ + + void test_xml() + { + string tmp; + + t1->to_xml(tmp); + + CPPUNIT_ASSERT(test_ok_xml == tmp); + } + + /* --------------------------------------------------------------------- */ + + void test_str() + { + string tmp; + + t1->to_str(tmp); + + CPPUNIT_ASSERT(test_ok_str == tmp); + } + + /* --------------------------------------------------------------------- */ + + void test_get() + { + vector attrs; + string *tmp; + + CPPUNIT_ASSERT(t1->get("DISK",attrs) == 2 ); + + CPPUNIT_ASSERT(attrs[0]->type() == Attribute::VECTOR); + + tmp = attrs[0]->to_xml(); + CPPUNIT_ASSERT( *tmp == + "disk attribute path1"); + delete tmp; + + CPPUNIT_ASSERT(attrs[1]->type() == Attribute::VECTOR); + + tmp = attrs[1]->to_xml(); + CPPUNIT_ASSERT( *tmp == + "strpath2disk"); + delete tmp; + + CPPUNIT_ASSERT(t1->get("CPU",attrs) == 1 ); + + CPPUNIT_ASSERT(attrs[2]->type() == Attribute::SIMPLE); + + tmp = attrs[2]->to_xml(); + CPPUNIT_ASSERT( *tmp == "4"); + delete tmp; + + string sval; + string sname = "REQUIREMENTS"; + + string iname = "MEMORY"; + int ival; + + t1->get(iname,ival); + t1->get(sname,sval); + + CPPUNIT_ASSERT ( ival == 345 ); + CPPUNIT_ASSERT ( sval == "HOSTNAME = \"host*.com\""); + + } + + /* --------------------------------------------------------------------- */ + + void test_remove() + { + vector attrs; + + string t1_xml; + string rm_xml=""; + + t1->remove("DISK",attrs); + t1->to_xml(t1_xml); + + CPPUNIT_ASSERT(t1_xml == rm_xml); + + delete attrs[0]; + delete attrs[1]; + } + + + /* --------------------------------------------------------------------- */ + + void test_set() + { + string t1_xml=""; + string xml; + + string nattr = "XTRA"; + string vattr = "44"; + + SingleAttribute *a = new SingleAttribute(nattr,vattr); + + t1->set(a); + t1->to_xml(xml); + + CPPUNIT_ASSERT(t1_xml == xml); + + nattr = "CPU"; + vattr = "5"; + + t1_xml=""; + SingleAttribute *b = new SingleAttribute(nattr,vattr); + + t1->set(b); + t1->to_xml(xml); + + CPPUNIT_ASSERT(t1_xml == xml); + + string tr_xml=""; + SingleAttribute *c = new SingleAttribute(nattr,vattr); + + tr->set(c); + tr->to_xml(xml); + + CPPUNIT_ASSERT(tr_xml == xml); + } + + /* ********************************************************************* */ + /* ********************************************************************* */ + + static CppUnit::TestSuite * suite() + { + CppUnit::TestSuite *ts=new CppUnit::TestSuite("Template Tests"); + + ts->addTest(new CppUnit::TestCaller( + "parse() Test", + &TemplateTest::test_parser)); + + ts->addTest(new CppUnit::TestCaller( + "marshall() Test", + &TemplateTest::test_marshall)); + + ts->addTest(new CppUnit::TestCaller( + "xml() Test", + &TemplateTest::test_xml)); + + ts->addTest(new CppUnit::TestCaller( + "str() Test", + &TemplateTest::test_str)); + + ts->addTest(new CppUnit::TestCaller( + "get() Test", + &TemplateTest::test_get)); + + ts->addTest(new CppUnit::TestCaller( + "remove() Test", + &TemplateTest::test_remove)); + + ts->addTest(new CppUnit::TestCaller( + "set() Test", + &TemplateTest::test_set)); + return ts; + } +}; + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + +int main(int argc, char ** argv) +{ + CppUnit::TextUi::TestRunner tr; + + tr.addTest(TemplateTest::suite()); + tr.run(); + + return 0; +} diff --git a/src/template/test/template_sql.cc b/src/template/test/template_sql.cc new file mode 100644 index 0000000000..008a220502 --- /dev/null +++ b/src/template/test/template_sql.cc @@ -0,0 +1,220 @@ +#include "TemplateSQL.h" +#include "SqliteDB.h" +#include "Log.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace std; + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + +/* --------------------------------------- */ +/* WRAPPER TO ACCESS TEMPLATESQL CLASS */ +/* --------------------------------------- */ + +class TSQL : public TemplateSQL +{ +public: + TSQL(const char * _table, + int template_id = -1, + bool replace = false, + const char separator = '=', + const char * xml_root = "TEMPLATE"): + TemplateSQL(_table,template_id,replace,separator,xml_root){} + + ~TSQL(){} + + /* --------------------------------------------------------------------- */ + int insert(SqliteDB * db){return TemplateSQL::insert(db);} + int update(SqliteDB * db){return TemplateSQL::update(db);} + int select(SqliteDB * db){return TemplateSQL::select(db);} + int drop (SqliteDB * db){return TemplateSQL::drop(db);} + + /* --------------------------------------------------------------------- */ + int replace_attribute(SqliteDB * db, Attribute * attr) + {return TemplateSQL::replace_attribute(db,attr);} + int insert_attribute(SqliteDB * db, Attribute * attr) + {return TemplateSQL::insert_attribute(db,attr);} + /* --------------------------------------------------------------------- */ + int id(){return TemplateSQL::id;}; +}; + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + +class TemplateSQLTest : public CppUnit::TestFixture +{ +private: + SqliteDB *db; + TSQL *t; + + string filename; + + string template_ok; + string template_xml; + + static void log( + const char * module, + const Log::MessageType type, + const ostringstream& message, + const char * filename = 0, + Log::MessageType clevel = Log::ERROR) + { + cerr << message.str() << endl; + }; + +public: + /* --------------------------------------------------------------------- */ + /* --------------------------------------------------------------------- */ + + TemplateSQLTest() + { + filename = "template_sql.db"; + + template_ok = + "#This line is a comment\n" + " # Other comment\n" + "MEMORY=345 # more comments behind an attribute\n" + " CPU = 4\n" + "#------------------------------\n" + "#Comments in the middle\n" + "#------------------------------\n" + " empty_var = \n" + "REQUIREMENTS = \"HOSTNAME = \\\"host*.com\\\"\"\n" + " DISK= [file = path1, extra = \"disk attribute \"]\n" + "DISK =[ FILE = \"path2\", EXTRA = str, TYPE=disk]\n" + " graphics = [\n" + " VNC = \"127.0.0.1\",\n" + " PORT = 12\n" + " ]\n"; + + template_xml = + ""; + } + + ~TemplateSQLTest() + { + unlink("template_sql.db"); + } + + /* --------------------------------------------------------------------- */ + /* --------------------------------------------------------------------- */ + + void setUp() + { + db = new SqliteDB (filename , TemplateSQLTest::log); + t = new TSQL("template"); + } + + void tearDown() + { + delete db; + delete t; + } + + /* ********************************************************************* */ + /* ********************************************************************* */ + + void test_bootstrap() + { + const char * db_bs = "CREATE TABLE template" + " (id INTEGER, name TEXT, type INTEGER, value TEXT)"; + + CPPUNIT_ASSERT( db->exec(db_bs) == 0); + } + + /* --------------------------------------------------------------------- */ + + void test_insert() + { + char * error = 0; + int rc; + string tmp; + + rc = t->parse(template_ok,&error); + + if ( error != 0 ) + { + cerr << error << endl; + free(error); + } + + CPPUNIT_ASSERT( rc == 0); + + CPPUNIT_ASSERT( t->insert(db) == 0 ); + CPPUNIT_ASSERT( t->id() == 0 ); + + CPPUNIT_ASSERT( t->insert(db) == 0 ); + CPPUNIT_ASSERT( t->id() == 1 ); + + CPPUNIT_ASSERT( t->insert(db) == 0 ); + CPPUNIT_ASSERT( t->id() == 2 ); + } + + /* --------------------------------------------------------------------- */ + + void test_select() + { + TSQL t2("template",1); + string t2_xml; + + CPPUNIT_ASSERT( t2.select(db) == 0 ); + + t2.to_xml(t2_xml); + + CPPUNIT_ASSERT( t2_xml == template_xml ); + + } + + /* ********************************************************************* */ + /* ********************************************************************* */ + + static CppUnit::TestSuite * suite() + { + CppUnit::TestSuite *ts=new CppUnit::TestSuite("TemplateSQL Tests"); + + ts->addTest(new CppUnit::TestCaller( + "db() Test", + &TemplateSQLTest::test_bootstrap)); + + ts->addTest(new CppUnit::TestCaller( + "insert() Test", + &TemplateSQLTest::test_insert)); + + ts->addTest(new CppUnit::TestCaller( + "update() Test", + &TemplateSQLTest::test_select)); + + return ts; + } +}; + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + +int main(int argc, char ** argv) +{ + CppUnit::TextUi::TestRunner tr; + + tr.addTest(TemplateSQLTest::suite()); + tr.run(); + + return 0; +} diff --git a/src/um/test/SConstruct b/src/um/test/SConstruct new file mode 100755 index 0000000000..7f4689477c --- /dev/null +++ b/src/um/test/SConstruct @@ -0,0 +1,71 @@ +# -------------------------------------------------------------------------- +# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# -------------------------------------------------------------------------- + +import os +import sys +import shutil +sys.path.append("../../../share/scons") +from lex_bison import * + +# This is the absolute path where the project is located +cwd="../../../" + +# Environment that will be applied to each scons child +main_env=Environment() +main_env['ENV']['PATH']=os.environ['PATH'] + +# Add builders for flex and bison +add_lex(main_env) +add_bison(main_env) + +# Include dirs +main_env.Append(CPPPATH=[ + cwd + '/include', + '/usr/include/cppunit/', +]) + +# Library dirs +main_env.Append(LIBPATH=[ + cwd + '/src/common', + cwd + '/src/nebula', + cwd + '/src/pool', + cwd + '/src/um', + '/usr/include/openssl/', +]) + +main_env.Append(LIBS=[ + 'nebula_um', + 'nebula_pool', + 'nebula_common', + 'nebula_core', + 'cppunit', + 'dl', + 'pthread', + 'sqlite3', + 'crypto' +]) + +# Compile flags +main_env.Append(CPPFLAGS=[ + "-g", + "-Wall" +]) + +# Linking flags +main_env.Append(LDFLAGS=["-g "]) + +main_env.Program('UserPoolTest.cc') + diff --git a/src/um/test/UserPoolTest.cc b/src/um/test/UserPoolTest.cc new file mode 100755 index 0000000000..65cd82c7b1 --- /dev/null +++ b/src/um/test/UserPoolTest.cc @@ -0,0 +1,366 @@ +/* -------------------------------------------------------------------------- */ +/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); you may */ +/* not use this file except in compliance with the License. You may obtain */ +/* a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ +/* -------------------------------------------------------------------------- */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "UserPool.h" + +using namespace std; + +/* ************************************************************************* */ +/* ************************************************************************* */ + +class UserPoolTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE (UserPoolTest); + CPPUNIT_TEST (sha1_digest); + CPPUNIT_TEST (initial_user); + CPPUNIT_TEST (authenticate); + CPPUNIT_TEST (get_from_cache); + CPPUNIT_TEST (get_from_db); + CPPUNIT_TEST (drop_and_get); + CPPUNIT_TEST (update); + CPPUNIT_TEST (dump); + CPPUNIT_TEST_SUITE_END (); + +private: + UserPool * pool; + SqliteDB * db; + + User* user; + + +public: + UserPoolTest(){}; + + ~UserPoolTest(){}; + + void setUp() + { + string db_name = "test.db"; + unlink("test.db"); + + db = new SqliteDB(db_name); + + + UserPool::bootstrap(db); + + // The UserPool constructor checks if the DB contains at least + // one user, and adds one automatically from the ONE_AUTH file. + // So the ONE_AUTH environment is forced to point to a test one_auth + // file. + string pwd = getenv("PWD"); + const char * auth = (pwd + "/one_auth").c_str(); + + setenv("ONE_AUTH", auth, 1); + + pool = new UserPool(db); + }; + + void tearDown() + { + delete db; + delete pool; + remove ("test.db"); + }; + + /* ********************************************************************* */ + /* ********************************************************************* */ + + void sha1_digest() + { + string st = "top_secret_string"; + string sha1 = "773260f433f7fd6f89c1f1bfc32e080fc0748478"; + + CPPUNIT_ASSERT( sha1 == User::sha1_digest(st) ); + } + + void initial_user() + { + // When creating a new pool, the constructor will check if the DB + // contains at least one user. + // If it doesn't, it adds one automatically from: + // * The $ONE_AUTH file. + // * The ~/.one/one_auth file. + + // The ONE_AUTH environment variable was forced to point to a prepared + // one_auth file at set-up, so the pool should contain the user + // one_user_test:password + + user = pool->get(0, false); + CPPUNIT_ASSERT(user != 0); + + CPPUNIT_ASSERT( user->get_uid() == 0 ); + CPPUNIT_ASSERT( user->get_username() == "one_user_test" ); + CPPUNIT_ASSERT( user->get_password() == User::sha1_digest("password") ); + } + + void authenticate() + { + // There is an initial user, created with the one_auth file: + // one_user_test:password + string session = + "one_user_test:5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8"; + int oid = pool->authenticate( session ); + CPPUNIT_ASSERT( oid == 0 ); + + session = "one_user_test:wrong_password"; + oid = pool->authenticate( session ); + CPPUNIT_ASSERT( oid == -1 ); + + session = + "unknown_user:5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8"; + oid = pool->authenticate( session ); + CPPUNIT_ASSERT( oid == -1 ); + } + + // Try to allocate two objects, and retrieve them + void get_from_cache() + { + string username_1 = "A user"; + string username_2 = "B user"; + + string pass_1 = "A pass"; + string pass_2 = "B pass"; + + int oid_1, oid_2; + + pool->allocate(&oid_1, username_1, pass_1, true); + // first element in the pool should have oid=1 (the 0th one is created + // by the UserPool constructor) + CPPUNIT_ASSERT(oid_1 == 1); + + pool->allocate(&oid_2, username_2, pass_2, true); + // second element in the pool should have oid=2 + CPPUNIT_ASSERT(oid_2 == 2); + + + // --------------------------------- + user = pool->get(oid_1, false); + CPPUNIT_ASSERT(user != 0); + + CPPUNIT_ASSERT( user->get_uid() == 1 ); + CPPUNIT_ASSERT( user->get_username() == username_1 ); + CPPUNIT_ASSERT( user->get_password() == pass_1 ); + + // --------------------------------- + user = pool->get(oid_2, true); + CPPUNIT_ASSERT(user != 0); + + CPPUNIT_ASSERT( user->get_uid() == 2 ); + CPPUNIT_ASSERT( user->get_username() == username_2 ); + CPPUNIT_ASSERT( user->get_password() == pass_2 ); + user->unlock(); + }; + + // Try to allocate two objects, and retrieve them + void get_from_db() + { + string username_1 = "A user"; + string username_2 = "B user"; + + string pass_1 = "A pass"; + string pass_2 = "B pass"; + + int oid_1, oid_2; + + pool->allocate(&oid_1, username_1, pass_1, true); + pool->allocate(&oid_2, username_2, pass_2, true); + + string str; + // Get the xml representation of the two users + string xml_1 = pool->get(oid_1, false)->to_xml(str); + string xml_2 = pool->get(oid_2, false)->to_xml(str); + + // Clean the users from the cache, forcing the pool to read them from + // the DB when we retrieve them + pool->clean(); + + // --------------------------------- + user = pool->get(oid_1, false); + CPPUNIT_ASSERT(user != 0); + + // The user objects constructed from the data in the DB should be the + // same as the previous ones + CPPUNIT_ASSERT(user->to_xml(str) == xml_1); + + CPPUNIT_ASSERT(user->get_uid() == oid_1); + CPPUNIT_ASSERT(user->get_username() == username_1); + CPPUNIT_ASSERT(user->get_password() == pass_1); + + // --------------------------------- + user = pool->get(oid_2, true); + CPPUNIT_ASSERT(user != 0); + + CPPUNIT_ASSERT(user->to_xml(str) == xml_2); + + CPPUNIT_ASSERT(user->get_uid() == oid_2); + CPPUNIT_ASSERT(user->get_username() == username_2); + CPPUNIT_ASSERT(user->get_password() == pass_2); + user->unlock(); + }; + + void drop_and_get() + { + string username_1 = "A user"; + string username_2 = "B user"; + + string pass_1 = "A pass"; + string pass_2 = "B pass"; + + int oid_1, oid_2; + + pool->allocate(&oid_1, username_1, pass_1, true); + pool->allocate(&oid_2, username_2, pass_2, true); + + // Get the first user (A) + user = pool->get(oid_1,true); + CPPUNIT_ASSERT(user != 0); + + // Delete it + pool->drop(user); + user->unlock(); + + // It should be gone now + user = pool->get(oid_1,true); + CPPUNIT_ASSERT(user == 0); + + // The cache is cleaned, the user should be also gone from the DB + pool->clean(); + user = pool->get(oid_1,true); + CPPUNIT_ASSERT(user == 0); + + // But the other user must be accessible + user = pool->get(oid_2,false); + CPPUNIT_ASSERT(user != 0); + }; + + void update() + { + string username_1 = "A user"; + string pass_1 = "A pass"; + + int oid_1, oid_2; + + // Allocate some users, to popullate the DB + pool->allocate(&oid_2, "someone", pass_1, true); + pool->allocate(&oid_2, "some_user", pass_1, true); + + // The user we are interested in + pool->allocate(&oid_1, username_1, pass_1, true); + + // Some more users... + pool->allocate(&oid_2, "not_used", pass_1, true); + pool->allocate(&oid_2, "no_name", pass_1, true); + + + user = pool->get(oid_1, true); + + // User object should be cached. Let's update its status + user->disable(); + + pool->update(user); + user->unlock(); + + + // When the user is updated, there should be only one entry at the DB + vector results; + int rc; + ostringstream oss; + + oss << "oid = " << oid_1; + + rc = pool->search(results,"user_pool", oss.str()); + + CPPUNIT_ASSERT(rc == 0); + CPPUNIT_ASSERT(results.size() == 1); + CPPUNIT_ASSERT(results.at(0) == oid_1); + + user = pool->get(oid_1,false); + CPPUNIT_ASSERT( user->isEnabled() == false ); + + //Now force access to DB + + pool->clean(); + user = pool->get(oid_1,false); + CPPUNIT_ASSERT( user->isEnabled() == false ); + }; + + void dump() + { + string xml_result = + "0one_user_test" + "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8" + "True1a" + "pTrue" + "2a namepass" + "True3a_name" + "passwordTrue" + "4another namesecret" + "True5user" + "1234True" + ""; + + + string names[] = {"a", "a name", "a_name", "another name", "user"}; + string pass[] = {"p", "pass", "password", "secret", "1234"}; + + int oid; + + for(int i=0; i<5; i++) + { + pool->allocate(&oid, names[i], pass[i], true); + } + + ostringstream oss; + pool->dump(oss, ""); + + CPPUNIT_ASSERT( oss.str() == xml_result ); + + // Allocate and delete a new user + pool->allocate(&oid, "new name", "new pass", true); + user = pool->get(oid, true); + pool->drop(user); + user->unlock(); + + ostringstream new_oss; + pool->dump(new_oss, ""); + + CPPUNIT_ASSERT( new_oss.str() == xml_result ); + } +}; + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + +int main(int argc, char ** argv) +{ + CppUnit::TextUi::TestRunner runner; + runner.addTest( UserPoolTest::suite() ); + runner.run(); + return 0; +} diff --git a/src/um/test/one_auth b/src/um/test/one_auth new file mode 100644 index 0000000000..2f55c9c47b --- /dev/null +++ b/src/um/test/one_auth @@ -0,0 +1 @@ +one_user_test:password