fogbound.net




Wed, 13 Feb 2013

PHPUnit/Selenium and iframes

— SjG @ 10:20 am

I ran into an interesting issue with a functional test, and wasn’t able to Google a specific solution out there. So here’s my solution.

The Problem:
When testing a web form that contains a Javascript “wysiwyg” editor (in this case xhEditor, since it’s a site built on Yii, and there’s a great extension), the Selenium IDE was not logging anything typed into that field. When I tried using the field ID, the data was also silently vanishing.

The Explanation:
xhEditor converts the TextArea into an iFrame, and captures keystrokes to populate the HTML body of the dependent frame. The Selenium plugin for Firefox doesn’t grok this, and the data goes missing.

The Solution:
Manually switch frames in your PHPUnit/Selenium code.

$this->selectFrame("//*[@id='xhEdt0_iframe']"); // switch to the iframe
$this->type("//body","This text shows up in the xhEdit WYSIWYG!"); // type into the body
$this->selectFrame("relative=top"); // switch back to the surrounding frame


Wed, 30 Jan 2013

Failures in Typographical Experimentation

— SjG @ 8:35 pm

This started with an idea.

Perhaps it would be interesting to create a family of type faces where the density of the characters was related to the frequency of their use. This font, to be called Densitas, would have variants based upon the text analyzed. For example, Densitas Shakespeare would use the collected works of Shakespeare for the character frequency corpus, while Densitas Brontë would use the works of the Brontë sisters for the corpus. For aesthetic purposes, perhaps the initial faces could be selected based on relevance to the source corpus as well.

What would this accomplish? It might reveal something interesting about the difference in usages between authors. It might end up being environmentally friendly by using less ink on more common characters. It might enhance readability. After all, it’s popularly understood that we tend to look at the shapes of words rather than the constituent letters. De-emphasizing the more common shapes may even make it easier to process text.

Any time I have an idea of this nature, I start thinking about code and design and try to avoid thinking about the end result. As my Father is wont to say, it is just as difficult to create something ugly as it is to create something beautiful. If I think too much on the end result, I will obsess over whether it will be worth the effort, and never get to the actual work. If I just dive in, I may find myself wasting a lot of time, but at least I will learn something.

This turns out to be one of those experiences. I thought it was an interesting idea. The end result is mediocre at best, dull perhaps, a waste of time. Still, I learned something in the process.

Step one was to write a character frequency analyzer. This code does a few things:

  • read a text file
  • compute the character frequencies
  • scale the results across the frequency range, so the least frequent character has a value of zero and the most frequent character has a value of one
  • map the characters to glyph names
  • write out a chunk of code to substitute into the next step

The next step is a FontLab Studio/RoboFab script, hence glyph names instead of raw character names. Since FontLab/RoboFab scripts are in Python, I figured I’d write this in Python as well (I don’t really know Python, but that kind of ignorance never stops me from writing code).

I ended up with this program: cf.py

I ran it against the plaintext
The Complete Works of William Shakespeare from Project Gutenberg
(after stripping out the Project Gutenberg-specific text, which I believe is permitted since I’m not redistributing the text, merely crunching it with code).

The FontLab/RoboFab script accepts two font sources, and interpolates each glyph according to the frequency computed in the previous step, where the less frequently used glyphs are darkest. For my test, I used the current state a sans-serif font I’ve been developing1. I have it in several weights, so I interpolated between the lightest and heaviest. The code to do this interpolation looks like shakespeare_weighter.py.

The results were unimpressive, to say the least:

(click to enlarge)

There are some of the obvious problems: distribution between is too stark; there seem to be only two or three densities. Similarly, kerning gets really disrupted by the different densities. But first things first. Why is the density contrast so extreme? Looking at the weighted frequency data answers that question:

For this chart, punctuation and other glyphs have been omitted.

So the next approach is to make the differences more gradual. Instead of doing by pure letter frequency, we use a gradient based on the ranking of frequency. In other words, the least common glyph is the darkest, the next least common glyph is one increment lighter, and so on, until the most common glyph is the lightest. This code to compute this looks like cf2.py, and the output distribution looks like this:

Looks more promising, does it not? We substitute the values into our FontLab/RoboFab script (like this: shakespeare_weighter2.py), and run it. Alas, the end results are still pretty dull:


(click to enlarge)

For the last try, we’ll do a few things differently. First, the thing that probably jumped out at you when you saw the first distribution graph: we’ll ignore all non-alphabetical characters when doing the frequency calculation. For the sake of readability, we’ll set all non-alphabetical characters to the median value. Secondly, we’ll take accented characters and consider them the same weight as their non-accented versions, so, for example, “á” and “ä” are the same density as “a.” Lastly — and this might be the big shift — we won’t interpolate between two weights of a font based on the frequency, but instead we will effectively halftone each glyph with a screen density based on the frequency.

To do this, we use the RoboFab halftoneGlyph() pen for inspiration. We do a much blunter approach: we impose a grid over the glyph, determine which points on the grid are inside, and replace those points with squares. The size of the squares is the same across a given glyph, and is based on the frequency. This process will then convert a nice, smooth glyph into a rougher, pixellated gray version of itself.

The revised frequency computation code is here (cf3.py), and the resulting frequency graph looks like this:

From this, we generate the final FontLab/RoboFab script (this one: shakespeare_weighter3.py), and run it.

And yet again, we look at the results, and sigh. All this work, and really nothing to show for it. There are a number of problems. The font stresses most rendering engines with its very high contour count, and either gets blurred into oblivion or converted into a plaid checkerboard nightmare when viewed on a display. The differences in shades are only apparent when the characters are enormous, even when printing. And, of course, aesthetically, it’s nothing to write home about.

(click to enlarge)

