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

Introduce utils dispatcher #1872

Closed
wants to merge 20 commits into from
Closed

Conversation

cicnavi
Copy link
Contributor

@cicnavi cicnavi commented Oct 10, 2023

I am trying to find a way to make SSP code base easier to unit test in a non-breakable way for current release.

What I have noticed is that different utility classes are often being used without the possibility to inject them, that is without the possibility to mock them.

I have gone ahead and created a "utility dispatcher" class and then injected it into several constructors where it could be used. I have provided a few examples on how it can be used in unit tests with previously "hard to mock" cases. I think with this approach we can more easily cover basically the whole SSP with unit tests (which would still be a lot of work)...

What do you think about this?

@tvdijen
Copy link
Member

tvdijen commented Oct 10, 2023

Pretty cool @cicnavi !

@cicnavi
Copy link
Contributor Author

cicnavi commented Oct 10, 2023

Alright then, will continue working on this when I "invent" some free time!

@tvdijen
Copy link
Member

tvdijen commented Oct 10, 2023

Only a matter of less sleep and more coffee ;)

@tvdijen tvdijen force-pushed the master branch 3 times, most recently from bc1c5c8 to d0a5974 Compare October 17, 2023 21:17
@tvdijen tvdijen added this to In progress in 2.2 release via automation Oct 18, 2023
@tvdijen tvdijen force-pushed the master branch 3 times, most recently from ccb9b02 to 120a100 Compare December 1, 2023 14:34
@pradtke
Copy link
Contributor

pradtke commented Feb 6, 2024

@cicnavi I often have the same pain with unit testing, and I'm intrigued by your approach.

Do you know how this behaves when the processing chain is running and an authproc filter performs a redirect? My impression is that all authproc filters that have not yet run will be serialized and stored in the session, so they can be resumed after. So in the current world, where all the dependencies are created with new, none of those dependencies are fields in the authproc objects and there is no issue. If the dependencies are now fields in the authproc objects then they will also get serialized, perhaps unsuccessfully. Of course the specific authproc class could implement php features to control serialization/unserialization, but I don't think the need for that is always obvious when writing an authproc filter. Anyhow, I'm curious if you've tried this approach with authproc filters (since I didn't see any in the sample PR).

@cicnavi
Copy link
Contributor Author

cicnavi commented Feb 8, 2024

@cicnavi I often have the same pain with unit testing, and I'm intrigued by your approach.

Do you know how this behaves when the processing chain is running and an authproc filter performs a redirect? My impression is that all authproc filters that have not yet run will be serialized and stored in the session, so they can be resumed after. So in the current world, where all the dependencies are created with new, none of those dependencies are fields in the authproc objects and there is no issue. If the dependencies are now fields in the authproc objects then they will also get serialized, perhaps unsuccessfully. Of course the specific authproc class could implement php features to control serialization/unserialization, but I don't think the need for that is always obvious when writing an authproc filter. Anyhow, I'm curious if you've tried this approach with authproc filters (since I didn't see any in the sample PR).

No, I didn't test with authprocs... I know resources or callbacks can't be serialized, but do you have an example on the unsuccessful serialization for properties which are objects? Below is a simple script just to get us on the same page regarding this...

#!/usr/bin/env php
<?php

class First
{
    protected string $hello = 'Hi, I\'m first';

    public function sayHi(): string
    {
        return $this->hello;
    }
}

class Second
{
    protected string $hello = 'Hi, I\'m second';
    protected ?First $first = null;

    public function __construct()
    {
        $this->first = new First();
    }

    public function sayHi(): string
    {
        return $this->hello;
    }

    public function getFirst(): ?First
    {
        return $this->first;
    }
}

$secondSerialized = serialize(new Second());

var_dump($secondSerialized);

/** @var Second $secondUnserialized */
$secondUnserialized = unserialize($secondSerialized);

var_dump($secondUnserialized->sayHi(), $secondUnserialized->getFirst()?->sayHi());

@tvdijen
Copy link
Member

tvdijen commented Feb 8, 2024

Authprocs are not serialized, just their configs in idp/sp metadata... Unless I'm horribly mistaking

@pradtke
Copy link
Contributor

pradtke commented Feb 8, 2024

@cicnavi Thanks, it may have just been something specific to one of our authprocs, or me misremembering, or maybe it was us having dependencies containing secrets that we didn't want being incorporated in the $state and potentially ending up in our store. If I come across a concrete example I'll update this.

@tvdijen I believe ProcessingChain is assigning the instantiated authproc objects into the $state and $state is serialized when stored.

    $state[self::FILTERS_INDEX] = $this->filters;

