Friday, 8 December 2017

Sublime Text for Clojure

Sublime Text actually changed the text editor landscape. Before it was all TextMate which was stealing the thunder. But that is somehow a begone era. In this post we will have a sneak peak on using Sublime Text 3 for Clojure development. At this time there is no Emacs to cider kind of integration right from within Sublime Text, but it is possible to write one if required, however, connecting to nrepl from command line would just do fine. Also Clojure is not Java development where you would require to add breakpoint and step code execution as things are fairly straight forward to understand as opposed to having bazillion class files when it comes typical enterprise Java projects. However if one needs, you can resort to Eclipse with Counterclockwise plugin which works just fine.

1. Have Package Control installed.
2. In the beginning there were no parenthesis. It all started with a Big Bang, after which the amount of parenthesis started expanding. Since Clojure has the eternal brackets from the beginning of universe, we need a better bracket highlighter.
Add the following config to the Sublime user settings, so that the bracket highlighter works properly and does not conflict with the editor's own matching.
{
    "auto_match_enabled": false,
    "match_brackets": false,
    "match_brackets_angle": false,
    "match_brackets_braces": false,
    "match_brackets_content": false,
    "match_brackets_square": false,
    "match_tags": false
}
This package is pretty cool as it will show the matched brackets in the gutter.
3. To keep the sanity in own pattern matching of brackets and since most Lisp programmers are borderline hippie, to commemorate that let us use Rainbowth. Once installed add the following palette in the path ~/Library/Application Support/Sublime Text 3/Packages/User/Rainbowth.sublime-settings which is taken from Emacs's package to make the highlighting easier on eyes when used in conjunction with Solarized Dark theme.
{
  "palettes": {
    "default": ["#707183", "#7388d6", "#909183", "#709870", "#907373", "#6276ba", "#858580", "#80a880", "#887070"]
  }
}
But Rainbowth needs to update the colour scheme so we need to do some extraction of the desired scheme. Let's say we are using Solarized Dark theme, then do the following.
$ cd "/Applications/Sublime Text.app"
$ mkdir -p ~/temp/subl
# Solarized theme is inside the legacy package 
$ cp "Contents/MacOS/Packages/Color Scheme - Legacy.sublime-package" ~/temp/subl
# For some other themes which are not in the above, use
# $ cp "Contents/MacOS/Packages/Color Scheme - Default.sublime-package" ~/temp/subl
$ cd ~/temp/subl && unzip "Color Scheme - Legacy.sublime-package"
$ cp "Solarized (Dark).tmTheme" "~/Library/Application Support/Sublime Text 3/Packages/"
4. Add Clojure.sublime-settings in the same directory with the below contents so that by default, the source uses two spaces, which is the standard as per style guide and since we use `-` to separate words instead of camel case or `_`, the word separator helps us to easily select symbols with double click. Else, doing a double click on a word will select up to the separator.
{
    "tab_size": 2,
    "word_separators": "./\\()\"':,.;<>~!@#$%^&*|+=[]{}`~?"
}
That's all there is specific to Clojure development.

Theming
Next we can look into few enhancements and theming to make it easy on eyes. I generally prefer dark themes as it looks cool and tends towards Solarized Dark. While generally most articles say to use a lighter background with a darker text, it depends on various other conditions like the room lighting, and of course personal preference. Refer the Dark UI section of the post for citations.

1. Install Ayu colour scheme. We will be using Ayu Mirage with Solarized Dark theme. Add the following config under user settings.
{
    "color_scheme": "Packages/Solarized (Dark).tmTheme",
    "theme": "ayu-mirage.sublime-theme",
    "ui_big_tabs": false,
    "ui_fix_tab_labels": true,
    "ui_font_size_small": true,
    "ui_font_source_code_pro": true,
    "ui_separator": true,
    "ui_wide_scrollbars": true
}
2. Additional UI settings follows. Since I got used to Monaco font from early days of OS X, I tend to stick with it instead of newer ones like Menlo.
{
    "font_face": "Monaco",
    "font_options": [
        "subpixel_antialias"
    ],
    "font_size": 16,
    "gpu_window_buffer": true,
    "highlight_modified_tabs": true,
    "scroll_past_end": true,
    "show_full_path": true,
    "translate_tabs_to_spaces": true,
    "word_wrap": false
}

Other Enhancements
1. GitGutter to see source control changes.
2. SideBarEnhancements plugin which adds more options to the side bar right click menu.
3. EDN for Clojure EDN syntax highlighting.