The lack of results are dispiriting enough to resort to quoting that reprobate Thomas Edison: “Results! Why, man, I have gotten a lot of results! I know several thousand things that won’t work.”

I can’t claim to know thousands of things that won’t work, but I do have another handful to add to the collection.

1 The font will be released as WL Hope Grotesque, when and if I ever complete it to my satisfaction.


Fri, 12 Oct 2012

Resizing LVM partitions

— SjG @ 10:30 am

I ran into a problem where the default installer for RHEL had configured a server’s partitions in a way that was really suboptimal for how the server was being used. It looks like the default was intended for workstation use or one in which a lot of users would keep their stuff in home directories, but this system is being used as a web application server. The root partition filled up, and the database (with its files in /var) got quite unhappy.

[root@epicwin]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vg_epicwin-lv_root
50G 47G 0 100% /
tmpfs 1.9G 76K 1.9G 1% /dev/shm
/dev/sde1 485M 80M 380M 18% /boot
/dev/mapper/vg_epicwin-lv_home
532G 198M 505G 1% /home

So I had to learn some LVM basics, and move the space around. I found various instructions out there, but many of them were missing steps or glossed over whether or not I’d suffer data loss. Here’s how I solved my problem (without data loss!) and got the system back on its feet.

  • Boot into “rescue” mode.
  • Decline to mount the existing system or filesystem for repair, instead go straight to a root shell.
  • Activate the LVM system:
    lvm vgchange -a y
  • Make sure the filesystems are clean:
    e2fsck -f /dev/mapper/vg_epicwin-lv_home
    e2fsck -f /dev/mapper/vg_epicwin-lv_root
  • Reduce the size of the lv_home logical volume from 540G to 40G:
    resize2fs /dev/mapper/vg_epicwin-lv_home 40g
    lvreduce -L 40g /dev/mapper/vg_epicwin-lv_home
  • Expand the size of the lv_root logical volume from 50G to 550G:

    lvextend -L +500g /dev/mapper/vg_epicwin-lv_root

  • Expand the filesystem on the root logical volume:

    resize2fs /dev/mapper/vg_epicwin-lv_root

  • Exit shell / reboot.
  • Watch SELinux freak out on next boot:

    *** Warning -- SELinux targeted policy relabel is required. ***
    *** Relabeling could take a very long time, depending on file ***
    *** system size and speed of hard drives. ***

  • Watch SELinux print asterisks and then the system reboot unexpectedly in a way that looks quite disturbingly bad.
  • System comes up clean!

A few notes:
If /home had a lot of stuff in it, this would obviously be a lot more complicated. This approach works because I had the space and it wasn’t being utilized. if /home had been closer to full, the approach would have been to add a new physical drive, and it to the logical volume set, and then do something similar to the above.


Mon, 6 Aug 2012

Sneaky, sneaky SELinux

— SjG @ 4:38 pm

I was getting a web site up and running on Centos 6.3, and PHP was refusing to talk to the SMTP server on the same box. This, in and of itself, is not unusual. There’s a checklist:

  • Verify SMTP’s running
  • Check that the SMTP server is configured to accept connections from localhost
  • Check the firewall rules
  • Really check the firewall rules by generating an email using telnet localhost 25 or nc localhost 25 from the command line
  • Check that PHP is trying to talk to the SMTP server you think it is
  • Look in the system log for SELinux being a bully and preventing communication

In this case, all of the above checked out cleanly. I was perplexed. But it turns out that, in what is as shocking and surprising as my cat wanting to be fed,
SELinux was indeed the culprit. It just wasn’t logging the problem anywhere.

A quick
setsebool -P httpd_can_network_connect=1

as root solved the problem.

Moral(s) of the Story: The cat is always hungry. SELinux is always fuckin’ shit up.


Sun, 22 Jul 2012

Teensy board example code “usb_debug_only.c” and gcc > 4.6

— SjG @ 9:44 pm

Wow, now there’s a blog title that will have very limited appeal 🙂

I was trying to validate my toolchain worked for building Teensy/ATMEGA32u4 applications. I used the mac port avr-gcc, avr-bintools, avr-libc install, and it failed to build the sample “blinky.c” program. I tried using the recommended AVR CrossPack, just in case it had different versions of the tools, but I got the same results:


samuelg$ make
-------- begin --------
avr-gcc (GCC) 4.7.0
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Compiling C: usb_debug_only.c
avr-gcc -c -mmcu=atmega32u4 -I. -gdwarf-2 -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -ffunction-sections -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./usb_debug_only.lst -std=gnu99 -MMD -MP -MF .dep/usb_debug_only.o.d usb_debug_only.c -o usb_debug_only.o
usb_debug_only.c:96:24: error: variable ‘device_descriptor’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
usb_debug_only.c:113:24: error: variable ‘hid_report_descriptor’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
usb_debug_only.c:128:24: error: variable ‘config1_descriptor’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
usb_debug_only.c:175:52: error: variable ‘string0’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
usb_debug_only.c:180:52: error: variable ‘string1’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
usb_debug_only.c:185:52: error: variable ‘string2’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
usb_debug_only.c:198:11: error: variable ‘descriptor_list’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
make: *** [usb_debug_only.o] Error 1

Google didn’t immediately help me with this. Eventually, I actually went ahead and read the error messages, and then tried following directions, i.e., I looked at line 96, and changed


static uint8_t PROGMEM device_descriptor[] = {

to


static const uint8_t PROGMEM device_descriptor[] = {

That’s all it took to make gcc happy with that line. Repeat the process for all of the error lines, and it compiles and builds correctly.

Evidently, the change to gcc happened between 4.5.3 and 4.6, and, once I knew what to look for, I found numerous discussions of why and wherefore (although these discussions were quite frankly beyond my comprehension). I was, however, happy to find the simple solution detailed above.