Thursday, July 17, 2014

Retro Dude Review: Pitfall

Hello everyone! Shall we play a game?

This time we're gonna take a closer look on a classic atari 2600 game better known as Pitfall or Pitfall Harry's Jungle Adventure.

The year was 1982 and the gaming industri was booming. An arcade on every corner and Starcade on the T.V. not a bad year to be a gamer at all. Atari was making the big bucks but failed to give credit where credit was due and because of that Activision was born. But thats enough brief history for now.

Pitfall made by brilliant designer David Crane who is also responsible for such titles as Dragster, Freeway, Laser Blast and many others, is an adventure game where you take the role as Harry. Your task is to find the 32 treasures of the jungle within 20 minutes while avoiding pits, lakes, crokodiles, snakes, huge scorpions, rolling logs everywhere and much more. The game ends when all the treasure is found, your time is up or when you have used up all your lives. The game itself contains 255 trees all of wich Harry will pass on his journey making the game a cirkular maze. That basicly means when you have finished the end screen the first screen reappears. Now while the graphics might not seem like much today back in that time it must have been impressive I'm sure. The sounds are typical Atari and it's the first game I have ever encountered with no music. There is only sound while you jump, die or run into logs and it makes the game at first glance seem rather boring (But I guess it beats the Astroids soundtrack) The gameplay on the other hand is very nice. Its smooth controlling all the way but its still hard as *!#@ Trust me on this one when you try jumping over a crokodile pit your accuracy and precision has to be perfect, and I do mean perfect if you're just a split second off you are dead. Then we got these almost trap like pits that just apears out of nowhere on the ground and they will lure you into sweet, sweet game over, right until you're ready to explode of pure agony! But once you get the hang of it the only real trick is to collect all the treasure before the timer runs out. So far after countless tries im still missing 2 (But hey im no expert)



Pitfall is all in all a very decent game compared to alot of other games that came out in that time period, the graphics and gameplay is nice and its almost addictive when you decide on getting all 32 treasures, and its one of the few atari games with an actual end goal, not just scoring points for all eternity. The commercial even had a very young Jack Black (that  at the time might not have meant that much but today its pretty damn cool) So all in all if I had to rate it I would say its an 8/10 due to the missing soundtrack.

 

Thats all for my first review this is the Retro Dude saying goodbye and I do hope you get a chance on playing an instant classic!

Sunday, July 6, 2014

Learning java selenium webdriver

Today, we are going to something different, we explore software test technology. As end user, we are mostly dealing with point and click, and with this article, we are going to learn how to test user interface.

There are many testing software out there, just google and you find plenty. In this article, we are going to use Java Selenium webdriver. To quickly start, you will have to complete these bullet points. For complete information of selenium, read here.

or additional optional download at http://docs.seleniumhq.org/download/



Let's see continue this article with two example.
import java.util.List;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;

public class GoogleSuggest {

public static void main(String[] args) throws Exception {
// The Firefox driver supports javascript
WebDriver driver = new FirefoxDriver();

// Go to the Google Suggest home page
driver.get("http://www.google.com/webhp?complete=1&hl=en");

// Enter the query string "Cheese"
WebElement query = driver.findElement(By.name("q"));
query.sendKeys("Cheese");

// Sleep until the div we want is visible or 5 seconds is over
long end = System.currentTimeMillis() + 5000;
while (System.currentTimeMillis() < end) {
WebElement resultsDiv = driver.findElement(By.className("gssb_e"));

// If results have been returned, the results are displayed in a drop down.
if (resultsDiv.isDisplayed()) {
break;
}
}

// And now list the suggestions
List<WebElement> allSuggestions = driver.findElements(By.xpath("//td[@class='gssb_a gbqfsf']"));

for (WebElement suggestion : allSuggestions) {
System.out.println("suggestion => " + suggestion.getText());
}

driver.quit();
}

}

import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;

import com.thoughtworks.selenium.SeleneseTestBase;
import com.thoughtworks.selenium.webdriven.WebDriverBackedSelenium;

