Tuesday, September 4, 2012

PPPoE with Zyxel Q1000Z and Cisco 2600 router with CenturyLink DSL

Comcast's service broke and their customer support was rude one too many times, so I switched to CenturyLink. Being that I am not a "normal" customer by any stretch of the imagination, I wanted to set up something a bit more advanced than a simple NATted connection. Specifically, I wanted to get an IPv6 tunnel to Hurricane Electric while also keeping my corporate VPN connection up and running. (Ideally, get my VPN running on the same box as the tunnel and other services.) I have an old Cisco 2621 kicking around that seems it should be up to the task.

Getting this going was surprisingly difficult. Initially, I had the 2600 plugged in behind Q1000Z with the 2600 running in NAT mode providing access to the networks in my house. I was double NATted because the Q1000Z didn't seem to want to set up static routes in any sane way. Obviously, not an ideal setup.

There are numerous configurations around the net on how to do PPPoE from a Cisco device to a possible non-Cisco remote end. (I say "possible" because CenturyLink doesn't advertise what their back-end network looks like. Not surprising since most people wouldn't understand it anyway.) Most of these configurations look very similar to each other.

The configuration that finally worked for me is this (some important information replaced with Xs, you will have to fill in your own values. Also, the configuration has been edited to remove irrelevant settings.) :

!
version 12.3
service timestamps debug datetime msec
service timestamps log datetime msec
service password-encryption
!
hostname frontdoor-with-v6
!
boot-start-marker
boot-end-marker
!
!
no aaa new-model
ip subnet-zero
!
!
ip name-server X.X.X.X
ip name-server X.X.X.X
ip name-server X.X.X.X
!
ip cef
vpdn enable
!
vpdn-group 1
request-dialin
protocol pppoe
!
interface FastEthernet0/0
ip address 192.168.0.1 255.255.255.0
ip nat inside
no ip mroute-cache
duplex auto
speed auto
!
interface FastEthernet0/1
no ip address
speed 100
half-duplex
pppoe enable
pppoe-client dial-pool-number 1
!
interface Dialer1
ip address negotiated
ip mtu 1492
ip nat outside
encapsulation ppp
ip tcp adjust-mss 1450
no ip mroute-cache
dialer pool 1
dialer-group 1
ppp authentication pap chap callin optional
ppp chap hostname XXXXXXX@qwest.net
ppp chap password 0 XXXXXXXXX
ppp pap sent-username XXXXXXXXXX password 0 XXXXXXXXXXXX
!
ip nat inside source list 1 interface Dialer1 overload
ip classless
ip route 0.0.0.0 0.0.0.0 Dialer1
ip route 10.1.0.0 255.255.0.0 192.168.0.2
!
access-list 1 permit 10.1.0.0 0.0.255.255
dialer-list 1 protocol ip permit
!
end

Most of this is taken almost verbatim from the numerous example sites. However, when I originally set this up, FastEthernet0/1 was set to auto for both speed and duplex. When the 2600 was set up in NAT mode behind the Q1000Z, the auto mode worked fine. But, once I got the PPPoE session up, I got lots of random drop-outs in my connectivity. Some things worked fine, others would load slowly, and still others just plain wouldn't work. After digging around forever, I found a site that suggested setting the speed and duplex to 100-half instead of auto. There were no obvious signs on a duplex mismatch on the Cisco side of the link, and the Zyxel didn't have any obvious way to look for errors. So, I decided to give it a shot and see what happened.

Strangely enough, it worked. My connectivity was nice and speedy again, and all sites are coming up correctly.

Hopefully this helps someone else that might be struggling to get a similar setup going. Next, for the v6 tunnel and the VPN.

Thursday, July 19, 2012

Code coverage with Android and EMMA

Recently, I have been looking in to tools in Android that would help me improve code quality and find bugs before putting the product out.  I picked up a copy of Diego Torres Milano's "Android Application Testing Guide" as a good place to get me started.   Since there are a lot of tools out there, and not all of them support Android, it was a useful guide to tools that should be working.

One of the tools I was looking in to is code coverage.   Over the years, EMMA has been integrated with the Android build tools, which is supposed to make it easier to use.   Unfortunately, if you don't use them just the right way they can end up being a horrid time suck trying to figure out why your instrumented build just isn't working.

For my testing, I was using the latest tools available as of this writing.  (That would be ADT 20)   Lots of the information available on the Internet is for older versions of tools that don't use the same commands as ADT 20.  I also started with the most basic app I could, and set it up so that I had an easy way to intentionally miss some code, or make sure I hit it all.   The code looked something like this :
@Override
public void onCreate(Bundle savedInstanceState) {
   String appname = "unknown.app";
   super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);
}

public void testme() {
    System.out.println("This is a test!");
}

A pretty simple "app" that mostly comes out of the Android tools when you create a new project.   The "testme()" method is there because it will allow us to explicitly call some code (or not) to let us see that code coverage is really working.

