lysergicjava

oh, technology

Menu Close

Wikileaks

Wikileaks is still alive, at http://213.251.145.96/.

Ron Paul and I don’t agree on a whole lot, but on this we do: “In a society where truth becomes treason, we’re all in big trouble.”

Oh, the humanity

Predictably, the hand-wringing and hysteria over Wikileaks’ cablegate release is ramping up. Also predictably, the powers-that-be are fishing about for the most damaging moral condemnation of Wikileaks’ action as they can find, as, at least here in the western hemisphere, moralizing is the most effective way of keeping the educated in line. By casting the release of the State Department memoranda as reckless vandalism or even terrorism (the latter charge was even too much Joe Lieberman) governments and their media lapdogs around the world hope to drive public opinion away from not just Wikileaks itself, but the very future Wikileaks represents.

Take, for example, Hillary Clinton’s remarks earlier today.  “This disclosure is not just an attack on America’s foreign policy interests,” she claimed, adding that “It is an attack on the international community: the alliances and partnerships, the conversations and negotiations that safeguard global security and advance economic prosperity.” Standard stuff; but Mama Beeb included another, telling quote in their writeup: “But Mrs Clinton said diplomats often needed confidentiality to be effective.”

Now that last statement, I’ll argue, has a kernel of truth in it. Diplomats often do need confidentiality to be “effective”, but one may well ask why this is so, and whose interest it serves. It makes perfect sense for secrecy to be the coin of the realm when you’re actively working against the interest of the majority of the world’s population. One can’t, however, resist the temptation to apply the US government’s own PATRIOT-Act logic here: if you’ve done nothing wrong, you’ve got nothing to hide, right?

No, they have plenty to hide, and while the released documents contain nothing that should shock a reasonably astute twelve-year-old, it’s not the actual facts that have been disclosed that has Clinton’s club’s panties in a pinch, it’s that anyone, anywhere, had the audacity to release any document not carefully prepared for public consumption. It’s the fact that Wikileaks is a harbinger of a future beyond their control, and boy oh boy do they not like it.

But here’s the thing. Wikileaks, or something for all intents and purposes just like it, is here to stay. The rational response would be to realize that the world has changed, to accept that despotism, command-and-control, and US hegemony are all due their swan song, and begin to act appropriately. Not only is this particular genie out of its bottle, no genie will ever be contained for long ever again. Rail against Wikileaks all you like, Mrs. Clinton, but realize, like Caligula attacking the ocean, you are fighting a losing battle.

Feeding TestNG data providers (stupid TestNG tricks volume 1)

TestNG is great.  It’s one of my favorite tools.  Beneath the simple facade lurks a creature of flexibility and power.  That being said, every tool has its limitations, and when TestNG doesn’t give me what I want out of the box, which is rarely, I go poking around looking for ways to game the system.  Here’s one.

Data providers are pretty sweet.  They can feed a test method with a wide variety of data to run against, and the framework even reports the arguments the provider passed in, making forensics easier.  There are limitations in their design which can make them clunky to use in certain situations, though.  Chief among these is that the data providers themselves don’t have an easy interface to accept arguments.

Why, you may ask, would a data provider need to accept arguments?  It’s a fair question, seeing as how the data provider’s responsibility is to dole out arguments.  Turns out there are good reasons.  For instance: I had created a data provider that reads through a file and sends each line as an argument to a test method.  Fairly straightforward stuff; but my first implementation had the provider reading the same file every time.  The file name was hardcoded in the provider.  What I wanted was a way to have a single provider read any arbitrary file, and what’s more, to have the test method itself tell the provider where its data could be found.  Code reuse, yah?

Problem is, data providers can’t take arbitrary inputs.  They can, however, accept a reference to the current test method.  So, with this chink in the armor, I created a new annotation, DataProviderArguments, which I could attach to a test method:

package com.netflix.systemtests.api.commons.dataproviders;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
* Annotation for feeding arguments to methods conforming to the
* "@DataProvider" annotation type.
* @author jharen
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface DataProviderArguments
{
  /**
  * String array of key-value pairs fed to a dynamic data provider.
  * Should be in the form of key=value, e.g., <br />
  * args={"foo=bar", "biz=baz"}
  */
String[] value();
}

Next, I wrote a helper class to unravel the test method and extract the arguments:

package com.netflix.systemtests.api.commons.dataproviders;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class DataProviderUtils
{
	protected static Map<String, String> resolveDataProviderArguments(Method testMethod) throws Exception
	{
		if (testMethod == null)
			throw new IllegalArgumentException("Test Method context cannot be null.");

		DataProviderArguments args = testMethod.getAnnotation(DataProviderArguments.class);
		if (args == null)
			throw new IllegalArgumentException("Test Method context has no DataProviderArguments annotation.");
		if (args.value() == null || args.value().length == 0)
			throw new IllegalArgumentException("Test Method context has a malformed DataProviderArguments annotation.");
		Map<String, String> arguments = new HashMap<String, String>();
		for (int i = 0; i < args.value().length; i++)
		{
			String[] parts = args.value()[i].split("=");
			arguments.put(parts[0], parts[1]);
		}
		return arguments;
	}
}

