our hardware runs better without windows

Vu sur http://wtanaka.com/node/7656. C’est une publicité de BMW qui date de 1998. On peut y lire « Notre matériel fonctionne mieux sans fenêtres (windows) »..

Petit coup de pouce : si vous passez à rails 2.3 et que vous avez une ancienne version de rake installée, vous verrez peut-être le message suivant au lancement de commandes rake

rake aborted!
undefined method `reenable' for  [environment]>:Rake::Task

La raison ? Vous utilisez rake 0.8.x là où la version 0.8.4 est nécessaire. Il suffit de mettre à jour la gemme. Si le paquet rake est installé mais est trop vieux, désinstallez le. Tout devrait rentrer dans l’ordre.

ssh est un outil merveilleux : il permet de se connecter à un hôte et exécuter des commandes à distances de manière sécurisée.

Il permet également de tunneler un port local vers un port distant d’une autre machine. Ainsi tout ce qui est envoyé sur le port local va être transmis au port distant via la communication ssh sécurisée. Cette manipulation s’avère très pratique pour sortir d’un réseau dont seuls les ports 22 et 80 sont ouverts.

Je viens d’apprendre récemment comment faire l’inverse : tunneler un port d’une machine distante vers un port d’une machine locale. Ainsi tout ce qui est envoyé sur le port de la machine distante va être transmis au port de la machine locale. En résumé, si votre machine locale est sur un réseau protégé par un NAT et un firewall, çette manipulation met en place une backdoor vers le réseau protégé.
Lire la suite…

Lors de l’écriture de tests unitaires, on peut se retrouver à écrire ce genre de code :

assertEquals(42, answer);
assertFalse(answer == 34);
assertTrue(info.matches("color") || info.matches("colour"));
assertTrue(colorsList.contains("red"));
assertTrue(s instanceof MagicString);

Mais JUnit propose depuis la version 4.4 une nouvelle syntaxe à base de Matchers. En fait, cette syntaxe n’est pas totalement nouvelle : elle est empruntée à JMock qui possède déjà les Matchers JMock pour décrire les contraintes d’un mock. L’idée vient de Joe Walnes dans son article Flexible JUnit assertions with assertThat().

Les assertions précédentes peuvent alors s’écrire de la manière suivante :

assertThat(answer, is(42));
assertThat(answer, is(not(34)));
assertThat(info, either(containsString("color")).or(containsString("colour")));
assertThat(colorsList, hasItem("red"));
assertThat(s, instanceOf(MagicString.class));

Les avantages sont multiples :

  • Ça se lit mieux : le développeur communique donc mieux son intention aux autres développeurs, ce qui est essentiel !
  • Contrairement aux méthodes assertEquals et consorts, on ne risque pas de tromper dans l’ordre des arguments : la syntaxe d’assertEquals est assertEquals([expected], [actual]) mais beaucoup de gens se trompent et écrivent assertEquals(answer, 42). Avec assertThat, aucun risque.
  • Les matchers peuvent être modifiés: par exemple : not(s) pour inverser la condition, either(s).or(t) pour combiner des conditions, each(s) pour appliquer une condition sur chaque élément d’une collection, afterFiveSeconds(s) pour attendre 5 secondes avant de tester…
  • En cas d’échec de l’assertion, les messages sont beaucoup plus lisibles. Si on reprend l’exemple précédents, avec les assertXxx classiques, les messages ressembleraient à ça :
    assertEquals(42, answer);
     => expected:<42> but was:<36>
    assertFalse(answer == 34);
     => junit.framework.AssertionFailedError:
    assertTrue(info.matches("color") || info.matches("colour"));
     => junit.framework.AssertionFailedError:
    assertTrue(colorsList.contains("red"));
     => junit.framework.AssertionFailedError:
    assertTrue(s instanceof MagicString);
     => junit.framework.AssertionFailedError:
    

    Avec assertThat, les message ressemblent plutôt à ça :

    assertThat(answer, is(42));
     => Expected: is <42>
             got: <36>
    assertThat(answer, is(not(34)));
     => Expected: is not <34>
             got: <34>
    assertThat(info, either(containsString("color")).or(containsString("colour")));
     => Expected: (a string containing "colour" or a string containing "color")
             got: "rainbow"
    assertThat(colorsList, hasItem("red"));
     => Expected: a collection containing "hello"
             got: <[bonjour, ia orana]>
    assertThat(s, instanceOf(MagicString.class));
     => Expected: an instance of sandbox.FooTest$MagicString
             got: "polop"
    

    Inutile de dire qu’il est beaucoup plus facile de débugguer des tests écrits avec assertThat…

  • Il est plus facile d’écrire des Matcher maison plutôt que des méthodes assertXxxx maison. En plus ces Matchers pourront être réutilisés dans des tests JMock.
  • C’est sexy :)

Pour plus d’informations, je vous recommande la lecture de ce billet. Il est en français, il est très détaillé et je suis tombé dessus en écrivant cet article.

meuble_sdb Pas facile de remplacer son vieux lavabo par un beau meuble avec vasque, robinet neuf, miroir, et bonde Champi clic-clac quand on n’y connaît rien.

Et pour corser le tout, Murphy était de la partie : entre le robinet général d’eau froide grippé, le robinet général d’eau chaude qui ne ferme pas complètement, les cotes de la notice qui sont fausses, l’installation de robinets d’arrêt impossible, une coulisse de tiroir qui est plus basse que les autres, la conduite d’évacuation trop loin du mur et qui oblige à tailler le meuble à la scie sauteuse pour qu’il puisse plaquer, l’évacuation du siphon qui tombe 12 cm plus haut que le conduit d’évacuation parce que la nouvelle vasque est plus haute que le vieux lavabo, les aller-retours aux magasins de bricolage pour trouver une solution, et une fois que tout est fini, on essaie enfin, et là, ça fuit…
Lire la suite…

boîte de conserveEn java, n’importe quel objet implémentant l’interface Serializable peut être converti facilement en une séquence d’octets. Cette même séquence peut ensuite être reconverti en l’objet original. Ce mécanisme est par exemple utilisé pour transmettre des objets par RMI.

Voici une petite méthode pour vérifier que votre classe est bien sérialisable

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
 
public class Assert {
    /**
     * Assert that an object is serializable by dumping it and then reading it
     * back and finally by checking the original object and the dumped and read
     * object are equals.
     *
     * <p>Obviously, the method <code>equals()</code> has to be implemented
     * correctly for this method can work.
     * @param objOriginal the instance which will be checked against serialization;
     * must implement <code>equals()</code> or it won't work
     */
    public static void assertSerializable(Object objOriginal) {
        try {
            final ByteArrayOutputStream stream = new ByteArrayOutputStream();
            final ObjectOutputStream out = new ObjectOutputStream(stream);
            out.writeObject(objOriginal);
            out.close();
 
            final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(stream.toByteArray()));
            final Object objSerialized = in.readObject();
            assertEquals(objOriginal, objSerialized);
        } catch (IOException e) {
            fail("unable to serialize or deserialize object " + objOriginal + ": " + e.getMessage());
        } catch (ClassNotFoundException e) {
            // unlikely to happen...
            fail(e.getMessage());
        }
    }
}
</p>

Lire la suite…

rubyDans un article précédent, je donnais une méthode pour convertir rapidement un nombre en binaire et inversement quand on n’avait pas python 3. Ça m’est pratique quand j’ai besoin de faire une conversion rapide : un terminal, on lance python, on tape l’expression et on a le résultat. En regardant les nouveautés de ruby 1.8.7, j’ai découvert que c’était encore plus trivial.

% irb
irb(main):001:0> 42.to_s(2)
=> "101010"
irb(main):002:0> "%b" % 42
=> "101010"
irb(main):003:0> "1001".to_i(2)
=> 9
irb(main):004:0> 0b1001
=> 9

Enfantin non ?

zsh est un shell complet qui remplace avantageusement bash dont on entend beaucoup parler en bien. J’ai décidé de l’essayer récemment.

Sans chercher à exploiter toutes les fonctionnalités qu’il propose, certaines facilités me sont maintenant indispensables lorsque je passe à bash. Une seule en fait : le ** qui se substitue à n’importe quel dossier ou sous-dossier. Un globbing puissant qui permet de s’affranchir de find.

Lire la suite…

Depuis python 2.6, le langage python peut gérer les nombres entier dans leur représentation binaire.

$ python2.6
>>> 0b101111
47
>>> int('1101', 2)
13
>>> int('0b1101', 2)
13
>>> bin(13)
'0b1101'

Cependant, avec les versions précédentes, seule la conversion de binaire vers décimal est possible facilement.

$ python2.5
>>> int('1101', 2)
13
>>> bin(13)
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'bin' is not defined

Voici donc une petite fonction bin :

def bin(n):
    """Convert an integer to its binary string representation"""
    res = []
    while n > 0:
        res.insert(0, str(int(n % 2)))
        n = n // 2
    return "".join(res)

Et ainsi :

$ python2.5
>>> def bin(n):
...     """Convertit un nombre en binaire"""
...     res = []
...     while n > 0:
...         res.insert(0, str(int(n % 2)))
...         n = n // 2
...     return "".join(res)
...
>>> bin(13)
'1101'
>>> int(bin(13), 2)
13

En installant rubygems et en l’utilisant avec Netbeans, on se rend vite compte que rubygems est configuré pour stocker ses gemmes dans /var/lib/gems et que Netbeans n’a pas les droits d’écriture à cet endroit. En effet, la manière traditionnelle d’installer gem implique d’utiliser sudo, en ligne de commande :

$ sudo gems install rails -y

Oui mais voilà, Netbeans n’utilise pas sudo. Pour que Netbeans puisse gérer les gemmes lui-même, il lui faut donc les droits d’écriture sur le dossier /var/lib/gems et ses sous-répertoires. Le plus naïf est de donner tous les droits en écriture, mais c’est mal ! Sinon, on peut aussi créer un groupe nommé rubygems et donner le droit d’écriture à ce groupe. Cette approche est meilleure mais un problème se pose lorsque l’utilisateur y crée un nouveau fichier ou dossier : non seulement celui-ci appartient à l’utilisateur et non pas à root, mais en plus le groupe n’a pas le droit d’écriture. C’est là qu’interviennent les ACLs…

Lire la suite…