A threaded Go language application with semaphores

After hearing about Go and its love of parallelism, I wanted to give it a try. I couldn’t think of any small projects that needed to be threaded until recently.  My employer uses an RPM system, but I’m using Ubuntu, which requires deb files.  Searching through the RPMs in a browser is a pain, so I wanted a small script that would search for me.  Here’s the script with server names changed.

package main

import (
  "bufio"
  "fmt"
  "http"
  "os"
  "regexp"
  "strings"
)

var servers = []string {
  "http://www.google.com/search?client=ubuntu&channel=fs&q=go+language&ie=utf-8&oe=utf-8",
  "http://golang.org/",
  "http://golang.org/doc/go_tutorial.html"}

var maxOpenRequests int = 3

var rpmRegexp = regexp.MustCompile("href=\"[^\"]+\"")

func main() {
  search := getSearchTerm()
  out := make(chan string)
  done := make(chan int)
  go printer(out)
  for _, url := range servers {
    go searchURL(search, url, out, done)
  }
  for i := 0; i < len(servers); i++ {
    <- done
  }
}

func getSearchTerm() string {
  args := os.Args
  if len(args) != 2 {
    die("Please enter one search term")
  }
  return args[1]
}

func die(message string) {
  fmt.Println(message)
  os.Exit(1)
}

func printer(out chan string) {
  for {
    fmt.Println(<- out)
  }
}

var requestSemaphore = make(chan int, maxOpenRequests) // Integer chanel with a maximum queue size

func searchURL(search string, url string, out chan string, done chan int) {
  requestSemaphore <- 1 // Block until put in the semaphore queue
  response, realURL, err := http.Get(url)
  if err == nil {
    bufferedReader := bufio.NewReader(response.Body)
    err = searchAll(search, bufferedReader, url, out)
    response.Body.Close()
  }
  if err != nil {
    die("Could not read from " + realURL + ":" + err.String())
  }
  <- requestSemaphore // Dequeue from the semaphore
  done <- 1 // Signal that function is done
}

func searchAll(search string, reader *bufio.Reader, httpRoot string, out chan string) (os.Error) {
  var error os.Error = nil;
  for {
    var line, err = reader.ReadString('\n')
    if err != nil {
      if err == os.EOF {
        break
      }
      return error
    }
    var hrefs = rpmRegexp.AllMatchesStringIter(line, 0)
    for href := range hrefs {
      start := strings.Index(href, "\"") + 1
      end := len(href) - 1
      packageFile := href[start : end]
      if strings.Index(packageFile, search) != -1 {
        out <- httpRoot + packageFile
      }
    }
  }
  return error
}

A quick overview

Go uses “channels” for communication among threads.

  1. The main thread creates two channels, one to receive search output and one to receive “done” responses when a child thread finishes.
  2. The main thread attaches the output channel to a simple function that prints to standard out.
  3. The main thread spawns one child thread per server, giving each the output and done channels.
  4. The main thread loops over the done channel once for each server, waiting until all requests are complete.
  5. Each child blocks immediately until space is available in a semaphore.
  6. The child performs the HTTP get, then searches the response for anything matching a regular expression.  Any matches are signaled back to the output channel.
  7. The child opens a space in the semaphore and signals to the main thread that it is done.

There isn’t much more to say.  The Go web site has great tutorials, so I don’t yet feel the need to write one.

By the way, if you’re searching for Go resources, be sure to search for “go language” and not “go”.  But then, that’s probably how you found this page 😉

package main

import (
“bufio”
“fmt”
“http”
“os”
“regexp”
“strings”
)

