Fedora 19 installation from live USB might not work.. But can be fixed!

A short lengthy and vaguely related story about an SSD

It all started a few years ago, when I was just starting to work at Red Hat. SSDs were all the hype, but although promising, they were also pricey and feared of due to (IMHO unrealistic) MTBF concerns. Being a bit of a gadget freak, I liked the potential of the SSD and the promise of shorter read/write time. My first one was a 30GB Kingston SSDNow, which albeit rather slow compared to todays models, did deliver the promise and is still working until this very day (~4 years and counting).

Anyway, having a laptop from work I decided to ask my boss if it’s possible to get an SSD, seeing as I had a very good experience with it at home. Her reply was along the lines of “Sure, talk to our IT guy and see whats the procedure”. I went to the IT guy and asked him “Kind sir, how is it possible to get an SSD around here?” and in turn he replied “You know what, I have one lying around here which I was testing, you can have it”. Joy ensued as I had a new SSD for the work computer. It was a Lenovo branded one, which is logical since we use Lenovo computers.

I went on to install the SSD and again the difference was quite noticeable, Fedora booted faster, eclipse worked better, maven compiled like a champ, life was sweet. This was about two years ago, until now..

A few weeks ago I received my brand new Samsung Pro 840 SSD from work. I will be receiving a new laptop soon, and a new SSD instead of the Lenovo one I currently have sounded like a good idea so I went to my boss again and asked her “Tell me, is it possible to get a new SSD”, to which she replied “Well, we already spent the hardware budget, but I’ll see what I can do”. A week later the budget was approved, and the order went out. I chose the 840 as it seemed like a good one based on reviews, benchmarks, and it seemed like it would fit in the laptop I should be getting.

So what does it have to do with Fedora 19?

Well, seeing as on the last SSD I had Fedora 16 installed, I decided a new drive would be a good time to “upgrade” (also the development environment were working on works better on latest Fedora with latest packages). I didn’t clone the old SSD to the new since I’m not sure what support for SSD is put in place during install (from what I know it should be rather stable now) and also the size of the new drive was 2x larger.

I grabbed the Fedora 19 live ISO (being the advocated format) and created a live USB using the Linux Live USB Creator tool, swapped the drives and booted into “Live” mode where you have a choice either to experiment with the system or install to drive immediately. I chose the immediate option to install and followed the simple steps. After a few minutes the installer proclaimed it was done and that I should reboot, so I did.

At first everything worked, which quite amazes me every time since, while being very nice, Fedora isn’t a very stable OS (don’t try FedUp for example, unless you’re literally fed up with your OS and want to corrupt it, possibly.. I heard some people did have success with it, meh).

Fedora 19 tips & tricks

A few changes took place that I think are worth a mention:

  • The notifications area is in the bottom of the screen and appears if you press “Win” + M, or scroll the mouse down to the screen border, and then keep scrolling until it appears.
  • Changing the language is done via “Win” + Space combo, which is not that bad actually.
  • The CUPS service has split into a “server/client” bundle, so if you want to browse CUPS automatically you now need to:
echo BrowsePoll server.example.com >> /etc/cups/cups-browsed.conf
systemctl enable cups-browsed.service # To have the daemon start on boot
systemctl start cups-browsed.service # To start the daemon immediately
  • Install and use gnome-tweak-tool to adjust some basic settings which are hidden in the regular config.
  • If you use eclipse, or just don’t like them, you’ll probably want to disable “Ctrl” + “Alt” + “Up”/”Down” combo but this can only be done from command line, since the UI config tool doesn’t show all the combos (for moving one desktop up/down):
dconf write  /org/gnome/desktop/wm/keybindings/switch-to-workspace-up "['Page_Up']"
dconf write  /org/gnome/desktop/wm/keybindings/switch-to-workspace-down "['Page_Down']"

Happy after doing all the setting and tweaking I shut down the laptop.

Dracut.. It should be named Dracutla with all the time it sucked from me

Next day, it wouldn’t boot. “What, defective SSD? Are all those ghost stories true? Can’t be!” I thought to myself.. But the hard cold fact was that Fedora was throwing me to the dogs! I tried everything I could think of (at the time): swap back to the old SSD – it boots, swap to the new – it doesnt; Google – nothing of interest here; Launch live fedora – drive looks fine; fsck – all green; Reinstall Fedora – now it boots..

Well, weird but what can I say? Second time’s the charm?

Apparently not, since not an hour passed and it wouldn’t boot again. Until I notice something bizarre… When booting, if I’d plug the live USB back in it would boot, That’s weird.. What does the live USB got to do with it? Well apparently quite a lot, and then again nothing at all.. I rebooted a couple of times just to make sure and indeed with the USB plugged in it boots, but without it it doesn’t.. Seems like some sort of love affair between the two flash-based devices…

Well, after googling quite a bit I found the real culprit – Dracut! Seems that when using the Live USB (probably because it was created in LiLi?) there’s a swap partition on the USB itself, which is mounted and used by the live system. Sometime during the installation process, dracut is used to create an initramfs image for the new OS, unfortunately this image also contains a trace of the USB swap partition and this causes it to expect it to be present when the OS is booting, or fail the boot if not.

So what can you do?

Well there are a couple solutions which will work:

  • Don’t install from Live USB (perhaps it’s related to how you create it, I’m not sure). There are many flavors of Fedora that will work and not make you curse it.
  • If you did install and hit this problem, you can take the following steps:
    • Remove the live USB swap entry from the /etc/fstab file (identified by UUID)
    • Remove the swap from being used: swapoff (just to be safe)
    • Run:
      dracut -H -f --regenerate-all --fstab
    • Now you can safely remove the live USB and not worry about it any more.

Now it’s really a happy end!

Advertisements
Posted in Misc | Tagged , , , , , , | Leave a comment

HOWTO: Nested KVM based virtual setup with oVirt

I have been working on the oVirt project for almost 3 years now, but I rarely get to experience it from the user’s point of view. Sure there are test days, bug fixes, and other activities that require me to fiddle with oVirt, but I haven’t really experienced it as a user trying to set up his env. Until now…

The good

For those of you who don’t know, oVirt is a rising star in the virtualization world, allowing users to create their own virtual setups with the powerful KVM behind the scenes. Check it out @ www.ovirt.org – it’s 100% free & open source!

The bad

These last few days I have been trying to install OpenStack using devstack as part of my job – what a nightmare!
First of all, I had to set up a host for the OpenStack environment. “That’s easy”, I thought to myself, “I’ll just grab this mini DELL that’s lying under my feet and install a new OS on it”.
I went to the devstack site and they recommended Ubuntu 12.04 (Precise Pangolin) which is the LTS (Long Term Support) edition – makes sense, you better go with something stable right?

It’s not that i hate Ubuntu, Until now…

I went to the Ubuntu site and saw there’s a few editions, one supposedly including OpenStack – “That’s too easy”, I thought, “I want to control the devstack installation myself and tweak it if necessary”. The server edition seemed the logical choice, but I decided to alsdo grab the desktop edition just in case.. BTW I don’t want to be asked to donate each time I want to download Ubuntu, it’s not that I’m cheap but it’s just annoying to be pushed towards it each time..

