-
Notifications
You must be signed in to change notification settings - Fork 127
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
Better default behaviour inside of unit tests #823
Conversation
After putting this together, I realise I have focused only on |
I really like the intention of this change, and it's approach to having a default for 'testing mode'. However, I don't really like the 'linking' to zaza; i.e. creating it as a dependency. i.e. charms use charm-helpers; zaza tests charms (and, when incorrectly mocked), accidentally use charm-helpers, and in this case, expose that it's not multi-process/thread safe. This change kind of creates a reverse dependency of charm-helpers on zaza, (even if only tangentially). My first thoughts on how to resolve this for consideration, are instead to add a charm-helpers specific environment variable that, if set to some value, will inform charmhelpers that it needs to use |
Yes I see your point and I'm liking the module check less as I think about it more. Writing out what might be good to have:
It's 4 that is the tricky one, but I think your suggestion will handle that case too. The problem that people seem to be facing currently is 4, because you have to be bitten by the concurrency issue to know you should look for these changes. And we definitely don't want to break 5 as you mentioned. Finally, relying on Here's a list of approaches I've thoought of, plus what you mentioned:
Option E is my interpretation of what you wrote and it seems to tick the most boxes. I'm very new to charms, is the coverage of zaza across various charm packages close to 100%? I added F too but that still suffers from the reverse dependency issue. |
I make a small change to switch from checking for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pengwyn so I led you slightly astray as I was thrown a bit by seeing zaza in it and hadn't thought things through properly. zaza
is a red-herring as it's not involved in unit tests at all. It's only a functional test framework and is never in the same process as any charm code. e.g. it runs outside of the juju model and thus would never interact with the charm code.
Having said that, the change to introduce a CHARM_HELPERS_TESTMODE
seems quite reasonable, but does mean that the library still has no automatic mechanism of detecting whether it is running in unit tests of within a charm on a unit.
One option to detect whether charmhelpers is running in a charm is to check for one or more of these env variables: (e.g. from vault running in a test model, during update-status):
# env | grep JUJU
JUJU_METER_INFO=not set
JUJU_CHARM_HTTPS_PROXY=
JUJU_CONTEXT_ID=vault/0-update-status-7919217765836578507
JUJU_MODEL_UUID=5fbe3e08-8eb6-4f1c-820d-0a68d362f428
JUJU_VERSION=2.9.37
JUJU_CHARM_HTTP_PROXY=
JUJU_UNIT_NAME=vault/0
JUJU_HOOK_NAME=update-status
JUJU_AGENT_SOCKET_ADDRESS=@/var/lib/juju/agents/unit-vault-0/agent.socket
JUJU_CHARM_FTP_PROXY=
JUJU_AVAILABILITY_ZONE=nova
JUJU_METER_STATUS=AMBER
JUJU_CHARM_DIR=/var/lib/juju/agents/unit-vault-0/charm
JUJU_DEBUG=/tmp/juju-debug-hooks-1193241599
JUJU_API_ADDRESSES=172.20.0.182:17070 252.182.0.1:17070
JUJU_PRINCIPAL_UNIT=
JUJU_MODEL_NAME=zaza-e79c0a05dd9d
JUJU_MACHINE_ID=3
JUJU_SLA=unsupported
JUJU_DISPATCH_PATH=hooks/update-status
JUJU_AGENT_SOCKET_NETWORK=unix
JUJU_CHARM_NO_PROXY=127.0.0.1,localhost,::1
Then a test where UNIT_STATE_DB
is not present, but, say, at least JUJU_CHARM_DIR
is also not present might be enough to say "running in test mode."
charmhelpers/core/unitdata.py
Outdated
in_memory_db = ("UNIT_STATE_DB" not in os.environ) and ("CHARM_HELPERS_TESTMODE" in os.environ) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a better overall solution; it drops the dependency on zaza.
My bad! I think I got confused originally and didn't realise the test failures were all unit tests. I like that idea, so I made an update to still keep It's a bit over-engineered, but this should give an option to anyone doing odd tests with faking |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Occasionally there can be a race condition in tests which use the KV store. This is because the store does not need to be tolerant of concurrent writes in normal juju execution, but when tests are run in parallel they can write to the same (default) sqlite DB.
See https://bugs.launchpad.net/charm-helpers/+bug/1911919 for a collection of similar bugs.
The workaround in charms has been to manually create the KV store with ":memory:" so that each test will run with a different DB. This PR replicates this behaviour, by changing the default KV store location if zaza is imported. It can be overridden with the
UNIT_STATE_DB
as normal.The actual fix is very small. The bulk of the PR is introducing a test to see that a) this behaviour can be forced and b) that the behaviour is fixed when a fake zaza is imported. I forced the problem by starting a subprocess that locks the DB.
My main worry with the PR is the crude checking of "zaza" in the imported modules. But I went with this approach to avoid any extra dependencies of charmhelpers on zaza or zaza on charmhelpers.
The tests can be checked by looking at commit
ec50d90
, which should give a failure.