Monday 27 May 2019

Project Euler 148 - Exploring Pascal's triangle

We can easily verify that none of the entries in the first seven rows of Pascal's triangle are divisible by 7:
 1
 1  1
 1  2  1
 1  3  3  1
 1  4  6  4  1
 1  5 10 10  5  1
1  6 15 20 15  6  1
However, if we check the first one hundred rows, we will find that only 2361 of the 5050 entries are not divisible by 7.
Find the number of entries which are not divisible by 7 in the first one billion (109) rows of Pascal's triangle.

Solution

Rewrite the number N in the format of:

N = q1 * 7p1 + q2 * 7p2 + q3 * 7p3 .... + qk-1 * 7 + qk

For example:

1934 = 343 * 5 + 49 * 4 + 7 * 3 + 2

Define PA(N) as the function to find the number of entries which are not divisible by 7 in the first N rows of Pascal's triangle.

PA(q1 * 7p1) = 28p1 * (q1 + 1) * q1 / 2

For example:

PA(5 * 73) = 283 * 6 * 5 / 2 = 329280

The final formula

PA(q1 * 7p1 + q2 * 7p2 + q3 * 7p3 .... + qk-1 * 7 + qk) = PA(q1 * 7p1) + (p1 + 1) * PA(q2 * 7p2) + (p1 + 1)*(p2 + 1)*PA(q3 * 7p3) + .....

For example:

PA(1934) = PA(343 * 5 + 49 * 4 + 7 * 3 + 2) = PA(345 * 5) + (5+1) * PA(49 * 4) + (5+1)*(4+1)*PA(7*3) + (5+1)*(4+1)*(3+1)*PA(2)=381720

I don't know how to prove it.

Monday 20 May 2019

Project Euler 147 - Rectangles in cross-hatched grids

Rectangles in cross-hatched grids

Problem 147

In a 3x2 cross-hatched grid, a total of 37 different rectangles could be situated within that grid as indicated in the sketch.
There are 5 grids smaller than 3x2, vertical and horizontal dimensions being important, i.e. 1x1, 2x1, 3x1, 1x2 and 2x2. If each of them is cross-hatched, the following number of different rectangles could be situated within those smaller grids:
1x11
2x14
3x18
1x24
2x218
Adding those to the 37 of the 3x2 grid, a total of 72 different rectangles could be situated within 3x2 and smaller grids.
How many different rectangles could be situated within 47x43 and smaller grids?

Solution

The normal rectangles that are parallel to the borders are easy to count. For the 'diagonal rectangles', it is relatively straight forward to figure out the pattern for square ones (1*1, 2*2). It's the counting of the non-square 'diagonal rectangles' that is the trickiest.

The first step is given the width (m) and height (n) of the box, work out a list of 'max length' of 'diagonal rectangles' with a width of 1 block, starting from top left corner to bottom right corner.


For example, for m = 7, n = 5, we have the list as [2, 4, 6, 8, 9, 9, 8, 6, 4, 2]

Assume m >= n, the general pattern is [2, 4, ... 2(n-1), 2n - 1, ..., 2n - 1,  2(n-1), ..., 4, 2]. There are (m - n) of the (2n - 1) item in the middle. Apparently, when m=n, there is no (2n - 1) item.

The key of this problem is how to calculate the max length of any consecutive blocks that can form a rectangle. Let's define it as M(consecutive_blocks)

For example, for M([2, 4]) = 2. For M([6, 8, 9, 9]) = 6.

By taking advantage of symmetry, there is no need to work out all the cases. Assuming the width of the block is always less than the M(consecutive_blocks), we don't need to consider [4, 6, 8, 8, 6] because the width of [4, 6, 8, 8, 6] = 5, which is greater than M([4, 6, 8, 8, 6]) = 4. Also M([8, 9, 9, 8, 6]) is the same as M([6, 8, 9, 9, 8]).

Start with 'max length' being the first item of the list, iterate over the list, how far can it go before the 'max length' starts to decrease?

In this example, we can see that M([6]) = 6, M([6, 8]) = 6, M([6, 8, 9]) = 6, M([6, 8, 9, 9]) = 6, but the next one, M([6, 8, 9, 9, 8]) = 5. Since m >= n, the length of the 'L' shape is fixed, which is 2n - 1. So the max length can go (2n - 1 - first_item) steps before it starts to decease.

Next question is deceasing by 1 or 2? It can be proved that as long as the first item is less than or equal to the last item, it's always decreasing by 1.

Once we know the value of M(consecutive_blocks), we can easily calculate the number of full-width non-square rectangles (only consider length > width) that can be situated in the blocks.

For example, if M(cb) = 6 and width(cb) = 3, we just calculate the number of 4*3, 5*3, 6*3 rectangles, which is 3+2+1=6. 

Multiply this number by 2 (due to symmetry), we can get the total number of non-square 'diagonal rectangles

Finally, let's prove 'as long as the first item is less than or equal to the last item, it's always decreasing by 1.'


Suppose m >= n, then b >= a, we move the line P toward bottom right, when the lower end hits point X, the 'max length' will start to decease, but until it coincides line R, it deceases by 1 unit. After that, it decreases by 2 units. Line Q which is of the same length of line P, sits between line P and Line R. So between line P and line Q, the 'max length' can decrease by 1 unit at most.

https://github.com/sunmingtao/sample-code/blob/master/python/projecteuler/p147.py


Thursday 16 May 2019

Get rid of boilerplate code (setters and getters) - Lombok

Maven dependency

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.8</version>
</dependency>

Code template

@Getter @Setter @RequiredArgsConstructor @ToString
public class User {
    private final String name;
    private int age;
}

Install Lombok in eclipse

Go to the directory where lombok.jar sits. (e.g. /Users/msun/.m2/repository/org/projectlombok/lombok/1.18.8/)


java -jar lombok-1.18.8.jar



Monday 13 May 2019

Test callback logic

Suppose we need to write unit tests for the Service class. The Dao class interacts with database, so it needs to be mocked.

class Service{
    
    Dao dao;
    
    Service(Dao dao){
        this.dao = dao;
    }
    
    public void doStuff(String s) {
        Callback<String> callback = i -> {
            System.out.println("Hello "+i);  
        };
        dao.doStuff(s, callback);
    }
    
}

class Dao{
    public void doStuff(String s, Callback<String> callback) {
        callback.apply(s);
        //Some DB operation
    }
    
}

interface Callback<T>{
    void apply(T t);
}

The question is how to test the callback logic (the System.out.println() line). If we simply write test case as below, it doesn't print out 'Hello John'.



@ExtendWith(MockitoExtension.class)
@RunWith(JUnitPlatform.class)
public class CallbackTest {

    @Mock Dao dao;
    
    @Test
    void test() {
        Service service = new Service(dao);
        service.doStuff("John");
    }

}

Well, we can mock dao.doStuff() by using doAnswer() method. It allows us to define the method body. What we do here is only invoking callback.apply(s) while skipping the database operations.


@Test
void test() {
    Service service = new Service(dao);
    doAnswer(i -> {
        Callback<String> callback = i.getArgument(1);
        callback.apply(i.getArgument(0));
        return null;
    }).when(dao).doStuff(anyString(), any());
    service.doStuff("John");
}

Sunday 12 May 2019

JUnit 5 / Mockito / Catch-exception/ Jmockit pom and sample code

pom
<!-- JUnit 5 dependencies -->
<dependency>
    <groupId>org.junit.platform</groupId>
    <artifactId>junit-platform-runner</artifactId>
    <version>1.4.2</version>
    <scope>test</scope>
</dependency>
<dependency> 
    <groupId>org.junit.platform</groupId> 
    <artifactId>junit-platform-launcher</artifactId> 
    <version>1.4.2</version> 
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.4.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>5.4.2</version>
    <scope>test</scope>
</dependency>
<dependency> <!-- Allows the legacy unit tests code under JUnit 4 still to run -->
    <groupId>org.junit.vintage</groupId>
    <artifactId>junit-vintage-engine</artifactId>
    <version>5.4.2</version>
    <scope>test</scope>
</dependency>
        
<!-- Mockito dependencies -->
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>2.23.4</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <version>2.23.4</version>
    <scope>test</scope>
</dependency>
      
<!-- catch exception dependencies -->
<dependency>
    <groupId>eu.codearte.catch-exception</groupId>
    <artifactId>catch-exception</artifactId>
    <version>2.0</version>
    <scope>test</scope>