During a resume, it invokes them directly form the state

        $filter = array_shift($state[self::FILTERS_INDEX]);
        try {
            if ($filter->checkPrecondition($state) === true) {
                $filter->process($state);
            }
        } catch (Error\Exception $e) {

which is why I think it is serialized/unserialized.

@tvdijen
Copy link
Member

tvdijen commented Feb 8, 2024

Hmm, you may be right. I think any object can be serialized, but private properties can become a problem. Also properties that hold items that cannot be serialized (DOMElement for example) can be problematic.

So, bottom line is, authprocs should have protected properties and if one of the properties hold unserializable items they have to implement the Serializable-interface. You can find examples for this in saml2 NameID or AttributeValue.

@cicnavi
Copy link
Contributor Author

cicnavi commented Feb 9, 2024

Cool, I wasn't aware that DOMElement can't be serialized. Do you have any example on the private properties being an issue with serialization? In this basic example it seems to work fine (the class 'Third' holds the private property '$second').

#!/usr/bin/env php
<?php

class First
{
    public string $hello = 'Hi, I\'m first';

    public function sayHi(): string
    {
        return $this->hello;
    }
}

class Second
{
    public string $hello = 'Hi, I\'m second';

    public function __construct(protected First $first)
    {
    }

    public function getFirst(): First
    {
        return $this->first;
    }
}

class Third
{
    public string $hello = 'Hi, I\'m third';

    public function __construct(private Second $second)
    {
    }

    public function getSecond(): Second
    {
        return $this->second;
    }
}

$thirdSerialized = serialize(new Third(new Second(new First())));

var_dump($thirdSerialized);

/** @var Third $thirdUnserialized */
$thirdUnserialized = unserialize($thirdSerialized);

var_dump(
    $thirdUnserialized->hello,
    $thirdUnserialized->getSecond()->hello,
    $thirdUnserialized->getSecond()->getFirst()->hello,
);

@tvdijen
Copy link
Member

tvdijen commented Feb 9, 2024

I was slightly wrong when I mentioned this last night..
For our saml2-library we came up with a solution to be able to serialize DOMElements:
https://github.com/simplesamlphp/xml-common/blob/master/src/SerializableElementTrait.php#L77-L79

However this solution won't work if the object has any private properties, because get_object_vars() wouldn't show them.. Their values would get lost during serialization/de-serialization.

@tvdijen
Copy link
Member

tvdijen commented Mar 8, 2024

@cicnavi How much work/time do you need to finish this?

@cicnavi
Copy link
Contributor Author

cicnavi commented Mar 8, 2024

I apologize, I don't know :(, can't find time to work on it...

Marko Ivančić and others added 6 commits March 8, 2024 10:03
Bumps [symfony/http-foundation](https://github.com/symfony/http-foundation) from 6.4.2 to 6.4.3.
- [Release notes](https://github.com/symfony/http-foundation/releases)
- [Changelog](https://github.com/symfony/http-foundation/blob/7.0/CHANGELOG.md)
- [Commits](symfony/http-foundation@v6.4.2...v6.4.3)

---
updated-dependencies:
- dependency-name: symfony/http-foundation
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
@tvdijen
Copy link
Member

tvdijen commented Mar 8, 2024

No problem! I was just wondering if this is something we had to wait on for the 2.2 release..

@tvdijen tvdijen removed this from In progress in 2.2 release Mar 8, 2024
@tvdijen tvdijen added this to the 2.3 milestone Mar 8, 2024
@tvdijen tvdijen force-pushed the master branch 2 times, most recently from 6004a77 to 58bf8db Compare May 4, 2024 23:45
dependabot bot and others added 14 commits May 24, 2024 16:08
Bumps [gettext/php-scanner](https://github.com/php-gettext/PHP-Scanner) from 1.3.1 to 2.0.0.
- [Release notes](https://github.com/php-gettext/PHP-Scanner/releases)
- [Changelog](https://github.com/php-gettext/PHP-Scanner/blob/master/CHANGELOG.md)
- [Commits](php-gettext/PHP-Scanner@v1.3.1...v2.0.0)

---
updated-dependencies:
- dependency-name: gettext/php-scanner
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…instead of at top level of authsource config
Bumps the dev-dependencies group with 1 update: [simplesamlphp/simplesamlphp-test-framework](https://github.com/simplesamlphp/simplesamlphp-test-framework).


Updates `simplesamlphp/simplesamlphp-test-framework` from 1.5.10 to 1.6.0
- [Commits](simplesamlphp/simplesamlphp-test-framework@v1.5.10...v1.6.0)

---
updated-dependencies:
- dependency-name: simplesamlphp/simplesamlphp-test-framework
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…atisticsWithAttribute

Document and remove configuration for StatisticsWithAttribute module

The changelog is updated with more recent versions from the cherry
pick.
Bumps the dev-dependencies group with 1 update: [simplesamlphp/simplesamlphp-test-framework](https://github.com/simplesamlphp/simplesamlphp-test-framework).


Updates `simplesamlphp/simplesamlphp-test-framework` from 1.6.0 to 1.6.1
- [Commits](simplesamlphp/simplesamlphp-test-framework@v1.6.0...v1.6.1)

---
updated-dependencies:
- dependency-name: simplesamlphp/simplesamlphp-test-framework
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [symfony/http-foundation](https://github.com/symfony/http-foundation) from 6.4.2 to 6.4.3.
- [Release notes](https://github.com/symfony/http-foundation/releases)
- [Changelog](https://github.com/symfony/http-foundation/blob/7.0/CHANGELOG.md)
- [Commits](symfony/http-foundation@v6.4.2...v6.4.3)

---
updated-dependencies:
- dependency-name: symfony/http-foundation
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
@cicnavi
Copy link
Contributor Author

cicnavi commented May 24, 2024

I don't have a slightest idea on when to work on this. Will close for now and maybe reopen sometime in the future... :/

@cicnavi cicnavi closed this May 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants