Watchr Continuous Testing with Growl

Ruby — Dillon @ 6:45 pm

An improvement to the post I did about the doom faces for growl status and watchr config with ruby testing. This improvement will give you a pass screen that is a bit easier to read because it will have a slight green or red tint to it.

First, it requires a bit of Growl set up. You just need to change the severity colors from all black to look like this. You can keep the normal level as black and hopefully this will keep your normal growl messages from other programs as normal black.

Note that the high severity color in that screenshot is a really dark red. This is important to get that slight red tint from the dead doomguy shot above.

This also requires and new and improved watchr.rb file to go along with it.

def growl(message)
  growlnotify = `which growlnotify`.chomp
  title = "Watchr Test Results"
  passed = message.include?('0 failures, 0 errors')
  image = passed ? "~/.watchr_images/passed.png" : "~/.watchr_images/failed.png"
  severity = passed ? "-1" : "1"
  options = "-w -n Watchr --image '#{File.expand_path(image)}'"
  options << " -m '#{message}' '#{title}' -p #{severity}"
  system %(#{growlnotify} #{options} &)
end

Optional Bit

My previous post was inside a rails project, which is fine and good until you want to write a command-line ruby program or something outside of rails. First, you’ll need some tests and then you’ll need a Rakefile that invokes your tests. I have an example project here. There’s also a zip archive here. It’s a non-rails app with a rake file that you can run for testing:
combo-guesser$ rake
(in ./combo_guesser)
/bin/ruby ./test/combo_guesser_test.rb
Loaded suite ./test/combo_guesser_test
Started
.
Finished in 0.000755 seconds.

1 tests, 10 assertions, 0 failures, 0 errors, 0 skips

All this makes for a really fast testing feedback loop.

Ruby Koans Notes and Solutions

Ruby — Dillon @ 12:04 am

Just finished EdgeCase UK’s rubykoans test/project. It’s a test driven development style learning session that you should really check out even if you’re only partial curious in what ruby is. If you’ve got some ruby experience under your belt, you should go through the exercise too because it’s good practice, reference and you’ll probably learn something new.

I’m not posting this so someone can cheat. I’m posting this for the me out there who wants to see if they did it the same. There were many “THINK ABOUT IT” sections that were open-ended or tricky. The whole thing took me about 4 days while on vacation. Maybe 16-20 hours of solid work. It’s good, just do it!

I used auto_enlighten.rb which I nabbed from davesquared.net. It was really handy. Using watchr, all I had to do was save an .rb file and the test ran again. So I could just try my answer and continually monitor my progress and get feedback on errors. This was very much the #1 bullet point in the Ted talk 7 ways games reward the brain. The whole exercise is one long experience bar with continuous feedback. Excellent! Books should be this way!

I definitely had some learning experiences along the way and I’ve posted my solutions with notes on gotchas to github. And there were many gotchas. Sometimes, I would nail a solution, first shot, very elegantly. Other times, I would churn on a test for many minutes and research for more information. There were some very, very deep and specific issues that I would read more about.

For example, take this excerpt one of the early tests: test_slicing_arrays. For the ruby koans, they created a special __ method that is equal to “FILL ME IN” (slick move EdgeCase). So you just have to change the __ for the test to pass. In this case, I expected it to be nil. So I filled in nil and it failed.

def test_slicing_arrays
    array = [:peanut, :butter, :and, :jelly]
    # snip for blog post
    # Learned: this is crazy!  empty when beyond range but at .size, nil when beyond .size
    assert_equal __, array[4,0]
    # snip for blog post
end

Notice my Learned: note there in the middle. This was surprising. If you open up irb and follow along, you’ll find that slicing an array of 4 things from 4 to 0 gives you an empty array. Wow. That’s a bug if you ask me. There’s a bunch of notes marked “Learned:” like this in the github project. The README has a grep example you can use to find all the things I thought were gotchas. But do them yourself first! It’s way more fun to do this interactively.

BTW, Internet, I would love a node.js koans project.

Reconnect a Mac mouse without a mouse

Mac — Dillon @ 7:23 pm

So you’ve replaced the batteries, restarted your mouse or whatever. You have a bluetooth mouse that you need to reconnect or re-pair but you don’t have a mouse to get to the bluetooth icon in the notification area or status bar location.

Here what you do:

  1. Command Key + Shift + / – gets you into the help area in any menu
  2. Right arrow – gets you to the Apple menu
  3. Down arrow until System Preferences
  4. Enter – opens System Preferences
  5. Type mouse – in the search box and hit enter will open the mouse pane
  6. Hit enter at the “no mouse found” screen – this will pair your mouse if it’s powered on and trying to pair

Problem solved. Leave a comment if it works or a similar problem but different solution worked for you. If you can’t click in the comment box, just scream really loud towards my email address. :)