</dependency>
        
<!-- JMockit used to mock static methods -->
<dependency>
    <groupId>org.jmockit</groupId>
    <artifactId>jmockit</artifactId>
    <version>1.24</version>
    <scope>test</scope>
</dependency>

Test case template


import static com.googlecode.catchexception.CatchException.*;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*; 
import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.platform.runner.JUnitPlatform; 

@ExtendWith(MockitoExtension.class)
@RunWith(JUnitPlatform.class)
class HttpClientUtilTest {

    @Mock CloseableHttpClient httpclient;
    
    @BeforeEach
    void setUp() throws Exception {
        
    }

    @Test
    void test(){

    }

    @Nested
    @DisplayName("test getRequest()")
    class testGetRequest{
    
     @BeforeEach
     void setUp() throws Exception {
        
     }

        @Test
        void test() {
        }     
    }
}

Mock static method

new MockUp<HttpClients>() {
    @mockit.Mock
    public CloseableHttpClient createDefault() {
        return httpclient;
    }
};

Catch exception

catchException(() -> HttpClientUtil.postRequest("dummyUri", params, responseHandler)); 
assertThat(caughtException(), instanceOf(IllegalArgumentException.class));

Argument captor

ArgumentCaptor<HttpPost> httpPostArgument = ArgumentCaptor.forClass(HttpPost.class);
verify(httpclient, times(1)).execute(httpPostArgument.capture(), Mockito.eq(responseHandler));
HttpPost httpPost = httpPostArgument.getValue();
assertThat(httpPost.getEntity().getContentLength(), is(0L));

Sample test cases

https://www.petrikainulainen.net/programming/testing/junit-5-tutorial-writing-nested-tests/
https://www.petrikainulainen.net/programming/testing/writing-clean-tests-to-verify-or-not-to-verify/
https://www.baeldung.com/jmockit-static-method

Thursday 9 May 2019

JUnit5 test error: java.lang.Exception: No tests found matching

My JUnit5 test class is very simple.


import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;

@RunWith(JUnitPlatform.class)
public class UmsServiceTest {

    @BeforeEach
    public void setUp() {
    }

    @Test
    public void getPrefixUsernames() {
        assertThat(UmsService.getPrefixedUsername("msun", STAFF), is("user:msun"));
        assertThat(UmsService.getPrefixedUsername("msun", PUBLIC_USER), is("user:public:msun"));
    }

}

Upon running it (by right clicking on the test and 'Run as' -> JUnit test, I get this error.

java.lang.Exception: No tests found matching [{ExactMatcher:fDisplayName=getPrefixUsernames], {ExactMatcher:fDisplayName=getPrefixUsernames(au.gov.nla.ums.keycloak.service.UmsServiceTest)], {LeadingIdentifierMatcher:fClassName=au.gov.nla.ums.keycloak.service.UmsServiceTest,fLeadingIdentifier=getPrefixUsernames]] from org.junit.internal.requests.ClassRequest@77ec78b9
 at org.junit.internal.requests.FilterRequest.getRunner(FilterRequest.java:40)
 at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createFilteredTest(JUnit4TestLoader.java:80)
 at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:71)
 at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:46)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:522)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)

This is because I have created this class as JUnit 4 class in Eclipse.




































And now I am trying to run it as JUnit 5 test case.

To fix this, I need to change the test runner to JUnit 5 by right clicking on the test -> 'Run as' -> Run Configurations, and selecting 'JUnit 5' as the tester runner


Tuesday 7 May 2019

Selenium + JUnit 5 maven dependency and sample test case

pom.xml

<!-- Allows the legacy unit tests code under JUnit 4 still to run -->
<dependency>
    <groupId>org.junit.vintage</groupId>
    <artifactId>junit-vintage-engine</artifactId>
    <version>5.4.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.4.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>5.4.2</version>
    <scope>test</scope>
</dependency>
<dependency> 
    <groupId>org.junit.platform</groupId> 
    <artifactId>junit-platform-launcher</artifactId> 
    <version>1.5.0-M1</version> 
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>3.141.59</version>
</dependency>

Sample test case:


import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class SeleniumTest {

    private WebDriver browser;
    
    @BeforeAll
    public static void init(){
        System.setProperty("webdriver.chrome.driver", "chromedriver");
    }
    
    @BeforeEach
    protected void setUp() throws Exception {
        browser = new ChromeDriver();
    }

    @Test
    public void browseGoogle() {
        browser.get("https://www.google.com.au");
    }
    
    @AfterEach
    protected void tearDown() throws Exception {
        browser.close();
    }

}

Selenium issue: java.lang.NoClassDefFoundError: okhttp3/WebSocketListener

A simple selenium test case yields the following error.

java.lang.NoClassDefFoundError: okhttp3/WebSocketListener
 at org.openqa.selenium.remote.internal.OkHttpClient.openSocket(OkHttpClient.java:75)
 at org.openqa.selenium.devtools.Connection.<init>(Connection.java:58)
 at org.openqa.selenium.chrome.ChromeDevToolsLocator.getChromeConnector(ChromeDevToolsLocator.java:81)
 at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:196)
 at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:176)
 at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:131)
 at au.gov.nla.ums.keycloak.selenium.TroveTest.test(TroveTest.java:21)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:498)
 ....

It's caused by the version of selenium-java:

<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>4.0.0-alpha-1</version>
</dependency>

Downgrading it to 3.141.59 solves the error.


<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>3.141.59</version>
</dependency>

No tests found with test runner 'Junit 5'

When I execute a junit 5 test case, I get this error.









This is part of my pom.xml that is relevant.

<!-- Allows the legacy unit tests code under JUnit 4 still to run -->
<dependency>
    <groupId>org.junit.vintage</groupId>
    <artifactId>junit-vintage-engine</artifactId>
    <version>5.4.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.4.2</version>
    <scope>test</scope>
</dependency>
<dependency> 
    <groupId>org.junit.platform</groupId> 
    <artifactId>junit-platform-launcher</artifactId> 
    <version>1.5.0-M1</version> 
    <scope>test</scope>
</dependency>

I try various suggestions on https://stackoverflow.com/questions/46717693/eclipse-no-tests-found-using-junit-5-caused-by-noclassdeffounderror, and the solution that works for me is adding another dependency of junit-jupiter-engine.

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>5.4.2</version>
    <scope>test</scope>
</dependency>

It is this article that gives me the decisive hint.

Monday 6 May 2019

Local build OK but fails on Jenkins -- NoSuchMethodException

A couple of integration tests run well on my local but Jenkins is not happy and gives this error:

[ERROR] Tests run: 2, Failures: 0, Errors: 2, Skipped: 0, Time elapsed: 0.583 s <<< FAILURE! - in au.gov.nla.ums.keycloak.integration.ITKeyCloakIntegrationTest
[ERROR] getUserInfoFromUsernameAndPassword(au.gov.nla.ums.keycloak.integration.ITKeyCloakIntegrationTest)  Time elapsed: 0.488 s  <<< ERROR!
java.lang.NoSuchMethodError: org.apache.commons.io.output.DeferredFileOutputStream.<init>(ILjava/lang/String;Ljava/lang/String;Ljava/io/File;)V
 at au.gov.nla.ums.keycloak.integration.ITKeyCloakIntegrationTest.getUserInfoFromUsernameAndPassword(ITKeyCloakIntegrationTest.java:65)

[ERROR] getRolesAndGroupsFromClientCredentials(au.gov.nla.ums.keycloak.integration.ITKeyCloakIntegrationTest)  Time elapsed: 0.088 s  <<< ERROR!
javax.ws.rs.ProcessingException: java.lang.NoSuchMethodError: org.apache.commons.io.output.DeferredFileOutputStream.<init>(ILjava/lang/String;Ljava/lang/String;Ljava/io/File;)V
 at au.gov.nla.ums.keycloak.integration.ITKeyCloakIntegrationTest.getRolesAndGroupsFromClientCredentials(ITKeyCloakIntegrationTest.java:46)
Caused by: java.lang.NoSuchMethodError: org.apache.commons.io.output.DeferredFileOutputStream.<init>(ILjava/lang/String;Ljava/lang/String;Ljava/io/File;)V
 at au.gov.nla.ums.keycloak.integration.ITKeyCloakIntegrationTest.getRolesAndGroupsFromClientCredentials(ITKeyCloakIntegrationTest.java:46)