Well, let me tell you, Ubuntu 12.04 is utterly uninstallable. You might think it was just my imagination, but each of the images had some corrupt file which halted the installation dead in it’s tracks. I thought maybe it’s because I’m trying to use a USB stick, so I even burned the ISO to a real CD (so 90’s…) but the problem existed even there.. “Right, I must’ve gotten a corrupt download”.. I ran md5sum and compared it with the one they hid on their site.. Completely identical! ARGH!!

As a rather stubborn guy I had to make it work, but how? I found a “minimal ISO” of Ubuntu 12.04, this time no corrupt files as the installation downloads everything – excellent, except that it takes ages! By the time the installation had finished and asked me to reboot, I wanted to go home, so I turned off the computer and said to myself “Eh, I’ll just continue tomorrow”. Lo and behold, the next day the OS booted into a black screen.. Frustration ensued.

At this stage I decided Ubuntu was not my friend in this journey.. Having been scolded by Fedora 19 installation from Live USB, I turned to my last resort: RHEL 6.4.

Virtualization for the win

I decided that I won’t be installing on bare metal anymore. Of course a VM would be a logical choice, one I even considered in the beginning, but because of the need to run VMs on OpenStack I was hesitant at the beginning (before this fiasco). Having spent a couple days work trying to install Ubuntu, while climbing under my desk a lot (It’s rather clean there, but still inconvenient), I decided to give nested virtualization a try.

Of course, you can get a very quick and simple environment running using virt-manager or boxes, but I wanted to:

  • Be able to live migrate the VMs between hosts easily.
  • Be able to take live snapshots of the VMs.
  • Have templates with thin provisioning of disks.
  • Have a centralized place to manage it, that is accessible via web for:
  • When I’m working from home.
  • Someone else from the team wants a VM there.

All the above reasons led me to pick oVirt which I know well, and suits all my needs (and much more).

The good again

Well, turns out it’s rather easy to set up an oVirt env as a user, you’ll probably spend most of the time installing stuff and the administration itself is a breeze. There are some pitfalls to be aware of, but I’ll try to write them all so you know what to avoid.

Setting up oVirt

OK, so for starters I wanted my oVirt host to be virtualized by itself, to be able to back it up and if necessary move to another host. I took my RHEL 6.4 host which also runs Jenkins (probably should move this to a VM also). This one doesn’t have to run nested since we’re not planning to run any VMs on it. For this I used virt-manager + qemu-kvm + libvirt (In the near future, oVirt will have a feature which allows to run itself inside a VM managed by itself, but until then I’ll use plain virt..).
Just install the three on a host that you want to run oVirt on:

sudo yum install -y virt-manager qemu-kvm libvirt \
&& service libvirtd start \
&& chkconfig libvirtd on

If your host doesn’t forward X11 when you ‘ssh -X’ to it, you need to install xauth on it:

sudo yum install xauth

Now start virt-manager and create a new VM, I chose:

  • Disk size 20 GB (this can be resized later anyway)
  • 3 GB RAM (oVirt requires at least 2, but setting exactly 2 will give you trouble)
  • MAC address that probably won’t collide with other MACs in the office network (since we launch VMs they might get the same MAC so we need to make sure not to step on each other’s toes).
  • Fedora 19 image (I installed server packages only, no UI).

Right, install the host and then SSH to it. If you can, give it a DNS or DDNS entry or just remember the IP and make sure it sticks (make it static, or change the DHCP server definition to always give you this IP).

On the host you need to download and install oVirt – just follow the 3 simple steps at http://www.ovirt.org/Download

Note: If the installation complains that you don’t have a reverse DNS record, you can add your oVirt VM’s IP and “hostname” that’s used in the installation to /etc/hosts – since you’ll be using a local user, you don’t need a reverse DNS record anyway.

Now that you have oVirt installed you can back it up just to be safe. You can copy the disk image and dump the vm’s XML:

virsh dumpxml [vm name] > /path/to/vm.xml

Later you can easily restore by copying back the disk image and restoring the VM from XML:

virsh define /path/to/vm.xml

However, any changes that were made to the data storage domains will remain there and would need to be cleaned manually.

Setup your basic oVirt environment

First of all, we must disable the MAC anti spoofing configuration value (otherwise the VM inside the VM won’t be able to send traffic since it’s MAC address is different):

engine-config -s EnableMACAntiSpoofingFilterRules=false --cver=3.2 \
&& engine-service restart

Also it’s a good idea to configure a MAC range that won’t interfere with other people (optional):

engine-config -s MacPoolRanges=66:1A:4A:23:11:00-66:1A:4A:23:11:FF \
&& engine-service restart

Next, log into oVirt and add a new data-center in the Data Centers tab. The Default DC is limited a bit (can’t be deleted, etc) so it doesn’t hurt to add another one.
As a bonus, you’ll get the “Guide Me” wizard which walk you through the different steps that you need to do so just follow the steps:

  • Add a cluster.
  • Add hosts to the cluster (Make sure to use F18 or higher).
  • Add a shared storage (NFS most likely).
  • Add a VM.

Now, to have ISO images available you’ll need to import or create an ISO domain (Unless you chose to have one created during installation, which I haven’t tried).
To create an ISO domain:

  • Go to the ‘Storage domains’ tab.
  • Click ‘Add’, the new storage dialog will open.
  • Choose your data center (An active host should be chosen automatically).
  • Choose ‘NFS/ISO’ type.
  • Enter the path to the storage domain, for example ‘example.com:/export/iso’.
  • Click ‘OK’.

The domain will be created and attached to the data center, select it and go to the ‘Data Center’ sub-tab and click on ‘Activate’.
Once the domain is active you can upload ISO images to it. I actually didn’t use the ISO uploader tool, but rather just downloaded the images directly to the ‘images’ folder that was created (it will be in the path you provided, under a folder named after the UUID of the domain). Either way you get the images there is fine.

Enabling nesting on the hosts

Now, we have a working environment, and for regular oVirt usage it would be fine to use like this.
However, to enable nested virtualization, a bit (really just a bit) of manual work has to be done.

Note: If you need to reboot the host, better put it to Maintenance first just to be safe.

Note: You can also use a VM for this, same as you used a VM for the oVirt machine. The only adjustments needed are to enable nested virtualization on the host machine of the VM (explained later on), and have “vmx” required by the CPU of the VMnsel0.

SSH to each host and do the following:

  • To make sure you avoid nested virt bugs (esp. kernel bug that I stumbled upon) better update the host software:
  • yum update -y
  • Make sure nested virtualization is enabled in the KVM:
  • For Intel based hosts (not sure about AMD):
  • sudo yum install -y vdsm-hook-nestedvt

And now you’re basically good to go!

You can check if it works, create a new VM in oVirt and install it, and create another VM inside that VM (You can use virt-manager, boxes, or be adventerous and add the “host” VM as a host in oVirt ;)).

Posted in Uncategorized | Tagged , , , , , , , , , | Leave a comment

Mapping keys for the Mele F10 – for Android 4.2.2

I recently purchased a Mele F10 “air mouse” for my MK808B.
I already had the RC11, but preferred the F10 due to several advantages:

  • Slicker looks, it’s a much more sexy remote with a nice Piano Black finish
  • Smaller frame, not as bulky as the RC11
  • Two sided design
    • Front side is the “remote side” with easy buttons for the mouse, and general navigation (up, down, left, right).
    • Back side is a qwerty keyboard, with bigger buttons than the RC11 due to a use of a FN button to change the key function.
  • Built-in battery which
    • Makes it lighter to hold
    • Probably doesn’t leak like some AA/AAA batteries

The Mele F10

ImageImage

Out of the box, the remote side buttons which work are the enter, back, mute, directional and volume buttons.
However, one thing that I was desperately missing from RC11 was media control buttons (Oh, and the home button didn’t work as it should, it just went to the start of a line)…

Having successfully remapped the RC11 keys using the guide at http://nullfactory.blogspot.co.il/2013/02/bind-media-keys-on-rc11-air-mouse.html I was sure I could quickly fix my problems, by remapping the bottom 4 keys (Which are unused) plus the home & the “TV” key to suit my needs.

So first thing was to download the /system/usr/keylayout/Generic.kl file (Using AirDroid) and renaming to “Vendor_1915_Product_af11.kl”, which is the correct name determined by looking at /proc/bus/input/devices.

Next thing was to use the KeyTest app to determine the scan codes (note that they “key code” is not what you need, it’s the scan code) for the keys I wanted to remap.

I then edited the file so that:

  • The ‘Home’ key worked
  • The ‘TV’ key (A square with an arrow pointing outwards) opens the menu
  • The ‘Square’ is stop
  • The ‘X’ is rewind
  • The ‘Circle’ is play/pause
  • The ‘Triangle’ is fast forward

I then copied this file to the device, and then using ES File Explorer copied it over to /system/usr/keylayout
I pulled the dongle out, disconnecting it, and then pushed it back in and… Nothing! The damn keys still don’t work!
I could swear this worked before, on Android 4.1, and the paths and all were still the same, so what’s wrong?!

After a few tedious forum readings, I found out the problem.. I haven’t set the permissions correctly!
Apparently, on Android 4.1 this didn’t matter (Or perhaps default mask for the keylayout dir was correct?!), but on Android 4.2.2 the file had permissions “-rw——-“.
I used ES Explorer to set the permissions to the same as the Generic.kl file (-rw-r–r–), replugged the dongle, and voila! The keys are now working!

So, the lesson is, always check your permissions, and don’t give up.

You can download the file for the Mele F10 if you want the same mappings that I have: https://docs.google.com/file/d/0Bxb0Tx-Akl7vZ3YzX3Z6S3NlOGM/edit?usp=sharing

Posted in Android | Tagged , , , , | 4 Comments

Getting rid of java.lang.ClassNotFoundException when deploying exploded ear

Been having trouble deploying an ear in Eclipse to a JBoss server.
Apparently, when you use the server connectors from the JBossAS Tools project, the server deploys the ear as exploded. This is different from the default JBoss server connector, which deploys the ear packed.

For some reason (which is not clear to me yet), the packed ear starts up fine in the server, while the exploded one doesn’t, yelling that it can’t find some class. This seemed weird since the packed ear works, and also since the exploded ear directory contains the jar which the file resides in.

After a few good hours of trial and error, I glanced at the application.xml file and saw that the file lists all the EJB/Web modules it uses. Strangely enough, it doesn’t list the regular jars – and that’s our culprit. After adding the jars as java modules to the xml file.

Joy 🙂

Posted in Java | Leave a comment

Getting rid of “Exception in thread “main” java.lang.SecurityException: Failed to authenticate principal=null, securityDomain=jmx-console”

When I tried to stop the server I always got this annoying exception, and could only stop it by kill.

A quick google search found this post: http://community.jboss.org/message/246272#246272
The solution there is to comment out the interceptor named “org.jboss.jmx.connector.invoker.AuthenticationInterceptor” in the file [server]/deploy/jmx-invoker-service.xml

It worked, Oh joy 🙂

Posted in Uncategorized | 2 Comments

JiperRandom: A better random solution

This is an extension of java.util.Random which I find very useful and use in my tests.

Some very useful methods are: nextString, nextEnum, pickRandom and other methods for random numbers as well (which are more flexible than the standard ones in java.util.Random).



import java.math.BigInteger;
import java.util.*;

/**
 * Jiper's <code>Random</code> class adds utility methods in an attempt to 
 * corrects Sun's laziness, and produce a better solution.<P>
 * This class also corrects (what I believe to be) an historical mistake, and
 * is a <b>singleton</b> class..<P>
 * Useful methods include:
 * <UL>
 * <LI><code>nextXXX()</code> for the <tt>byte</tt> and <tt>short</tt> types.
 * <LI><code>nextXXX(mod)</code> for all types.
 * <LI><code>nextXXX(min,max)</code> for all types.
 * <LI><code>pickRandom()</code> - picks a random element from a given 
 *                                 <code>List</code> or <code>Set</code>.
 * </UL>
 *
 * @see java.util.Random
 */
public final class JiperRandom extends java.util.Random {
    
    /**
     * The <tt>JiperRandomQualifier</tt> defines how to further qualify a value 
     * requested from {@link JiperRandom}.<br><br>
     * 
     * This class is awefully useful when you want a value is isn't completely 
     * random, but adheres to some more application-specific logic (for example:
     * a value that isn't present in a database, a palyndrom, a value with some
     * specific <tt>hashCode()</tt>, etc.)
     *  
     * @author Allon M.
     */
    public interface JiperRandomQualifier {
        
        /**
         * Checks if the parameter adheres to the logic the 
         * <tt>JiperRandomQualifier</tt> is supposed to check
         * @param o The object to check (usually, the random value generated by
         * {@link JiperRandom} 
         * @return <tt>true</tt> if <tt>o</tt> adheres to the logic the 
         * <tt>JiperRandomQualifier</tt> checks, or <tt>false</tt> if not. 
         */
        boolean matches(Object o);
    }
    
    private static final String MIN_MAX = "min must be less than or equal to max";
    
    /* --- Singleton-related Methods --- */

    /**
     * Returns the single(ton) instance.
     * The first time this method is called, a new instance is created with the
     * default seed (current time in millis).
     */
    public static synchronized JiperRandom instance() {
        if (instance == null) {
            instance = new JiperRandom();
        }

        return instance;
    }

    /**
     * Returns the single(ton) instance.
     * The first time this method is called, a new instance is created with the
     * given seed, consecutive calls return the existing instance set with the
     * given seed.
     */
    public static synchronized JiperRandom instance(long seed) {
        if (instance == null) {
            instance = new JiperRandom(seed);
        } else {
            instance.setSeed(seed);
        }

        return instance;
    }


    /* --- Seed-related Methods --- */

    /**
     * The last seed is saved, so it is possible to
     * {@link #getSeed()} it later. Since <code>java.util.Random</code>'s seed
     * is private, I am obliged to save my own copy.
     *
     * See {@link java.util.Random#setSeed(long)}.
     */
    public synchronized void setSeed(long seed) {
        super.setSeed(seed);
        this.seed = seed;
    }