Biggest object_id value in Ruby

Ruby — Dillon @ 4:38 pm

0 = 1, 1 = 3, 2 = 5, 100 = 201. What is going on? Ruby has object_ids on objects but they are shorter on small integers. Fire up irb and follow along:

> obj = Object.new
 => #<Object:0x100362a30> 
> obj.object_id
 => 2149258520

The value of object_id is the normal looking ids I’ve seen in the past. But then I did this:

 0.object_id
 => 1 
> 1.object_id
 => 3 
> 2.object_id
 => 5 
> 100.object_id
 => 201

Ok, why the values? Why is 0′s id 1 and 100′s id 201? It looks like it’s doubling the value and adding one but that seems a little random and probably not what it’s actually doing. So I read a bit by Caleb Tennis on Oreilly and found a tip off that it’s related to binary:

Thus 0×0101 (5) becomes 0×1011 (11).

Notice that Caleb is noting that “101″ is shifting left and adding 1 at the lowest bit. So then this should work:

x = 0
puts x.object_id == ( (x << 1) + 1 )
true
=> nil

And it does. We can set a bigger number and run it again and it still works.

x = 65536
puts x.object_id == ( (x << 1) + 1 )
true
=> nil

I will call this predictable behavior later. x.object_id is 131073 on both sides because we know how object_id is generated:

x = 65536
 => 65536 
> puts x.object_id
131073
> puts ( (x << 1) + 1 )
131073

So what is going on? Well first, let’s print out the binary. Taken from icfun.blogspot.com, we’ll define a number to binary string method in irb.

def dec2bin(number)
   number = Integer(number);
   if(number == 0)
      return 0;
   end
   ret_bin = "";
   ## Untill val is zero, convert it into binary format
   while(number != 0)
      ret_bin = String(number % 2) + ret_bin;
      number = number / 2;
   end
   return ret_bin;
end

We can test that it works with any integer. Let’s test with the number 5 like this: puts dec2bin(5). Prints out 101. If we shift left by one bit like this: dec2bin((5 << 1)) then we'll get 1010. Add 1 bit and we get the binary of eleven: 1011. We can see if this is eleven with dec2bin(11) and we get "1011" which is what we expected. It makes sense.

So wtf. Why know this stuff? Well, when doing object comparisons, I always expected some garbage or randomness and length similar to a hash. Like when doing (Object.new).object_id but this isn't dependable or consistent when getting the object_id of a Fixnum. And even that is not consistent. The examples above are using small numbers. When we try this:

x = 4; puts x.object_id == ( (x << 1) + 1 )
true

It works fine. 4 is small. Let's call this "predictable". We can bit shift and add 1 to get the same value as ruby does with object_id.

But a big enough number like 5000000000000000000 is false. So what's the inflection point? Maybe the inflection point is 2^32 because it's memory related:

x = 4294967296; puts x.object_id == ( (x << 1) + 1 )

Nope. Strange.

So I played around manually and started finding that 4 quintillion is true but 5 quintillion is false. Weird. If it's memory related, it's no number I recognize. So we know that there's some inflection point between 4 quintillion and 5 quintillion. I'm not about to figure this thing out by hand. Let's write a program to find our magic number.

Note: the current version (if any) is on github.