public class BaseSeleniumTest extends SeleneseTestBase {

@Before
public void setUp() throws Exception {
WebDriver driver1 = new FirefoxDriver();
String baseUrl = "http://google.com/";
selenium = new WebDriverBackedSelenium(driver1, baseUrl);
}

@Test
public void testGoogle() throws Exception {
selenium.open("http://google.com/");
System.out.println(selenium.getTitle());
assertEquals("Google", selenium.getTitle());
selenium.close();
}
}

The first example construct a FireFox WebDriver. Load google url and mimic a typing by sending a keys of Cheese to the query. When Web Element resultsDiv is displayed, then all the suggestion get printed.

The second example is much easier to construct test. By extending SeleneseTestBase, you can use the object selenium and start to call the rich methods it provides for your sub test class. As seem here, similar to the first example, the test started with construction of FirefoxDriver. Then the very familiar junit test, open up google link, assert that the title is Google and then close the selenium object.

That's it for this article, I hope it help you get started. Remember to donate us if you would like to contribute back.

Saturday, July 5, 2014

Study MongoDB GridFS with java example

In the past, we have learned basic MongoDB and study data model, in this article , we will study MongoDB GridFS by storing a file into MongoDB. Below is the java simple application to show how to store, retrieve, and delete eventually.
import java.io.File;
import java.io.IOException;

import com.mongodb.DB;
import com.mongodb.DBCursor;
import com.mongodb.Mongo;
import com.mongodb.MongoException;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSDBFile;
import com.mongodb.gridfs.GridFSInputFile;

public class LearnMongo {

public static void main(String[] args) throws MongoException, IOException {
Mongo mongo = new Mongo("192.168.0.2", 27017);
DB db = mongo.getDB("mp3db");

// save image
String newFilename = "django.mp3";
File mp3File = new File("src/resources/django.mp3");
GridFS gfsMp3 = new GridFS(db, "mp3");
GridFSInputFile gfsFile = gfsMp3.createFile(mp3File);
gfsFile.setFilename(newFilename);
gfsFile.setContentType("audio/mpeg");
System.out.println(gfsFile.toString());
gfsFile.save();

// get mp3
GridFSDBFile imageForOutput = gfsMp3.findOne(newFilename);
System.out.println(imageForOutput);

// print image
DBCursor cursor = gfsMp3.getFileList();
while (cursor.hasNext()) {
System.out.println(cursor.next());
}

// save into another image
imageForOutput.writeTo("/home/jason/Desktop/newsong.mp3");

// delete image
gfsMp3.remove(gfsMp3.findOne(newFilename));

}

}

We start by connecting to the server, so with this example MongoDB instance running on server 192.168.0.2 on port 27017. You may want to check the configuration for MongoDB if you connect remotely as the default MongoDB configuration only listen to localhost.

Then we form a MongoDB DB object on mp3db. You can store other object as well but for this example, I'm going to store a mp3. With this ready, we are going to store the mp3. The important piece of code is probably below.
GridFS gfsMp3 = new GridFS(db, "mp3");
GridFSInputFile gfsFile = gfsMp3.createFile(mp3File);

Instantiate two object, GrisFS and GridFSInputFile. You can set additional information like filename, content type. Calling GridFSInputFile.save() will save the object into MongoDB. If you have access to MongoDB cli, command such as > db.mp3.files.find(); will shown below the output.
{ "_id" : ObjectId("53ad60f944aeaca83109d253"), "chunkSize" : NumberLong(262144), "length" : NumberLong(316773), "md5" : "7293e9fd795e2bb6d5035e5b69cb2923", "filename" : "django.mp3", "contentType" : "audio/mpeg", "uploadDate" : ISODate("2014-06-27T12:18:01.934Z"), "aliases" : null }

To find the mp3, you can use the code, GridFSDBFile imageForOutput = gfsMp3.findOne(newFilename); below is the output.
{ "_id" : { "$oid" : "53ad60f944aeaca83109d253"} , "chunkSize" : 262144 , "length" : 316773 , "md5" : "7293e9fd795e2bb6d5035e5b69cb2923" , "filename" : "django.mp3" , "contentType" : "audio/mpeg" , "uploadDate" : { "$date" : "2014-06-27T12:18:01Z"} , "aliases" : null }

