Skip to content
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

fix of issue dev/core#127 (at gitlab), incorrect cache records for smart groups #12249

Merged
merged 1 commit into from
Jun 4, 2018

Conversation

hosseinzoda
Copy link
Contributor

Overview

There was an issue with creating multiple smart group with related contact component mode.
https://lab.civicrm.org/dev/core/issues/127
filterRelatedContacts at Query.php, was not distinguishing different queries.

Before

screenshot from 2018-06-02 16-09-24

After

screenshot from 2018-06-02 16-13-26

Technical Details

I did add a check for already filtered queries at the beginning to prevent multiple calls to filter duplicate it. And it prevents to not distinguish a unique $arg_sig for each input.

@civicrm-builder
Copy link

Can one of the admins verify this patch?

@hosseinzoda hosseinzoda changed the title fix for issue #127 (at gitlab) incorrect cache records for smart groups fix for issue dev/core#127 (at gitlab) incorrect cache records for smart groups Jun 2, 2018
@hosseinzoda hosseinzoda changed the title fix for issue dev/core#127 (at gitlab) incorrect cache records for smart groups fix of issue dev/core#127 (at gitlab) incorrect cache records for smart groups Jun 2, 2018
@hosseinzoda hosseinzoda changed the title fix of issue dev/core#127 (at gitlab) incorrect cache records for smart groups fix of issue dev/core#127 (at gitlab), incorrect cache records for smart groups Jun 2, 2018
@seamuslee001
Copy link
Contributor

Jenkins ok to test

@seamuslee001
Copy link
Contributor

@hosseinamin Hossin are you able to fix the style issues found by our test bot? https://test.civicrm.org/job/CiviCRM-Core-PR/20982/checkstyleResult/new/

@hosseinzoda
Copy link
Contributor Author

@seamuslee001 did fix the styling issues.

@seamuslee001
Copy link
Contributor

looks like there are still a couple of issues https://test.civicrm.org/job/CiviCRM-Core-PR/20984/checkstyleResult/new/

@eileenmcnaughton
Copy link
Contributor

test this please