    /**
     * Returns the seed that was set last.
     */
    public synchronized long getSeed() {
        return seed;
    }


    /* --- Byte-related Methods --- */

    /**
     * Randomizes a <tt>byte</tt> value.
     */
    public byte nextByte() {
        return (byte) super.nextInt();
    }

    /**
     * Randomize a <tt>byte</tt> value between 0 (inclusive) and the specified
     * value (exclusive).
     */
    public byte nextByte(byte b) {
        return (byte) super.nextInt(b);
    }

    /**
     * Randomize a <tt>byte</tt> value in the given range [min, max].
     */
    public byte nextByte(byte min, byte max) {
        if (min > max) {
            throw new IllegalArgumentException(
                    MIN_MAX);
        }

        return (byte) (min + nextByte((byte) (max - min + 1)));
    }


    /* --- Short-related Methods --- */

    /**
     * Randomizes a <tt>short</tt> value.
     */
    public short nextShort() {
        return (short) super.nextInt();
    }

    /**
     * Randomize a <tt>short</tt> value between 0 (inclusive) and the specified
     * value (exclusive).
     */
    public short nextShort(short s) {
        return (short) super.nextInt(s);
    }

    /**
     * Randomize a <tt>short</tt> value in the given range [min, max].
     */
    public short nextShort(short min, short max) {
        if (min > max) {
            throw new IllegalArgumentException(
                    MIN_MAX);
        }

        return (short) (min + nextShort((short) (max - min + 1)));
    }


    /* --- Integer-related Methods --- */

    /**
     * Randomizes an <tt>int</tt> value until it matches the provided 
     * <code>JiperRandomQualifier</code>. <b>NOTE</b>: The qualifier is 
     * provided an <code>Integer</code> with the randomized value as the 
     * <code>Object</code> to match.
     * 
     * @param qualifier The <code>JiperRandomQualifier</code> which qualifies
     *                     the randomized values.
     * @return A random integer which matches the 
     * <code>JiperRandomQualifier</code>.
     */
    public int nextInt(JiperRandomQualifier qualifier) {
        int returnValue;
        do {
            returnValue = nextInt();
        } while (! qualifier.matches(new Integer(returnValue)));
        
        return returnValue;
    }
    
    /**
     * Randomizes and <tt>int</tt> value in the given range, which answers the
     * specified qualifier.
     * 
     * @param min            The minimum value of the integer returned. 
     * @param max            The maximum value of the integer returned.
     * @param qualifier        The qualifier the returned integer must match.
     * @return an <tt>int</tt> in the specified range which matches the
     * specified qualifier.
     */
    public int nextInt(int min, int max, JiperRandomQualifier qualifier) {
        int returnValue;
        do {
            returnValue = nextInt(min, max);
        } while (! (qualifier.matches(new Integer(returnValue))));
        
        return returnValue;
    }
    
    /**
     * Randomize an <tt>int</tt> value in the given range [min, max].
     */
    public int nextInt(int min, int max) {
        if (min > max) {
            throw new IllegalArgumentException(
                    MIN_MAX);
        }

        return (min + super.nextInt(max - min + 1));
    }

    
    /* --- Long-related Methods --- */

    /**
     * Randomize a <tt>long</tt> value between 0 (inclusive) and the specified
     * value (exclusive).
     */
    public long nextLong(long l) {
        if (l <= 0) {
            throw new IllegalArgumentException("l must be greater than 0!");
        }

        return (Math.abs(super.nextLong()) % l);
    }

    /**
     * Randomize a <tt>long</tt> value in the given range [min, max].
     */
    public long nextLong(long min, long max) {
        if (min > max) {
            throw new IllegalArgumentException(
                    MIN_MAX);
        }

        return (min + nextLong(max - min + 1));
    }

    /* --- Float-related Methods --- */

    /**
     * Randomize a <tt>float</tt> value between 0.0 (inclusive) and the
     * specified value (exclusive).
     */
    public float nextFloat(float f) {
        return nextFloat(f, false);
    }

    /**
     * Randomize a <tt>float</tt> value between 0.0 (inclusive) and the
     * specified value (inclusive or exclusive as required).
     *
     * @param inclusive  Whether or not, the returned value should include the
     *                   given one.
     */
    public float nextFloat(float f, boolean inclusive) {
        if (f <= 0.0F) {
            throw new IllegalArgumentException("f must be greater than 0!");
        }

        // Randomize a float
        float rand = super.nextFloat();

        // If the returned value should not include the given one,
        // make sure that the randomized float is not exactly 1.0
        if (! inclusive) {
            while (rand == 1.0F) {
                rand = super.nextFloat();
            }
        }
 
        return (rand * f);
    }

    /**
     * Randomize a <tt>float</tt> value in the given range [min, max].
     */
    public float nextFloat(float min, float max) {
        if (min > max) {
            throw new IllegalArgumentException(
                    MIN_MAX);
        }

        return (min + nextFloat(max - min, true));
    }


    /* --- Double-related Methods --- */

    /**
     * Randomize a <tt>double</tt> value between 0.0 (inclusive) and the 
     * specified value (exclusive).
     */
    public double nextDouble(double d) {
        return nextDouble(d, false);
    }

    /**
     * Randomize a <tt>double</tt> value between 0.0 (inclusive) and the 
     * specified value (inclusive or exclusive as required).
     *
     * @param inclusive  Whether or not, the returned value should include the
     *                   given one.
     */
    public double nextDouble(double d, boolean inclusive) {
        if (d <= 0.0D) {
            throw new IllegalArgumentException("d must be greater than 0!");
        }

        // Randomize a double
        double rand = super.nextDouble();

        // If the returned value should not include the given one,
        // make sure that the randomized float is not exactly 1.0
        if (! inclusive) {
            while (rand == 1.0D) {
                rand = super.nextDouble();
            }
        }

        return (rand * d);
    }

    /* --- Collections-related Methods --- */

    /**
     * Picks a random element from the given <code>Collection</code>.
     */
    public <T> T pickRandom(Collection<T> c) {
        int elementIndex = super.nextInt(c.size());

        Iterator<T> iter = c.iterator();
        for (int i = 0; i < elementIndex; ++i) {
            iter.next();
        }

        return iter.next();
    }
    
    /**
     * Picks a random element, which matches the provided 
     * <code>JiperRandomQualifier</code>, from the given 
     * <code>Collection</code>.
     * 
     * @param c            The <code>Collection</code> to pick an element from.
     * @param qualifier    The <code>Qualifier</code> the picked element has to
     *                     match.
     * 
     * @return            A random, qualified element from the
     *                     <code>Collection</code>.
     */
    public <T> T pickRandom(Collection<T> c, JiperRandomQualifier qualifier) {
        T returnValue = null;
        do {
            int elementIndex = super.nextInt(c.size());

            Iterator<T> iter = c.iterator();
            for (int i = 0; i < elementIndex; ++i) {
                iter.next();
            }
        
            returnValue = iter.next();
        } while (! qualifier.matches(returnValue));
        
        return returnValue;
    }
    
    /* --- Array-related Methods --- */

    /**
     * Picks a random element from the given array.
     */
    public <T> T pickRandom(T[] o) {
        return pickRandom(Arrays.asList(o));
    }
    
    /**
     * Picks a random element, which matches the provided 
     * <code>JiperRandomQualifier</code>, from the given array.
     * 
     * @param o                The array to pick an element from.
     * @param qualifier        The <code>Qualifier</code> the picked element has 
     *                         to match.
     * 
     * @return                A random, qualified element from the 
     *                         <code>Collection</code>.
     */
    public <T> T pickRandom(T[] o, JiperRandomQualifier qualifier) {
        return pickRandom(Arrays.asList(o), qualifier);
    }

    
    /* --- String-related Methods --- */
    
    /**
     * Randomize a <code>String</code>.
     *
     * @param length     The requested length of the string. 
     * @param printable  Whether or not, the string should contain only
     *                   printable characters.
     */ 
    public String nextString(int length, boolean printable) {
        if (printable) {
            byte[] data = new byte[length];

            for (int i = 0; i < length; ++i) {
                data[i] = (byte) nextInt(
                            FIRST_PRINTABLE_CHAR, 
                            LAST_PRINTABLE_CHAR);
            }

            return new String(data);

        }
        return new String(nextBytes(length));
    }
    
    /**
     * Randomize a <code>String</code> that adheres to the given 
     * {@link JiperRandomQualifier.util.JiperRandomQualifier}
     *
     * @param length     The requested length of the string. 
     * @param printable  Whether or not, the string should contain only
     *                   printable characters.
     * @param qualifier  The <code>JiperRandomQualifier</code> the return value
     *                      must adhere to
     * @return             A random value that adheres to <code>qualifier</code>
     */ 
    public String nextString
        (int length, boolean printable, JiperRandomQualifier qualifier) {
        String returnVal;
        
        do {
            returnVal = nextString(length, printable);
        } while (!qualifier.matches(returnVal));
        
        return returnVal;
    }
    
    /**
     * Randomize a valid numeric string.
     *
     * @param length The requested length of the string.
     */
    public String nextNumericString(int length) {
        return Long.toString(nextLong(
                (long) Math.pow(10, length - 1), (long) (Math.pow(10, length) - 1)));
    }

    /**
     * Randomize a valid XML Element name.
     *
     * @param length    The requested length of the string.
     */
    public String nextXmlString(int length) {
        byte[] data = new byte[length];
        for (int i = 0; i < length; ++i) {
            data[i] = (byte) nextInt(
                        FIRST_XML_PRINTABLE_CHAR,
                        LAST_XML_PRINTABLE_CHAR);
        }

        return new String(data);
    }
    
    /**
     * Randomize a valid XML Element name.
     *
     * @param length    The requested length of the string.
     * @param qualifier  The <code>JiperRandomQualifier</code> the return value
     *                      must adhere to
     */
    public String nextXmlString(int length, JiperRandomQualifier qualifier) {
        String returnVal;
        
        do {
            returnVal = nextXmlString(length);
        } while (!qualifier.matches(returnVal));
        
        return returnVal;
    }

    /**
     * Randomize a printeable <code>String</code>.
     *
     * @param length  The requested length of the string. 
     */ 
    public String nextString(int length) {
        return nextString(length, true);
    }
    
    /**
     * Randomize a <code>String</code> that adheres to the given 
     * {@link JiperRandomQualifier.util.JiperRandomQualifier}
     *
     * @param length     The requested length of the string. 
     * @param qualifier  The <code>JiperRandomQualifier</code> the return value
     *                      must adhere to
     * @return             A random value that adheres to <code>qualifier</code>
     */ 
    public String nextString(int length, JiperRandomQualifier qualifier) {
        return nextString(length, true, qualifier);
    }
    

    /**
     * Randomize a <code>String</code> of a length in the 
     * given range [min, max].
     *
     * @param printable  Whether or not, the string should contain only
     *                   printable characters.
     */
    public String nextString(int min, int max, boolean printable) {
        return nextString(nextInt(min, max), printable);
    }
    
    /**
     * Randomize a <code>String</code> that adheres to the given 
     * {@link JiperRandomQualifier.util.JiperRandomQualifier} of a length in the 
     * given range [min, max]
     *
     * @param length     The requested length of the string. 
     * @param printable  Whether or not, the string should contain only
     *                   printable characters.
     * @param qualifier  The <code>JiperRandomQualifier</code> the return value
     *                      must adhere to
     * @return             A random value that adheres to <code>qualifier</code>
     */ 
    public String nextString
        (int min, int max, boolean printable, JiperRandomQualifier qualifier) {
        String returnVal;
        
        do {
            returnVal = nextString(min, max, printable);
        } while (!qualifier.matches(returnVal));
        
        return returnVal;
    }

    /**
     * Randomize a printable <code>String</code> of a length in the 
     * given range [min, max].
     */
    public String nextString(int min, int max) {
        return nextString(nextInt(min, max), true);
    }
    
    /**
     * Randomize a <code>String</code> that adheres to the given 
     * {@link JiperRandomQualifier.util.JiperRandomQualifier} of a length in the 
     * given range [min, max]
     *
     * @param length     The requested length of the string. 
     * @param qualifier  The <code>JiperRandomQualifier</code> the return value
     *                      must adhere to
     * @return             A random value that adheres to <code>qualifier</code>
     */ 
    public String nextString(int min, int max, JiperRandomQualifier qualifier) {
        return nextString(min, max, true, qualifier);
    }

    /* --- General Utility Methods --- */

    /**
     * Creates a <tt>byte</tt> array of the specified size, 
     * initialized with random values.
     */
    public byte[] nextBytes(int size) {
        byte[] data = new byte[size];
        nextBytes(data);
        return data;
    }
    
    /* -- Big Integer related methods -- */
    
    /**
     * generates a new big integer with the desired number of bits
     * the generated number will always be positive.
     * @param numOfBits the number of bits of the Big Integer
     * @return the randomized big integer.
     */
    public BigInteger nextBigInt(int numOfBits) {
        return new BigInteger(numOfBits, this);
    }
    
    /**
     * Returns a random value from an enum.
     * 
     * @param <T> The enum type.
     * @param enumClass The enum class to randomize.
     * 
     * @return A random enum from the given enum, or null if got null.
     */
    @SuppressWarnings("unchecked")
    public <T extends Enum> T nextEnum(Class<T> enumClass) {
        if (enumClass == null) {
            return null;
        }
        
        return pickRandom(enumClass.getEnumConstants());
    }

    /* --- Private Methods and Fields --- */

    /**
     * Constructs the object.
     */
    private JiperRandom() {
    }

    /**
     * Constructs the object with the given random seed.
     */
    private JiperRandom(long seed) {
        super(seed);
    }

    /** The single(ton) instance. */
    private static JiperRandom instance;

    /** The seed that was last set. */
    private long seed;

    /** The first printable character. */
    private static final char FIRST_PRINTABLE_CHAR = ' ';

    /** The last printable character. */
    private static final char LAST_PRINTABLE_CHAR  = '~';

