Showing posts with label testing. Show all posts
Showing posts with label testing. Show all posts

Tuesday, May 27, 2025

Fix: Large file upload tests in a Rails app start failing after bumping rack to 3.0.16

Problem: After bumping the Rack gem in a Rails app from 3.0.14 to 3.0.16, a couple of tests which tested an HTTP POST of a large-ish (~30 MB) PDF file to a controller started failing. Other similar tests, which did not upload a large file, continued passing.

The failure symptom was the POST returning an HTTP 400 Bad Request error. The error was returned before the request made it to any of our application code (as evidenced by none of our breakpoints being hit, or debug statements appearing in the output log).  

For our particular test, the specific error message was: Minitest::Assertion: Expected response to be a <413: payload_too_large>, but was a <400: Bad Request>

Fortunately, there were no other gem dependencies that came with the bump of Rack to 3.0.16. So we knew the problem must be caused by some change in Rack 3.0.15 or 3.0.16. 

Solution: The single item in the rack 3.0.16 release notes did turn out to be the pertinent change:

Security: CVE-2025-46727 Unbounded parameter parsing in Rack::QueryParser can lead to memory exhaustion.

As that linked advisory mentions, a new check is added in rack 3.0.16 that turns away "extremely large" application/x-www-form-urlencoded bodies. From this nist.gov page on CVE-2025-46727, links were available to the fix's specific code changes. From the first linked change, we can see that a "BYTESIZE_LIMIT" of 4194304 (a little over 4 MB) is now imposed on application/x-www-form-urlencoded request bodies. 

Per the mozilla.org page on HTTP POSTapplication/x-www-form-urlencoded is only one possible form Content-Type HTTP header value -- and not the one that is supposed to be used with binary data, such as PDF file uploads! Instead, multipart/form-data should be used.

Our original unit test code was actually not specifying any Content-Type HTTP header value in our test POST request. Changing the test's POST request to additionally send the HTTP header Content-Type: multipart/form-data fixed the problem, and got our test passing once again.

Aside: When I spent a minute during the investigation to ask ChatGPT about this problem -- a POST request failure introduced as of Rack 3.0.16, possibly due to a large request payload -- ChatGPT obligingly hallucinated up a plausible-sounding (but 100% fictional) response about Rack introducing a default limit in POST request payload size, and a corresponding plausible-sounding (but 100% fictional) response about a configuration line to be added to config/applicaiton.rb to override the supposed new behavior. 😂🙄

Wednesday, July 13, 2016

C# Reflection: Setting a private enum-type member variable with a private inner enum type value

Today, while creating a C# unit test, I had a situation where I needed to set the value of a private variable on the class under test.  The variable was an enum-type variable, where the enum type itself was a private inner type defined in the class under test.

(I won’t in this post get into why I ended up landing on doing this, instead of some other solution such as refactoring the actual class under test in order to avoid the need to do so, as that would be a separate discussion.)

This post describes the technique using reflection that I ended up using to accomplish this.

For example, given a class defined like:

class Card
{
    private Suit _suit;

    private enum Suit
    {
        Hearts,
        Diamonds,
        Clubs,
        Spades
    }
}

Given an instance of that class named card, I was able to set the value of that object's private _suit variable by doing:

using System.Reflection;

...

// Get a reference to the _suit member variable.
FieldInfo suitField = card.GetType().GetField("_suit", BindingFlags.NonPublic | BindingFlags.Instance);

// Get a reference to the Spades member of the Suit enum.
object spades = card.GetType().GetNestedType("Suit", BindingFlags.NonPublic).GetField("Spades").GetValue(card);

// Set the value of _suit on our card object to Spades.
suitField (card, spades);

This kind of reflection hackery probably isn’t a best practice in most situations! Still, I thought it might be helpful to record here as an aid for those rare situations where it does make sense to manipulate this kind of enum-type private variable for unit testing purposes.

Wednesday, May 19, 2010

HTPC Build Part 4 - Testing an Intel-based HTPC

