ETT-1346: testing for populate_rights_data.pl#79
Conversation
aelkiss
commented
May 12, 2026
- wrap populate_rights_data.pl in "main" function so we can unit test
- use Test2::Tools::Spec (similar to Test::Spec but maintained)
- remove unused --source option from populate_rights
- don't set a default source (from old HT-1733)
| 'archive=s' => \$archive, | ||
| 'rights_dir=s' => \$rights_dir, | ||
| 'note=s' => \$note, | ||
| 'source=s' => \$new_source_cmdline, |
There was a problem hiding this comment.
As far as I know this is not an option we would ever use.
| } | ||
|
|
||
| # Structure to keep track of results - which records were created. | ||
| my %results; |
There was a problem hiding this comment.
As written now, these need to be global, which makes this a bit more difficult to test. We could consider turning this whole thing into an object to have some place to store those results.
| print $rights "prtest.goodline2\tpd\tbib\ttestuser\tgoogle\n"; | ||
| close($rights); | ||
|
|
||
| my $res = qx(perl -w bin/populate_rights_data.pl --data=$tempdir/testfile3.rights --archive=$tempdir/archive 2>&1); |
There was a problem hiding this comment.
I wanted to avoid too much refactoring without tests. Adding main got it to the point where we could unit test anything, but running main itself leaves things in a weird state and potentially calls exit and ends the tests early. I guess the question is if it's worth it right now to do more refactoring on populate_rights_data.pl to make this more amenable to integration tests as well without needing to shell out.
There was a problem hiding this comment.
I would put a ticket in to refactor the logic in a more OO way, but would be perfectly satisfied with the new level of testing represented here.
7feb98f to
cacc03f
Compare
|
@moseshll questions to consider for review:
|
| use File::Temp qw(tempdir); | ||
| use POSIX qw(strftime); | ||
| use Test2::Bundle::Extended; | ||
| use Test2::Tools::Spec; |
There was a problem hiding this comment.
This is similar to Test::Spec in syntax, but appears to be maintained.
| like $@, qr(Invalid source); | ||
| }; | ||
|
|
||
| it "requires source if not previously loaded" => sub { |
There was a problem hiding this comment.
This is new behavior. Bib rights is generally responsible for getting the "source" (digitizer) from the Zephir metadata and setting it. In practice, this prevents us from accidentally loading rights for things that aren't in the repository.
| is([2,1,4],$rights); | ||
| }; | ||
|
|
||
| it "new source updates access profile (as specified in sources)" => sub { |
There was a problem hiding this comment.
The access profile stuff is kind of a mess; it's specified in multiple tables -- ht_collection_digitizers as well as sources. Ideally we'd probably be using ht_collection_digitizers in preference to sources. (There are also multiple keys for the digitization agent, and part of this stems from work around sources and access profiles that was started in 2014 and never fully completed after some staff departures.)
| ok($?); | ||
| ok($res =~ /Invalid namespace\/barcode/); | ||
|
|
||
| # Should have loaded goodline1, but not goodline2 (since it bailed out after badline) |
There was a problem hiding this comment.
I'm not sure this is really the behavior that we want, but it is the current behavior.
We should probably consider what we want to happen in this case -- I suspect ideally it would load the rest of the file and alert us in some way to the problem line, or maybe load nothing (but still alert.) Loading part of the file seems like a recipe for problems.
There was a problem hiding this comment.
Personally I do not like the idea of loading part of a file. Bad lines should be skipped and reported, and since they're independent of each other a bad one need not bring everything to a halt. (I suspect the most likely issue we will see is Unicode or other text weirdness in the note field.)
|
I have a couple of suggestions. is a repeated trope that can be stuck in something like Another thing I would add to increase coverage (and in the gfv overrides tests. More test coverage we want in place for OO refactor. In the main the changes make sense and seem well exercised. The coverage achieved here is respectable for a monolith with so much edge case resilience baked in. |
moseshll
left a comment
There was a problem hiding this comment.
I would definitely add the suggested additional gfv tests, provided they are actually correct (I think they are). All else passes muster.
|
I don't think I went ahead and added the gfv tests. I also did some other refactoring for readability and work on the way towards the desired behavior w/ access profile for harvard material. |
|
Verified the constant checks for database error don't do anything -- if there is a database error, DBI raises an exception itself rather than returning, at least in the way we're using it. |
|
What's here now passes the tests and I believe implements the requirement around using the 'open' access profile for Harvard, but there are several things we should fix while we have the opportunity; having the tests enables refactoring. I went ahead and removed the explicit error checking for database operations, because I don't think it was doing anything. I set this to draft for now; there are a few things I'd like to do:
If it makes sense to extract some objects in the course of doing that I think there's no reason to hold off. |
|
This also has the risk of becoming a bigger/long running PR, and it might make sense to draw a line at adding the tests and doing a little bit of the cleanup/refactoring before moving on to the support for the Harvard access profiles. @moseshll let me know what you think; again, I can take care of that when I'm back. |
|
@moseshll Let me know what you think about the new commits since you last reviewed and where to draw the line here with what we merge:
|
|
@aelkiss I would suggest addressing items #1 (partial file load "bug") and #3 (pre-fetch) from the checklist you have above. The former because it's kinda yucky. The latter is an opportunity to get some more into I optimistically put some of this ticket on my TODO notes but alas it stayed buried near the back of the LIFO. |
| } | ||
| while (my ($priority, $codes) = each %$priorities) { | ||
| if (grep {$_ eq $code} @$codes) { | ||
| warn("$attr/$reason has two priorities ($priority and $toreturn)??") if defined $toreturn; |
There was a problem hiding this comment.
An argument could be made for not doing this check at all here, but instead checking the data for > 1 priority assigned to a rights combination as part of the tests. Since by the presence of this line it is worth checking for. Better to fail test than be warned at runtime.
There was a problem hiding this comment.
I've pushed a fix that obviates the need for this by inverting the hash.
|
Sounds good. I'll aim to work on this next week. |
ad2c87a to
a8bec4c
Compare
|
@moseshll I've addressed everything I think I'm planning to at this time. However, I'm rethinking the partial load thing. Right now, we have no way to get alerted when there are problems in a file. So far as I know, we haven't ever really run into the case of malformed rights files in production (this would be more likely to happen if we were manually generating rights files, which we don't any more.) However, what we could run into is a database issue, which would succeed if retried. In the current production behavior, a file that's only partially been processed will be left in the directory to be automatically retried later. If we report the failures but continue on, we will move the file to the processed area and be unaware of the failures. If we instead keep the current retry process, we could still end up with a situation where there are flappings rights -- e.g. a file with a partial failure gets loaded over and over again, overriding later generated rights. Ultimately I'm not sure what makes sense to do without significant changes to the whole process, so @moseshll I think we should discuss further. |
|
That said, I think my leaning @moseshll is that the current behavior (bail out and leave the file in the 'to process' directory) is somewhat safer given that the more likely source of problems is database connection issues or other external, temporary issues rather than issues with the data. If we were able to easily separate out data issues from database issues, maybe I'd lean the other way, but Perl's entirely text-based free-form exception system leaves something to be desired on that front. I suppose we could include some kind of tag if there was a data issue and skip that line if so, and re-raise if not, BUT given that (so far as I know) there's never been a data issue with automatically generated rights files, that level of complexity is probably not worth it right now. In any case @moseshll let me know what you think but my leaning at this point is to:
|
moseshll
left a comment
There was a problem hiding this comment.
I agree with the reversion to "bail out and leave for subsequent run" approach. Other than that, what we have here is plenty good. APPROVE
* wrap populate_rights_data.pl in "main" function so we can unit test * use Test2::Tools::Spec (similar to Test::Spec but maintained) * remove unused --source option from populate_rights * don't set a default source (from old HT-1733)
* add constants for numerical values
* make process_rights_line tests more readable by using join("\t",...)
* stub out tests for harvard access profile (skipped; currently failing)
* use selectrow_array when only fetching a single value
* use placeholders for values selectrow_arrayref (more to do)
* add additional gfv tests
* Avoid explicit error checking -- if there is an error, the DBI functions themselves raise an exception. * Prepare statements for things previously using selectrow_arrayref / selectcol_arrayref in populate_rights_data.pl
a8bec4c to
c436422
Compare
Initial pass at updating access profile for Harvard material based on scan date.
https://metacpan.org/pod/DBI#finish says: "When all the data has been fetched from a SELECT statement, the driver will automatically call finish for you. So you should not call it explicitly except when you know that you've not fetched all the data from a statement handle and the handle won't be destroyed soon." Generally we're fetching one row from things that should return one or zero rows, so there isn't a need to use it.
* reduces number of database calls * simplifies nested conditionals
Avoids issue of needing to search arrays and the possibility of values being present for multiple keys. Removes unused 'orph/ddd' and 'orphcand/ddd' combinations.
c436422 to
bb2e086
Compare
|
I backed out that commit. I'm going to go ahead and merge this, but I'll wait until next week to deploy. |