# find the inflection point of how ruby calculates object_ids predictably
# for example:
# x = 4; x.object_id == ( (x << 1) + 1 )
# => true
# however,
# x = 5000000000000000000; x.object_id == ( (x << 1) + 1 )
# => false
 
# answer = 4611686018427387903
 
# we'll start with a number that's close
starting_number = 4000000000000000000
 
# this will be the number we'll try with
current_number = starting_number
 
# our decimal position that will be used for the loop
# we don't need to start with 4, which is starting_nmber[0..0]
index = 1
digit_at_index = current_number.to_s[index..index].to_i
 
# digit state
digit_second = 0
digit_third = 0
 
# vector for current_number
# true = up, false = down
direction = true
last_direction = direction
changed_directions = 0
 
# have we exhausted all digits for the current rank/position
# if so, we move on to the next position
digit_done = false
 
jump = 5
 
 
# is our result the same as shift left plus one?
def predictable?(number)
  number.object_id == ( (number << 1) + 1 )
end
 
 
# go until we've iterated along the length of starting_number
while (index <= starting_number.to_s.length - 1)
  digit_done = false
 
  digit_at_index = current_number.to_s[index..index].to_i
 
  # shift our cheap history variables
  digit_third = digit_second
  digit_second = digit_at_index
 
  # this tests whether we went over our solution
  if predictable?(current_number.to_i)
    # if true, try incrementing but only if we can later
    direction = true
  else
    # if false, number is too high
    direction = false
  end
 
  #puts "index: #{index}"
  if last_direction != direction
    jump -= jump / 2
    changed_directions += 1
  else
    jump -= 1 unless jump == 1
  end
 
  last_direction = direction
 
 
  # split the distance
  # if we start with 0, this becomes 5 if going up
  # if we start with 5, this becomes 3 if going down
  # it's a half to target number
 
  # increase
  if direction
    digit_at_index += jump unless digit_at_index == 9
 
    #puts digit_at_index
    if digit_at_index == 9 && digit_second == 9
      digit_done = true
    else
      digit_done = false
    end
 
  # decrease
  else
    digit_at_index -= jump unless digit_at_index == 0
 
    if digit_at_index == 0 && digit_second == 0
      digit_done = true
    else
      digit_done = false
    end
 
  end
 
  # if we flip-flop back and forth between finding our number is too high
  # or too low then our number is probably in the middle
  # 4 swaps will leave us with the lower number
  # which then the next digit will need to increase
  # TODO: if this flops the wrong way, the algorithm breaks.
  if changed_directions == 4
    digit_done = true
    digit_at_index = digit_second
  end
 
 
  # substitute our done digit in place
  current_number_string = current_number.to_s
  current_number_array = current_number_string.chars.to_a
  current_number_array[index] = digit_at_index
  current_number = current_number_array.join.to_i
 
  # move on to the next digit
  if digit_done
    index += 1
    digit_at_index = current_number.to_s[index..index].to_i
    digit_ceiling = 10
    digit_floor = 0
    jump = 5
 
    changed_directions = 0
    direction = true
 
    digit_second = 0
    digit_third = 0
  end
 
  puts current_number
 
  # bug avoid
  if current_number.to_s.length != starting_number.to_s.length
   exit
  end
 
  # not needed but useful for watching how the algorithm works
  sleep 0.1
 
end

When we run this little number searcher we find our overflow (or inflection) point. It will run for a while, finding each digit like this:
4400000000000000000
4700000000000000000
4500000000000000000
.
.
.
4611686018427387900
4611686018427387904
4611686018427387902
4611686018427387903
4611686018427387904
4611686018427387903
4611686018427387903

Eventually we'll have a final value of 4611686018427387903 which we can test like this:

4611686018427387903.object_id => 9223372036854775807
4611686018427387904.object_id => 2152612560

You can see it overflow making 9223372036854775807 the largest object_id in Ruby.

This program is not very efficient or well written. There's a better way to find a number but I decided to go with a digit-by-digit algorithm. It was not very easy and quick to write. I nearly scrapped it and did it the right way but managed to get it working around midnight one night. I hope it makes for a good (or anti-pattern) example.