Next, I created a test app using the Android tools and created a new test case.   The test case extends ActivityInstrumentationTestCase2, as it will start up the activity we want to test in a state that is easy to use.  The test class looked something like this :

public class MyTest extends ActivityInstrumentationTestCase2 {
public MyTest()
{
   super(TestActivity.class);
}

public void testCodeCoverage()
{
}

The "TestActivity" referenced in the above code is the name of the Activity that we created earlier.   Also, note that our test doesn't actually do anything.   For now, this is okay.   When the MyTest class is run, ActivityInstrumentationTestCase2 will create the activity, which will result in the onCreate() method being called.   So, once we have our code coverage running, we will have a block of code that was covered, and a block that was not.

At this point, we are going to use the command line.   We also need to make sure that we have a fairly current version of Apache Ant ready to use.   For my tests I was using 1.8.2.

At the command line, we want to convert our apps to use Ant for building.   To do this, we need to use the "android" command that is included in the SDK.  (On Windows, it is "android.bat")  We need to run two commands, one to convert the "TestActivity" app and one to convert the "MyTest" test project.  The command will look something like this :

android update project --path /path/to/TestActivityProject --name TestActivityProject --target android-16
The "--name" parameter should be set to whatever you named your project, and "--target" should be set to the API level that you want to test with.   The "--path" parameter requires the FULL path name to your project.   So, if you are on windows it might be something like "c:\users\foo\workspace\TestActivityProject" I tested with an Android 4.1 VM, so I chose "android-16".  The version you use isn't too important, unless you plan to use Ant to make your final builds.

Next, to convert the test project :

android update test-project --main ../TestActivityProject --path /path/to/MyTestProject
The "--main" parameter confused me a bit at first.   It should be a relative path from the directory you store "MyTestProject" in, to the path of "TestActivityProject".   If you are using Eclipse and putting your code in a workspace, you should normally need to use ../.

Finally, we are ready to build and run our test.  Go in to the directory for "TestActivityProject" and run "ant".  (If ant isn't in your path, you may need to use a full path to ant instead.)

But, whats this?  We get a help screen like the following :


Android Ant Build. Available targets:
   help:      Displays this help.
   clean:     Removes output files created by other targets.
              The 'all' target can be used to clean dependencies
              (tested projects and libraries)at the same time
              using: 'ant all clean'
   debug:     Builds the application and signs it with a debug key.
              The 'nodeps' target can be used to only build the
              current project and ignore the libraries using:
              'ant nodeps debug'
   release:   Builds the application. The generated apk file must be
              signed before it is published.
              The 'nodeps' target can be used to only build the
              current project and ignore the libraries using:
              'ant nodeps release'
   instrument:Builds an instrumented package and signs it with a
              debug key.
   test:      Runs the tests. Project must be a test project and
              must have been built. Typical usage would be:
                  ant [emma] debug install test
   emma:      Transiently enables code coverage for subsequent
              targets.
   install:   Installs the newly build package. Must either be used
              in conjunction with a build target (debug/release/
              instrument) or with the proper suffix indicating
              which package to install (see below).
              If the application was previously installed, the
              application is reinstalled if the signature matches.
   installd:  Installs (only) the debug package.
   installr:  Installs (only) the release package.
   installi:  Installs (only) the instrumented package.
   installt:  Installs (only) the test and tested packages (unless
              nodeps is used as well.
   uninstall: Uninstalls the application from a running emulator or
              device. Also uninstall tested package if applicable
              unless 'nodeps' is used as well.

This is where I really screwed up and spent a lot of time scratching my head.   Since we want to use EMMA, we need an instrumented build, right?   So the command that we need is "ant emma instrument install test" to get a build, install it, and run the test in it.

While this seems like the most intuitive answer, you will quickly find out that it doesn't work.  Everything will compile and install fine, and we can assume that the resulting apps are instrumented.   However, when it gets down to running the test, you will be greeted with something like this :


     [echo] Running tests ...
     [exec] INSTRUMENTATION_RESULT: shortMsg=java.lang.IllegalAccessError
     [exec] INSTRUMENTATION_RESULT: longMsg=java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation     [exec] INSTRUMENTATION_CODE: 0

Hmm..  Something didn't work.  This is where I spent a ton of time trying different combinations and searching to understand what was going on.   Finally, as I was giving up, I noticed a browser page that I had already opened that said for EMMA code coverage, we need to run "ant emma debug install test".  I didn't think it would work, but I gave it a shot.  Crazy as it is, it DID work!  (I literally spent 7 hours trying to figure out what the above error message was all about.)

Once your instrumented build is run, the necessary coverage files will be downloaded, and a coverage.html file will be created in your test project's "bin" directory.   Opening that up should show that your onCreate() method ran all of its code, but the testme() method wasn't touched at all.   If you go in to the testCodeCoverage() method in the test app, you should be able to add the line "getActivity().testme()" and then run the instrumented build again.   This time, you should get 100% code coverage.

Hopefully, this post saves someone out there a significant portion of their time getting started with code coverage!