DeferredFileOutputStream comes from commons-io.jar. Version 1.3 doesn't have such constructor while version 2.5 does. OK, It should be an easy fix, I think, I just have to explicitly set the version of this jar by:

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.5</version>
    <scope>test</scope>
</dependency>

But it doesn't work.

Then I use reflection to print out all the constructor signature in the hope to ascertain the version of the jar.

Class<?> cl = Class.forName("org.apache.commons.io.output.DeferredFileOutputStream");
Constructor<?>[] cons = cl.getConstructors();
System.out.println("Constructors:---");
for (Constructor<?> con : cons) {
    System.out.println(con);
}

Here is the output:

Constructors:---
public org.apache.commons.io.output.DeferredFileOutputStream(int,java.io.File)

OK, now I am pretty certain that version 1.3 is at play. But the question is which jar is dependent upon commons-io and brings it on our classpath. More importantly, why can't the version of it be overwriten?

Eclipse's Dependency Hierarchy shows it comes indirectly from keycloak-modal-jpa. It says 'omitted for conflict with 2.5', and that's why local is working. How to get Jenkins show something like this?
















A maven command comes to rescue:

mvn dependency:tree

The result shows commons-io is not being omitted



























Compared to the result of my local run, everthing is the same except the local result doesn't have commons-io included in the tree.



























Then I try excluding common-io from the keycloak-model-jar:

<dependency>
    <groupId>org.keycloak</groupId>
    <artifactId>keycloak-model-jpa</artifactId>
    <scope>provided</scope>
    <version>${keycloak.version}</version>
    <exclusions>
        <exclusion>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Unfortunately, Jenkins shows exactly the same dependency tree.

Oh, wait a second. The group id in the dependency tree is org.apache.common, but the group id of what I exclude is commons-io.

Changing the group id to org.apache.commons:

<dependency>
    <groupId>org.keycloak</groupId>
    <artifactId>keycloak-model-jpa</artifactId>
    <scope>provided</scope>
    <version>${keycloak.version}</version>
    <exclusions>
        <exclusion>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-io</artifactId>
        </exclusion>
    </exclusions>
</dependency>

And finally it's working!

Upon closely inspecting the pom.xml of openshift-restclient-jar, which is directly dependent on commons-io, I make some surprising discovery. Both org.apache.commons.commons-io and commons-io.commons-io are on its dependency list.

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-io</artifactId>
    <version>1.3.2</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.1</version>
</dependency>

It looks like a bug to me. Having said that, it remains a mystery to me as to why Jenkins sovles dependency differently from my local maven build. Could it be due to the different version of Maven?

NCM Investigation

Story 1: Why the deployment didn't pick up my changes?

I created a new jvmctl node of NCM on Hammer. I changed the port number and specified the git branch, and the deployment was successful. However, the system didn't seem to pick up my changes.

After making sure all my code changes were indeed deployed on Hammer (by checking the /apps folder), initially I thought the JSP might be cached, but then I realised not only JSP changes were not picked up, but none of the other changes were effective either.

I suspected, albeit a long shot, that it could be an issue of environmental nature. Then I repeated the same steps on Hoist, only to prove my theory wrong – it had exactly the same symptom. I went so far as to rename start.jar to start2.jar and yet the server still managed to start successfully. How was that even possible?

Upon carefully inspecting the jcmctl node, I finally found the culprit.

APP_OPTS=-Denv=dev -Dconfig=/apps/ncm/jetty/ncm/webapps/ndp/ -Dndpqa=yes -Djetty.http.port=9900 -Dorg.eclipse.jetty.server.Request.maxFormContentSize=20000000 -Dorg.eclipse.jetty.util.FileResource.checkAliases=false -Djetty.home=/apps/ncm/jetty -Djetty.base=/apps/ncm/jetty/ncm -jar /apps/ncm/jetty/start.jar --lib=/apps/ncm/jetty/ncm/lib/nla.jar /apps/ncm/jetty/ncm/etc/jetty.xml

There are numerous references made to the folder /apps/ncm, while it should be /apps/

I did, more than ten times, have looked at this line of configuration. It had continued eluding me because the word 'ncm' looked so innocuous sitting there. The eureka moment only hit me when I was checking the contents under /apps/ncm/jetty, fully expecting to see start2.jar. Of course start2.jar wouldn't be there. The sight of start.jar made me mumble "of course, of course, that's it!" and I felt a great sense of satisfaction.

