3 months Ago

Questions to consider when designing APIs: Part I

Published by marco on in Programming

A big part of an agile programmer’s job is API design. In an agile project, the architecture is defined from on high only in broad strokes, leaving the fine details of component design up to the implementer. Even in projects that are specified in much more detail, implementers will still find themselves in situations where they have to design something.

This means that programmers in an agile team have to be capable of weighing the pros and cons of various approaches in order to avoid causing performance, scalability, maintenance or other problems as the API is used and evolves.

When designing an API, we consider some of the following aspects. This is not meant to be a comprehensive list, but should get you thinking about how to think about the code you’re about to write.

Reusing Code

  • Will this code be re-used inside the project?
  • How about outside of the project?
  • If the code might be used elsewhere, where does that need lie on the time axis?
  • Do other projects already exist that could use this code?
  • Are there already other implementations that could be used?
  • If there are implementations, then are they insufficient?
  • Or perhaps not sufficiently encapsulated for reuse as written?
  • How likely is it that there will be other projects that need to do the same thing?
  • If another use is likely, when would the other project or projects need your API?

Organizing Code

  • Where should the API live in the code?
  • Is your API local to this class?
  • Is it private?
  • Protected?
  • Are you making it public in an extension method?
  • Or internal?
  • Which namespace should it belong to?
  • Which assembly?

Testing Code

  • What about testability?
  • How can the functionality be tested?

Even if you don’t have time to write tests right now, you should still build your code so that it can be tested. It’s possible that you won’t be writing the tests. Instead, you should prepare the code so that others can use it.

It’s also possible that a future you will be writing the tests and will hate you for having made it so hard to automate testing.

Managing Dependencies

  • Is multi-threading a consideration?
  • Does the API manage state?
  • What kind of dependencies does the API have?
  • Which dependencies does it really need?
  • Is the API perhaps composed of several aspects?
  • With a core aspect that is extended by others?
  • Can core functionality be extracted to avoid making an API that is too specific?

Documenting Code

  • How do callers use the API?
  • What are the expected values?
  • Are these expectations enforced?
  • What is the error mechanism?
  • What guarantees does the API make?
  • Is the behavior of the API enforced?
  • Is it at least documented?
  • Are known drawbacks documented?

Error-handling

This is a very important one and involves how your application handles situations outside of the design.

  • If you handle externally provided data, then you have to handle extant cases
  • Are you going to log errors?
  • In which format?
  • Is there a standard logging mechanism?
  • How are you going to handle and fix persistent errors?
  • Are you even going to handle weird cases?
  • Or are you going to fail early and fail often?
  • For which errors should your code even responsible?
  • How does your chosen philosophy (and you should be enforcing contracts) fit with the other code in the project?

Fail fast; enforce contracts

While we’re on the subject of error-handling, I want to emphasize that this is one of the most important parts of API design, regardless of which language or environment you use.[1]

Add preconditions for all method parameters; verify them as non-null and verify ranges. Do not catch all exceptions and log them or—even worse—ignore them. This is even more important in environments—I’m looking at you client-side web code in general and JavaScript in particular—where the established philosophy is to run anything and to never rap a programmer on the knuckles for having written really knuckle-headed code.

You haven’t tested the code, so you don’t know what kind of errors you’re going to get. If you ignore everything, then you’ll also ignore assertions, contract violations, null-reference exceptions and so on. The code will never be improved if it never makes a noise. It will just stay silently crappy until someone notices a subtle logical error somewhere and must painstakingly track it down to your untested code.

You might say that production code shouldn’t throw exceptions. This is true, but we’re explicitly not talking about production code here. We’re talking about code that has few to no tests and is acknowledged to be incomplete. If you move code like this into production, then it’s better to crash than to silently corrupt data or impinge the user experience.

A crash will get attention and the code may even be fixed or improved. If you write code that will crash on all but the “happy path” and it never crashes? That’s great. Do not program preemptively defensively in fresh code. If you have established code that interfaces with other (possibly external) components and you sometimes get errors that you can’t work around in any other way, then it’s OK to catch and log those exceptions rather than propagating them. At least you tried.

In the next article, we’ll take a look at how all of these questions and considerations can at all be reconciled with YAGNI. Spoiler alert: we think that they can.