You can also use GridFS.getFileList(); to retrieve all the files currently store on this database. The code continue on writing the object into a file. As you can see, I'm writing to desktop just to ensure it is not from the source.

I end this article by removing the object in the MongoDB database.

Friday, July 4, 2014

Study MongoDB data models

Today we are going to learn on MongoDB Data Models.

It is important to study data modal is because as a developer, you would want to leverage what MongoDB is excel at and aware what it is not suitable for.

You can basically store a few document and reference then using and id field.
But remember this need two round trip back and forth from the application servers
to the mongo database.

As such, in this scenario if it better to embed the document into a document.
user document
{
_id: <ObjectId1>, <-------------+
username : "jasonwee" |
} |
|
contact document |
{ |
_id: <ObjectId2>, |
user_id: <ObjectId1> <-------------+
phone: "012-3456789"
}

into
user document
{
_id: <ObjectId1>,
contact : {
phone: "012-3456789"
}
}

This modelling guarantee you atomicity of a document as mongodb write operations
are atomic at document level.

Indexes

Use indexes to improve performance for common queries. Build indexes on fields that appear often in queries and for all operations that return sorted results. MongoDB automatically creates a unique index on the _id field.

Each index requires at least 8KB of data space.

GridFS

GridFS is a specification for storing and retrieving files that exceed the BSON-document size limit of 16MB.

Model Relationships Between Documents

  • Model One-to-One Relationships with Embedded Documents
    Presents a data model that uses embedded documents to describe one-to-one relationships between connected data.

  • Model One-to-Many Relationships with Embedded Documents
    Presents a data model that uses embedded documents to describe one-to-many relationships between connected data.

  • Model One-to-Many Relationships with Document References
    Presents a data model that uses references to describe one-to-many relationships between documents.


Model Tree Structures

MongoDB allows various ways to use tree data structures to model large hierarchical or nested data relationships.

  • Model Tree Structures with Parent References 
    Presents a data model that organizes documents in a tree-like structure by storing references to “parent” nodes in “child” nodes.

  • Model Tree Structures with Child References
    Presents a data model that organizes documents in a tree-like structure by storing references to “child” nodes in “parent” nodes.

  • Model Tree Structures with an Array of Ancestors
    Presents a data model that organizes documents in a tree-like structure by storing references to “parent” nodes and an array that stores all ancestors.

  • Model Tree Structures with Materialized Paths
    Presents a data model that organizes documents in a tree-like structure by storing full relationship paths between documents. In addition to the tree node, each document stores the _id of the nodes ancestors or path as a string.

  • Model Tree Structures with Nested Sets
    Presents a data model that organizes documents in a tree-like structure using the Nested Sets pattern. This optimizes discovering subtrees at the expense of tree mutability.

Sunday, June 22, 2014

Learning basic MongoDB by installing and using CRUD

Today, we are going to learn MongoDB, including understand what is MongoDB, installation and doing CRUD operation. We start with the basic question.

what is MongoDB?

MongoDB (from "humongous") is a cross-platform document-oriented database. Classified as a NoSQL database, MongoDB eschews the traditional table-based relational database structure in favor of JSON-like documents with dynamic schemas (MongoDB calls the format BSON), making the integration of data in certain types of applications easier and faster.

With that said, let's move on to install MongoDB. There are many ways to install MongoDB but with this article, the one I'm chosen is to install MongoDB using deb package built by MongoDB. Even though MongoDB comes with ubuntu however the version in the repository is just too old. Current in the ubuntu repository, mongodb version is 1:2.4.9-1ubuntu2 and meanwhile official production release version is 2.6.1.

The instructions below are from http://docs.mongodb.org/manual/tutorial/install-mongodb-on-ubuntu/ . But I summarize into one liner. You will add a new MongoDB repository from official database site and install latest version.
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10 && echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list && sudo apt-get update && sudo apt-get install mongodb-org