Once done, the editor will look elegant as in the screenshot.



Dark UI
[1] Negative contrast computer displays (dark letters on a light background) generally provide a more legible image than positive contrast displays (light letters on a dark background). Either black characters on a white background or white characters on a black background have been found to be more visible than green, yellow-orange, blue or red characters.20

[2] The greatest difference among groups is on the black & white pair: while the majority of people without dyslexia prefer it (32.67%), only 13.64% of the participants with dyslexia chose black text on white background.
Participants without dyslexia tend to prefer color pairs with a higher color and brightness contrast while people with dyslexia read faster when color pairs have lower contrasts. For instance, the color pair which was the fastest to read by the participants with dyslexia was black & creme (mean of 0.214 for the fixation duration) while black text over yellow background presents the largest fixation duration mean (0.239 seconds). Although the pair off-black & off-white is the one recommended in Web design for dyslexics (Bradford, 2011), none of the users with dyslexia selected it. This pair presents the highest fixation duration mean for the participants without dyslexia (0.193 seconds).

[3] Maureen did mention two situations when a dark background makes sense.

However, if you are using a display in a dark environment, it’s better to use a dark background as it lets you keep your eyes dark adapted. That’s why controls for airplanes and GPS units for cars switch to a dark background at night. Usually, however, the results don’t look like symbols and text floating in the darkness of space…there’s still a sense of there being a dark surface to ground the view. So the concerns above are somewhat mitigated.

I’ve seen recommendations that white on black is better for aging eyes, and for people with low vision because it reduces the amount of light scattering and distorting the image.

[4] Chief among the reasons many of you have expressed for preferring dark backgrounds is the reduced strain placed on the eyes when staring at the screen for many hours. Many developers state that light text on a dark background is easier to read over longer periods of time than dark text on a light background.

Thursday, 7 December 2017

Integration Tests with pytest

pytest is a unit testing library and coupled with requests package can be used for writing integration tests. With integration tests, couple of things we would need is a way to distinguish between environments like local, staging, production, different datacenters and run tests in all or some specific tests per env and such.

1. We need a way to pass env during test runs. We will use pytest-variables for that which makes it easy to get variables passed in from command line available to the tests. Another way is to write conftest. So our requirements.txt file will now have pytest-variables[hjson]==1.5.1 apart from other packages.
2. We will name our pytest file starting which starts with test as something like test_api.py
3. Now on writing the tests. I would recommend that the python code be modular and well organised instead of spaghetti coding. Read Modular Programming with Python by Erik Westra if you are interested. We could separate parts into different file or have things organised under class and keep it under the same file. The point is separation of concerns, readability and maintainability (especially by other programmers). A thing with OOP is that go for composition as opposed to inheritance when possible.
4. We will go with how to write pytests in an object oriented fashion rather than just writing test_ functions. Let's call the below module as test_api.py
import pytest
import logging
import requests

__version__ = "0.0.42"  # corresponds to app version
logging.basicConfig(level=logging.DEBUG)
__timeout = 90  # seconds

def get_headers(props):
    """Return header map."""
    # ...

def http_post(params, data, headers=None):
    """Send an HTTP POST request."""
    return requests.post(params['server'] + params['endpoint'], data=data, headers=headers)

class FooAPI:
    """Sample Foo API helper class.""""

    def __init__:
        pass

@pytest.mark.timeout(__timeout)
class TestFooAPI:
    """Test Foo API service."""

    pytestmark = [pytest.mark.local, pytest.mark.ny1, pytest.mark.ams1, pytest.mark.ny1_green, pytest.mark.stg1]

    @pytest.fixture()
    def foo(self):
        """Return Foo object."""
        return FooAPI()

    def gen_name():
        """Standalone function that not pytest functions."""
        pass

    def test_add_user(self, variables, foo):
        """Test adding of user."""
        log = logging.getLogger('test_add_user')
        resp = foo.create_request(variables)
        headers = get_headers(variables)
        http_resp = http_post(variables, data, headers)
        assert http_resp.status_code == 200

    @pytest.mark.ams1_beta
    def test_beta_endpoint(self, variables, foo):
        """Test beta endpoint."""
        log = logging.getLogger("test_beta_endpoint")
        data = {'users': base64.b64encode('something'), 'bar': 'baz'}
        start = time.time()
        headers = get_headers(variables)
        log.info("\nheaders: %s", headers)
        http_resp = http_post(variables, data, headers)
        rtt = time.time() - start
        log.debug("\nrtt: %s\n", rtt)
        body = json.loads(http_resp.content)
        assert body['status'] is True
        assert body['code'] == 0
        assert http_resp.status_code == 200, 'Expecting 200 OK status code.'