This is the forth in a series of posts I’m writing about an HTPC (Home Theatre PC) build that I recently completed.  To see a list of all posts in this series, click here.

Before finalizing a parts list and placing an order for the parts for my new HTPC build, I was fortunate to be able to gain access to a "test machine": A newly-built, working HTPC that my friend Dave was kind enough to let me borrow for a few days.  Specs on this machine:

CPU Intel Core 2 Quad
Motherboard Intel BOXDG43GT LGA 775
Memory 2 GB Kingston DDR2-800
Onboard Video Intel GMA X4500 with HDMI
Add-on Video Card (None)
Operating System Windows 7 Home Premium 64-bit

I brought the Intel HTPC home and hooked it up to my TV, a Philips 3000 series LCD HDTV.  As with the old 2004 PC that I tested using as an HTPC, the Intel test PC had some pros and cons.  Pros first:

  • The PC ran very silently -- there was no noticeable fan noise at all while the machine was on.
  • It was easy to connect the PC to the TV via the built-in HDMI port, and both video and sound output were transmitted from the PC to the TV via a single HDMI cable.
  • No problems at all with HD video playback.

I ran into a significant problem, though: When rendering video output at the TV's native resolution (1920x1080), the rendered screen image was "too big" for the TV.  The edges of the Windows desktop, including the taskbar and Start button, were off the screen.  Those elements were still present -- I could move the mouse off the screen to where the Start button should be located, click, and (partially) see the Start menu appear -- I just couldn't see them.

After spending a while trying to research this problem online but running into problems getting quality Google search results when trying to search using terms like "htpc tv image too large" or "tv display edges not visible" (and multiple other variants), I finally came across an article where I learned that there is a specific word for this phenomenon: Overscan

Now, searching with search terms including the word "overscan," the quality of search results I was able to find markedly improved.  However, I was still unable to solve the problem; in several hours of trying, I was unable to correct for the overscan either from the PC side, or from the TV side.

Most PC monitors include geometry controls that allow the screen image size, but there were no such controls available in the my TV's built in software menu.  In further poking around online, I found an avsforum.com thread that described how to access a "secret" admin/service menu where additional TV controls could be accessed; I actually got this to work on my TV and accessed the TV menu (after bypassing a warning about possibly voiding my warranty -- the TV is out of warranty anyway), but on my TV, there were no geometry controls in the admin menu, either.  Finally, I tried to do a firmware update for the TV's software to see if a later version would have the geometry controls I was looking for, but the TV reported that it was already running the latest version of the software when I tried to apply the update via the TV's built-in USB port.

I also investigated correcting the overscan on the PC end of things.  The Intel video card comes with software that allows a lower screen resolution to be sent to the monitor/TV to correct for overscan; however, whenever I tried to apply a "non-standard" lower resolution, the Intel software itself complained that the target resolution was not supported by my display.  Setting the screen to the next-lowest standard widescreen resolution (1680x1050) resulted in wide areas of black around all four edges of the display, so that wasn't a good solution either.  I tried updating to the latest version of the Intel video driver and video software utility package, but that didn't help either.

So, I was left with the question of whether the overscan problem would be a deal-breaker for my intended uses of the HTPC.  My goals for the HTPC were as follows:

Primary goal:

  • Be able to automatically record and playback HDTV program broadcasts.  (Tivo-like DVR functionality)

Secondary goals:

  • Be able to use the HTPC as a secondary home PC, i.e. to do things like browse the Web, check email, and view photos and videos.
  • Be able to play DVD movies (and later, Blu-Ray movies, once the price of Blu-Ray optical drives drops).
  • Be able to play old NES, SNES, and N64 games that I own the cartridges for (via emulation).
  • Be able to play newer games while sitting on the couch and using my XBox 360 controller for PC -- have the HTPC act as a "poor man's XBox 360." (Ironically, though, an actual XBox 360 now retails for significantly less than my overall budget for the HTPC!)