If everything goes well, you should get a similar output installation MongoDB such as below:
jason@localhost:~$ sudo apt-get install mongodb-org
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages were automatically installed and are no longer required:
jhead libcec2 libgdata-google1.2-1 libgdata1.2-1 libjdependency-java liblockdev1 libmaven-archiver-java libmaven-clean-plugin-java
libmaven-compiler-plugin-java libmaven-dependency-tree-java libmaven-filtering-java libmaven-install-plugin-java libmaven-jar-plugin-java
libmaven-resources-plugin-java libmaven-shade-plugin-java libphp-adodb libpigment0.3-11 libplexus-compiler-java libplexus-digest-java oxideqt-codecs-extra
php-auth-sasl php-cache php-date php-file php-http-request php-log php-mail php-mail-mime php-mdb2 php-mdb2-driver-mysql php-net-dime php-net-ftp
php-net-smtp php-net-socket php-net-url php-services-weather php-soap php-xml-parser php-xml-serializer printer-driver-c2esp printer-driver-min12xxw
printer-driver-pnm2ppa printer-driver-pxljr python-axiom python-coherence python-configobj python-epsilon python-gpod python-louie python-nevow python-pgm
python-pyasn1 python-storm python-tagpy python-twill python-twisted-conch python-twisted-web2 qtdeclarative5-window-plugin tinymce2 xbmc-pvr-argustv
xbmc-pvr-dvbviewer xbmc-pvr-mediaportal-tvserver xbmc-pvr-mythtv-cmyth xbmc-pvr-nextpvr xbmc-pvr-njoy xbmc-pvr-tvheadend-hts xbmc-pvr-vdr-vnsi
xbmc-pvr-vuplus xdg-user-dirs-gtk
Use 'apt-get autoremove' to remove them.
The following extra packages will be installed:
mongodb-org-mongos mongodb-org-server mongodb-org-shell mongodb-org-tools
The following NEW packages will be installed:
mongodb-org mongodb-org-mongos mongodb-org-server mongodb-org-shell mongodb-org-tools
0 upgraded, 5 newly installed, 0 to remove and 51 not upgraded.
Need to get 113 MB of archives.
After this operation, 284 MB of additional disk space will be used.
Do you want to continue? [Y/n] Y
Get:1 http://downloads-distro.mongodb.org/repo/ubuntu-upstart/ dist/10gen mongodb-org-shell i386 2.6.1 [4,389 kB]
Get:2 http://downloads-distro.mongodb.org/repo/ubuntu-upstart/ dist/10gen mongodb-org-server i386 2.6.1 [9,308 kB]
Get:3 http://downloads-distro.mongodb.org/repo/ubuntu-upstart/ dist/10gen mongodb-org-mongos i386 2.6.1 [7,045 kB]
Get:4 http://downloads-distro.mongodb.org/repo/ubuntu-upstart/ dist/10gen mongodb-org-tools i386 2.6.1 [92.3 MB]
Get:5 http://downloads-distro.mongodb.org/repo/ubuntu-upstart/ dist/10gen mongodb-org i386 2.6.1 [3,652 B]
Fetched 113 MB in 3min 25s (549 kB/s)
Selecting previously unselected package mongodb-org-shell.
(Reading database ... 564794 files and directories currently installed.)
Preparing to unpack .../mongodb-org-shell_2.6.1_i386.deb ...
Unpacking mongodb-org-shell (2.6.1) ...
Selecting previously unselected package mongodb-org-server.
Preparing to unpack .../mongodb-org-server_2.6.1_i386.deb ...
Unpacking mongodb-org-server (2.6.1) ...
Selecting previously unselected package mongodb-org-mongos.
Preparing to unpack .../mongodb-org-mongos_2.6.1_i386.deb ...
Unpacking mongodb-org-mongos (2.6.1) ...
Selecting previously unselected package mongodb-org-tools.
Preparing to unpack .../mongodb-org-tools_2.6.1_i386.deb ...
Unpacking mongodb-org-tools (2.6.1) ...
Selecting previously unselected package mongodb-org.
Preparing to unpack .../mongodb-org_2.6.1_i386.deb ...
Unpacking mongodb-org (2.6.1) ...
Processing triggers for man-db (2.6.7.1-1) ...
Processing triggers for ureadahead (0.100.0-16) ...
Setting up mongodb-org-shell (2.6.1) ...
Setting up mongodb-org-server (2.6.1) ...
Adding system user `mongodb' (UID 143) ...
Adding new user `mongodb' (UID 143) with group `nogroup' ...
Not creating home directory `/home/mongodb'.
Adding group `mongodb' (GID 155) ...
Done.
Adding user `mongodb' to group `mongodb' ...
Adding user mongodb to group mongodb
Done.
mongod start/running, process 22386
Setting up mongodb-org-mongos (2.6.1) ...
Setting up mongodb-org-tools (2.6.1) ...
Processing triggers for ureadahead (0.100.0-16) ...
Setting up mongodb-org (2.6.1) ...