    /** The first XML printable character. */
    private static final char FIRST_XML_PRINTABLE_CHAR = 'A';

    /** The last XML printable character. */
    private static final char LAST_XML_PRINTABLE_CHAR = 'Z';
}


import java.math.BigInteger;
import java.util.*;

/**
* Jiper’s Random class adds utility methods in an attempt to
* corrects Sun’s laziness, and produce a better solution.


* This class also corrects (what I believe to be) an historical mistake, and
* is a singleton class..


* Useful methods include:
*


    *
  • nextXXX() for the byte and short types.
    *
  • nextXXX(mod) for all types.
    *
  • nextXXX(min,max) for all types.
    *
  • pickRandom() – picks a random element from a given
    * List or Set.
    *

*
* @see java.util.Random
*/
public final class JiperRandom extends java.util.Random {

/**
* The JiperRandomQualifier defines how to further qualify a value
* requested from {@link JiperRandom}.

*
* This class is awefully useful when you want a value is isn’t completely
* random, but adheres to some more application-specific logic (for example:
* a value that isn’t present in a database, a palyndrom, a value with some
* specific hashCode(), etc.)
*
* @author Allon M.
*/
public interface JiperRandomQualifier {

/**
* Checks if the parameter adheres to the logic the
* JiperRandomQualifier is supposed to check
* @param o The object to check (usually, the random value generated by
* {@link JiperRandom}
* @return true if o adheres to the logic the
* JiperRandomQualifier checks, or false if not.
*/
boolean matches(Object o);
}

private static final String MIN_MAX = “min must be less than or equal to max”;

/* — Singleton-related Methods — */

/**
* Returns the single(ton) instance.
* The first time this method is called, a new instance is created with the
* default seed (current time in millis).
*/
public static synchronized JiperRandom instance() {
if (instance == null) {
instance = new JiperRandom();
}

return instance;
}

/**
* Returns the single(ton) instance.
* The first time this method is called, a new instance is created with the
* given seed, consecutive calls return the existing instance set with the
* given seed.
*/
public static synchronized JiperRandom instance(long seed) {
if (instance == null) {
instance = new JiperRandom(seed);
} else {
instance.setSeed(seed);
}

return instance;
}

/* — Seed-related Methods — */

/**
* The last seed is saved, so it is possible to
* {@link #getSeed()} it later. Since java.util.Random‘s seed
* is private, I am obliged to save my own copy.
*
* See {@link java.util.Random#setSeed(long)}.
*/
public synchronized void setSeed(long seed) {
super.setSeed(seed);
this.seed = seed;
}

/**
* Returns the seed that was set last.
*/
public synchronized long getSeed() {
return seed;
}

/* — Byte-related Methods — */

/**
* Randomizes a byte value.
*/
public byte nextByte() {
return (byte) super.nextInt();
}

/**
* Randomize a byte value between 0 (inclusive) and the specified
* value (exclusive).
*/
public byte nextByte(byte b) {
return (byte) super.nextInt(b);
}

/**
* Randomize a byte value in the given range [min, max].
*/
public byte nextByte(byte min, byte max) {
if (min > max) {
throw new IllegalArgumentException(
MIN_MAX);
}

return (byte) (min + nextByte((byte) (max – min + 1)));
}

/* — Short-related Methods — */

/**
* Randomizes a short value.
*/
public short nextShort() {
return (short) super.nextInt();
}

/**
* Randomize a short value between 0 (inclusive) and the specified
* value (exclusive).
*/
public short nextShort(short s) {
return (short) super.nextInt(s);
}

/**
* Randomize a short value in the given range [min, max].
*/
public short nextShort(short min, short max) {
if (min > max) {
throw new IllegalArgumentException(
MIN_MAX);
}

return (short) (min + nextShort((short) (max – min + 1)));
}

/* — Integer-related Methods — */

/**
* Randomizes an int value until it matches the provided
* JiperRandomQualifier. NOTE: The qualifier is
* provided an Integer with the randomized value as the
* Object to match.
*
* @param qualifier The JiperRandomQualifier which qualifies
* the randomized values.
* @return A random integer which matches the
* JiperRandomQualifier.
*/
public int nextInt(JiperRandomQualifier qualifier) {
int returnValue;
do {
returnValue = nextInt();
} while (! qualifier.matches(new Integer(returnValue)));

return returnValue;
}

/**
* Randomizes and int value in the given range, which answers the
* specified qualifier.
*
* @param min The minimum value of the integer returned.
* @param max The maximum value of the integer returned.
* @param qualifier The qualifier the returned integer must match.
* @return an int in the specified range which matches the
* specified qualifier.
*/
public int nextInt(int min, int max, JiperRandomQualifier qualifier) {
int returnValue;
do {
returnValue = nextInt(min, max);
} while (! (qualifier.matches(new Integer(returnValue))));

return returnValue;
}

/**
* Randomize an int value in the given range [min, max].
*/
public int nextInt(int min, int max) {
if (min > max) {
throw new IllegalArgumentException(
MIN_MAX);
}

return (min + super.nextInt(max – min + 1));
}

/* — Long-related Methods — */

/**
* Randomize a long value between 0 (inclusive) and the specified
* value (exclusive).
*/
public long nextLong(long l) {
if (l <= 0) {
throw new IllegalArgumentException("l must be greater than 0!");
}

return (Math.abs(super.nextLong()) % l);
}

/**
* Randomize a long value in the given range [min, max].
*/
public long nextLong(long min, long max) {
if (min > max) {
throw new IllegalArgumentException(
MIN_MAX);
}

return (min + nextLong(max – min + 1));
}

/* — Float-related Methods — */

/**
* Randomize a float value between 0.0 (inclusive) and the
* specified value (exclusive).
*/
public float nextFloat(float f) {
return nextFloat(f, false);
}

/**
* Randomize a float value between 0.0 (inclusive) and the
* specified value (inclusive or exclusive as required).
*
* @param inclusive Whether or not, the returned value should include the
* given one.
*/
public float nextFloat(float f, boolean inclusive) {
if (f <= 0.0F) {
throw new IllegalArgumentException("f must be greater than 0!");
}

// Randomize a float
float rand = super.nextFloat();

// If the returned value should not include the given one,
// make sure that the randomized float is not exactly 1.0
if (! inclusive) {
while (rand == 1.0F) {
rand = super.nextFloat();
}
}

return (rand * f);
}

/**
* Randomize a float value in the given range [min, max].
*/
public float nextFloat(float min, float max) {
if (min > max) {
throw new IllegalArgumentException(
MIN_MAX);
}

return (min + nextFloat(max – min, true));
}

/* — Double-related Methods — */

/**
* Randomize a double value between 0.0 (inclusive) and the
* specified value (exclusive).
*/
public double nextDouble(double d) {
return nextDouble(d, false);
}

/**
* Randomize a double value between 0.0 (inclusive) and the
* specified value (inclusive or exclusive as required).
*
* @param inclusive Whether or not, the returned value should include the
* given one.
*/
public double nextDouble(double d, boolean inclusive) {
if (d <= 0.0D) {
throw new IllegalArgumentException("d must be greater than 0!");
}

// Randomize a double
double rand = super.nextDouble();

// If the returned value should not include the given one,
// make sure that the randomized float is not exactly 1.0
if (! inclusive) {
while (rand == 1.0D) {
rand = super.nextDouble();
}
}

return (rand * d);
}

/* — Collections-related Methods — */

/**
* Picks a random element from the given Collection.
*/
public T pickRandom(Collection c) {
int elementIndex = super.nextInt(c.size());

Iterator iter = c.iterator();
for (int i = 0; i < elementIndex; ++i) {
iter.next();
}

return iter.next();
}

/**
* Picks a random element, which matches the provided
* JiperRandomQualifier, from the given
* Collection.
*
* @param c The Collection to pick an element from.
* @param qualifier The Qualifier the picked element has to
* match.
*
* @return A random, qualified element from the
* Collection.
*/
public T pickRandom(Collection c, JiperRandomQualifier qualifier) {
T returnValue = null;
do {
int elementIndex = super.nextInt(c.size());

Iterator iter = c.iterator();
for (int i = 0; i < elementIndex; ++i) {
iter.next();
}

returnValue = iter.next();
} while (! qualifier.matches(returnValue));

return returnValue;
}

/* — Array-related Methods — */

/**
* Picks a random element from the given array.
*/
public T pickRandom(T[] o) {
return pickRandom(Arrays.asList(o));
}

/**
* Picks a random element, which matches the provided
* JiperRandomQualifier, from the given array.
*
* @param o The array to pick an element from.
* @param qualifier The Qualifier the picked element has
* to match.
*
* @return A random, qualified element from the
* Collection.
*/
public T pickRandom(T[] o, JiperRandomQualifier qualifier) {
return pickRandom(Arrays.asList(o), qualifier);
}

/* — String-related Methods — */

/**
* Randomize a String.
*
* @param length The requested length of the string.
* @param printable Whether or not, the string should contain only
* printable characters.
*/
public String nextString(int length, boolean printable) {
if (printable) {
byte[] data = new byte[length];

for (int i = 0; i < length; ++i) {
data[i] = (byte) nextInt(
FIRST_PRINTABLE_CHAR,
LAST_PRINTABLE_CHAR);
}

return new String(data);

}
return new String(nextBytes(length));
}

/**
* Randomize a String that adheres to the given
* {@link JiperRandomQualifier.util.JiperRandomQualifier}
*
* @param length The requested length of the string.
* @param printable Whether or not, the string should contain only
* printable characters.
* @param qualifier The JiperRandomQualifier the return value
* must adhere to
* @return A random value that adheres to qualifier
*/
public String nextString
(int length, boolean printable, JiperRandomQualifier qualifier) {
String returnVal;

do {
returnVal = nextString(length, printable);
} while (!qualifier.matches(returnVal));

return returnVal;
}

/**
* Randomize a valid numeric string.
*
* @param length The requested length of the string.
*/
public String nextNumericString(int length) {
return Long.toString(nextLong(
(long) Math.pow(10, length – 1), (long) (Math.pow(10, length) – 1)));
}

/**
* Randomize a valid XML Element name.
*
* @param length The requested length of the string.
*/
public String nextXmlString(int length) {
byte[] data = new byte[length];
for (int i = 0; i < length; ++i) {
data[i] = (byte) nextInt(
FIRST_XML_PRINTABLE_CHAR,
LAST_XML_PRINTABLE_CHAR);
}

return new String(data);
}

/**
* Randomize a valid XML Element name.
*
* @param length The requested length of the string.
* @param qualifier The JiperRandomQualifier the return value
* must adhere to
*/
public String nextXmlString(int length, JiperRandomQualifier qualifier) {
String returnVal;

do {
returnVal = nextXmlString(length);
} while (!qualifier.matches(returnVal));

return returnVal;
}

/**
* Randomize a printeable String.
*
* @param length The requested length of the string.
*/
public String nextString(int length) {
return nextString(length, true);
}

/**
* Randomize a String that adheres to the given
* {@link JiperRandomQualifier.util.JiperRandomQualifier}
*
* @param length The requested length of the string.
* @param qualifier The JiperRandomQualifier the return value
* must adhere to
* @return A random value that adheres to qualifier
*/
public String nextString(int length, JiperRandomQualifier qualifier) {
return nextString(length, true, qualifier);
}

/**
* Randomize a String of a length in the
* given range [min, max].
*
* @param printable Whether or not, the string should contain only
* printable characters.
*/
public String nextString(int min, int max, boolean printable) {
return nextString(nextInt(min, max), printable);
}

/**
* Randomize a String that adheres to the given
* {@link JiperRandomQualifier.util.JiperRandomQualifier} of a length in the
* given range [min, max]
*
* @param length The requested length of the string.
* @param printable Whether or not, the string should contain only
* printable characters.
* @param qualifier The JiperRandomQualifier the return value
* must adhere to
* @return A random value that adheres to qualifier
*/
public String nextString
(int min, int max, boolean printable, JiperRandomQualifier qualifier) {
String returnVal;

do {
returnVal = nextString(min, max, printable);
} while (!qualifier.matches(returnVal));

return returnVal;
}

/**
* Randomize a printable String of a length in the
* given range [min, max].
*/
public String nextString(int min, int max) {
return nextString(nextInt(min, max), true);
}

/**
* Randomize a String that adheres to the given
* {@link JiperRandomQualifier.util.JiperRandomQualifier} of a length in the
* given range [min, max]
*
* @param length The requested length of the string.
* @param qualifier The JiperRandomQualifier the return value
* must adhere to
* @return A random value that adheres to qualifier
*/
public String nextString(int min, int max, JiperRandomQualifier qualifier) {
return nextString(min, max, true, qualifier);
}

/* — General Utility Methods — */

/**
* Creates a byte array of the specified size,
* initialized with random values.
*/
public byte[] nextBytes(int size) {
byte[] data = new byte[size];
nextBytes(data);
return data;
}

/* — Big Integer related methods — */

/**
* generates a new big integer with the desired number of bits
* the generated number will always be positive.
* @param numOfBits the number of bits of the Big Integer
* @return the randomized big integer.
*/
public BigInteger nextBigInt(int numOfBits) {
return new BigInteger(numOfBits, this);
}

/**
* Returns a random value from an enum.
*
* @param The enum type.
* @param enumClass The enum class to randomize.
*
* @return A random enum from the given enum, or null if got null.
*/
@SuppressWarnings(“unchecked”)
public T nextEnum(Class enumClass) {
if (enumClass == null) {
return null;
}

return pickRandom(enumClass.getEnumConstants());
}

/* — Private Methods and Fields — */

/**
* Constructs the object.
*/
private JiperRandom() {
}

/**
* Constructs the object with the given random seed.
*/
private JiperRandom(long seed) {
super(seed);
}

/** The single(ton) instance. */
private static JiperRandom instance;

/** The seed that was last set. */
private long seed;

/** The first printable character. */
private static final char FIRST_PRINTABLE_CHAR = ‘ ‘;

/** The last printable character. */
private static final char LAST_PRINTABLE_CHAR = ‘~’;

/** The first XML printable character. */
private static final char FIRST_XML_PRINTABLE_CHAR = ‘A’;

/** The last XML printable character. */
private static final char LAST_XML_PRINTABLE_CHAR = ‘Z’;
}

