New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
All CI runs are using the sqlite fallback connection instead of the expected driver #8532
Conversation
OK - I've now got this far enough to identify all the issues. The more I think about it the more I think it's better to move towards structuring the config the way doctrine/dbal does so that the github actions and phpunit configs are equivalent (as they are now). So I've rejigged the logic and config key naming in TestUtil to work the same way. This will mean that if developers have a local phpunit.xml that was working with the older code, they'll have to rename some variables to get their connection working again. Obviously doesn't affect end-users at all. There are still some naming differences between TestUtil here and in dbal, e.g. dbal has There were 3 very minor phpunit failures that I've fixed in 7388aa7. The only thing I'm stuck on is the GH7941 test which I'll annotate separately. Obviously I will deal with coding standards, squashing up commits sensibly etc, just wanted to get a steer first. |
Well… this is embarrassing… thankfully you spotted it before things became too hard to fix, although there are already pretty weird things like this type difference between pdo_mysql and mysqli. Anyway, great job with this!
I'm not sure why we had 2 sets of parameters in the first place, and I'd go with the second solution for the sake of simplicity.
Nice coverage improvement! |
It looks like it's on the assumption you might have a less-privileged user for running the main tests and then a more privileged one to create / drop the databases and run setup etc. I'm not sure how crucial that is. Maybe dbal has some tests that need to run as a less-privileged user to assert permission handling or something and this came from there but isn't really necessary? I'd thought maybe it was in case there were devs / environments where you were happy to provide limited-permission creds but couldn't give root access to the DB. But AFAICS the I can't see any case where it would make sense to be using a different driver or speaking to a different database platform though. Again if you're happy to diverge from dbal it looks like I could just remove the whole |
The privileged credentials are used to create a test database. The regular credentials should be scoped to the test database to run tests there. |
Looks like they are not, since they were apparently used to do that creation. Also, what is the point of this? I know it's good to be close to a real situation, and people will scope restrict credentials in real life to avoid disasters, but I can't imagine what bugs we want to catch here, and there certainly can't be a disaster in the case of the CI. Maybe it's in the case of a local run on the development environment? |
Another reason is that when the test starts, the test database will likely not exist, so if it's used as a parameter of the only connection, this only connection will fail. So we temporarily connect to some other database or don't use any (if the platform allows) and create the database to which the test connection will be able to connect. |
So the question is: why does it currently work? Currently, we only have one connection, and it specifies the database. For mysql and mariadb, there is a simple answer, the database is created because we specify its name as a standard env variable of the docker image:
For PostgreSQL, I have no idea why it works. We have one set of credentials: orm/ci/github/phpunit/pdo_pgsql.xml Lines 10 to 14 in 93f31d2
And there is no mention on the database name in the github workflow. UPD: apparently the database is dropped and re-created every time, so having it created with a Docker variable does not explain how it works for Mysql and MariaDB: orm/tests/Doctrine/Tests/TestUtil.php Lines 38 to 40 in 93f31d2
Ah I think I have a good explanation! Although we can indeed specify a database, it will not be passed on when creating the temporary connection: orm/tests/Doctrine/Tests/TestUtil.php Lines 162 to 171 in 93f31d2
@acoulton IMO you do not need to restore the |
OK, so this is potentially a platform-specific thing, it did fail on the db not existing on an at least one of the builds, possibly postgres, earlier in this branch. Then I updated TestUtil to the full method from dbal, which does this:
So basically if you don't provide explicit details for a privileged connection, it just uses the normal connection config but removes the dbname before connecting. That's how postgres is now able to connect before the database exists, but still only uses one set of credentials / config. In orm, the In dbal, the method is called |
@greg0ire sorry my post crossed with your edit. So yeah, AFAICS the only theoretical use for the That's because TestUtil always attempts to drop and recreate the database at the start of the run - https://github.com/doctrine/orm/blob/2.8.x/tests/Doctrine/Tests/TestUtil.php#L110 - that will ignore a failure on the So there's no scenario at the moment where you can actually run anything without giving doctrine root-level permissions in one or both of those configs. I can't see a case where:
In my mind either you don't care about the db and doctrine can be root, or you care and doctrine can't run at all? |
I guess what I'm saying is, if this was my project I'd remove the entire If the ambition is that a developer should also be able to run locally against a system they care about it would be better that they provide restricted Or I can just tidy up what's here and leave |
I think it hardly makes sense indeed. The only way I could see it having sense is if you decide to trust the code that does the create/drop because it rarely changes,and don't trust code from tests because it might not be as well vetted, and every new line makes it more prone to error. Or you don't want contributors to be able to write tests that perform admin tasks from a concrete tests. IMO these concerns are not super valid. My call would be: let's remove it, but it might be just me. WDYT @beberlei @morozov ? |
6c00742
to
35dbfb6
Compare
OK, I have squashed and tidied what I have so far, which solves the actual current problems. The outstanding questions are whether I should:
|
I've given this more thought, and I think you can compare this to something we do often as developers, which is installing a piece of software like follows:
I think the issue is not one of security, we are not assuming malice here, we are just being cautious with privileges, which can sometimes spare some disasters like this one. I would be (bandwagon) fallacious of me to say that this suddenly makes these concerns valid, but we can't pretend this kind of practice is unheard of, quite the contrary. In the case of the CI, we are ourselves not following that best practice since apparently the main credentials are enough, but that mechanism gives contributors the option to follow it while developing. So I'd keep that
I agree it would be best to remove that fallback mechanism. 👍 I'm not sure about removing the |
Hey @acoulton ! I discussed internally with Benjamin and Sergei, and got the answers you needed:
|
48a855a
to
f29f3e4
Compare
Builds using the github actions phpunit.xml files were not properly recognising driver-specific configuration values, so were all falling back to use the in-memory sqlite database instead of the expected driver. This also meant a number of tests were skipped as they rely on functionality not available in sqlite. This commit addresses that by: * REMOVING the automatic fallback to the sqlite memory database - phpunit.xml must now always specify explicit parameters for the desired connection. * Displaying the active driver in the build output for visibility and debugging. * Changing the way TestUtil loads the database config in line with the equivalent logic in doctrine/dbal, and to support the way that the config is/was specified in the phpunit.xml files for CI. Note that this means a couple of the expected config variable names have changed. Developers that are using customised phpunit.xml files locally will need to update them to provide: * Database config variables if they want to use the sqlite/memory driver - see phpunit.xml.dist for details. * `db_driver` instead of `db_type` * `db_user` instead of `db_username` * `db_dbname` instead of `db_name` * And, if in use, the equivalent changes to the `tmpdb_` values The other change is that now if you provide any value for `db_driver` we will attempt to create that connection type and that will throw if other details (username / password / etc as required by the driver) are not provided. Previously providing partial configuration would cause TestUtil to silently fall back to the in-memory sqlite driver.
These tests had not been running in CI so missed the previous phpunit upgrade. Note that assertions in decimal/floaty values in GH7941Test have been changed to compare numerically with a reasonable level of precision, instead of using regex. This is because the types returned by the different drivers are inconsistent, and phpunit now only allows regex comparisons on strings.
To avoid confusion, the `tmpdb_` test config values are now named `privileged_db_` and better documented in the phpunit.xml.dist. The TestUtil class has been refactored to more closely mirror the structure and method / variable naming of the equivalent in doctrine/dbal. This does not introduce any significant functional changes. The only real difference is that the test output now prints the selected database driver the first time it is referenced, rather than repeating this through the test run.
dc08543
to
61c4a5d
Compare
@greg0ire great - that's all done and tidied up now. I thought it made sense to get rid of the redundant / arbitrary differences between the TestUtil class here and in doctrine/dbal (and their method etc naming is clearer) so have done that too - sorry that makes the diff a little bit harder to follow. The only real diff between those classes now is that we have removed the fallback connection and changed the naming of the |
Thanks a lot for the top-notch quality PR!
Yes please 🙏 |
This commit follows doctrine/orm#8532 to reduce the potential for confusion / error when configuring database connections for unit testing. In particular it: * REMOVES the automatic fallback to the sqlite memory database - phpunit.xml must now always specify explicit parameters for the desired connection. * Displays the active driver in the build output for visibility and debugging. * RENAMES the previous `tmpdb_xxx` test config values to `privileged_db_xxx` to clarify their meaning and usage. Developers that are using customised phpunit.xml files locally will need to update them as follows: * Add new database config variables if they want to use the sqlite/memory driver - see phpunit.xml.dist for details. * Rename the variables for the temporary / privileged database connection if they are using it.
While writing a test for an unrelated issue, I noticed that the unit tests are not loading the expected database connection details. Regardless of the config file provided, the
TestUtil
class is providing the fallback sqlite driver.As a result a) none of the code is being tested against other platforms and b) tests that rely on platform-specific features (e.g. pessimistic locking) are being skipped on all builds.
It looks like this has been the case ever since the migration from Travis CI. Therefore some of the consistently-skipped tests are also not valid with phpunit 9 - e.g.
Doctrine\Tests\ORM\Functional\Locking\LockTest
has two tests that fail due to using->assertContains
with a string argument, which need to be upgraded to->assertStringContainsString
.The root cause is that when the driver-specific phpunit.xml files were updated for github actions, the various
tmpdb_type
/tmpdb_username
etc with the config for the privileged temporary connection were removed. It looks like this might be valid for doctrine/dbal because it falls back to using the main db params however the TestUtil class in doctrine/orm does not and it has a much stricter list of required parameters before it will use the specified driver.I can finish this off, but could you advise whether you'd prefer me to add the missing vars to the phpunit.xml or update TestUtil to work as expected with the current configs?