Looks like installation processed is done and fine. Even it is already started. So now let's play using mongo db command line.
jason@localhost:~$ mongo
MongoDB shell version: 2.6.1
connecting to: test
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
http://docs.mongodb.org/
Questions? Try the support group
http://groups.google.com/group/mongodb-user
Server has startup warnings:
2014-06-02T22:29:43.933+0800 [initandlisten]
2014-06-02T22:29:43.933+0800 [initandlisten] ** NOTE: This is a 32 bit MongoDB binary.
2014-06-02T22:29:43.933+0800 [initandlisten] ** 32 bit builds are limited to less than 2GB of data (or less with --journal).
2014-06-02T22:29:43.933+0800 [initandlisten] ** Note that journaling defaults to off for 32 bit and is currently off.
2014-06-02T22:29:43.933+0800 [initandlisten] ** See http://dochub.mongodb.org/core/32bit
2014-06-02T22:29:43.934+0800 [initandlisten]
>

As you can see, I'm running 32bit cpu, but it should work fine for 64bit cpu and the rest of this article. So everything has been smooth sailing so far, we will start to create, read, update and delete operation.

  • create




To create or insert a document, it is as easy as
db.inventory.insert( { _id: 10, type: "misc", item: "card", qty: 15 } )

More insert example
db.inventory.update(
{ type: "book", item : "journal" },
{ $set : { qty: 10 } },
{ upsert : true }
)

Interesting insert using save
db.inventory.save( { type: "book", item: "notebook", qty: 40 } )



  • read




to read or query document, it is as easy as
db.inventory.update(
{ type: "book", item : "journal" },
{ $set : { qty: 10 } },
{ upsert : true }
)

read more example here.




  • update


see create above for example.


  • delete




to remove all documents,
db.inventory.remove({})


That's it for this lengthy introduction.

Saturday, June 21, 2014

measure java object size using jamm

Often when you develop a java application, you want to measure how big the object occupied in the heap. There are many available tool, such as the SizeOf.jar but today we will take a look at jbellis/jamm. What is Jamm? Jamm provides MemoryMeter, a java agent to measure actual object memory use including JVM overhead.

It is very easy to use, get the source and build the jar. Below is the output of building jar .
jason@localhost:~/codes/jamm$ ant jar
Buildfile: /home/jason/codes/jamm/build.xml

ivy-download:
[echo] Downloading Ivy...
[mkdir] Created dir: /home/jason/codes/jamm/target
[get] Getting: http://repo2.maven.org/maven2/org/apache/ivy/ivy/2.1.0/ivy-2.1.0.jar
[get] To: /home/jason/codes/jamm/target/ivy-2.1.0.jar

ivy-init:
[mkdir] Created dir: /home/jason/codes/jamm/target/lib