And with that, my FileDataProvider can read any given file:

package com.netflix.systemtests.api.commons.dataproviders;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.testng.annotations.DataProvider;

public class FileDataProvider
{
	@DataProvider(name="getDataFromFile")
	public static Iterator<Object[]> getDataFromFile(Method testMethod) throws Exception
	{
		Map<String, String> arguments = DataProviderUtils.resolveDataProviderArguments(testMethod);
		List<String> lines = FileDataProvider.getRawLinesFromFile(arguments.get("filePath"));
		List<Object[]> data = new ArrayList<Object[]>();
		for (String line : lines)
		{
			data.add(new Object[]{line});
		}
		return data.iterator();
	}

	public static List<String> getRawLinesFromFile(Method testMethod) throws Exception
	{
		Map<String, String> arguments = DataProviderUtils.resolveDataProviderArguments(testMethod);
		return FileDataProvider.getRawLinesFromFile(arguments.get("filePath"));
	}

	@SuppressWarnings("unchecked")
	public static List<String> getRawLinesFromFile(String filePath) throws Exception
	{
		InputStream is = new FileInputStream(new File(filePath));
		List<String> lines = IOUtils.readLines(is, "UTF-8");
		is.close();
		return lines;
	}
}

And now, my test methods can specify what file to fetch their data from:

@Test(dataProviderClass=com.netflix.systemtests.api.commons.dataproviders.TestAccountDataProvider.class, dataProvider="getTestAccountsFromFile")
@DataProviderArguments("filePath=src/main/resources/input-files/testAccounts.txt")
public void fetchInstantQueueAsJSON(String email, String accountID) throws Exception
{
  // blah blah blah testy test goes here
}

For my next trick, I think I’ll work on getting TestNG TestFactories to play the same game.  Then it’ll get interesting.  Till then, keep your bars green and your code clean.  Happy testing!

JPath 1.0 released

Ask anyone who’s had to work with JSON in Java: consuming, querying, and validating JSON objects in Java is a tedious chore. Either you’re stuck writing structured beans mapped to JSON responses, which is time-consuming and brittle, or you need to resort to circumlocutious chains of get() calls with typecasting (or foreknowledge of types) at every step. In particular, there is no equivalent (or even approximation) of XML’s XPath — until now.  JPath allows for concise, flexible navigation and validation of JSON data.  Check it out over at BLC.

Mounting shared folders with Win7 / Ubuntu Virtualbox pair

The classic instruction set for mounting a shared folder between a windows host and a linux guest, found here, works as advertised except for one small detail.  If your host is a windows7 install, you must define the shared folder in Virtualbox BEFORE starting the guest OS.  If, like me, you define the shared folder while the guest OS is running, the shared folder definition will be placed under the “transient folders” section of the definitions, not the “machine folders” section which is where it needs to be.  The trouble starts when you try to mount the shared folder.  You’ll get the error:

“/sbin/mount.vboxsf: mounting failed with the error: No such device”

Shut down the guest OS, add the shared folder to the virtual machine’s definition, and then you’re good to go.

Wireshark on MacOS X happy fun time

Wireshark is killer, except when it doesn’t play well with the underlying OS.  Like how OS X finds it hilarious to hide your network interfaces from your applications.  Go ahead, fire up Wireshark on the mac and watch as it can’t find a single interface.  I’ll wait.

Yeah, pain, isn’t it?

Well, you can fix that:

sudo chmod 664 /dev/b*

And you’re back in action.

Fixing Apple Laptop Network Slowness Problems

I’ve experienced this on two different laptops now: the wireless connections start to suck.  Out of nowhere the network just slows to a crawl.  Plug into ethernet and you’re jake.  All other wireless devices on the network are humming away just fine with no loss of bandwidth.  It’s just the Apple laptops.  It’s infuriating, but there’s a very simple (albeit weird) fix for it.

Just go to network preferences and pull down the location menu. From there select edit locations. Create a new location. Doesn’t matter what you call it, it’s all arbitrary. Then delete whatever location you were using, even if it is “Automatic”. Switch to the new location and set it up like normal.

That’s it.

God only knows why this works, but it does.

Making Maven builds platform-independent

This isn’t much publicized, but encoding issues can bite you in the butt, especially when switching platforms.  There’s an easy way to eliminate 95% of all encoding hassles,  though — just add a single property:


<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

to your pom, or parent pom.  Voila!  You're set for life.

Google grows a pair

According to the latest Google Public Policy blog post, the big G is “reconsidering” what doing business with the big C means.  Apparently, someone (cough: the Chinese government) has been attempting to break Google’s security and steal information about human rights activists. Google’s of the opinion that enough is enough, and I couldn’t agree more.

Everyone, lend your support to Google in this endeavor.

Original post: Official Google Blog: A new approach to China.

…and, another one

I’ve got a new and shiny (but rough) Netflix Command-line client over at BLC.  That’s right, Command-line. Roll with it unix style.