Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 3323738
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 17, 20262026-05-17T23:20:17+00:00 2026-05-17T23:20:17+00:00

How can I test that resource (file based cache for caching output of a

  • 0

How can I test that resource (file based cache for caching output of a webapp in Perl) behaves sanely under concurrent access to said shared resource?

I wrote a simple file-based cache, written in Perl, which uses locking to serialize write access, i.e. to have only one process that (re)generates cache entry. This cache is to be used for caching output of Perl webapp (gitweb), if it matters.

I’d like to test that said cache behaves sanely under concurrent access, for example that only one process would run subroutine used to generate cache ($cache->compute($key, sub { ... })), that all processes would get generated data, that if process writing to cache entry dies it wouldn’t deadlock processes waiting for cache to be (re)generated etc.

How should I do it? Is there a ready Perl module that I can use?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-17T23:20:18+00:00Added an answer on May 17, 2026 at 11:20 pm

    In the end I based my work on Unix for Perl programmers: pipes and processes by Aaron Crane; though in those notes he simplified things to not deal with reading from multiple processes without locking (in those notes temporary file is used for second stream).

    The code uses only Test::More and no non-core Perl modules

    #!/usr/bin/perl
    
    use warnings;
    use strict;
    
    use POSIX qw(dup2);
    use Fcntl qw(:DEFAULT);
    use IO::Handle;
    use IO::Select;
    use IO::Pipe;
    
    use Test::More;
    
    # [...]
    
    # from http://aaroncrane.co.uk/talks/pipes_and_processes/
    sub fork_child (&) {
        my ($child_process_code) = @_;
    
        my $pid = fork();
        die "Failed to fork: $!\n" if !defined $pid;
    
        return $pid if $pid != 0;
    
        # Now we're in the new child process
        $child_process_code->();
        exit;
    }
    
    sub parallel_run (&) {
        my $child_code = shift;
        my $nchildren = 2;
    
        my %children;
        my (%pid_for_child, %fd_for_child);
        my $sel = IO::Select->new();
        foreach my $child_idx (1..$nchildren) {
            my $pipe = IO::Pipe->new()
                or die "Failed to create pipe: $!\n";
    
            my $pid = fork_child {
                $pipe->writer()
                    or die "$$: Child \$pipe->writer(): $!\n";
                dup2(fileno($pipe), fileno(STDOUT))
                    or die "$$: Child $child_idx failed to reopen stdout to pipe: $!\n";
                close $pipe
                    or die "$$: Child $child_idx failed to close pipe: $!\n";
    
                # From Test-Simple-0.96/t/subtest/fork.t
                #
                # Force all T::B output into the pipe (redirected to STDOUT),
                # for the parent builder as well as the current subtest builder.
                {
                    no warnings 'redefine';
                    *Test::Builder::output         = sub { *STDOUT };
                    *Test::Builder::failure_output = sub { *STDOUT };
                    *Test::Builder::todo_output    = sub { *STDOUT };
                }
    
                $child_code->();
    
                *STDOUT->flush();
                close(STDOUT);
            };
    
            $pid_for_child{$pid} = $child_idx;
            $pipe->reader()
                or die "Failed to \$pipe->reader(): $!\n";
            $fd_for_child{$pipe} = $child_idx;
            $sel->add($pipe);
    
            $children{$child_idx} = {
                'pid'    => $pid,
                'stdout' => $pipe,
                'output' => '',
            };
        }
    
        while (my @ready = $sel->can_read()) {
            foreach my $fh (@ready) {
                my $buf = '';
                my $nread = sysread($fh, $buf, 1024);
    
                exists $fd_for_child{$fh}
                    or die "Cannot find child for fd: $fh\n";
    
                if ($nread > 0) {
                    $children{$fd_for_child{$fh}}{'output'} .= $buf;
                } else {
                    $sel->remove($fh);
                }
            }
        }
    
        while (%pid_for_child) {
            my $pid = waitpid -1, 0;
            warn "Child $pid_for_child{$pid} ($pid) failed with status: $?\n"
                if $? != 0;
            delete $pid_for_child{$pid};
        }
    
        return map { $children{$_}{'output'} } keys %children;
    }
    
    # [...]
    
    @output = parallel_run {
        my $data = $cache->compute($key, \&get_value_slow);
        print $data;
    };
    is_deeply(
        \@output,
        [ ($value) x 2 ],
        'valid data returned by both process'
    );
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

How can I test if a file is identical in all branches that it
How can I test that a gen_fsm does indeed timeout with eunit? {ok, GH}
Can someone tell me why this unit test that checks for exceptions fails? Obviously
I'd like to use JMeter test that I can send a message to a
I have a feature that uses the camera so I can test it only
I hate generating an exception for things that I can simply test with an
As topic suggested, how can I unit test a function that does not return
How can it be that this test case import unittest class PropTest(unittest.TestCase): def test(self):
Let's say I have a subroutine/method that a user can call to test some
When using NUnit, I can turn off shadow copy so that my test assemblies

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.