Posts Tagged by Golang
git bisect run – example
| 15-Mar-2013 | Posted by Sonia Hamilton under Git, Golang |
Git bisect is a great tool for finding bugs in a program. But many examples show manual uses of git bisect – here’s an example of automating the process using git bisect run.
tl;dr
Using git bisect run is easy if you’ve make small atomic commits and you have good tests. run makes a large debug easier (compared to manually doing git bisect good and git bisect bad) – you’re less likely to make errors due to boredom. And run means you can use an iterative process – use rebase to split bad commits then just run again.
Example
So I had an elusive bug in a long running process (an snmp poller, calculator and aggregator for a large network). I had a point where the program was good, but I’d added more features since good and now results were bad. The first step was to write a shell script to be called from git bisect run:
% cat bisect.sh
#!/bin/bash
# copy this to ~ before running with `git bisect run ~/bisect.sh`
cp ~/Makefile .
make clean
# make modifies manpage output, so stash after build
if make &> /dev/null ; then
git stash
git stash clear
else
git stash
git stash clear
exit 125
fi
sudo cat /var/tmp/empty > /var/log/abc/abc-poller.log
sudo ./abc-poller --tmp --once -d 2 -c 150 || exit 125
echo "=== poller finished"
percent=`godir=/var/tmp/data/abcmon/poll_queue/new ~/checker | \
tail -1 | awk '{print $5}' | awk -F. '{print $1}'`
echo "=== percent is $percent"
(( percent < 5 ))
Things that make writing the test script easier:
- first get it working outside of git bisect run – usually means echoing results along the way
- already having a test suite that produces a quantified pass/fail output, In my case the I had already written the checker program, whose last line of output contained a “percentage failure” figure
Next step was having an abbreviated log of commits to refer to:
% git log --oneline f00f232 sql.go - better debugging # bad 9780d44 dummy .gitignore, so out dir preserved 0de0796 Makefile for nsch1abcs01 a2f6c96 defaults - 20 workers, udp 15 b8ee3d9 GOMAXPROCS() 04f21ba start v0.0.2 dbc6a60 Makefile: Jenkins as default for env vars 557a5e3 more work on stats ef6a453 remove excessive debugging ccc4644 remove file buffering - wasn't writing..??? 98bf4b1 stats write failing 9a9682d move type queue_t struct 467aeed buffered writes for queue file 148a8cc stats: + device_run, device_ok c61be42 done chan *Stats_t; calculate_value() bool 0e41461 debugging - print out device_id as %5s 7cbe167 default workers 5000, correct stop/start commands 544e8d7 gather statistics 6990cf2 rename data chan to device_id 5e8562b rename sql -> sqlconn; global var fd52d89 remove dead code 4d7b9b1 device_for() - err if count != 1 6ceb305 deb: fail if version main.go isn't same changelog 5ce1855 deb: rules producing abc-poller_0.0.1_amd64.deb db5bff4 deb: cleaned up Makefile, roffs 76674c2 JSON -> SQL; version 0.0.1 4cf198e deb: basic removal of 64 references d980f26 deb: rename 64 to vanilla b933570 deb: remove 32 bit stuff 970bd82 current debug level is 2; adjust output 70f8921 Revert "deb build - don't init, cron while testing" 855ce00 default debug is 2; misc tidy f3d80e1 remove timeoutOpt - no longer used 48ced38 misc tidys before release a3fe13c runonceOpt, revert cycling code # good 24cd998 use passed in udpOpt 5ca1830 remove stash/sender.old.go 06b9566 remove gsnmpgo; use gosnmp bffd430 rules: add note about "too many open files"
Mark bad and good, start the run, go and have a coffee :-)
% git bisect start f00f232 a3fe13c % git bisect run ~/bisect.sh # lots of output
I get the result that the ominously named 557a5e3 more work on stats is the first bad commit – I remember it as one of those large “kitchen sink” commits done at the end of the day. So “first rule of fightclub git” remembered – always do small atomic commits.
I have a useful shell function gri() – I used that to interactively rebase and break up 557a5e3 into many small commits:
gri () {
git rebase -i HEAD~${1:-7}
}
After rebasing git log looked like this – notice the many small commits named “bisect1″ etc:
382b3ee defaults - 20 workers, udp 15 11db314 GOMAXPROCS() 4b547ea start v0.0.2 c92feef Makefile: Jenkins as default for env vars 8fcc595 bisect6: calc/noncalc ad3a18f bisect5: tweak debug msgs 311bb8d bisect4: mv stats init 957c234 bisect3: remove stats from send_gosnmp() 3c01d62 bisect2: use Add(); Calcs/NonCalcs 947cb27 bisect1: move Stats_t; Add() ef6a453 remove excessive debugging ccc4644 remove file buffering - wasn't writing..??? 98bf4b1 stats write failing
And here’s the real win of writing bisect.sh – you can just keep rebasing and running until you’ve narrowed down the bad code to a few lines:
=== poller finished
=== percent is 49
947cb27fd57642dc545ee23090d7ae8fd8b14b3f is the first bad commit
commit 947cb27fd57642dc545ee23090d7ae8fd8b14b3f
Author: Sonia Hamilton <sonia@snowfrog.net>
Date: Thu Mar 14 10:02:42 2013 +1100
bisect1: move Stats_t; Add()
I do another interactive rebase, fix the logic error, and then HEAD is good.
GoSnmp – SNMP for GoLang
| 11-Mar-2013 | Posted by Sonia Hamilton under Golang |
Today I released soniah/gosnmp – an update of alouca/gosnmp.
Many, many thanks to Andreas Louca for writing alouca/gosnmp. The major difference between his version and soniah/gosnmp is that the latter has tests written. (However the code could do with refactoring). The tests were used to find and correct errors in the following SNMP BER Types:
- Counter32
- Gauge32
- Counter64
- OctetString
- ObjectIdentifier
- IpAddress
Also, this version contains functions for treating the returned snmp values as *big.Int (convenient, as SNMP can return int32, uint32, and uint64 values)
refactoring in Go – rather pleasant actually…
| 12-Feb-2013 | Posted by Sonia Hamilton under Golang, Perl, Python, Ruby, Vim |
I’ve just finished refactoring a large Go program, and the process was rather…. pleasant.
Static typing catches all those obscure errors I wouldn’t think about in a scripting language (Python, Perl, Ruby, etc). My process is:
- type :make in vim (I have a dummy Makefile in my Go project just for vim)
- vim jumps cursor to error (vim quickfix list)
- “oh, I shouldn’t do that” – fix (type type type)
- start again
Finish rather sooner than expected, run tests, smile in knowledge program is working properly.
Update
To quickly setup the make command for Go, type this in a Vim window:
:setlocal makeprg=go\ build\ \.
Or even better configure vim via your ~/.vimrc, for example:
autocmd BufRead *_test.go setlocal makeprg=go\ test\ \. autocmd BufRead *.go setlocal makeprg=go\ test\ \./..
Thanks Martin for the comment!
gsnmpgo – SNMP for Golang using gsnmp
| 10-Feb-2013 | Posted by Sonia Hamilton under CGo, Go, Golang, SNMP |
Update 8/Mar/13
Work on gsnmpgo has halted. Making the gsnmp C library multithreaded was proving too time consuming. Use http://github.com/soniah/gosnmp instead.
Previously…
I recently released gsnmpgo – a Go/CGo snmp library using gsnmp. Pull requests welcome!
From the gsnmpgo documentation, here’s an example of usage:
// do an snmp get; RFC 4088 is used for uris
uri := `snmp://public@192.168.1.10//(1.3.6.1.2.1.1.1.0)`
params := gsnmpgo.NewDefaultParams(uri)
results, err := gsnmpgo.Query(params)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
// check your results
gsnmpgo.Dump(results)
// turn on debugging
gsnmpgo.Debug = true
vim – bufexplorer
| 20-Nov-2012 | Posted by Sonia Hamilton under Golang, Vim |
Bufexplorer – my new favourite add-on for vim.
Why do I like it? It allows you to emulate the buffer list feature of emacs, as well as switch between horizontal/vertical buffer splits and find recently edited files. All this can already be done with vim buffers, but bufexplorer makes it easy.
Why don’t I just use emacs? Because as sysadmin/devop I’m often working on other people’s servers, and I don’t want to go installing buckets of stuff everywhere – vim is usually installed.
I found the best way to use bufexplorer is to open up all possible source files (eg vim src/*.go other/*.go) at the start of an editing session, then just skip between them (shown here with the excellent xMonad window manager, GNU Screen, and Gnome Terminal):

Recent Comments
<<EOF>>was eaten...cat <>~/.vi...