Posted in Java | Tagged , , , | Leave a comment

Useful Eclipse templates

These are some templates I use in eclipse for the auto-completion (Ctrl+Space):

Section comments:

General section comment (sec):


/* --- ${comment} --- */
${cursor}

Section comment for constants (secconstants):


/* --- Constants --- */
 ${cursor}

Section comment for constructors (secctors):


/* --- Constructors --- */
${cursor}

Section comment for class fields (secfields):


/* --- Class Fields --- */
 ${cursor}

Section comment for class getters & setters (secgettersetters):


/* --- Getters & Setters --- */
 ${cursor}

Section comment for helper methods (sechelpers):


/* --- Helper Methods --- */
 ${cursor}

Section comment for implemented methods (secimplemented):

/* --- Implemented methods of ${interface} --- */
${cursor}

Section comment for mocks (secmocks):


/* --- Mocks (isolating the tested class) --- */
${cursor}

Section comment for test setup (secsetup):


/* --- Set up for tests --- */
${cursor}

Section comment for tests (sectest):


/* --- Tests for ${testedFunctionality} --- */
${cursor}

Test related templates:

JUnit 4 setUp method (Setup):


/* --- Set up for tests --- */

@${testType:newType(org.junit.Before)}
public void setUp() throws Exception {
    ${cursor}
}