Story 2: Why changing JspWrapper has no effect?

Once I deployed my code changes on hammer, I noticed the changes made on JspWrapper.java had no effect. However, a new class added to the same package which JspWrapper belonged to was clearly functioning.

Considering JspWrapper was accessed in a less-than-usual fashion (by a JSP file), I wondered if the compiled JSP was cached, so I renamed JspWrapper to JspWrapper2, and changed other places accordingly. Yep, it worked. Then I changed it back to JspWrapper, much to my surprise, only to see it fail again.

I suspected there was a rogue JspWrapper class lurking somewhere. To prove it, I changed JspWrapper to JspWrapper2 again, only this time, without changing the places that referenced to it. And the system could still find this class.

Now how to locate this rogue class, which resided in one of jar files? I used this command:

find . -name *.jar

I went through the list of jars carefully, and one jar caught my eye: nla-backup.jar. What the hell was that? Oh, I remembered. Before I had made the changes to the infrastructure java classes, I backed up the old nla.jar by renaming it to nla-blackup.jar just in case something went wrong.

I had committed the jar into github, not unintentionally, because I thought storing the file on github was safer than keeping it locally. Obviously it backfired now. There were two JspWrapper classes (and many other duplicate classes) on classpath. Which one would be loaded by JVM was nondeterministic. In my local environment, it happened to be the newer class. However, on hammer, it was the old one that got loaded.

Separate unit test from integration test

This is the template of pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.smt</groupId>
    <artifactId>smt</artifactId>
    <version>0.1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <profiles>
        <!-- The Configuration of the development profile -->
        <profile>
            <id>dev</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <build.profile.id>dev</build.profile.id>
                <skip.integration.tests>true</skip.integration.tests>
                <skip.unit.tests>false</skip.unit.tests>
            </properties>
        </profile>
        <!-- The Configuration of the integration-test profile -->
        <profile>
            <id>integration-test</id>
            <properties>
                <build.profile.id>integration-test</build.profile.id>
                <skip.integration.tests>false</skip.integration.tests>
                <skip.unit.tests>true</skip.unit.tests>
            </properties>
        </profile>
    </profiles>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.2</version>
                <configuration>
                    <!-- Skips unit tests if the value of skip.unit.tests property is true -->
                    <skipTests>${skip.unit.tests}</skipTests>
                    <!-- Excludes integration tests when unit tests are run -->
                    <excludes>
                        <exclude>**/IT*.java</exclude>
                    </excludes>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>2.22.2</version>
                <executions>
                    <!-- Invokes both the integration-test and the verify goals of the Failsafe Maven plugin -->
                    <execution>
                        <id>integration-tests</id>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                        <configuration>
                            <!-- Skips integration tests if the value of skip.integration.tests property is true -->
                            <skipTests>${skip.integration.tests}</skipTests>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

To run unit test


mvn clean test

To run integration test


mvn clean verify -P integration-test

Sunday 5 May 2019

Project Euler 146 - Investigating a Prime Pattern

Investigating a Prime Pattern

Problem 146

The smallest positive integer n for which the numbers n2+1, n2+3, n2+7, n2+9, n2+13, and n2+27 are consecutive primes is 10. The sum of all such integers n below one-million is 1242490.
What is the sum of all such integers n below 150 million?



Well, the key was to find a good algorithm to test prime number.

import time
import sympy

now = time.time()
result = []
for n in range (10, 150000001, 10):
    if n ** 2 % 3 == 1 and n ** 2 % 7 == 2 and n ** 2 % 13 != 0 and sympy.isprime(n ** 2 + 1) and sympy.isprime(n ** 2 + 3) and sympy.isprime(n ** 2 + 7) and sympy.isprime(n ** 2 + 9) and sympy.isprime(n ** 2 + 13) and sympy.isprime(n ** 2 + 27) \
            and not sympy.isprime(n ** 2 + 23) and not sympy.isprime(n ** 2 + 21) and not sympy.isprime(n ** 2 + 19) and not sympy.isprime(n ** 2 + 17):
        result.append(n)
        print(n)
print ('result=', sum(result))
print('time spent is {}'.format(time.time() - now))