def test_bash_history(self): with open(os.path.expanduser('~/.bash_history')) as f: for line in f.readlines(): try: oyster.parse(line) except Exception as e: response = raw_input('Continue? [Y/n] ') if response.lower() != 'y': raise
def test_chain_iadd(self): first_cmd = 'mv foo.txt bar.txt' first = oyster.parse(first_cmd) second_cmd = 'cat bar.txt' second = oyster.parse(second_cmd) first_id = id(first) first += second self.assertEqual(first_id, id(first)) self.assertEqual(len(first), 2) self.assertEqual(str(first), 'mv foo.txt bar.txt; cat bar.txt') self.assertEqual(len(second), 1)
def test_parse(self): command_string = 'cat foo.txt' command = oyster.parse(command_string)[0] self.assertTrue(isinstance(command, oyster.Command)) self.assertEqual(command.program, 'cat') self.assertEqual(command.arguments, ('foo.txt',)) self.assertEqual(command.tokens, ('cat', 'foo.txt')) self.assertEqual(command.as_string, command_string) invalid_command = oyster.parse('#cat foo.txt') self.assertTrue(not invalid_command) invalid_command = oyster.parse('for i in $(seq 10); do echo $i; done') self.assertTrue(not invalid_command)
def test_parse(self): command_string = 'cat foo.txt' command = oyster.parse(command_string)[0] self.assertTrue(isinstance(command, oyster.Command)) self.assertEqual(command.program, 'cat') self.assertEqual(command.arguments, ('foo.txt', )) self.assertEqual(command.tokens, ('cat', 'foo.txt')) self.assertEqual(command.as_string, command_string) invalid_command = oyster.parse('#cat foo.txt') self.assertTrue(not invalid_command) invalid_command = oyster.parse('for i in $(seq 10); do echo $i; done') self.assertTrue(not invalid_command)
def test_redirects(self): command_str = 'rm -v -r some/path/* >> deleted.txt 2>> delete_err.txt' command = oyster.parse(command_str)[0] r = command.redirects self.assertEqual(len(r), 2) self.assertEqual(str(r[0]), '>> deleted.txt') self.assertEqual(str(r[1]), '2>> delete_err.txt')
def test_tokenize(self): # Only limited testing required since shlex handles the dirty work command = "grep -r 'foo' /some/file" tokens = oyster.tokenize(command) self.assertTrue(isinstance(tokens, list)) self.assertEqual(len(tokens), 4) no_whitespace = 'cd /some/path;ls|wc -l' chain = oyster.parse(no_whitespace) self.assertTrue(len(chain), 3) self.assertEqual(str(chain[0]), 'cd /some/path') self.assertEqual(str(chain[1]), 'ls') self.assertEqual(str(chain[2]), 'wc -l') with_cmd_substitution = 'grep $(echo $1 | sed "s/^\\(.\\)/[\\1]/g")' chain = oyster.parse(with_cmd_substitution) self.assertEqual(len(chain), 1) self.assertEqual(len(chain[0].arguments), 1)
def test_simple_command(self): command_str = 'cat -nb --fake=yes /foo/bar' command = oyster.parse(command_str)[0] self.assertTrue(command.program == 'cat') self.assertEqual(len(command.arguments), 3) self.assertTrue(command.has_option('-n')) self.assertTrue(command.has_option('-b')) self.assertEqual(command.get_option_values('--fake')[0], 'yes') self.assertEqual(str(command), command_str)
def test_option_sanitization(self): cmd = 'curl -H "Host: oyster.com" -d bar=foo http://localhost' command = oyster.parse(cmd)[0] host = command.get_option_values('-H').pop() self.assertEqual(host, 'Host: oyster.com') data = command.get_option_values('-d').pop() self.assertEqual(data, 'bar=foo')
def test_pop(self): chain = oyster.parse('mv foo.txt bar.txt; ls | wc -l') self.assertEqual(len(chain), 3) wc = chain.pop() self.assertEqual(wc.program, 'wc') mv = chain.pop(0) self.assertEqual(mv.program, 'mv') self.assertEqual(len(chain), 1) self.assertEqual(chain[0].program, 'ls') self.assertRaises(IndexError, chain.pop, 1337)
def test_delete(self): chain = oyster.parse('ls | wc -l') self.assertEqual(len(chain), 2) del chain[1] self.assertEqual(len(chain), 1) self.assertEqual(str(chain), 'ls') try: del chain[1337] did_raise = False except IndexError: did_raise = True self.assertTrue(did_raise)
def test_chain_add(self): cmd = 'mv foo.txt bar.txt' chain = oyster.parse(cmd) combined = self.chain + chain self.assertTrue(id(combined) != id(self.chain)) self.assertTrue(id(combined) != id(chain)) as_str = 'cat foo.txt | grep python | wc -l; mv foo.txt bar.txt' self.assertEqual(len(self.chain), 3) self.assertEqual(len(chain), 1) self.assertEqual(len(combined), 4) self.assertEqual(str(combined), as_str)
def test_repeated_option_values(self): command = oyster.parse('pip -v -v -v install oyster')[0] self.assertEqual(command.get_option_count('-v'), 3) cmd = 'curl -v --data "foo=bar" --data "bar=foo" http://localhost' command = oyster.parse(cmd)[0] values = command.get_option_values('--data') self.assertEqual(values[0], 'foo=bar') self.assertEqual(values[1], 'bar=foo') cmd = 'curl -v -d "foo=bar" -d "bar=foo" http://localhost' command = oyster.parse(cmd)[0] values = command.get_option_values('-d') self.assertEqual(values[0], 'foo=bar') self.assertEqual(values[1], 'bar=foo') # Determening whether the next token is actually the option value # or an application argument is up to the application. As illustrated # in by this valid, curl, command. cmd = 'curl -v http://localhost' command = oyster.parse(cmd)[0] values = command.get_option_values('-v') self.assertEqual(values[0], 'http://localhost')
def index(): statistics = {} with open(os.path.expanduser('~/.bash_history')) as f: for line in f.readlines(): try: chain = oyster.parse(line) for command in chain: if command.program not in statistics: statistics[command.program] = 0 statistics[command.program] += 1 except: pass chart = pygal.Pie() ordered = sorted(statistics, key=statistics.__getitem__, reverse=True)[:5] for name in ordered: chart.add(name, statistics[name]) return chart.render()
def test_remove(self): chain = oyster.parse('mv foo.txt bar.txt; ls | wc -l') chain.remove('wc -l') self.assertEqual(str(chain), 'mv foo.txt bar.txt; ls') chain.remove(chain[chain.index('ls')]) self.assertEqual(str(chain), 'mv foo.txt bar.txt')
def test_delete_slice(self): chain = oyster.parse('cd /some/path; ls | wc -l') self.assertEqual(len(chain), 3) del chain[-1] self.assertEqual(len(chain), 2) self.assertEqual(str(chain), 'cd /some/path; ls')
def setUp(self): self.cmd = 'cat foo.txt | grep python | wc -l' self.chain = oyster.parse(self.cmd)
def test_equal(self): copy = oyster.parse(str(self.chain)) self.assertTrue(id(self.chain) != id(copy)) self.assertEqual(self.chain, copy)
def test_not_equal(self): copy = oyster.parse(str(self.chain)) copy.append('less') self.assertTrue(self.chain != copy)
def setUp(self): self.command_string = 'pip install -U -vvv -r requirements.txt' self.command = oyster.parse(self.command_string)[0]