/**
* group update_smart_groups action test
*/
public function testGroupUpdateSmartGroupsForRelatedContacts() {
Copy link
Contributor

@eileenmcnaughton eileenmcnaughton Jun 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately we don't really run these webtests anymore - @totten @colemanw perhaps the time has come to remove them to avoid things like this?

We would normally use unit tests - likely calling loadAll directly [EDITED - or by calling the api per my examples below]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't how the other tests would work. Did try to run the test with closest example i could find.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is probably the test I would start with

https://github.com/davecivicrm/civicrm-core/blob/fae75b583b102cf9cfdc64ba0adc08091f8dd5a8/tests/phpunit/api/v3/ContactTest.php#L3523

It already loads multiple groups - so that is good - but none of them have this specific related contact criteria that is hitting the problem

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I'm trying to find a test that creates a smart group now)

Copy link
Contributor

@eileenmcnaughton eileenmcnaughton Jun 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK - this is from ActionSchedule Test

    // create smart group which will contain all Male contacts
    $smartGroupParams = array('formValues' => array('gender_id' => 1));
    $smartGroupID = $this->smartGroupCreate(
      $smartGroupParams,
      array(
        'name' => 'new_smart_group',
        'title' => 'New Smart Group',
        'parents' => array($groupID => 1),
      )
    );

So something like

public function testLoadMultipleRelatedGroups
    // create smart group which will contain all Male contacts
    $smartGroupParams = array('formValues' => array(... related group params 1....));
    $smartGroupID = $this->smartGroupCreate(
      $smartGroupParams,
      array(
        'name' => 'new_smart_group',
        'title' => 'New Smart Group',
        'parents' => array($groupID => 1),
      )
    );
   // create related group 2
   // create a contact that would be in only 1
   $result = $this->callApiSuccess('Contact', 'get', ['group' => $group1['id']);
    $result2 $this->callApiSuccess('Contact', 'get', ['group' => $group2['id']);
  // Check result is not cross-contaminated

Copy link
Contributor Author

@hosseinzoda hosseinzoda Jun 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to perform a unit-test. I get an error. Can you direct me to a guide for preparing to run the test?
Here's the command.

phpunit4 --filter testAddCreateIndividual tests/phpunit/api/v3/ContactTest.php

Error

exception 'RuntimeException' with message '_populateDB requires CIVICRM_UF=UnitTests'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I normally run tests from within phpunit - this is what my command line (generated by phpunit) ooks like

phpunit.php --bootstrap /Users/emcnaughton/buildkit/build/dmaster/sites/all/modules/civicrm/tests/phpunit/CiviTest/bootstrap.php --configuration /Users/emcnaughton/buildkit/build/dmaster/sites/all/modules/civicrm/phpunit.xml.dist --filter "/::testAddCreateIndividual( .*)?$/" api_v3_ContactTest /Users/emcnaughton/buildkit/build/dmaster/sites/all/modules/civicrm/tests/phpunit/api/v3/ContactTest.php

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh - looks like this is specifically relevant https://docs.civicrm.org/dev/en/latest/testing/phpunit/

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The doc helped. Thank you @eileenmcnaughton

@@ -81,19 +81,19 @@ public static function check($groupIDs) {
* @return string
* the sql query which lists the groups that need to be refreshed
*/
public static function groupRefreshedClause($groupIDClause = NULL, $includeHiddenGroups = FALSE) {
public static function groupRefreshedClause($groupIDClause = NULL, $includeHiddenGroups = FALSE, $ignoreCache = FALSE) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can avoid adding $ignoreCache here - I think it's being added purely for the unit test? If we use the \Civi::statics pattern we can probably solve the test issue

Copy link
Contributor Author

@hosseinzoda hosseinzoda Jun 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's ok. We can remove it with unit-test.
I don't think \Civi::statics will help with unit-test.

Edited: An independent call to removing cache. Before loadAll method can help.

if (!$_rTypeProcessed) {
$_rTypeProcessed = TRUE;

static $_rTempCache = array();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so per above - the way we can avoid cross-test contamination is using \Civi::statics - eg.

$arg_sig = sha1("$from $where $having");
if (!isset(\Civi::statics[CLASS]['related_contacts_filter'][$arg_sig]) {
// buld that key}

return !isset(\Civi::statics[CLASS]['related_contacts_filter'][$arg_sig]

Copy link
Contributor Author

@hosseinzoda hosseinzoda Jun 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not placed these code for the unit-test. This is the fix. Maybe changing it to \Civi::statics has advantages that i don't know.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hosseinamin yes - I realised that the use of $arg_sig is the test & I think it will fix the bug as described once we get the tests sorted. And thank you for working on this!

You may find that once your test running in the phpunit Continuous integration the type of static might need changing. The reason is that the Civi::statics cache is flushed between tests so you might see unexpected fails elsewhere in the suite.

We used to have 2 suites of tests - the phpunit ones & the selenium / webtests ones. The latter still exist but they are too full of false negatives to run whereas the former run against every PR that is submitted and are run nightly on different php / mysql combos

@hosseinzoda
Copy link
Contributor Author

@eileenmcnaughton I've removed ignore_cache, and new testing is working for me now.

@eileenmcnaughton
Copy link
Contributor

@hosseinamin - looks like a few style tweaks needed - https://test.civicrm.org/job/CiviCRM-Core-PR/20990/checkstyleResult/new/

@eileenmcnaughton
Copy link
Contributor

I just checked & I can confirm the test fails without the patch and passes with it and the patch seems correct.

A couple of stylistic things

  1. are you able to rebase -i & squash the commits into one (you will need to do a force push)
  2. the use of references for variables is less preferred stylistically in our code base (in part because it can lead to mistakes. I'll add a couple of in-line comments
  3. I think this might be your first PR to be merged? If so thank you and well done. Could you follow up with a PR to the contributor's file to add your details? https://github.com/civicrm/civicrm-core/blob/master/contributor-key.yml

}
$arg_sig = sha1("$from $where $having");
if (isset($_rTempCache[$arg_sig])) {
$cache =& $_rTempCache[$arg_sig];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case referring as reference doesn't actually help because it's being used read only anyway

"from" => "",
"where" => "",
);
$cache =& $_rTempCache[$arg_sig];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case I think it would be more consistent with other places to build up the $cache value by itself & assign it to
Civi::$statics[CLASS]['related_contacts_filter'][$arg_sig] right at the end of this else

@hosseinzoda
Copy link
Contributor Author

Did the changes.

$_rTempCache =& Civi::$statics[__CLASS__]['related_contacts_filter'];
// skip if filter has already applied
foreach ($_rTempCache as $acache) {
if (strpos($from, $acache['from']) !== FALSE) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm just wondering about this - it seems a bit unpredictable - ie. like it would happen when it is a subset of the response & like hopefully the improved $sig_arg would make it unnecessary - did you hit any case when it was invoked in your testing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes i received an error. for injection of select and where parts twice. This loop will prevent it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately we can't do much with $sig_arg. Since there's no unique argument given.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK - I think that convinces me - if there are scenarios that are not correctly calculated they will still be less & we can add tests for them if we find any. This one won't regress with your test

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried with turning the cache variable for each instance. The down side is, it is getting instantiated multiple times and going through filter.

@eileenmcnaughton
Copy link
Contributor

@agh1 @guanhuan do either of you have any specific acknowledgement process for first time committers. This is a great first contribution - fixes a somewhat obscure but critical bug and has a test to prevent recurrence

@seamuslee001
Copy link
Contributor

merging as per the tag

@seamuslee001 seamuslee001 merged commit 0d4655e into civicrm:master Jun 4, 2018
@agh1
Copy link
Contributor

agh1 commented Jun 4, 2018

@eileenmcnaughton I have no particular procedure for bringing out the welcome wagon, but it would be great to have one. Frankly, I don't usually notice until compiling the credits for a release and noticing that someone's user name isn't in contributor-key.yml.

Realistically, that's probably where it has to happen--you can't count on reviewers to remember who's new when they're merging PRs. However, it's also not a bad time: it's one thing to have a PR merged, and you get emails about that automatically. It's another to have your contribution be out in the world in a release, so a welcome/congratulations note then would be nice.

@agh1
Copy link
Contributor

agh1 commented Jun 4, 2018

But to that end--welcome @hosseinamin and thanks for the contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants