devlog > testing

Writing bad crypto code

Captain's Log: Stardate 78089.3

Today I tried to slam out as much work as I could on the lower-level c++ code to do all the license activation stuff. Since I got all the PITA stuff done yesterday to get openssl, libcurl, etc, working, today was actually fairly productive. The c++ code now has APIs to call the license API server to register a new license key, save the signed key to disk, check if the key is still valid, and so on.

I find all this anti-piracy stuff pretty annoying/frustrating, since none of the work makes the plugin more fun to use. And one particular worry I have is that I want to make VERY sure that it never screws over someone who has paid for the software. So I have been thinking a lot about testing the license activation code. I wrote a few unit tests, but eventually got to the HTTP parts, and mocking out the HTTP responses just didn't feel great.

The solution I came to was to actually just write a bunch of integration tests that have the c++ license activation/verification code call the production license API server. I added some hidden/test-only APIs that allow the integration tests to reset the server state, and created a test-only license key. So the tests actually go through all the real flows a user will go through and make sure the c++ code and the API server talk to one another correctly, and that the API database reflects the correct state, etc.

I'm quite happy with this testing solution, because it gives me a ton of confidence that the client/server interactions all work the way they should. And since nothing is mocked, it's a really faithful test of what the actual binary will do.

Tomorrow I'll start on the c++ GUI for entering the license key and so on.

Prepping website for pre-alpha

Captain's Log: Stardate 78026.5

I've been having a lot of fun working on the website, so I'm going with that and focusing on getting a lot of web stuff done.

Auth is working pretty well now, and I'm starting to get set up to send the various account lifecycle emails. I have a bit of a start on some of the ancillary auth stuff like password resets and so forth, and have figured out how React form actions work, which let me clean up all the various auth forms. Form fields are validated server-side and the errors are automatically shown inline in the form client-side, it's all very nice and simple. (I continue to be impressed and pleased with React and next.js.)

I've also done some annoying grunt work like setting up CSRF protections that automatically work on all forms.

Given how fast this is all going, I probably will just charge forward on the website until it's basically read for a closed pre-alpha, in terms of providing the API endpoints for product key registration, and the GUI for managing product keys. This isn't strictly necessary at this point, but it certainly won't hurt to test out the web stuff during the pre-alpha, and like I said, I'm having fun building it so why not?

Don't ever use boost::numeric::interval

Captain's Log: Stardate 78014.7

I burned the first half of the day reviewing a bunch of legal stuff that I need for the business -- the EULA, privacy policy, website terms, etc. This has to be the least exciting part of the whole project, and as much as I'd like to just skip it, if there's any chance that the product will be even moderately successful I really do need this stuff. Fortunately, the lawyer I hired specializes in small tech businesses, so he understood what I am doing super-quickly. Hopefully in another week or so I'll have final documents and won't have to use any further brain cells on legal matters.

Code-wise, I finally just got fed up with boost::numeric::interval and wrote my own. The frustrating thing is that I started with my own Interval class, and when I saw there was a Boost one I figured, "why not use it?" I needed a few of the handy methods it had (hull, median, etc) and figured it was a great implementation.

WRONG. The API is fine, but the implementation is vastly over-complex and it is incredibly difficult to understand what conditions it will throw exceptions under. For example, for my PrecisionSlider implementation, an interval where the lower and upper bound are the same (a "singleton") is used to represent a slider that displays a single point, not a range. (Duh.) This works fine most of the time, but some of the GUI fuzz tests were failing under rare/obscure cases where the boost library would throw a "not supposed to be a singleton" exception.

I looked into how to disable that, and what caused it in the first place, and... dear lord the code is horrible. After 10 minutes of noodling on whether I needed the policy "checking_no_nan<>" (which allows nan) or "checking_catch_nan<>" (which throws nan, i.e. the opposite of catching it), I threw the whole library in the incinerator and burned it.

Now I have a 25-line Interval class again that does exactly what I need and can be understood by a 6 year old. Sigh...

Loading...

© 2024 Anukari LLC, All Rights Reserved
Contact Us|Legal