With respect to the primary goal of playing back HDTV content, I needed to be able to use the Windows Media Center (WMC) interface in order to accomplish this.  With the overscan problem, several of the key UI elements of Windows Media Center appeared off the screen.  However, I found a post on Aaron Stebner's WebLog detailing a series of registry keys that can control advanced options in Windows Media Center.  Using these registry tweaks, I was able to get WMC to "pull in" from the screen edges its various UI elements, such that everything was visible on my screen, even with the overscan.  Pretty cool.

However, I had no such luck with applications outside of Windows Media Center.  With the Windows taskbar, the Start button, and the edges of the Windows desktop being out of view, using the HTPC as a regular Windows PC wasn't a very nice experience. 

I also encountered one other problem: On the Windows desktop, thin black lines (such as "divider lines" in various applications) sometimes rendered on screen with quite a bit of "flicker".  This didn't make the display unusable, but it was pretty annoying to look at.

Between the overscan problem and the "flicker" problem, I made a decision not to go with an onboard Intel video card for my final HTPC build.  Having had good experiences with ATI video cards in the past, I decided I would instead go with an AMD-based build including an onboard ATI video card. (The processor company AMD acquired the video card company ATI back in 2006, so now AMD is presumably using the solid ATI technology in its onboard video cards.)

I did also do some testing with the Intel machine with my secondary goals in mind.  Old NES and SNES games ran just fine on the PC via emulation; I was worried there might be some lag time between controller button presses and the responsiveness of the games, but there was no noticeable lag at all, and the games I tested were very playable. 

WoW_OverscanCrop2 I also tested a couple of newer games: World of Warcraft, and Batman Arkham Asylum.  Warcraft (being a 5-year-old game at this point) ran quite acceptably when configured to use lower-end video settings.  However, the game was affected by the overscan issue, making the action button bar at the bottom of the game window partially invisible, resulting in the game being not very playable, at least in full-screen mode.  (The screen capture at right approximates what I was seeing on my HDTV in terms of the game image being clipped.)

Batman Arkham Asylum, a newer game, ran on the PC, but the game ran very slowly, even on minimum video settings.  Although the game ran, it wasn't really playable.  Somewhat interestingly, rather than drop frames and run at normal speed but with a poor framerate, the game just slowed down the overall gameplay to match the throughput that the video card was able to produce -- the end result was although the display was smooth, the game just ran at about 50% of normal speed (so it took Batman an unusually long time to walk from place to place, etc.). 

The poor performance of the Batman game was actually in line with my expectations: I didn't expect the onboard video card to be performant for high-end gaming.  My plan at this point is to run with only onboard video for the time being (sacrificing the goal of being able to use the HTPC as a "poor man's XBox 360"); at some point in the future, I'll purchase an add-on video card for the machine (or maybe, I'll purchase a new video card for my primary desktop PC, and do a hand-me-down of that PC's old video card to the HTPC).

The next post in this series will (finally!) cover my final HTPC parts list, and my experiences with the completed build.

Monday, September 08, 2008

How to: Get Firefox to discard a cached set of basic authentication credentials

While using Firefox 3 to work with a web application that uses basic authentication for access control earlier today, I wanted to be able to log in to the application as a different user account without needing to close and restart Firefox in order to get it to stop automatically resending the authentication data from my original login.  (After logging in to a site via basic authentication, Firefox will automatically continue to resend the credentials from that login on any subsequent requests to that same site, until the browser is shut down.)

After hunting around for a while looking for a Firefox extension that would do this, I discovered a way to do this built into Firefox itself: In the Tools menu, select Clear Private Data; then in the Clear Private Data dialog that appears, check the Authenticated Sessions checkbox, clear all other checkboxes, and click the Clear Private Data Now button.

ClearPrivateDataAuthenticatedSessions

This will get Firefox to "throw away" its saved basic authentication credentials from the current session, and allow you to log in as another user, without having to close Firefox.  I've found this to be handy when I have a lot of Firefox tabs open, and don't want to shut down Firefox (and close all of my open tabs in the process) just to "log out" of the basic authentication session that I have open in a particular tab.