ivy-retrieve-build:
[ivy:retrieve] :: Ivy 2.1.0 - 20090925235825 :: http://ant.apache.org/ivy/ ::
[ivy:retrieve] :: loading settings :: url = jar:file:/home/jason/codes/jamm/target/ivy-2.1.0.jar!/org/apache/ivy/core/settings/ivysettings.xml
[ivy:retrieve] :: resolving dependencies :: jamm#jamm;working@debby.e2e.serveftp.net
[ivy:retrieve] confs: [default]
[ivy:retrieve] found junit#junit;4.11 in public
[ivy:retrieve] found org.hamcrest#hamcrest-core;1.3 in public
[ivy:retrieve] downloading http://repo1.maven.org/maven2/junit/junit/4.11/junit-4.11-javadoc.jar ...
[ivy:retrieve] .................................................................................................................................................................................................................. (370kB)
[ivy:retrieve] .. (0kB)
[ivy:retrieve] [SUCCESSFUL ] junit#junit;4.11!junit.jar(javadoc) (2772ms)
[ivy:retrieve] downloading http://repo1.maven.org/maven2/junit/junit/4.11/junit-4.11.jar ...
[ivy:retrieve] ........................................................................................................................................... (239kB)
[ivy:retrieve] .. (0kB)
[ivy:retrieve] [SUCCESSFUL ] junit#junit;4.11!junit.jar (1725ms)
[ivy:retrieve] downloading http://repo1.maven.org/maven2/junit/junit/4.11/junit-4.11-sources.jar ...
[ivy:retrieve] ................................................................................................. (147kB)
[ivy:retrieve] .. (0kB)
[ivy:retrieve] [SUCCESSFUL ] junit#junit;4.11!junit.jar(source) (1403ms)
[ivy:retrieve] downloading http://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar ...
[ivy:retrieve] ........................... (43kB)
[ivy:retrieve] .. (0kB)
[ivy:retrieve] [SUCCESSFUL ] org.hamcrest#hamcrest-core;1.3!hamcrest-core.jar (1363ms)
[ivy:retrieve] :: resolution report :: resolve 9107ms :: artifacts dl 7338ms
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| default | 2 | 2 | 2 | 0 || 4 | 4 |
---------------------------------------------------------------------
[ivy:retrieve] :: retrieving :: jamm#jamm [sync]
[ivy:retrieve] confs: [default]
[ivy:retrieve] 3 artifacts copied, 0 already retrieved (431kB/40ms)

init:
[mkdir] Created dir: /home/jason/codes/jamm/target/classes
[mkdir] Created dir: /home/jason/codes/jamm/target/test/classes

build:
[echo] jamm: /home/jason/codes/jamm/build.xml
[javac] Compiling 3 source files to /home/jason/codes/jamm/target/classes
[javac] Note: /home/jason/codes/jamm/src/org/github/jamm/AlwaysEmptySet.java uses unchecked or unsafe operations.
[javac] Note: Recompile with -Xlint:unchecked for details.

jar:
[jar] Building jar: /home/jason/codes/jamm/target/jamm-0.2.7-SNAPSHOT.jar

BUILD SUCCESSFUL
Total time: 26 seconds

The jar is found in target/jamm-0.2.7-SNAPSHOT.jar . You can start testing the built jar using ant test. Below is the output.
jason@localhost:~/codes/jamm$ ant test
Buildfile: /home/jason/codes/jamm/build.xml

ivy-download:

ivy-init:

ivy-retrieve-build:
[ivy:retrieve] :: Ivy 2.1.0 - 20090925235825 :: http://ant.apache.org/ivy/ ::
[ivy:retrieve] :: loading settings :: url = jar:file:/home/jason/codes/jamm/target/ivy-2.1.0.jar!/org/apache/ivy/core/settings/ivysettings.xml
[ivy:retrieve] :: resolving dependencies :: jamm#jamm;working@debby.e2e.serveftp.net
[ivy:retrieve] confs: [default]
[ivy:retrieve] found junit#junit;4.11 in public
[ivy:retrieve] found org.hamcrest#hamcrest-core;1.3 in public
[ivy:retrieve] :: resolution report :: resolve 266ms :: artifacts dl 23ms
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| default | 2 | 0 | 0 | 0 || 4 | 0 |
---------------------------------------------------------------------
[ivy:retrieve] :: retrieving :: jamm#jamm [sync]
[ivy:retrieve] confs: [default]
[ivy:retrieve] 0 artifacts copied, 3 already retrieved (0kB/18ms)

init:

build:
[echo] jamm: /home/jason/codes/jamm/build.xml

jar:

build-test:
[javac] Compiling 2 source files to /home/jason/codes/jamm/target/test/classes
[javac] Note: /home/jason/codes/jamm/test/org/github/jamm/MemoryMeterTest.java uses or overrides a deprecated API.
[javac] Note: Recompile with -Xlint:deprecation for details.
[javac] Note: /home/jason/codes/jamm/test/org/github/jamm/MemoryMeterTest.java uses unchecked or unsafe operations.
[javac] Note: Recompile with -Xlint:unchecked for details.

checkos:

test-mac:

test:
[echo] running tests
[mkdir] Created dir: /home/jason/codes/jamm/target/test/output
[echo] Testing with default Java
[junit] Testsuite: org.github.jamm.GuessTest
[junit] Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 5.869 sec
[junit]
[junit] Testsuite: org.github.jamm.MemoryMeterTest
[junit] Tests run: 13, Failures: 0, Errors: 0, Skipped: 3, Time elapsed: 0.813 sec
[junit]
[junit] Testcase: testMacOSX_i386(org.github.jamm.MemoryMeterTest):SKIPPED: got: "Linux", expected: is "Mac OS X"
[junit] Testcase: testMacOSX_x86_64(org.github.jamm.MemoryMeterTest):SKIPPED: got: "Linux", expected: is "Mac OS X"
[junit] Testcase: testCollections(org.github.jamm.MemoryMeterTest):SKIPPED: These vary quite radically depending on the JVM.

BUILD SUCCESSFUL
Total time: 14 seconds

Very easy and work out of the box. To even start to use, just import the class and start measure the object you interested in,
MemoryMeter meter = new MemoryMeter();
meter.measure(object);

but remember to add "-javaagent:<path to>/jamm.jar" to your classpath when you run your app.

Friday, June 20, 2014

Test subversion project using jenkins

In our last article, we learned basic of jenkins. If you do not know what is jenkins and how to install it, please read the article before continue on this. Today, we will learned by configured a project to be test by jenkins.

This article will focus using subversion. If you store code in git, jenkins support it too but you need to install git plugin for jenkins. The installation process is a few clicks only.

To configure the project to jenkins, point your browser to the jenkins server. The click on 'New Item'. This article continue with the first option 'Build a free-style software project' and as for the Item name, you can basically name after your project but if you have specific scope of test, you can also name it as such. The click next and browser is redirected to another page similar to the one below.



I will explain using the screenshot above. For obvious reason, I have to obfuscate certain part of image to protect party interest but you should get the idea easily. With field Description, you can fill additional information here. First four options, you can play around for it but for this simple project, I don't see the need for it. For field Advanced Project Options, you will most likely to start to use it once you get better understanding of jenkins. So we leave those untick as well.

Next, field Source Code Management, this is where you need to select your code repository. As mentioned earlier, we will select the radio button for Subversion. Field Repository URL must be fill it as you tell jenkins where to get your code from. Most likely you code is security protected and hence you should also provide access credential for jenkins to retrieve project codebase. For field Check-out Strategy, you can choose the strategy you like, for me, I just goes for Use 'svn update' as much as possible because there is no point to checkout everything everytime to build project.

So in order to trigger this project within jenkins, you can specify how you want to trigger it. You can also specified by ticking a few options you want to trigger the build process. For me, I like to trigger manually when I want to quickly test my project. Also, I have setup a periodic build that every friday evening at 11pm, the build will be kickstarted automatically.

Normally target is test, but it should be easily understandable if you develop using ant before. This is the target where jenkins will execute. So for your project, open up ant build file and check out the test target. I recommend you click on Advanced... button to see additional configurations which you might need to change. If you ant build file is on the same directory as you configured in Repository URL just now, then you will not need to modify. If you have special configurations which you need to feed into ant build file during jenkins build, specify in properties.

Last step, Post-build Actions, Click on the drop down button Add post-build action, you can add as many action you want but as a starter, a simple email notification would be suffice. That's it and remember to click Save button to save all your configuration!

Go to the dashboard, you should see now your project configured, in the content page, for your project, you click on a drop down button and select Build now, jenkins would check out your project and execute the test target. If you click on the project, you should be able to see the build history on the left menu. This should get you started and by now, you should get a feel on where to go further, so on the left menu, click on Configure and alter advanced configuration and see how it goes!

That's it for this article, I hope you like it.