Nmap won’t compile in homebrew solution

Development,Mac,Unix — Dillon @ 1:11 am

I recently moved my Mac Pro dev box to homebrew from macports. Doing the mysql move (the lazy way — moving the data directory) was easy enough but doing a massive `brew install` of a bunch of packages didn’t work when I got to nmap (the network port scanner).

Specifically the linker error (maybe the linker … looks to a stacktrace to a Ruby and Java guy) was this:

Undefined symbols:
  "ScriptResult::get_id() const", referenced from:
      formatScriptOutput(ScriptResult)       in output.o
      printhostscriptresults(Target*)     in output.o
      printportoutput(Target*, PortList*)    in output.o
  "ScriptResult::get_output() const", referenced from:
      formatScriptOutput(ScriptResult)       in output.o
      printhostscriptresults(Target*)     in output.o
      printportoutput(Target*, PortList*)    in output.o
  "open_nse()", referenced from:
      nmap_main(int, char**)in nmap.o
  "close_nse()", referenced from:
      nmap_free_mem()     in nmap.o
  "script_scan(std::vector >&)", referenced from:
      nmap_main(int, char**)in nmap.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
make[1]: *** [nmap] Error 1
make: *** [all] Error 2
Exit status: 2

http://github.com/mxcl/homebrew/blob/master/Library/Formula/nmap.rb#L1

Error: Failure while executing: make
Please report this bug at http://github.com/mxcl/homebrew/issues
These existing issues may help you:

http://github.com/mxcl/homebrew/issues/#issue/3128

I love the little URL for more help at the bottom, unfortunately a redirect killed the help. The correct URL is here. Maybe an anchor tag in the wrong place on the URL, who knows. Anyway, I posted a note on the issue site as well, I got around the issue by doing this first:
brew install lua

Then just install nmap like before:
brew install nmap

Worked for me.

Macports upgrade breaks ImageMagick

Mac,Ruby — Dillon @ 1:55 pm

A blind upgrade of all macports packages broke my ruby project because it uses imagemagick.


dlopen(/opt/local/lib/ruby/gems/1.8/gems/rmagick-2.13.1/lib/RMagick2.bundle, 9): Library not loaded: /opt/local/lib/libMagickCore.3.dylib
Referenced from: /opt/local/lib/ruby/gems/1.8/gems/rmagick-2.13.1/lib/RMagick2.bundle
Reason: image not found - /opt/local/lib/ruby/gems/1.8/gems/rmagick-2.13.1/lib/RMagick2.bundle

Massive hack incoming:

cd /opt/local/lib
sudo ln -s libMagickCore.4.dylib libMagickCore.3.dylib

There should be a better solution but I can’t find one until macports gets it’s goddamn *bEEp* straight. I swear to deity, every time I do a sudo port upgrade outdated, something breaks. I know it’s not macports fault but the nature of native ruby gem extensions but I’m just going to avoid upgrading.

Something else to consider is my recent switch to homebrew. I haven’t made the switch on all my boxes and the ImageMagick problem isn’t related to the package manager. I do prefer brew’s command structure. Moving MySQL wasn’t insanely difficult but I did cheat by just doing a stupid copy of the MySQL data files.

Ubuntu One True Way

Ruby,Unix — Dillon @ 11:38 am

For a Linux development box, I typically install the same packages over and over again. For any new OS install, I call this the “One True Way” (OTW taken from a now defunct source online). Almost every box needs development libraries at some point. There’s a lot of extra stuff thrown in here too. These packages are circa ubuntu 10.04. Keep this in mind.

# aptitude install ruby ruby1.8-dev mysql-server mysql-client libmysql-ruby libmysqlclient-dev nmap htop nginx git-core postgresql nethack-console irssi tightvncserver xtightvncviewer distcc build-essential linux-kernel-headers linux-source couchdb solr-common solr-tomcat tomcat6 rar unrar p7zip k3b libk3b6-extracodecs gparted ubuntu-restricted-extras libdvdcss libxml2-dev libxslt-dev curl libcurl4-openssl-dev lua50 liblua50-dev libsqlite3-ruby libmagick9-dev