Junit4 + Mockito setup method (SetupMockito):


/* --- Set up for tests --- */

@${testType:newType(org.junit.Before)}
public void setUp() throws Exception {
    ${mockito:newType(org.mockito.MockitoAnnotations)}.initMocks(this);
    ${testedInstance:field} = new ${testedClass:argType(testedInstance, 0)}();
    ${testedInstance}.set${mockedClass};
    // ${todo}: Set the other mocks into the tested instance.${cursor}
}

Create a new Mockito argument captor for a given class (captor):


@${captorAnnotation:newType(Captor)}
private ${argCaptor:newType(ArgumentCaptor)}<${captured:link}> ${cursor}${captured}Captor;

Assert the value inside a captor (assertCaptor):


${:importStatic(Assert)}assertEquals(${expected}, ${captor:var(ArgumentCaptor)}.getValue().get${property});${cursor}

And here’s an export of the aforementioned templates to a single xml file (+ some specific ones for randomness which I might edit).

<?xml version="1.0" encoding="UTF-8" standalone="no"?><templates><template autoinsert="true" context="java" deleted="false" description="Assert the value inside a captor" enabled="true" name="assertCaptor">${:importStatic(Assert)}assertEquals(${expected}, ${captor:var(ArgumentCaptor)}.getValue().get${property});${cursor}</template><template autoinsert="true" context="java" deleted="false" description="Create a new argument captor for a given class" enabled="true" name="captor">@${captorAnnotation:newType(Captor)}

private ${argCaptor:newType(ArgumentCaptor)}&lt;${captured:link}&gt; ${cursor}${captured}Captor;

</template><template autoinsert="true" context="java" deleted="false" description="Put in a viper random field." enabled="true" name="randomField">/**

 * Random generator.

 */

private ${randomGen:newType(ViperRandom)} random = ViperRandom.instance();

${cursor}</template><template autoinsert="true" context="java" deleted="false" description="Random.nextBoolean()" enabled="true" name="rnb">${random:var(com.muzicall.commons.random.ViperRandom, java.util.Random)}.nextBoolean()${cursor}</template><template autoinsert="true" context="java" deleted="false" description="Random.nextEnum()" enabled="true" name="rne">${random:var(ViperRandom)}.nextEnum(${enumClass})${cursor}</template><template autoinsert="true" context="java" deleted="false" description="Random.nextLong()" enabled="true" name="rnl">${random:var(ViperRandom, Random)}.nextLong(${:link})${cursor}</template><template autoinsert="true" context="java" deleted="false" description="Random.nextString()" enabled="true" name="rns">${random:var(ViperRandom)}.nextString(${10:link})${cursor}</template><template autoinsert="true" context="java" deleted="false" description="Section comment" enabled="true" name="sec">/* --- ${comment} --- */

${cursor}</template><template autoinsert="true" context="java" deleted="false" description="Section comment for constants" enabled="true" name="secconstants">



/* --- Constants --- */

${cursor}</template><template autoinsert="true" context="java" deleted="false" description="Section comment for class constructors" enabled="true" name="secctors">



/* --- Constructors --- */

${cursor}</template><template autoinsert="true" context="java" deleted="false" description="Section comment for class fields" enabled="true" name="secfields">



/* --- Class Fields --- */

${cursor}</template><template autoinsert="true" context="java" deleted="false" description="Section comment for class getters &amp; setters" enabled="true" name="secgettersetters">



/* --- Getters &amp; Setters --- */

${cursor}</template><template autoinsert="true" context="java" deleted="false" description="Section comment for helper methods" enabled="true" name="sechelpers">



/* --- Helper Methods --- */

${cursor}</template><template autoinsert="true" context="java" deleted="false" description="Section comment for implemented methods" enabled="true" name="secimplemented">



/* --- Implemented methods of ${interface} --- */

${cursor}</template><template autoinsert="true" context="java" deleted="false" description="Section comment for mocks" enabled="true" name="secmocks">/* --- Mocks (isolating the tested class) --- */

${cursor}</template><template autoinsert="true" context="java" deleted="false" description="Section comment for overriding methods" enabled="true" name="secoverride">/* --- Override methods from ${superClass} --- */

${cursor}</template><template autoinsert="true" context="java" deleted="false" description="Section comment for setup" enabled="true" name="secsetup">/* --- Set up for tests --- */

${cursor}</template><template autoinsert="true" context="java" deleted="false" description="Section comment for tests" enabled="true" name="sectest">/* --- Tests for ${TESTED_FUNCTIONALITY} --- */

${cursor}</template><template autoinsert="true" context="java" deleted="false" description="set pointcut (AspectJ)" enabled="true" name="set">set(${modifier_pattern} ${ret_type_pattern} ${type_pattern}.${id_pattern})</template><template autoinsert="true" context="java" deleted="false" description="JUnit 4 setUp method" enabled="true" name="Setup">/* --- Set up for tests --- */



@${testType:newType(org.junit.Before)}

public void setUp() throws Exception {

 ${cursor}

}</template><template autoinsert="true" context="java" deleted="false" description="Junit4 + Mockito setup method" enabled="true" name="SetupMockito">/* --- Set up for tests --- */



@${testType:newType(org.junit.Before)}

public void setUp() throws Exception {

 ${mockito:newType(org.mockito.MockitoAnnotations)}.initMocks(this);

 ${testedInstance:field} = new ${testedClass:argType(testedInstance, 0)}();

 ${testedInstance}.set${mockedClass};

 // ${todo}: Set the other mocks into the tested instance.${cursor}

}</template></templates>
<pre>

Fun!

Posted in Java | Tagged , , | Leave a comment