var servers = []string {
“http://apt.duncllc.com/dist/WS4.0/RedHat/RPMS/”,
“http://apt.duncllc.com/dist/WS4.0/RedHat/RPMS.extras/”,
“http://apt.duncllc.com/dist/WS4.0/RedHat/RPMS.java/”}

var maxOpenRequests int = 3

var rpmRegexp = regexp.MustCompile(“href=\”[^\”]+\””)

func main() {
search := getSearchTerm()
out := make(chan string)
done := make(chan int)
go printer(out)
for _, url := range servers {
go searchURL(search, url, out, done)
}
for i := 0; i < len(servers); i++ {
<- done
}
}

func getSearchTerm() string {
args := os.Args
if len(args) != 2 {
die(“Please enter one search term”)
}
return args[1]
}

func die(message string) {
fmt.Println(message)
os.Exit(1)
}

func printer(out chan string) {
for {
fmt.Println(<- out)
}
}

var requestSemaphore = make(chan int, maxOpenRequests) // Integer chanel with a maximum queue size

func searchURL(search string, url string, out chan string, done chan int) {
requestSemaphore <- 1 // Block until put in the semaphore queue
response, realURL, err := http.Get(url)
if err == nil {
bufferedReader := bufio.NewReader(response.Body)
err = searchAll(search, bufferedReader, url, out)
response.Body.Close()
}
if err != nil {
die(“Could not read from ” + realURL + “:” + err.String())
}
<- requestSemaphore // Dequeue from the semaphore
done <- 1 // Signal that function is done
}

func searchAll(search string, reader *bufio.Reader, httpRoot string, out chan string) (os.Error) {
var error os.Error = nil;
for {
var line, err = reader.ReadString(‘\n’)
if err != nil {
if err == os.EOF {
break
}
return error
}
var hrefs = rpmRegexp.AllMatchesStringIter(line, 0)
for href := range hrefs {
start := strings.Index(href, “\””) + 1
end := len(href) – 1
packageFile := href[start : end]
if strings.Index(packageFile, search) != -1 {
out <- httpRoot + packageFile
}
}
}
return error
}

Posted in Go at May 21st, 2010. No Comments.

Testing in Android with mock UI components

As described in an earlier post, Android is not friendly to mocking frameworks or mock-style testing.  If you want to test any class in your application that deals with the Android API, it’s best to run your tests through the emulator, accessing real Android classes.  It’s unfortunate because you’re not just testing your application.  You’re also testing Android.  Anyway, here’s a way to mock a UI component.

If you’re just starting, here are a couple notes to keep you on the right track.

  • Android is bundled with JUnit 3.  Don’t try using an updated JUnit library or another testing framework.  The Android jar doesn’t contain any functional code, so all test cases have to be run in the emulator, which uses JUnit 3.  The test framework that will work best is in the Android API.
  • If you need basic implementations of Android classes, try to avoid mocking them.

“Mock”ing

In my latest test, I needed a TextView so that I could call the simplest method, setText(String).  I’ll describe how I got one.

Don’t bother with the android.test.mock package.  It just contains implementations of classes that throw UnsupportedOperationExceptions.  There isn’t anything there that I have yet found useful.

  1. In the test case, instead of extending TestCase, extend at InstrumentationTestCase or, if necessary, one of its subclasses.  It’ll set up most of the stuff that’s available in an Activity and make it available to your test case.
    public class AnAndroidTest extends InstrumentationTestCase {
  2. Create a mock implementation of TextView or the class you need.
    public class MockTextView extends TextView {
      public MockTextView(final Context context) {
        super(context);
      }
    }
  3. The TextView constructor needs a real Context object because it will call methods on it.  The context is difficult to mock because parts of it are private to Android.  Since the Android JAR is just an API and doesn’t have any functional code, you couldn’t even see the methods if you tried.  They only exist in the VM in the emulator.  AFAIK, if you can’t see a method, you can’t mock it.  That’s why your test case extends InstrumentationTestCase.  Put this in it.
    final TextView textView = new MockTextView(this.getInstrumentation().getContext());

Now write the test case.  The text view is real and has a fully functional context, so the emulator will have everything it needs to support your test case.

Posted in Android at June 1st, 2009. 1 Comment.

Android application Green Mileage open sourced

Green Mileage is now an open source application at Google Code.  You can find the full source for most of the Android posts on this site in it at http://code.google.com/p/greenmileage/.  Just click the Source tab, then the Browse link.

The code needs a lot of cleanup, but is still probably worth a look if you’re new to Android.

Posted in Android at April 27th, 2009. 4 Comments.

Simple JavaFX Spinner Using a Timeline

I’ve been working on a demonstration JavaFX application.  It was originaly written for the prerelease candidate.  I just updated it to work with JavaFX version 1.1 and thought I’d share it.  This is a simple spinner that can be stopped and started.  Here’s the full source.  A description of how it works is below.

package org.mediabrowser;

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.scene.CustomNode;
import javafx.scene.Group;
import javafx.scene.image.ImageView;
import javafx.scene.image.Image;
import javafx.scene.Node;
import javafx.scene.shape.Rectangle;
import javafx.scene.transform.Rotate;

/**
 * A spinning icon, indicating the application is working
 * @author Connor Garvey
 * @created Oct 22, 2008, 8:12:48 PM
 * @version 0.0.2
 * @since 0.0.1
 */

public class Spinner extends CustomNode {
  var rotation: Number = 0;
  var timeline: Timeline = Timeline {
    repeatCount: Timeline.INDEFINITE;
    keyFrames: [
      KeyFrame {
        time: 50ms
        action: tick
      }
    ]
  };

  public override function create(): Node {
    return Group {
      content: [
        ImageView {
          image: Image {
            url: "{__DIR__}resources/color_wheel.png"
          }
          transforms: Rotate {
            pivotX: 8
            pivotY: 8
            angle: bind this.rotation
          }
          translateX: 3
          translateY: 3
        },
        Rectangle {
          width: 22
          height: 22
        }
      ]
    };
  }

  public function start() {
    this.timeline.play();
  }

  public function stop() {
    this.timeline.stop();
  }

  function tick() {
    this.rotation += 20;
    if (this.rotation == 360) {
      this.rotation = 0;
    }
  }
}
  • First, the spinner extends CustomNode. That way, it can be placed anywhere in a UI.
  • The timeline is used to rotate the spinner
    • Since the application will be starting and stopping the spinner, set it to run forever, Timeline.INDEFINITE
    • The spinner only does one thing, turn, so it only needs one key frame.  It’s set to turn 20 degrees every 50ms.
  • JavaFX will call create() to create instances of the spinner
    • The __DIR__ makes the spinner image relative to the current class
    • Since the image is 16×16, set the rotation pivot point to 8×8, the center of the image
    • The angle of rotation is bound to a property of the class so that it can be easily modified
    • When an image starts to rotate, it appears to shake because it’s not round.  To smooth the rotation out, it’s transformed down and to the right and placed inside of a rectangle.
Posted in JavaFX at March 14th, 2009. No Comments.

Large, finger-sized buttons in Android

July 18, 2009: Updated for Android 1.5

Recently, I created a simple dial pad style number dialog.  I wanted to make the numbers as large as possible to make finger input simple.  Getting the buttons to stretch evenly and not look strange turned out to be a challenge, but I eventually arrived at a solution.  For the full source, scroll down.

Big buttons in Android

Big buttons in Android

  • The dialog uses a relative layout.  It’s usually best at placing objects on the screen no matter what the resolution or orientation.
  • The numbers are contained in a table layout, which is good at spacing things evenly.
  • To get the numbers to stretch to the bottom of the screen, layout_above is set to the OK button, which is aligned to the bottom of the dialog.  The width is fill_parent so that the buttons fill the width of the screen.
  • To get each row to be the same height in HTML, you would set the height to a percent.  In Android, use layout_weight.  Setting the weight of each row to the same value will make them the same size.
  • Also use layout_weight on each button to even out their widths.
  • In version 1.5, Android started to be “smart” about how it lays out items.  Since the content of the “Back” button is longer than any other button, Android will make that column in the table wider.  It will do so even though the layout weights of all of the items are the same.  To override that behavior, set the width of every item to 0.  That way, when Android stretches the buttons out to fit in the table, every button will start from the same width, 0.
<?xml version="1.0" encoding="utf-8"?>
<!--
Layout for a number input dialog
Author: Connor Garvey
Created: Jan 11, 2009
Version 0.0.4
Since 0.0.4
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="7dip">
  <EditText android:id="@+id/number"
      android:background="@android:drawable/editbox_background"
      android:cursorVisible="false"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"  />
  <View android:id="@+id/numberSeparator0"
      android:layout_width="fill_parent"
      android:layout_height="4dp"
      android:layout_below="@id/number" />
  <View android:id="@+id/numberSeparator1"
      android:background="@drawable/black_white_gradient"
      android:layout_width="fill_parent"
      android:layout_height="1dp"
      android:layout_below="@id/numberSeparator0" />
  <View android:id="@+id/numberSeparator2"
      android:layout_width="fill_parent"
      android:layout_height="4dp"
      android:layout_below="@id/numberSeparator1" />
  <Button android:id="@+id/ok"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="@string/message_ok"
      android:layout_alignParentBottom="true" />
	<TableLayout android:id="@+id/row1"
	    android:layout_width="fill_parent"
	    android:layout_height="wrap_content"
        android:layout_below="@id/numberSeparator2"
        android:layout_above="@id/ok"
        android:layout_weight="1">
    <TableRow
        android:layout_weight="1">
      <Button android:id="@+id/n1"
          android:layout_width="0dip"
          android:layout_height="fill_parent"
          android:text="1"
          android:layout_weight="1" />
      <Button android:id="@+id/n2"
          android:layout_width="0dip"
          android:layout_height="fill_parent"
          android:text="2"
          android:layout_weight="1" />
      <Button android:id="@+id/n3"
          android:layout_width="0dip"
          android:layout_height="fill_parent"
          android:text="3"
          android:layout_weight="1" />
    </TableRow>
    <TableRow
        android:layout_weight="1">
      <Button android:id="@+id/n4"
          android:layout_width="0dip"
          android:layout_height="fill_parent"
          android:text="4"
          android:layout_weight="1" />
      <Button android:id="@+id/n5"
          android:layout_width="0dip"
          android:layout_height="fill_parent"
          android:text="5"
          android:layout_weight="1" />
      <Button android:id="@+id/n6"
          android:layout_width="0dip"
          android:layout_height="fill_parent"
          android:text="6"
          android:layout_weight="1" />
    </TableRow>
    <TableRow
        android:layout_weight="1">
      <Button android:id="@+id/n7"
          android:layout_width="0dip"
          android:layout_height="fill_parent"
          android:text="7"
          android:layout_weight="1" />
      <Button android:id="@+id/n8"
          android:layout_width="0dip"
          android:layout_height="fill_parent"
          android:text="8"
          android:layout_weight="1" />
      <Button android:id="@+id/n9"
          android:layout_width="0dip"
          android:layout_height="fill_parent"
          android:text="9"
          android:layout_weight="1" />
    </TableRow>
    <TableRow
        android:layout_weight="1">
      <TextView
          android:layout_width="0dip"
          android:layout_height="fill_parent"
          android:layout_weight="1" />
      <Button android:id="@+id/n0"
          android:layout_width="0dip"
          android:layout_height="fill_parent"
          android:text="0"
          android:layout_weight="1" />
      <Button android:id="@+id/back"
          android:layout_width="0dip"
          android:layout_height="fill_parent"
          android:text="Back"
          android:layout_weight="1" />
    </TableRow>
  </TableLayout>
</RelativeLayout>

It is difficult to get references to buttons in dialogs. You first have to inflate the dialog’s view, then you can find a button by its ID.

LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.number_input_dialog, null);
this.button0 = (Button)view.findViewById(R.id.n0);
this.button0.setOnClickListener(new NumberButtonListener(this.number, "0"));
Posted in Android at January 16th, 2009. 14 Comments.