class TestBarAPI:
    # ....

Any class that starts with Test and any function that starts with test will be executed by pytest by default. However these behaviour can be configured. Fixtures are variables that are passed to each test as argument before it runs. There are various pytest markers. If whole pytest functions within a pytest class needs to executed by many different environments, we can pass specify them as pytestmark = [pytest.mark.en1, pytest.mark.env2, ...]. The env1, env2 correspond to env config file name. And if we need to execute specific tests against specific env then, exclude them from the above list and annotate it above that particular function as @pytest.mark.ams1_beta, which means, if the env passed via command line is ams1_beta, only then this test will execute and since the env is not specified common in the pytestmark list, other tests will be skipped. Example usecase is running sanity tests (a subset of tests) against productions at a specific interval, where we do not have to run the full testsuite. The variables argument contains the config values defined in the config json which will be available to the test methods as a python dictionary.
5. The configuration files are under config directory. Example local.json is below. The name of the file corresponds to the env which we will be passing to the pytest via command line.
{
    "server": "http://localhost:8080",
    "endpoint": "/foo/test/",
    "key": "local_key.pem",
    "cert": "local_cert.pem",
    "env": "local",
    "json": true
}
6. Tying it all together using shell script. It is better to use virtualenv. So below script does a bit of housekeeping before running the tests.
#!/bin/bash

# Integration test with pytest.

TEST_DIR=test_api
VENV_DIR=venv
CONFIG_DIR=config

function activateVirtualEnv {
    echo "Activating venv .."
    if ! hash virtualenv 2>/dev/null; then
        echo "virtualenv not found. Installing .."
        pip install virtualenv
    fi
    virtualenv $VENV_DIR
    source $VENV_DIR/bin/activate
}

function installDeps {
    echo "Installing dependencies .."
    pip install -r ../requirements.txt
}

function prepareForTest {
    echo "Running integration test .."
    activateVirtualEnv
    installDeps
}

function deactivateVirtualEnv {
    echo "Deactivating venv .."
    deactivate
}

function displayhelp {
    echo "Usage: $0 options"
    echo "where options include:"
    echo "  local    run test in local env"
    echo "  ams1     run test in Amsterdam production datacenter 1"
    echo "  stg1     run test in staging enviroment 1"
}

# $1 result xml file name
# $2 env variable name
function run {
    echo "Running test against $2"
    # -n xdist flag
    # -s capture output
    # -v verbose
    # --variables The config file
    # -m marker
    py.test -n 4 -s -v --junitxml="$1" --variables "$CONFIG_DIR/$2.json" -m "$2" test_api.py
}

# $1 results.xml
# $2 env : local, rqa2, etc. corresponds to the filename in config
# To run against all machines in staging and production, use env as stg and prod respectively
# For integration test
# ./runtests.sh results.xml local
function main {
    result="$1"
    env="$2"
    echo "result: $result"
    echo "env: $env"
    echo "config: $CONFIG_DIR"

    cd $TEST_DIR
    prepareForTest
    if [[ $env == "stg" ]]; then
        run stg1.xml stg1
        run stg2.xml stg2
        python merge_junit_results.py stg1.xml stg2.xml > $result
    elif [[ $env == "prod" ]]; then
        run ny1.xml ny1
        run ams1.xml ams1
        python merge_junit_results.py ny1.xml ams2.xml > $result
    else
        # individual
        run $result $env
    fi
    return_code=$?
    deactivateVirtualEnv
}

main $@

exit $return_code
The merge_junit_results.py can be obtained from the cgoldber gist.
To run the test we run the command ./runtests.sh ${result}.xml ${env-config-file-name}, which will check for virtualenv and such and run the test. To run the tests in parallel use xdist.
7. Sample reqirements.text file would look like
pytest==3.0.7
pytest-variables[hjson]==1.5.1
pytest-xdist==1.15.0
requests==2.13.0
pytest-timeout==1.2.0
8. To integrate the results with jenkins, it needs to know the final result of the testsuite which will be present in the results.xml file. To parse that use the code below.
#!/bin/python

"""Extract test result failure, error values for Jenkins job."""

import xml.etree.ElementTree as ET
import sys


def parse_result(file):
    """Parse the given results.xml file."""
    root = ET.parse(file).getroot()
    if root.attrib["failures"] == "0" and root.attrib["errors"] == "0":
        print "ALLTESTSUCCESS"
    else:
        print "ERROR"
        sys.exit(1)