Download rubygems and install.

Add git hub to our gems list:# gem source -a http://gems.github.com.

Install some gems I like. # gem install mysql RedCloth capistrano rmagick termios warbler sinatra feedzirra

Install Chrome. Download .deb 64 package (google-chrome-beta_current_amd64.deb or newer) and double-click on the deb file. Click install.

Grab proggy fonts: clean, square, tiny, small. Set terminal font to proggy font. Set scrollback to 9000 lines, hidden scrollbar (shift+page up works instead), turn off menu, turn off terminal bell.

Install dropbox.

Go to town.

Homebrew behind a proxy

Blog — Dillon @ 10:12 am

Git doesn’t work behind a proxy with homebrew (the macports new hotness). Because git:// is blocked at my office. There’s a patch here. Unfortunately, the drop-in replacement didn’t work for me (it’s an old commit).

Instead I made the modifications myself. Be warned, that this file will probably only work for the version I’m using (0.7.1), in which case you’ll have to look at the SVN commit yourself. :(


cd /usr/local/Library/Homebrew
cp download_strategy.rb download_strategy.rb.orig
wget http://squarism.com/files/download_strategy_proxy_fix.rb -O download_strategy.rb
export HOMEBREW_GIT_VIA_HTTP=1
brew install [something]

Any brew installs that use git should work now.

But then there’s curl. Curl doesn’t quite use the same env that others do. So solve it like this:

export http_proxy=http://proxy:80
export ALL_PROXY=$http_proxy

Curl likes that ALL_PROXY env for some reason.

After that, I was able to get my favorite homebrew apps installing:
brew install couchdb irssi git mysql watch lua p7zip htop openssl node npm nmap netcat

Update: If the above still doesn’t work for you (I had problems with Git URLs), try this:
cd /usr/local/Library/Homebrew
vi download_strategy.rb

Find the line when %r[^git://] then GitDownloadStrategy and replace (or comment it out) it with this:
when %r[^git://]
url.gsub!(/^git\:\/\//, ‘http://’)
GitDownloadStrategy

Git should use the http:// method of downloading code and brew install should work. Just to be clear, the relevant part of download_strategy.rb looks like this:

  when %r[^bzr://] then BazaarDownloadStrategy
  #when %r[^git://] then GitDownloadStrategy
  when %r[^git://]
        url.gsub!(/^git\:\/\//, 'http://')
        GitDownloadStrategy
  when %r[^hg://] then MercurialDownloadStrategy

Another thing to try is to edit ~/.curlrc to enable a SOCKS5 proxy if you have one.
socks5 = "yourserver:port"

Server side websockets

Brainstorm — Dillon @ 10:58 pm

For some reason I started researching server side websockets with a python module for apache. I thought, “oh this would be cool to create a reverse proxy or a socket to a port that’s not accessible through a firewall”. You could just have an apache module create a path back to some service.

Not knowing a lot about websockets, I kept reading and eventually realized that this problem would be best solved in an app server. The websocket module I found was written in python but if I used something like passenger to reverse back to a rails app server and then I could use whatever language I wanted. Besides, the web server shouldn’t be running code.

Anyway, fizzled idea.

Monty Hall Problem in Ruby

Ruby — Dillon @ 12:43 pm

I was reading a thread on stackoverflow about randomness and cryptography security and there was a comment that started me down a series of articles talking about the Monty Hall problem:

Suppose you’re on a game show, and you’re given the choice of three doors: Behind one door is a car; behind the others, goats. You pick a door, say No. 1, and the host, who knows what’s behind the doors, opens another door, say No. 3, which has a goat. He then says to you, “Do you want to pick door No. 2?” Is it to your advantage to switch your choice?

The take away from the probability puzzle is that you should switch. It’s completely unintuitive and I didn’t really get it even after reading about it for some time until I watched this youtube video. It’s a bit slow paced but it’s the best explanation and visuals out there.

So even after grok’ing the concept, I wanted to prove it. So I wrote a ruby program to simulate the game show. Here’s the results from one run:
Monty Hall Games Played: 1000
Player 1 (switches): 675/1000 : 67.50%
Player 2 (stays) : 325/1000 : 32.50%

The code is pretty simple and quick. Of note is that I sort of use the same game and player_2 just picks the same door of the same game using the same rand(3) number. So this is like two people playing at the same time and one always switches. I used the sleep statement near the bottom to keep the terminal from blinking. Seems to not blink on Mac or Linux but I remember having some weird behavior somewhere.

#!/usr/bin/ruby
# a simulation of the monty hall problem
 
# monkey patch
class Array
  def shuffle!
    size.downto(1) { |n| push delete_at(rand(n)) }
    self
  end
end
 
class Player
  attr_accessor :name
  attr_accessor :choice
  attr_accessor :played
  attr_accessor :won
  attr_accessor :lost
 
  def initialize(name)
    self.name = name
    self.played = 0
    self.won = 0
    self.lost = 0
  end
 
  def pick_door(door_number)
    self.choice = door_number
    #puts "PLAYER PICKS: #{self.choice}"
  end
 
  def win
    self.won += 1
    self.played += 1
  end
 
  def lose
    self.lost += 1
    self.played += 1
  end
 
  def percentage
    num = (self.won.to_f/self.played.to_f) * 100
    sprintf('%.2f', num) + "%"
  end
 
end
 
class Game
  attr_accessor :doors
  attr_accessor :door_states
 
  def initialize
    # set up doors
    self.doors = Array.new
    self.doors = [ "goat", "goat", "car" ]
    self.doors.shuffle!
 
    # set up door states
    self.door_states = Array.new
    self.door_states = [ "closed", "closed", "closed" ]
  end
 
  # main loop
  def run(player_1, player_2)
    # Player 1 randomly picks a door
    # Player 2 uses this door for simplicity
    player_choice = rand(3)
    player_1.pick_door(player_choice)
    player_2.pick_door(player_choice)
 
    # Host picks a door with a goat and reveals door
    goats = []
    self.doors.each_index {|d| goats << d if doors[d] == "goat"}
    goats.delete player_choice
 
    # if player won already then there are two goat doors, host picks one
    if goats.length > 1
      goats.delete_at rand(2)
    end
 
    # first is redundant but safe
    door_states[goats.first] = "open"
 
    # Player 1 switches between two remaining doors
    # Player 2 does not switch so do nothing
    remaining = []
    self.door_states.each_index {|d| remaining << d if door_states[d] == "closed"}
    remaining.delete player_choice
    player_1.choice = remaining.first      # first is redundant but safe
 
 
    # Log result
    if win?(player_1)
      player_1.win
    else
      player_1.lose
    end
 
    if win?(player_2)
      player_2.win
    else
      player_2.lose
    end
 
  end
 
  # did player win?
  def win?(player)
    if self.doors[player.choice] == "car"
      true
    else
      false
    end
  end
 
  # print out the game statistics
  def stats(p1, p2)
    # terminal clear code
    print %x{clear}
 
    puts "Monty Hall Games Played: #{p1.played}"
    puts "#{p1.name} (switches): #{p1.won}/#{p1.played} : #{p1.percentage}"
    puts "#{p2.name} (stays)   : #{p2.won}/#{p2.played} : #{p2.percentage}"
  end
 
end
 
 
# Create players
player_1 = Player.new("Player 1")
player_2 = Player.new("Player 2")
 
# Create new game show
while player_1.played < 1000
  g = Game.new
  g.run(player_1, player_2)
  g.stats(player_1, player_2)
 
  # for terminal sanity if terminal blinks too much
  #sleep 0.02
end

It was a good exercise. I was playing around with ruby-ncurses but it became too much of a hassle. Maybe some other project will need a TUI, I do still want to play with ncurses or something similar.

Next Page »
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License.
(c) 2012 SQUARISM | powered by WordPress with Barecity