[1] I recently read Erlang and code style by Jesper L. Andersen (Medium), which seems to have less to do with programming Erlang and much more to do with programming properly. The advice contained in it seems to be only for Erlang programmers, but the idea of strictly enforcing APIs between software components is neither new nor language-specific.

Dealing with improper disposal in WCF clients

Published by marco on in Programming

There’s an old problem in generated WCF clients in which the Dispose() method calls Close() on the client irrespective of whether there was a fault. If there was a fault, then the method should call Abort() instead. Failure to do so causes another exception, which masks the original exception. Client code will see the subsequent fault rather than the original one. A developer running the code in debug mode will have be misled as to what really happened.

You can see WCF Clients and the “Broken” IDisposable Implementation by David Barrett for a more in-depth analysis, but that’s the gist of it.

This issue is still present in the ClientBase implementation in .NET 4.5.1. The linked article shows how you can add your own implementation of the Dispose() method in each generated client. An alternative is to use a generic adaptor if you don’t feel like adding a custom dispose to every client you create.[1]

public class SafeClient<T> : IDisposable
  where T : ICommunicationObject, IDisposable
{
  public SafeClient(T client)
  {
    if (client == null) { throw new ArgumentNullException("client"); }

    Client = client;
  }
  
  public T Client { get; private set; }

  public void Dispose()
  {
    Dispose(true);
    GC.SuppressFinalize(this);
  }

  protected virtual void Dispose(bool disposing)
  {
    if (disposing)
    {
      if (Client != null)
      {
        if (Client.State == CommunicationState.Faulted) 
        {
          Client.Abort();
        }
        else
        {
          Client.Close();
        }

        Client = default(T);
      }
    }
  }  
}

To use your WCF client safely, you wrap it in the class defined above, as shown below.

using (var safeClient = new SafeClient<SystemLoginServiceClient>(new SystemLoginServiceClient(…)))
{
  var client = safeClient.Client;
  // Work with "client"
}

If you can figure out how to initialize your clients without passing parameters to the constructor, you could slim it down by adding a “new” generic constraint to the parameter T in SafeClient and then using the SafeClient as follows:

using (var safeClient = new SafeClient<SystemLoginServiceClient>())
{
  var client = safeClient.Client;
  // Work with "client"
}


[1] The code included in this article is a sketch of a solution and has not been tested. It does compile, though.

REST API Status codes (400 vs. 500)

Published by marco on in Programming

In a project that we’re working on, we’re consuming REST APIs delivered by services built by another team working for the same customer. We had a discussion about what were appropriate error codes to return for various situations. The discussion boiled down to: should a service return a 500 error code or a 400 error code when a request cannot be processed?

I took a quick look at the documentation for a couple of the larger REST API providers and they are using the 500 code only for catastrophic failure and using the 400 code for anything related to query-input validation errors.

Microsoft Azure Common REST API Error Codes

Code 400:

  • The requested URI does not represent any resource on the server.
  • One of the request inputs is out of range.
  • One of the request inputs is not valid.
  • A required query parameter was not specified for this request.
  • One of the query parameters specified in the request URI is not supported.
  • An invalid value was specified for one of the query parameters in the request URI.

Code 500:

  • The server encountered an internal error. Please retry the request.
  • The operation could not be completed within the permitted time.
  • The server is currently unable to receive requests. Please retry your request.

Twitter Error Codes & Responses

Code 400:

“The request was invalid or cannot be otherwise served. An accompanying error message will explain further.”

Code 500:

“Something is broken. Please post to the group so the Twitter team can investigate.”

REST API Tutorial HTTP Status Codes

Code 400:

“General error when fulfilling the request would cause an invalid state. Domain validation errors, missing data, etc. are some examples.”

Code 500:

“A generic error message, given when no more specific message is suitable. The general catch-all error when the server-side throws an exception. Use this only for errors that the consumer cannot address from their end—never return this intentionally.”

REST HTTP status codes

“For input validation failure: 400 Bad Request + your optional description. This is suggested in the book “RESTful Web Services”.”

4 months Ago

Movie recommendations #1

Published by marco on in Art, Film & Literature

I’ve been asked for movie recommendations often enough of late that I thought I’d put together a bit of a summary of the mini-reviews I’ve made over the years.

The following list is not comprehensive nor does it necessarily comprise my favorite movies, though many favorites are here. I made the list with a particular couple of friends in mind and tailored it to include the movies I thought they might find interesting but had most likely not heard of or hadn’t yet seen. I also only chose movies that I’d documented as having seen in the last six or seven years.

One friend was specifically interested in what he termed “mind-f&@k” movies—movies with unexpected twists, that are bizarre or otherwise make you think. With this in mind, please also note that some of the movies are not for the faint for heart. If you don’t like it, turn it off, but don’t come complaining to me. You may, however, feel free to judge me for the base creature that I am for having enjoyed whatever it was that shocked you so. I revel in your judgment; I feed off of your indignation.

Movies are sorted within their group by release date in ascending order.

Each sub-heading in the “Details” corresponds to a list of movies I’ve seen and reviewed. The movies listed under that section are the ones I thought noteworthy in that list. Of those, I selected my top recommendations and collected them into the “Genres” section.

People

Directors and screenwriters that tend to deliver work that I consistently find intriguing and worth watching:

  • David Lynch
  • David Cronenberg
  • Werner Herzog
  • Lars von Trier
  • David Mamet
  • Darren Aronofsky
  • Stanley Kubrick
  • Oliver Stone

Genres

Mindf$@k

  • A Clockwork Orange (1971)
  • Dead Ringers (1988)
  • The Cook, the Thief, His Wife & Her Lover (1989)
  • Pi (1998)
  • Magnolia (1999)
  • eXistenz (1999)
  • Memento (2000)
  • Das Experiment (2001) (de)
  • La Pianiste (2001) (fr)
  • Adaptation (2002)
  • Dogville (2003)
  • Primer (2004)
  • The Machinist (2004)
  • Synecdoche, New York (2008)
  • Antichrist (2009)
  • Shutter Island (2010)

Drama

  • The Bridge on the River Kwai (1957)
  • Catch 22 (1970)
  • Apocalypse Now (1979): try to get the Redux version
  • Do the Right Thing (1989)
  • A Few Good Men (1992)
  • Natural Born Killers (1994)
  • I Heart Huckabees (2004)
  • Syriana (2005)
  • The Wrestler (2008)
  • The Black Swan (2010)
  • The Fighter (2010)
  • Warrior (2011)

Crime Drama

  • Memories of Murder (2003)
  • The Inside Man (2006)
  • Zodiac (2007)
  • Gone Baby Gone (2007)
  • The Killer Inside Me (2010)
  • The Town (2010)
  • Drive (2011)
  • Descendants (2011)
  • The Guard (2011)
  • Kill the Irishman (2011)

Action

  • Demolition Man (1993)
  • Constantine (2005)
  • Running Scared (2006)
  • Lockout (2012)
  • Redemption (2013)

Martial Arts

  • Old Boy (2003)
  • Chocolate (2008)

Comedies

  • Blazing Saddles (1974)
  • Get Shorty (1985)
  • The Princess Bride (1987)
  • The Adventures of Priscilla, Queen of the Desert (1994) (au)
  • The Big Lebowski (1998)
  • Dogma (1999)
  • Bad Santa (2003)
  • Kiss Kiss Bang Bang (2005)
  • OSS 117: Le Caire, nid d’espions (2006) (fr)
  • Bienvenue chez les Ch’tis (2008) (fr)
  • Tropic Thunder (2008)
  • Micmacs à tire-larigot (2009) (fr)
  • Rien à Declarer (2010)
  • The Other Guys (2010)
  • Ted (2012)

Horror comedies

  • Rare Exports: A Christmas Tale (2010) (fi)
  • Tucker and Dale vs. Evil (2010)
  • Cabin in the Woods (2012)

Science Fiction

  • Blade Runner (1982)
  • The Thing (1982)
  • Equilibrium (2002)
  • Cargo (2009) (de/ch)
  • 2081 (2009)
  • Pandorum (2009)

Animated

  • Akira (1988)
  • Ghost in the Shell (1995)
  • Paprika (2006)
  • Renaissance (2006)

Documentary

  • Mark of Cain (2001)
  • Manufactured Landscapes (2006)
  • Examined Life (2008)
  • The End of Poverty (2008)
  • Entre les Murs (2008)
  • Defamation (2009)
  • Objectified (2009)
  • How to Make Money Selling Drugs (2012)
  • The House I Live In (2012)
  • The Act of Killing (2012)

There are many more documentaries that I can recommend, but those are the top ones that are somewhat less US-centric.

Details

Here are the lists of movies I found in my review articles. The link above leads to full reviews of the movies listed below it. IMDb will, of course, tell you what the rest of the world liked. Wikipedia will tell you what it’s about, probably with a detailed plot description that will ruin the movie.

Unreviewed movies

These are from an older list that I kept before I started keeping more detailed notes.

  • The Bridge on the River Kwai (1957)
  • Die Schweizermacher (1978)
  • The Princess Bride (1987)
  • Miller’s Crossing (1990)
  • Equilibrium (2002)
  • The Machinist (2004)
  • 2046 (2004): slow—typical Kar Wai Wong—but fascinating and has an awesome soundtrack
  • Shaun of the Dead (2004)
  • A Scanner Darkly (2006)
  • Last King of Scotland (2006)
  • Children of Men (2006)
  • The Prestige (2006)
  • Das Leben der Anderen (2006)
  • Rescue Dawn (2006)
  • The Host (2006): features Kang-ho Song, who’s even better in Memories of Murder
  • Zodiac (2007)
  • Eastern Promises (2007): David Cronenberg directs Viggo Mortenson as a Russian gangster
  • The Darjeeling Limited (2007)
  • No Country for Old Men (2007)
  • Synecdoche, New York (2008)
  • Hunger (2008)
  • Watchmen (2009)

Capsule Movie Reviews Vol.2011.1

  • Primer (2004)
  • Defendor (2009)
  • Moon (2009)
  • District 9 (2009)

Capsule Movie Reviews Vol.2011.2

  • Aguirre, der Zorn Gottes (1972)
  • Fitzcarraldo (1982)

I went through a bit of a David Lynch phase here, and he’s not for everyone but I kinda like him. He’s unique.

  • Wild at Heart (1990)
  • Lost Highway (1997)
  • Mulholland Drive (2001)

Capsule Movie Reviews Vol.2011.3

  • Evangelion 1.01 You Are (Not) Alone (2007)
  • Green Zone (2010)
  • Shutter Island (2010)

Capsule Movie Reviews Vol.2011.5

  • Magnolia (1999)
  • Felon (2008)
  • The Other Guys (2010)

Capsule Movie Reviews Vol.2011.6

  • Blazing Saddles (1974)
  • Ghost Busters (1984)
  • Do the Right Thing (1989)
  • A Few Good Men (1992)
  • Fifth Element (1997)

Capsule Movie Reviews Vol.2011.7

  • Das Experiment (2001) (de)
  • Bad Santa (2003)
  • Gone Baby Gone (2007)
  • The Wrestler (2008)
  • True Grit (2008)
  • Rien à Declarer (2010)
  • Horrible Bosses (2011)

Capsule Movie Reviews Vol.2011.8

  • Network (1976)
  • Brazil (1985)
  • The Hudsucker Proxy (1994)
  • Eternal Sunshine of the Spotless Mind (2004)
  • Operation: Endgame (2010)

Capsule Movie Reviews Vol.2012.1

  • The Cook the Thief His Wife & Her Lover (1989)
  • La Pianiste (2001) (fr)
  • Dogville (2003)
  • OSS 117: Le Caire, nid d’espions (2006) (fr)
  • Bienvenue chez les Ch’tis (2008) (fr)
  • The Imaginarium of Doctor Parnassus (2009)
  • Antichrist (2009)
  • Micmacs à tire-larigot (2009) (fr)

Capsule Movie Reviews Vol.2012.2

  • Forgetting Sarah Marshall (2008)
  • The Killer Inside Me (2010)
  • The Black Swan (2010)
  • The Fighter (2010)
  • Drive (2011)

Capsule Movie Reviews Vol.2012.3

  • Die Wannseekonferenz (1987) (de)
  • Equilibrium (2002)
  • The Inside Man (2006)
  • Ip Man (2008)
  • The Town (2010)

Capsule Movie Reviews Vol.2012.4

  • The Meaning of Life (1983)
  • Pitch Black (2000)

Capsule Movie Reviews Vol.2012.5

  • Demolition Man (1993)
  • Chocolate (2008)
  • The Descendants (2011)

Capsule Movie Reviews Vol.2012.6

  • 2081 (2009)

Capsule Movie Reviews Vol.2012.7

  • Midnight Express (1978)
  • Platoon (1986)
  • Captain America (2011)
  • In Time (2011)

Capsule Movie Reviews Vol.2012.8

  • Get Shorty (1985)
  • I Heart Huckabees (2004)
  • Kiss Kiss Bang Bang (2005)
  • Paprika (2006)
  • Superbad (2007)
  • Ted (2012)

Capsule Movie Reviews Vol.2012.9

  • Blade Runner (1982)
  • Joe vs. The Volcano (1990)
  • Examined Life (2008)
  • Rare Exports: A Christmas Tale (2010)
  • Tucker and Dale vs. Evil (2010)
  • Cabin in the Woods (2012)

Capsule Movie Reviews Vol.2013.1

  • Old Boy (2003)
  • Manufactured Landscapes (2006)
  • The End of Poverty (2008)
  • Objectified (2009)
  • Pandorum (2009)

Capsule Movie Reviews Vol.2013.2

  • Syriana (2005)
  • Tropic Thunder (2008)

Capsule Movie Reviews Vol.2013.3

  • The Big Lebowski (1998)
  • The Prestige (2006)
  • Flight (2012)

Capsule Movie Reviews Vol.2013.4

  • Kill Bill (2003)

Capsule Movie Reviews Vol.2013.5

  • Alien (1979)

Capsule Movie Reviews Vol.2013.6

  • Slap Shot (1977)
  • Repo Men (2009)
  • Lockout (2012)

Capsule Movie Reviews Vol.2013.7

  • Apocalypse Now (1979)
  • Natural Born Killers (1994)
  • Constantine (2005)
  • Sunshine (2007)
  • The Mechanic (2011)
  • Cloud Atlas (2012)

Capsule Movie Reviews Vol.2013.8

  • Catch 22 (1970)
  • Safe (2012)
  • 2 Guns (2013)

Capsule Movie Reviews Vol.2013.9

  • Looper (2012)
  • The Animatrix (2003)

Capsule Movie Reviews Vol.2013.10

  • Pi (1998)
  • eXistenz (1999)
  • Mark of Cain (2001)
  • Running Scared (2006)
  • Entre les Murs (2008)
  • Defamation (2009)
  • Kill the Irishman (2011)
  • How to Make Money Selling Drugs (2012)
  • The House I Live In (2012)
  • Redemption (2013)

Capsule Movie Reviews Vol.2014.1

  • The Thing (1982)
  • The Adventures of Priscilla, Queen of the Desert (1994)
  • Memories of Murder (2003)
  • Renaissance (2006)
  • Warrior (2011)
  • The Act of Killing (2012)

Capsule Movie Reviews Vol.2014.2

  • The Brood (1979)
  • Dead Ringers (1988)
  • Adaptation (2002)

Capsule Movie Reviews Vol.2014.3

  • Election (1999)

5 months Ago

OpenBSD takes on OpenSSL

Published by marco on in Technology

 Much of the Internet has been affected by the Heartbleed (Wikipedia) vulnerability in the widely used OpenSSL server-side software. The bug effectively allows anyone to collect random data from the memory of machines running the affected software, which was about 60% of encrypted sites worldwide. A massive cleanup effort ensued, but the vulnerability has been in the software for two years, so there’s no telling how much information was stolen in the interim.

The OpenSSL software is used not only to encrypt HTTPS connections to web servers but also to generate the certificates that undergird those connections as well as many PKIs. Since data could have been stolen over a period of two years, it should be assumed that certificates, usernames and passwords have been stolen as well. Pessimism is the only sure way.

In fact, any data that was loaded into memory on a server running a pre-Heartbleed version of the OpenSSL software is potentially compromised.

How to respond

So we should all generate new certificates, ensuring that the root certificate from which we generate has also been re-generated and is clean. We should also choose new passwords for all affected sites. I use LastPass to manage my passwords, which makes it much easier to use long, complicated and most importantly unique passwords. If you’re not already using a password manager, now would be a good time to start.

And this goes especially for those who tend to reuse their password on different sites. If one of those sites is cracked, then the hacker can use that same username/password combination on other popular sites and get into your stuff everywhere instead of just on the compromised site.

Forking OpenSSL

Though there are those who are blaming open-source software, we should instead blame ourselves for using software of unknown quality to run our most trusted connections. That the software was designed and built without the required quality controls is an entirely different issue.

An advantage of open-source software is that at least we can pinpoint exactly when a bug appeared. Another is that the entire codebase is available to all, so others can jump in and try to fix it. Sure, it would have been nice if the expert security programmers of the world had jumped in earlier, but better late than never.

The site OpenSSL Rampage follows the efforts of the OpenBSD team to refactor and modernize the OpenSSL codebase. They are documenting their progress live on Tumblr, which collects commit messages, tweets, blog posts and official security warnings that result from their investigations and fixes.

They are working on a fork and are making radical changes, so it’s unlikely that the changes will be taken up in the official OpenSSL fork but perhaps a new TLS/SSL tool will be available soon.

VMS and custom memory managers

The messages tell tales of support for extinct operating systems like VMS, whose continued support makes for much more complicated code to support current OSs. This complexity, in turn, hides further misuses of malloc as well as misuses of custom buffer-allocation schemes that the OpenSSL team came up with because malloc is too slow”. Sometimes memory is freed twice for good measure.

Lots o’ cruft

This is all sounds horrible and one wonders how the software ran at all. Don’t worry: the code base contains a tremendous amount of cruft that is never used. It is compiled and still included, but it acts as a cozy nest of code that is wrapped around the actual code.

There are vast swaths of script files that haven’t been used for years that can build versions of the software under compilers and with options that haven’t been seen on this planet since before .. well, since before Tumblr. For example, there’s no need to retain a forest of macros at the top of many header files for the Metrowerks compiler for PowerPC on OS9. No reason at all.

There are also incompatibly licensed components in regular use as well as those associated with components that don’t seem to be used anymore.

Modes and options and platforms: oh my!

There are compiler options for increasing resiliency that seem to work. Turning these off, however, yields an application that crashes immediately. There are clearly no tests for any of these modes. OpenSSL sounds like a classically grown system that has little in the way of code conventions, patterns or architecture. There seems to be no one who regularly cleans out and decides which code to keep and which to make obsolete.

Security professionals wrote this?

This is to say nothing of how their encryption algorithm actually works. There are tales on that web site of the developers desperately having tried to keep entropy high by mixing in the current time every once in a while. Or even mixing in bits of the private key.

A lack of discipline (or skill)

The current OpenSSL codebase seems to be a minefield for security reviewers or for reviewers of any kind. A codebase like this is also terrible for new developers, the onboarding of which you want to encourage in such a widely used, distributed, open-source project.

Instead, the current state of the code says: don’t touch, you don’t know what to change or remove because clearly the main developers don’t either. The last person who knew may have died or left the project years ago.

It’s clear that the code has not been reviewed in the way that it should be. Code on this level and for this purpose needs good developers/reviewers who constantly consider most of the following points during each review:

  • Correctness (does it do what it should? Does it do it in an acceptable way?)
  • Patterns (does this code invent its own way of doing things?)
  • Architecture (is this feature in the right module?)
  • Security implications
  • Performance
  • Memory leaks/management (as long as they’re still using C)
  • Supported modes/options/platforms
  • Third-party library usage/licensing
  • Automated tests (are there tests for the new feature or fix? Do existing tests still run?)
  • Comments/documentation (is the new code clear in what it does? Any tips for those who come after?)
  • Syntax (using braces can be important)

Living with OpenSSL (for now)

It sounds like it is high time that someone does what the BSD team is doing. A spring cleaning can be very healthy for software, especially once it’s reached a certain age. That goes double for software that was blindly used by 60% of the encrypted web sites in the world.

It’s wonderful that OpenSSL exists. Without it, we wouldn’t be as encrypted as we are. But the apparent state of this code bespeaks of failure to manage on all levels. The developers of software like this must be better than this. They must be the best of the best, not just anyone who read about encryption on Wikipedia.

OpenSSL will be with us for a while. It may be crap code and it may lack automated tests, but it has been tested and used a lot, so it has earned a certain badge of reliability and predictability. The state of the code means only that future changes are riskier but not that the current software is not usable.

Knowing that the code is badly written should make everyone suspicious of patches—which we now know are likely to break something in that vast pile of C code—but not suspicious of the officially supported versions from Debian and Ubuntu (for example). Even if the developer team of OpenSSL doesn’t test a lot (or not automatically for all options, at any rate—they may just be testing the “happy path”), the major Linux distros do. So there’s that comfort, at least.