if __name__ == '__main__':
    print "junit filename: ", sys.argv[1]
    parse_result(sys.argv[1])

Now we have a full blown integration testsuite which can be integrated with CI/CD pipeline.

For clarity, sample folder structure will look like below.
test
├── requirements.txt
├── runtests.sh
└── test_api
    ├── __init__.py
    ├── local.xml
    ├── config
    │   ├── ams1.json
    │   ├── ams1_beta.json
    │   ├── local.json
    │   ├── local_beta.json
    │   ├── ny1.json
    │   ├── ny1_beta.json
    │   ├── ny1_green.json
    │   └── vm.json
    ├── merge_junit_results.py
    ├── parse_xml.py
    ├── result.xml
    ├── test_api.py
    └── venv

Wednesday, 6 December 2017

Passcode Lock iPhone even with TouchID Enabled

I found a way to force lock iPhone that has TouchID enabled. If done as below, then the phone requires passcode to unlock even when TouchID is configured to unlock the device.
1. Enable AssistiveTouch from Accessibility.
2. And under AssistiveTouch->Custom Actions, say for Long Press set it to SOS.

Now when we need to passphrase lock, long press the assistive touch button, which will dial the emergency SOS number. Cancel the call immediately and the phone gets locked. The only problem is that it makes the emergency sound when dialling.

Or second option is to press the unlock button and tap the wrong finger five times and the phone will lock itself. Whichever is easy works. Now how would the second option work with FaceID?

Tuesday, 5 December 2017

Erlang is Famous as it appeared on TV series

Did you know that Erlang is famous as in Hollywood famous, and you had not heard about it? Turns out a chat conversation in BlindSpot TV series 1 episode 6 says "Sybok: how quickly can you learn erlang?". And it indirectly implies that the TRAKZER app was written in Erlang. Anyway that is just a story. But yeah, how quickly can you learn Erlang dear?



But unfortunately, there is a twist to the story (spoiler alert). The girl (Ana Montes) at a later point in time uses python to break into the FBI system and then switches to perl. Which suggests that the above assumption is likely false or may be due to the lack of time and to give a clue to Patterson she used it. And the interesting part is the girl writes well documented code that follows PEP-257 at gunpoint. Now that is what I call software craftsmanship.

Monday, 4 December 2017

I Origins and Superstring Theory

So far I have restricted myself to not post anything that are not related to computers and technology in this blog, but I decided it is time to change that as I do not see why not to. And then this blog is not a lore on computing and my intentions change and my thoughts adapt to changing situations just like any normal human being. So with that said, let us take a small dive into the wilderness.

I am touched by the I Origins movie which I watched a couple of months ago and ever since I am wondering on and off about the existence of something unknown to me as in what we would call God. My thought process is like, organisms that do not have the PAX6 gene do not have any idea or perception about vision. And then the organism gets the gene added and it starts experiencing the world around it in a total different way. It might be able to handle the sensory perceptions or it might not.

Now what if there are forces, vibrations that we are not able to detect but exists all along with us. Superstring theory suggests that there are more dimensions than the ones we perceive. Kaluza-Klein gravity merges Einstein's general theory of relativity (gravity) with Maxwell's theory of electro-magnetism by adding a fifth dimension, but we do not observe them because they are compactified, which means are microscopic in nature. But there are other explanations that are not based on compactification, like projective geometry which says these extra dimensions are not physically real and thus cannot be observed. Or non-compactification theory which suggests that extra dimensions are physical, but relaxes the cylindricity condition (physics depending on the first four coordinates), but the effects are negligible when unit conversions are considered. Nevertheless the point is that there can be extra-dimensions that we do not really understand and perceive as we have not yet had that thought, or concrete evidence or we lack something analogous to the PAX6 gene that would allow us to perceive the world around us in a different way.

We do not have the answers yet, whatever that might be and the search continues, which makes this subject a very interesting fascination of mine.

A Song by Siri

I said something, Siri heard something else and in the end she sang a song. Not bad I would say.

Sunday, 3 December 2017

Solitude by Jehnny Beth

These are the words from the video Start Making Sense by Jehnny Beth on Beats 1. I like these words, the poetry.

I'm close to the burn out,
doing nothing is all I dream about.
Friendships, career, phone,
even when we're together we're all alone.
I wish I could freeze time,
make this morning last longer.
Everything I do on my own,
I remember better.
Songs to enjoy my solitude.