blob: 13423a5b14534656a35eefacee755931dad564f8 [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
2'''
3Created on 20-Dec-2012
Jeremy Songsterae01bba2016-07-11 15:39:17 -07004Modified 2016 by ON.Lab
Jon Hall5f15fef2015-07-17 14:22:14 -07005
Jeremy Songsterae01bba2016-07-11 15:39:17 -07006Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
7the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
8or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
adminbae64d82013-08-01 10:50:15 -07009
10 TestON is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 2 of the License, or
13 (at your option) any later version.
14
15 TestON is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
Jon Hall4ba53f02015-07-29 13:07:41 -070021 along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070022
23
24'''
25
26
27"""
28cli will provide the CLI shell for teston framework.
29
30A simple command-line interface for TestON.
31
32The TestON CLI provides a simple console which
33makes it easy to launch the test. For example, the command run will execute the test.
34
35teston> run test DpctlTest
36Several useful commands are provided.
37"""
38
39from subprocess import call
40from cmd import Cmd
41from os import isatty
42import sys
43import re
44import os
45import time
46import threading
47import __builtin__
48import pprint
49dump = pprint.PrettyPrinter(indent=4)
50__builtin__.testthread = False
51introduction = "TestON is the testing framework \nDeveloped by Paxterra Solutions (www.paxterrasolutions.com)"
Jon Hall0bde9ba2015-03-19 11:32:57 -070052__builtin__.COLORS = False
adminbae64d82013-08-01 10:50:15 -070053
Jon Hall1dd5a0a2015-07-08 10:49:26 -070054path = re.sub( "/bin$", "", sys.path[0] )
55sys.path.insert( 1, path )
Jon Hall0bde9ba2015-03-19 11:32:57 -070056from core.teston import *
adminbae64d82013-08-01 10:50:15 -070057
58class CLI( threading.Thread,Cmd,object ):
59 "command-line interface to execute the test."
60
61 prompt = 'teston> '
62
63 def __init__( self, teston, stdin=sys.stdin ):
64 self.teston = teston
Jon Hall0bde9ba2015-03-19 11:32:57 -070065
adminbae64d82013-08-01 10:50:15 -070066 self._mainevent = threading.Event()
67 threading.Thread.__init__(self)
68 self.main_stop = False
69 self.locals = { 'test': teston }
70 self.stdin = stdin
71 Cmd.__init__( self )
72 self.pause = False
73 self.stop = False
74 __builtin__.cli = self
75
76 def emptyline( self ):
77 "Don't repeat last command when you hit return."
78 pass
79
80 helpStr = (
81 " teston help"
82 )
83
84 def do_help( self, line ):
85 "Describe available CLI commands."
86 Cmd.do_help( self, line )
87 if line is '':
88 output( self.helpStr )
89 def do_run(self,args):
90 '''
91 run command will execute the test with following optional command line arguments
92 logdir <directory to store logs in>
93 testcases <list of testcases separated by comma or range of testcases separated by hypen>
94 mail <mail-id or list of mail-ids seperated by comma>
95 example 1, to execute the examples specified in the ~/examples diretory.
96 '''
Jon Hall1306a562015-09-04 11:21:24 -070097 try:
98 args = args.split()
99 options = {}
100 options = self.parseArgs(args,options)
101 options = dictToObj(options)
102 if not testthread:
103 test = TestThread(options)
104 test.start()
105 while test.isAlive():
106 test.join(1)
107 else:
108 print main.TEST+ " test execution paused, please resume that before executing to another test"
109 except KeyboardInterrupt, SystemExit:
110 print "Interrupt called, Exiting."
111 test._Thread__stop()
112 main.cleanup()
113 main.exit()
Jon Hall4ba53f02015-07-29 13:07:41 -0700114
adminbae64d82013-08-01 10:50:15 -0700115 def do_resume(self, line):
116 '''
117 resume command will continue the execution of paused test.
118 teston>resume
119 [2013-01-07 23:03:44.640723] [PoxTest] [STEP] 1.1: Checking the host reachability using pingHost
120 2013-01-07 23:03:44,858 - PoxTest - INFO - Expected Prompt Found
121 ....
122 '''
123 if testthread:
124 testthread.play()
125 else :
126 print "There is no test to resume"
Jon Hall4ba53f02015-07-29 13:07:41 -0700127
adminbae64d82013-08-01 10:50:15 -0700128 def do_nextstep(self,line):
129 '''
Jon Hall4ba53f02015-07-29 13:07:41 -0700130 nextstep will execute the next-step of the paused test and
adminbae64d82013-08-01 10:50:15 -0700131 it will pause the test after finishing of step.
Jon Hall4ba53f02015-07-29 13:07:41 -0700132
adminbae64d82013-08-01 10:50:15 -0700133 teston> nextstep
134 Will pause the test's execution, after completion of this step.....
Jon Hall4ba53f02015-07-29 13:07:41 -0700135
adminbae64d82013-08-01 10:50:15 -0700136 teston> [2013-01-07 21:24:26.286601] [PoxTest] [STEP] 1.8: Checking the host reachability using pingHost
137 2013-01-07 21:24:26,455 - PoxTest - INFO - Expected Prompt Found
138 .....
139 teston>
Jon Hall4ba53f02015-07-29 13:07:41 -0700140
adminbae64d82013-08-01 10:50:15 -0700141 '''
142 if testthread:
143 main.log.info("Executing the nextstep, Will pause test execution, after completion of the step")
144 testthread.play()
145 time.sleep(.1)
146 testthread.pause()
147 else:
148 print "There is no paused test "
Jon Hall4ba53f02015-07-29 13:07:41 -0700149
adminbae64d82013-08-01 10:50:15 -0700150 def do_dumpvar(self,line):
151 '''
152 dumpvar will print all the test data in raw format.
Jon Hall4ba53f02015-07-29 13:07:41 -0700153 usgae :
adminbae64d82013-08-01 10:50:15 -0700154 teston>dumpvar main
155 Here 'main' will be the test object.
Jon Hall4ba53f02015-07-29 13:07:41 -0700156
157 teston>dumpvar params
adminbae64d82013-08-01 10:50:15 -0700158 here 'params' will be the parameters specified in the params file.
Jon Hall4ba53f02015-07-29 13:07:41 -0700159
adminbae64d82013-08-01 10:50:15 -0700160 teston>dumpvar topology
161 here 'topology' will be topology specification of the test specified in topo file.
162 '''
163 if testthread:
164 if line == "main":
165 dump.pprint(vars(main))
166 else :
167 try :
168 dump.pprint(vars(main)[line])
Jon Hall1306a562015-09-04 11:21:24 -0700169 except KeyError as e:
adminbae64d82013-08-01 10:50:15 -0700170 print e
171 else :
172 print "There is no paused test "
Jon Hall4ba53f02015-07-29 13:07:41 -0700173
adminbae64d82013-08-01 10:50:15 -0700174 def do_currentcase(self,line):
175 '''
176 currentcase will return the current case in the test execution.
Jon Hall4ba53f02015-07-29 13:07:41 -0700177
adminbae64d82013-08-01 10:50:15 -0700178 teston>currentcase
179 Currently executing test case is: 2
Jon Hall4ba53f02015-07-29 13:07:41 -0700180
adminbae64d82013-08-01 10:50:15 -0700181 '''
182 if testthread:
183 print "Currently executing test case is: "+str(main.CurrentTestCaseNumber)
184 else :
185 print "There is no paused test "
Jon Hall4ba53f02015-07-29 13:07:41 -0700186
187
adminbae64d82013-08-01 10:50:15 -0700188 def do_currentstep(self,line):
189 '''
190 currentstep will return the current step in the test execution.
Jon Hall4ba53f02015-07-29 13:07:41 -0700191
adminbae64d82013-08-01 10:50:15 -0700192 teston>currentstep
193 Currently executing test step is: 2.3
194 '''
195 if testthread:
196 print "Currently executing test step is: "+str(main.CurrentTestCaseNumber)+'.'+str(main.stepCount)
197 else :
198 print "There is no paused test "
Jon Hall4ba53f02015-07-29 13:07:41 -0700199
200
adminbae64d82013-08-01 10:50:15 -0700201 def do_stop(self,line):
202 '''
203 Will stop the paused test, if any !
204 '''
205 if testthread:
206 testthread.stop()
Jon Hall4ba53f02015-07-29 13:07:41 -0700207
adminbae64d82013-08-01 10:50:15 -0700208 return 'exited by user command'
Jon Hall4ba53f02015-07-29 13:07:41 -0700209
adminbae64d82013-08-01 10:50:15 -0700210 def do_gettest(self,line):
211 '''
212 gettest will return the test name which is under execution or recently executed.
Jon Hall4ba53f02015-07-29 13:07:41 -0700213
adminbae64d82013-08-01 10:50:15 -0700214 Test under execution:
Jon Hall4ba53f02015-07-29 13:07:41 -0700215 teston>gettest
adminbae64d82013-08-01 10:50:15 -0700216 Currently executing Test is: PoxTest
Jon Hall4ba53f02015-07-29 13:07:41 -0700217
adminbae64d82013-08-01 10:50:15 -0700218 Test recently executed:
219 Recently executed test is: MininetTest
220 '''
221 try :
222 if testthread :
223 print "Currently executing Test is: "+main.TEST
224 else :
225 print "Recently executed test is: "+main.TEST
Jon Hall4ba53f02015-07-29 13:07:41 -0700226
adminbae64d82013-08-01 10:50:15 -0700227 except NameError:
228 print "There is no previously executed Test"
Jon Hall4ba53f02015-07-29 13:07:41 -0700229
adminbae64d82013-08-01 10:50:15 -0700230 def do_showlog(self,line):
231 '''
232 showlog will show the test's Log
233 teston>showlog
234 Last executed test's log is : //home/openflow/TestON/logs/PoxTest_07_Jan_2013_21_42_11/PoxTest_07_Jan_2013_21_42_11.log
235 .....
236 teston>showlog
237 Currently executing Test's log is: /home/openflow/TestON/logs/PoxTest_07_Jan_2013_21_46_58/PoxTest_07_Jan_2013_21_46_58.log
238 .....
239 '''
240 try :
241 if testthread :
242 print "Currently executing Test's log is: "+main.LogFileName
Jon Hall4ba53f02015-07-29 13:07:41 -0700243
adminbae64d82013-08-01 10:50:15 -0700244 else :
245 print "Last executed test's log is : "+main.LogFileName
Jon Hall4ba53f02015-07-29 13:07:41 -0700246
adminbae64d82013-08-01 10:50:15 -0700247 logFile = main.LogFileName
248 logFileHandler = open(logFile, 'r')
249 for msg in logFileHandler.readlines() :
250 print msg,
Jon Hall4ba53f02015-07-29 13:07:41 -0700251
adminbae64d82013-08-01 10:50:15 -0700252 logFileHandler.close()
Jon Hall4ba53f02015-07-29 13:07:41 -0700253
adminbae64d82013-08-01 10:50:15 -0700254 except NameError:
255 print "There is no previously executed Test"
Jon Hall4ba53f02015-07-29 13:07:41 -0700256
257
258
adminbae64d82013-08-01 10:50:15 -0700259 def parseArgs(self,args,options):
260 '''
261 This will parse the command line arguments.
262 '''
263 options = self.initOptions(options)
264 try :
YPZhang16f6e562016-07-12 15:50:31 -0700265 index = 0
266 while index < len( args ):
267 option = args[index]
adminbae64d82013-08-01 10:50:15 -0700268 if index > 0 :
YPZhang16f6e562016-07-12 15:50:31 -0700269 if re.match("--params", option, flags=0):
YPZhang1c89e762016-06-29 10:43:58 -0700270 # check if there is a params
YPZhang16f6e562016-07-12 15:50:31 -0700271 options['params'].append(args[index+1])
272 elif re.match("logdir|mail|example|testdir|testcases|onoscell", option, flags = 0):
273 options[option] = args[index+1]
274 options = self.testcasesInRange(index+1,option,args,options)
275 index += 2
adminbae64d82013-08-01 10:50:15 -0700276 else :
277 options['testname'] = option
YPZhang16f6e562016-07-12 15:50:31 -0700278 index += 1
Jon Hall1306a562015-09-04 11:21:24 -0700279 except IndexError as e:
YPZhang16f6e562016-07-12 15:50:31 -0700280 print (e)
281 main.cleanup()
282 main.exit()
Jon Hall4ba53f02015-07-29 13:07:41 -0700283
adminbae64d82013-08-01 10:50:15 -0700284 return options
Jon Hall4ba53f02015-07-29 13:07:41 -0700285
adminbae64d82013-08-01 10:50:15 -0700286 def initOptions(self,options):
287 '''
288 This will initialize the commandline options.
289 '''
290 options['logdir'] = None
291 options['mail'] = None
292 options['example'] = None
293 options['testdir'] = None
294 options['testcases'] = None
Hari Krishna03f530e2015-07-10 17:28:27 -0700295 options['onoscell'] = None
YPZhang1c89e762016-06-29 10:43:58 -0700296 # init params as a empty list
297 options['params'] = []
Jon Hall4ba53f02015-07-29 13:07:41 -0700298 return options
299
adminbae64d82013-08-01 10:50:15 -0700300 def testcasesInRange(self,index,option,args,options):
301 '''
302 This method will handle testcases list,specified in range [1-10].
303 '''
304 if re.match("testcases",option,1):
305 testcases = []
306 args[index] = re.sub("\[|\]","",args[index],0)
307 m = re.match("(\d+)\-(\d+)",args[index],flags=0)
308 if m:
309 start_case = eval(m.group(1))
310 end_case = eval(m.group(2))
311 if (start_case <= end_case):
312 i = start_case
313 while i <= end_case:
314 testcases.append(i)
Jon Hall4ba53f02015-07-29 13:07:41 -0700315 i= i+1
adminbae64d82013-08-01 10:50:15 -0700316 else :
317 print "Please specify testcases properly like 1-5"
318 else :
319 options[option] = args[index]
320 return options
321 options[option] = str(testcases)
Jon Hall4ba53f02015-07-29 13:07:41 -0700322
adminbae64d82013-08-01 10:50:15 -0700323 return options
Jon Hall4ba53f02015-07-29 13:07:41 -0700324
adminbae64d82013-08-01 10:50:15 -0700325 def cmdloop(self, intro=introduction):
326 print introduction
327 while True:
328 try:
329 super(CLI, self).cmdloop(intro="")
330 self.postloop()
331 except KeyboardInterrupt:
Jon Hall1306a562015-09-04 11:21:24 -0700332 if testthread:
333 testthread.pause()
334 else:
335 print "KeyboardInterrupt, Exiting."
336 sys.exit()
adminbae64d82013-08-01 10:50:15 -0700337
338 def do_echo( self, line ):
339 '''
340 Echoing of given input.
341 '''
342 output(line)
343
344 def do_sh( self, line ):
345 '''
346 Run an external shell command
347 sh pwd
348 sh ifconfig etc.
349 '''
350 call( line, shell=True )
351
352
353 def do_py( self, line ):
354 '''
355 Evaluate a Python expression.
Jon Hall4ba53f02015-07-29 13:07:41 -0700356
adminbae64d82013-08-01 10:50:15 -0700357 py main.log.info("Sample Log Information")
358 2013-01-07 12:07:26,804 - PoxTest - INFO - Sample Log Information
Jon Hall4ba53f02015-07-29 13:07:41 -0700359
adminbae64d82013-08-01 10:50:15 -0700360 '''
361 try:
362 exec( line )
Jon Hall1306a562015-09-04 11:21:24 -0700363 except Exception as e:
adminbae64d82013-08-01 10:50:15 -0700364 output( str( e ) + '\n' )
Jon Hall4ba53f02015-07-29 13:07:41 -0700365
adminbae64d82013-08-01 10:50:15 -0700366 def do_interpret(self,line):
367 '''
368 interpret will translate the single line openspeak statement to equivalent python script.
Jon Hall4ba53f02015-07-29 13:07:41 -0700369
adminbae64d82013-08-01 10:50:15 -0700370 teston> interpret ASSERT result EQUALS main.TRUE ONPASS "Ping executed successfully" ONFAIL "Ping failed"
371 utilities.assert_equals(expect=main.TRUE,actual=result,onpass="Ping executed successfully",onfail="Ping failed")
Jon Hall4ba53f02015-07-29 13:07:41 -0700372
adminbae64d82013-08-01 10:50:15 -0700373 '''
374 from core import openspeak
375 ospk = openspeak.OpenSpeak()
376 try :
377 translated_code = ospk.interpret(text=line)
378 print translated_code
Jon Hall1306a562015-09-04 11:21:24 -0700379 except AttributeError as e:
adminbae64d82013-08-01 10:50:15 -0700380 print 'Dynamic params are not allowed in single statement translations'
Jon Hall4ba53f02015-07-29 13:07:41 -0700381
adminbae64d82013-08-01 10:50:15 -0700382 def do_do (self,line):
383 '''
384 Do will translate and execute the openspeak statement for the paused test.
385 do <OpenSpeak statement>
386 '''
387 if testthread:
388 from core import openspeak
389 ospk = openspeak.OpenSpeak()
390 try :
391 translated_code = ospk.interpret(text=line)
392 eval(translated_code)
Jon Hall1306a562015-09-04 11:21:24 -0700393 except ( AttributeError, SyntaxError ) as e:
394 print 'Dynamic params are not allowed in single statement translations:'
395 print e
adminbae64d82013-08-01 10:50:15 -0700396 else :
397 print "Do will translate and execute the openspeak statement for the paused test.\nPlease use interpret to translate the OpenSpeak statement."
Jon Hall4ba53f02015-07-29 13:07:41 -0700398
adminbae64d82013-08-01 10:50:15 -0700399 def do_compile(self,line):
400 '''
401 compile will translate the openspeak (.ospk) file into TestON test script (python).
Jon Hall4ba53f02015-07-29 13:07:41 -0700402 It will receive the openspeak file path as input and will generate
403 equivalent test-script file in the same directory.
404
adminbae64d82013-08-01 10:50:15 -0700405 usage:
406 -----
407 teston>compile /home/openflow/TestON/PoxTest.ospk
Jon Hall4ba53f02015-07-29 13:07:41 -0700408
adminbae64d82013-08-01 10:50:15 -0700409 Auto-generated test-script file is /home/openflow/TestON/PoxTest.py
410 '''
411 from core import openspeak
Jon Hall4ba53f02015-07-29 13:07:41 -0700412 openspeak = openspeak.OpenSpeak()
adminbae64d82013-08-01 10:50:15 -0700413 openspeakfile = line
414 if os.path.exists(openspeakfile) :
415 openspeak.compiler(openspeakfile=openspeakfile,writetofile=1)
416 print "Auto-generated test-script file is "+ re.sub("ospk","py",openspeakfile,0)
417 else:
418 print 'There is no such file : '+line
419
420 def do_exit( self, _line ):
421 "Exit"
422 if testthread:
423 testthread.stop()
Jon Hall4ba53f02015-07-29 13:07:41 -0700424
adminbae64d82013-08-01 10:50:15 -0700425 sys.exit()
426
427 return 'exited by user command'
428
429 def do_quit( self, line ):
430 "Exit"
431 return self.do_exit( line )
432
433 def do_EOF( self, line ):
434 "Exit"
435 output( '\n' )
436 return self.do_exit( line )
437
438 def isatty( self ):
439 "Is our standard input a tty?"
440 return isatty( self.stdin.fileno() )
441
442 def do_source( self, line ):
443 '''
444 Read shell commands from an input file and execute them sequentially.
445 cmdsource.txt :
Jon Hall4ba53f02015-07-29 13:07:41 -0700446
adminbae64d82013-08-01 10:50:15 -0700447 "pwd
448 ls "
Jon Hall4ba53f02015-07-29 13:07:41 -0700449
adminbae64d82013-08-01 10:50:15 -0700450 teston>source /home/openflow/cmdsource.txt
451 /home/openflow/TestON/bin/
452 cli.py __init__.py
Jon Hall4ba53f02015-07-29 13:07:41 -0700453
adminbae64d82013-08-01 10:50:15 -0700454 '''
Jon Hall4ba53f02015-07-29 13:07:41 -0700455
adminbae64d82013-08-01 10:50:15 -0700456 args = line.split()
457 if len(args) != 1:
458 error( 'usage: source <file>\n' )
459 return
460 try:
461 self.inputFile = open( args[ 0 ] )
462 while True:
463 line = self.inputFile.readline()
464 if len( line ) > 0:
465 call( line, shell=True )
466 else:
467 break
468 except IOError:
469 error( 'error reading file %s\n' % args[ 0 ] )
Jon Hall4ba53f02015-07-29 13:07:41 -0700470
adminbae64d82013-08-01 10:50:15 -0700471 def do_time( self, line ):
472 "Measure time taken for any command in TestON."
473 start = time.time()
474 self.onecmd(line)
475 elapsed = time.time() - start
476 self.stdout.write("*** Elapsed time: %0.6f secs\n" % elapsed)
477
478 def default( self, line ):
479 """Called on an input line when the command prefix is not recognized."""
480 first, args, line = self.parseline( line )
481 if not args:
482 return
483 if args and len(args) > 0 and args[ -1 ] == '\n':
484 args = args[ :-1 ]
485 rest = args.split( ' ' )
486
487 error( '*** Unknown command: %s\n' % first )
488
adminbae64d82013-08-01 10:50:15 -0700489class TestThread(threading.Thread):
490 '''
491 TestThread class will handle the test execution and will communicate with the thread in the do_run.
492 '''
493 def __init__(self,options):
494 self._stopevent = threading.Event()
495 threading.Thread.__init__(self)
496 self.is_stop = False
497 self.options = options
498 __builtin__.testthread = self
499
500 def run(self):
501 '''
502 Will execute the test.
503 '''
504 while not self.is_stop :
505 if not self._stopevent.isSet():
506 self.test_on = TestON(self.options)
507 try :
508 if self.test_on.init_result:
509 result = self.test_on.run()
510 if not self.is_stop :
511 result = self.test_on.cleanup()
512 self.is_stop = True
Jon Hall1306a562015-09-04 11:21:24 -0700513 except KeyboardInterrupt:
514 print "Recevied Interrupt, cleaning-up the logs and drivers before exiting"
adminbae64d82013-08-01 10:50:15 -0700515 result = self.test_on.cleanup()
516 self.is_stop = True
517
Jon Hall4ba53f02015-07-29 13:07:41 -0700518 __builtin__.testthread = False
adminbae64d82013-08-01 10:50:15 -0700519
520 def pause(self):
521 '''
522 Will pause the test.
523 '''
Jon Hall1306a562015-09-04 11:21:24 -0700524 if not cli.pause:
525 print "Will pause the test's execution, after completion of this step.....\n\n\n\n"
526 cli.pause = True
527 self._stopevent.set()
528 elif cli.pause and self.is_stop:
529 print "KeyboardInterrupt, Exiting."
530 self.test_on.exit()
531 else:
532 print "Recevied Interrupt, cleaning-up the logs and drivers before exiting"
533 result = self.test_on.cleanup()
534 self.is_stop = True
adminbae64d82013-08-01 10:50:15 -0700535
536 def play(self):
537 '''
538 Will resume the paused test.
539 '''
540 self._stopevent.clear()
541 cli.pause = False
Jon Hall4ba53f02015-07-29 13:07:41 -0700542
adminbae64d82013-08-01 10:50:15 -0700543 def stop(self):
544 '''
545 Will stop the test execution.
546 '''
Jon Hall4ba53f02015-07-29 13:07:41 -0700547
adminbae64d82013-08-01 10:50:15 -0700548 print "Stopping the test"
549 self.is_stop = True
550 cli.stop = True
551 __builtin__.testthread = False
Jon Hall4ba53f02015-07-29 13:07:41 -0700552
adminbae64d82013-08-01 10:50:15 -0700553def output(msg):
554 '''
555 Simply, print the message in console
556 '''
557 print msg
558
559def error(msg):
560 '''
561 print the error message.
562 '''
563 print msg
564
565def dictToObj(dictionary):
566 '''
567 This will facilitates the converting of the dictionary to the object.
568 This method will help to send options as object format to the test.
569 '''
570 if isinstance(dictionary, list):
571 dictionary = [dictToObj(x) for x in dictionary]
572 if not isinstance(dictionary, dict):
573 return dictionary
574 class Convert(object):
575 pass
576 obj = Convert()
577 for k in dictionary:
578 obj.__dict__[k] = dictToObj(dictionary[k])
579 return obj
580
581
582if __name__ == '__main__':
583 if len(sys.argv) > 1:
Jon Hall0bde9ba2015-03-19 11:32:57 -0700584 __builtin__.COLORS = True
adminbae64d82013-08-01 10:50:15 -0700585 CLI("test").onecmd(' '.join(sys.argv[1:]))
586 else:
Jon Hall0bde9ba2015-03-19 11:32:57 -0700587 __builtin__.COLORS = False
adminbae64d82013-08-01 10:50:15 -0700588 CLI("test").cmdloop()