After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 648811 - Add a dummy backend
Add a dummy backend
Status: RESOLVED FIXED
Product: folks
Classification: Platform
Component: general
git master
Other Linux
: Normal normal
: Future
Assigned To: folks-maint
folks-maint
Depends on: 711544
Blocks: 719502 719503
 
 
Reported: 2011-04-27 21:36 UTC by Travis Reitter
Modified: 2013-12-09 11:15 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Update code to works with the source code from mainline (16.99 KB, patch)
2013-10-22 18:03 UTC, Renato Araujo Oliveira Filho
none Details | Review
Add pc file for dummy backend library (1.99 KB, patch)
2013-10-25 00:41 UTC, Renato Araujo Oliveira Filho
none Details | Review
Initial unit test for dummy backend (16.34 KB, patch)
2013-10-25 00:42 UTC, Renato Araujo Oliveira Filho
none Details | Review
New tests for dummy backend (46.24 KB, patch)
2013-10-25 14:59 UTC, Renato Araujo Oliveira Filho
none Details | Review
dummy: Add a dummy backend (140.13 KB, patch)
2013-11-07 11:11 UTC, Philip Withnall
reviewed Details | Review
dummy: Add a dummy backend (141.72 KB, patch)
2013-11-07 12:29 UTC, Philip Withnall
none Details | Review
dummy: Add a dummy backend (142.41 KB, patch)
2013-11-07 14:07 UTC, Philip Withnall
none Details | Review
dummy: Add a dummy backend (141.08 KB, patch)
2013-11-27 16:48 UTC, Philip Withnall
needs-work Details | Review
tests: Add a standalone-individuals test program (8.61 KB, patch)
2013-11-27 16:48 UTC, Philip Withnall
reviewed Details | Review
individual: Add default values for PresenceDetails properties (1.09 KB, patch)
2013-11-27 16:48 UTC, Philip Withnall
committed Details | Review
individual: Allow Individual.id to be an empty string with no personas (1.82 KB, patch)
2013-11-27 16:48 UTC, Philip Withnall
committed Details | Review
dummy: Add a dummy backend (136.44 KB, patch)
2013-11-28 18:32 UTC, Philip Withnall
committed Details | Review
tests: Add a standalone-individuals test program (8.60 KB, patch)
2013-11-28 18:32 UTC, Philip Withnall
committed Details | Review
backends: Add [freeze|thaw]_notify() calls to [un]prepare() in backends (8.58 KB, patch)
2013-11-28 18:32 UTC, Philip Withnall
committed Details | Review

Description Travis Reitter 2011-04-27 21:36:03 UTC
Folks needs a dummy backend to make it possible for clients and, particularly, bindings (like QtFolks) to write tests that only depend upon the libfolks classes and interfaces, not upon the behavior of specific backends.

QtFolks is the main use case here though this will allow client programs to test any utility functions that depend upon Folks in a much more reliable way.

This dummy backend has a few requirements:

* client code must be able to set its state (so the client can verify that changes propagate through the Folks interfaces as expected)

* it must implement as many Folks.*Details interfaces as possible. Different clients may care about different details, and these clients must not need to build their tests against real backends which are often infeasible to set up in test suites (particularly when they depend upon state on a remote server, such as the Telepathy and libsocialweb backends)
Comment 1 Travis Reitter 2011-04-27 21:45:46 UTC
This bug blocks https://bugs.meego.com/show_bug.cgi?id=16787
Comment 2 Travis Reitter 2011-08-01 18:39:20 UTC
Punting bugs that won't be fixed by Folks 0.6.0.
Comment 3 Jeremy Whiting 2012-05-28 16:37:04 UTC
I've started a very basic dummy backend here: http://cgit.collabora.com/git/user/jwhiting/folks.git/log/?h=dummybackend and will continue working on it there.  If you have any feedback, let me know.
Comment 4 Philip Withnall 2012-05-29 09:31:58 UTC
(In reply to comment #3)
> I've started a very basic dummy backend here:
> http://cgit.collabora.com/git/user/jwhiting/folks.git/log/?h=dummybackend and
> will continue working on it there.  If you have any feedback, let me know.

I spotted this:
> /* FIXME: load personas from a file or something. */
which means we should probably expand on the use case for the dummy backend. I think one of the big requirements for it is to allow Personas to be added/removed/have their properties changed in the backend at runtime, so that we can easily write unit tests for folks’ dynamic behaviour. (e.g. Testing how libfolks re-links personas from the dummy backend in response to some of their linkable properties changing at runtime.)

I once started writing a dummy backend which implemented a D-Bus interface to allow these kinds of changes (e.g. AddPersona, AddPersonaStore, ChangePersonaProperty methods), and that felt like a reasonable approach. Unit tests would then call the D-Bus methods and watch for the expected changes coming back through libfolks. I didn’t get too far with my branch, though, so there may be problems with this approach that I didn’t run into.

This looks like a good start though!
Comment 5 Jeremy Whiting 2012-05-30 22:35:15 UTC
I added small unit tests for ImFieldDetails and WebServiceFieldDetails.  Next will start adding support for the other *Details interfaces along with unit tests for those interfaces.  Are the unit tests I've created for alias, imfield, and webservice detailed enough? or do they need to have more added to them?  If so, what needs to be added?
Comment 6 Travis Reitter 2012-06-04 14:43:59 UTC
(In reply to comment #5)
> I added small unit tests for ImFieldDetails and WebServiceFieldDetails.  Next
> will start adding support for the other *Details interfaces along with unit
> tests for those interfaces.  Are the unit tests I've created for alias,
> imfield, and webservice detailed enough? or do they need to have more added to
> them?  If so, what needs to be added?

They're a good starting point. See the EDS tests for an idea of the coverage we want for the various interfaces.

I think for each member, we try to check:

* non-existence of the final value
* (sometimes: checking for the existence of an expected initial value)
* set the final value
* after appropriate async functions return/signals emit: final value meets expectations
Comment 7 Travis Reitter 2012-06-04 14:45:40 UTC
Here are my current thoughts so far:

Required for new files which contain translations:

diff --git a/po/POTFILES.in b/po/POTFILES.in
index 20b9f9c..e43fa09 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,4 +1,5 @@
 [encoding: UTF-8]
+backends/dummy/lib/dummy-persona.vala
 backends/eds/lib/edsf-persona-store.vala
 backends/key-file/kf-backend-factory.vala
 backends/key-file/kf-persona-store.vala
diff --git a/po/POTFILES.skip b/po/POTFILES.skip
index a27b962..885042c 100644
--- a/po/POTFILES.skip
+++ b/po/POTFILES.skip
@@ -1,3 +1,4 @@
+backends/dummy/lib/dummy-persona.c
 backends/eds/lib/edsf-persona-store.c
 backends/key-file/kf-backend-factory.c
 backends/key-file/kf-persona-store.c


backends/dummy/dummy-backend.vala:

+          if (!this._is_prepared || this._prepare_pending == true)
+            {
+              return;
+            }

The second half of this branch seems like a bad idea -- in case we're part-way into preparing, we just give up the client's request to unprepare?

Similarly, this code later in the function seems wrong, since we're trying to tear down, not build up:

+              this._prepare_pending = true;

I see the point of these two snippets taken together, but it seems like this requires a new _unprepare_pending in both cases and to factor that into the code that uses _prepare_pending. This all sounds pretty ugly though :-/

Did you copy this code from elsewhere? We might need to fix that as well.


add_persona_from_details() needs to persist the changes to disk


backends/dummy/dummy-persona.vala:

The change_* functions also need to persist to disk


tests/folks/specific-field-details.vala:

+  private Dummy.Persona? _test_persona;
+  

Unnecessary whitespace on the second line

+      this._persona_store.prepare();
+      

Same here

+              this._test_persona.alias = new_alias;
+              

Same here


tests/folks/specific-field-details.vala



+              this._test_persona.alias = new_alias;
+              
+              /* Check the persona's alias has changed */
+              assert(this._test_persona.alias == new_alias);

This just checks that alias.set() function doesn't do something really silly. It'd be better to yield (or equivalent) upon the change_alias() function, since its changes should be written to disk by the time it's done.

This also applies to all the others tests, upon brief glimpse.


You might want to split test_alias_replacement() into a sync and async function (with most of the code here) to take advantage of the yield for all the called async functions. See some of the other tests.


+              this._test_persona = 
+                (Dummy.Persona) this._persona_store.add_persona_from_details.en

Trailing whitespace on both lines

+              assert(this._persona_store.personas.size == 0);
+      

Trailing whitespace on the second line


+      string path = "/usr/share/pixmaps/nobody.png";

We should use the avatar we have bundled, which we can guarantee exists: tests/data/avatar-01.jpg
Comment 8 Jeremy Whiting 2012-06-05 15:28:29 UTC
Travis,

Yes, the _prepare_pending is coming straight from the keyfile backend I created the dummy backend from.  Should the _prepare_pending stuff just be removed and if we are already prepared we return, otherwise we try to prepare?  I can fix in both dummy and keyfile backend if that's the case.

Thanks for the feedback.  I'll fix the other bits also.
Comment 9 Philip Withnall 2013-05-21 22:27:19 UTC
For what it’s worth, here’s my current WIP on this:

https://www.gitorious.org/folks/folks/commits/648811-dummy-backend-attempt3

It’s almost there. As far as I remember, the code is complete and most things work. It just needs testing (and test cases)…and rebasing against master.

I hope to get time to do this at some point. Maybe once I finish this darned degree of mine.
Comment 10 Renato Araujo Oliveira Filho 2013-05-22 19:48:28 UTC
this link is broken could you paste a new link, I want to try it and if possible implement the missing tests.
Comment 11 Philip Withnall 2013-05-22 22:52:46 UTC
(In reply to comment #10)
> this link is broken could you paste a new link, I want to try it and if
> possible implement the missing tests.

Whoops. I have an automatic git mirror script on a cronjob which deleted the branch. I’ve pushed it here instead:
https://git.gnome.org/browse/folks/log/?h=648811-dummy-backend-attempt3

Let me know if you have any questions. Thanks for taking a look at this!
Comment 13 Renato Araujo Oliveira Filho 2013-05-23 20:13:01 UTC
(In reply to comment #12)
> (In reply to comment #11)
> > I’ve pushed it here instead:
> > https://git.gnome.org/browse/folks/log/?h=648811-dummy-backend-attempt3
> 
> Or even here:
> https://git.gnome.org/browse/folks/log/?h=648811-dummy-backend-non-dbus

Apparently there is a missing directory in the branch. You did some references to it on "root/tests/lib/Makefile.am". The directory is "root/tests/lib/dummy"
Comment 14 Renato Araujo Oliveira Filho 2013-05-23 21:56:24 UTC
Any special reason to use the namespace Dummy"f"?? or is that a typo??
Comment 15 Philip Withnall 2013-05-23 23:33:12 UTC
(In reply to comment #13)
> Apparently there is a missing directory in the branch. You did some references
> to it on "root/tests/lib/Makefile.am". The directory is "root/tests/lib/dummy"

I guess I forgot to commit it to git. Unfortunately, I’ve done a `git clean -fxd` since then, so the directory’s lost. :-(

(In reply to comment #14)
> Any special reason to use the namespace Dummy"f"?? or is that a typo??

It follows the same naming scheme as the rest of the public folks backend libraries (e.g. Kf, Tpf, Trf, …). I think that scheme (‘f’ for ‘folks’) was originally chosen so that we didn’t collide with the Tp namespace. I’m not particularly attached to it, though it would do no harm to leave it.
Comment 16 Renato Araujo Oliveira Filho 2013-05-23 23:58:55 UTC
(In reply to comment #15)
> It follows the same naming scheme as the rest of the public folks backend
> libraries (e.g. Kf, Tpf, Trf, …). I think that scheme (‘f’ for ‘folks’) was
> originally chosen so that we didn’t collide with the Tp namespace. I’m not
> particularly attached to it, though it would do no harm to leave it.

Ok, understood. I will rename it back to Dummyf. Thanks

BTW, I am working on this repository: https://github.com/renatofilho/folks/tree/dummy
Comment 17 Renato Araujo Oliveira Filho 2013-10-22 18:03:30 UTC
Created attachment 257866 [details] [review]
Update code to works with the source code from mainline
Comment 18 Renato Araujo Oliveira Filho 2013-10-25 00:41:03 UTC
Created attachment 258072 [details] [review]
Add pc file for dummy backend library
Comment 19 Renato Araujo Oliveira Filho 2013-10-25 00:42:13 UTC
Created attachment 258073 [details] [review]
Initial unit test for dummy backend

The test is not working fine I am getting the following message:
tests/dummy/.libs/lt-individual-retrieval:15762): folks-WARNING **: Failed to find primary PersonaStore with type ID 'dummy-store' and ID ''.
Individuals will not be linked properly and creating new links between Personas will not work.
The configured primary PersonaStore's backend may not be installed. If you are unsure, check with your distribution.
Trace/breakpoint trap
cleaning up pid 15777


I am not sure how to fix that, could you help me?
Comment 20 Renato Araujo Oliveira Filho 2013-10-25 14:59:23 UTC
Created attachment 258129 [details] [review]
New tests for dummy backend
Comment 21 Philip Withnall 2013-10-27 18:25:36 UTC
(In reply to comment #17)
> Created an attachment (id=257866) [details] [review]
> Update code to works with the source code from mainline

This doesn’t apply for me on the gitorious branch I gave in comment #12, or on the rebased version of it.

Could you please rebase your git branch on this branch:
    https://git.gnome.org/browse/folks/log/?h=648811-dummy-backend-non-dbus-rebase1
which I’ve just rebased on master (as of today). Could you then please push your branch (with various fixup changes applied on top of my branch) to github or somewhere else? Then I can try it out and start reviewing.

Thanks. :-)
Comment 22 Renato Araujo Oliveira Filho 2013-10-27 23:48:44 UTC
(In reply to comment #21)
> (In reply to comment #17)
> > Created an attachment (id=257866) [details] [review] [details] [review]
> > Update code to works with the source code from mainline
> 
> This doesn’t apply for me on the gitorious branch I gave in comment #12, or on
> the rebased version of it.
> 
> Could you please rebase your git branch on this branch:
>    
> https://git.gnome.org/browse/folks/log/?h=648811-dummy-backend-non-dbus-rebase1
> which I’ve just rebased on master (as of today). Could you then please push
> your branch (with various fixup changes applied on top of my branch) to github
> or somewhere else? Then I can try it out and start reviewing.
> 
> Thanks. :-)


Done: https://github.com/renatofilho/folks2/tree/dummy
Comment 23 Philip Withnall 2013-11-07 11:11:58 UTC
Created attachment 259172 [details] [review]
dummy: Add a dummy backend

This is a new backend targeted at making libfolks more testable. It is
designed to be used in internal libfolks unit tests, allowing the test
driver code to manipulate the backing store state to test how that
affects front-end state in libfolks. For example, it will be useful in
more thoroughly testing the IndividualAggregator.

It includes work by Renato Araujo Oliveira Filho <renatox@gmail.com>.

The backend may also be useful for testing libfolks clients,
such as contacts UIs, by providing an easy way to create well-known
personas to appear in the the UI. Hence, it is an installed backend, and
is loaded by default (although creates no Backend or PersonaStore instances
unless API calls are made).

It is designed to allow delay and error injection into all major
PersonaStore operations, and to allow any kind of Persona implementation
to be returned from the store.

It includes a few small test cases to sanity-check that the backend
works, but no thorough self-test-coverage.

Full API documentation is included and installed by default. The API is
not currently stable, so while external projects may start to consume
it, they should be prepared for breakage in the future as the API
stabilises. No timescale is given for such stabilisation.

This commit does not include any changes to the core libfolks unit
tests, but future changes could be made to port them to use the dummy
backend.

New API:
 • libfolks-dummy.la mocking library and all its symbols
Comment 24 Philip Withnall 2013-11-07 11:14:09 UTC
Here we go. This patch is all updated, rebased on master as of today, and ready to be pushed (as far as I’m concerned).

I dispensed with porting the existing core folks tests to the dummy backend, and will work on them separately. I don’t want that work to block on getting the backend itself committed.

Thanks for your work on this Renato!
Comment 25 Philip Withnall 2013-11-07 11:43:07 UTC
I should mention that this is available as a series of fixup patches here: https://git.gnome.org/browse/folks/log/?h=648811-dummy-backend-rebase1 which might make reviewing a little easier (or perhaps not).
Comment 26 Philip Withnall 2013-11-07 12:29:18 UTC
Created attachment 259176 [details] [review]
dummy: Add a dummy backend

This is a new backend targeted at making libfolks more testable. It is
designed to be used in internal libfolks unit tests, allowing the test
driver code to manipulate the backing store state to test how that
affects front-end state in libfolks. For example, it will be useful in
more thoroughly testing the IndividualAggregator.

It includes work by Renato Araujo Oliveira Filho <renatox@gmail.com>.

The backend may also be useful for testing libfolks clients,
such as contacts UIs, by providing an easy way to create well-known
personas to appear in the the UI. Hence, it is an installed backend, and
is loaded by default (although creates no Backend or PersonaStore instances
unless API calls are made).

It is designed to allow delay and error injection into all major
PersonaStore operations, and to allow any kind of Persona implementation
to be returned from the store.

It includes a few small test cases to sanity-check that the backend
works, but no thorough self-test-coverage.

Full API documentation is included and installed by default. The API is
not currently stable, so while external projects may start to consume
it, they should be prepared for breakage in the future as the API
stabilises. No timescale is given for such stabilisation.

This commit does not include any changes to the core libfolks unit
tests, but future changes could be made to port them to use the dummy
backend.

New API:
 • libfolks-dummy.la mocking library and all its symbols
Comment 27 Philip Withnall 2013-11-07 12:29:52 UTC
Updated with some fixes from Renato.
Comment 28 Simon McVittie 2013-11-07 12:37:44 UTC
Review of attachment 259172 [details] [review]:

::: backends/dummy/Makefile.am
@@ +1,1 @@
+SUBDIRS = lib

Doesn't this need to be "SUBDIRS = lib ." so lib gets compiled first?

::: backends/dummy/lib/Makefile.am
@@ +80,3 @@
+	$(AM_LDFLAGS) \
+	$(CODE_COVERAGE_LDFLAGS) \
+	-version-info "$(LT_CURRENT)":"$(LT_REVISION)":"$(LT_AGE)" \

This gives it the same SONAME as the main library, which seems premature if it isn't stable.

Maybe use "-release $(VERSION)" for now, so it deliberately breaks SONAME in every release?

::: backends/dummy/lib/dummy-fat-persona.vala
@@ +204,3 @@
+    }
+
+  private HashSet<PhoneFieldDetails> _phone_numbers =

Might be worth trying SmallSet once you have a regression test to profile? Not a blocker, obviously.

@@ +714,3 @@
+      foreach (var k in input_multi_map.get_keys ())
+        {
+          var values = input_multi_map.get (k);

Not a merge blocker, but it would be good to get this using a MapIter after merge - realistically, people are going to copy/paste the dummy backend all over the place, and iterating a MultiMap in this style has pessimal performance. Iterating a SmallMultiMap like this is particularly bad.

@@ +1093,3 @@
+    {
+      /* Make sure it includes our local ID. */
+      local_ids.add (this.iid);

It seems pretty strange that this alters its parameter. Since this is only test code, I think it'd be OK to just document it.

::: backends/dummy/lib/dummy-persona-store.vala
@@ +837,3 @@
+   * Negative delays result in the call completing synchronously, zero delays
+   * result in completion in an idle callback, and positive delays result in
+   * completion after that many milliseconds.

I assume this is necessary for historical reasons, because Folks doesn't specify whether prepare can be synchronous? With hindsight, it'd be good for prepare to be GAsyncResult-based.

I would be unhappy to see real regression tests that need to delay for a positive time.

I'd be tempted to have an API more like this (pseudocode):

    void mock_prepare (PrepareCall prepare_call)
    {
#if 0
      prepare_call.succeed ();
#elif 0
      prepare_call.fail (error);
#else
      idle_add (lambda: prepare_call.succeed());
#endif
    }

but that can wait til a subsequent commit, if it's needed at all.

I'd say "use GTask", but GTask always returns async, which it seems is exactly what you're trying to avoid here.

::: tests/Makefile.am
@@ +32,3 @@
 	tools \
 	folks \
+    dummy \

Indentation is weird here
Comment 29 Philip Withnall 2013-11-07 14:07:17 UTC
Created attachment 259191 [details] [review]
dummy: Add a dummy backend

This is a new backend targeted at making libfolks more testable. It is
designed to be used in internal libfolks unit tests, allowing the test
driver code to manipulate the backing store state to test how that
affects front-end state in libfolks. For example, it will be useful in
more thoroughly testing the IndividualAggregator.

It includes work by Renato Araujo Oliveira Filho <renatox@gmail.com>.

The backend may also be useful for testing libfolks clients,
such as contacts UIs, by providing an easy way to create well-known
personas to appear in the the UI. Hence, it is an installed backend, and
is loaded by default (although creates no Backend or PersonaStore instances
unless API calls are made).

It is designed to allow delay and error injection into all major
PersonaStore operations, and to allow any kind of Persona implementation
to be returned from the store.

It includes a few small test cases to sanity-check that the backend
works, but no thorough self-test-coverage.

Full API documentation is included and installed by default. The API is
not currently stable, so while external projects may start to consume
it, they should be prepared for breakage in the future as the API
stabilises. No timescale is given for such stabilisation.

This commit does not include any changes to the core libfolks unit
tests, but future changes could be made to port them to use the dummy
backend.

New API:
 • libfolks-dummy.la mocking library and all its symbols
Comment 30 Philip Withnall 2013-11-07 14:11:43 UTC
Thanks for the fast review!

(In reply to comment #28)
> ::: backends/dummy/Makefile.am
> @@ +1,1 @@
> +SUBDIRS = lib
> 
> Doesn't this need to be "SUBDIRS = lib ." so lib gets compiled first?

True, although it was working before. Fixed.

> ::: backends/dummy/lib/Makefile.am
> @@ +80,3 @@
> +    $(AM_LDFLAGS) \
> +    $(CODE_COVERAGE_LDFLAGS) \
> +    -version-info "$(LT_CURRENT)":"$(LT_REVISION)":"$(LT_AGE)" \
> 
> This gives it the same SONAME as the main library, which seems premature if it
> isn't stable.
> 
> Maybe use "-release $(VERSION)" for now, so it deliberately breaks SONAME in
> every release?

I’ve attached a patch to bug #711544 to add separate LT versioning for each backend library. Might as well fix this properly.

> ::: backends/dummy/lib/dummy-fat-persona.vala
> @@ +204,3 @@
> +    }
> +
> +  private HashSet<PhoneFieldDetails> _phone_numbers =
> 
> Might be worth trying SmallSet once you have a regression test to profile? Not
> a blocker, obviously.

I’ll punt this for now.

> @@ +714,3 @@
> +      foreach (var k in input_multi_map.get_keys ())
> +        {
> +          var values = input_multi_map.get (k);
> 
> Not a merge blocker, but it would be good to get this using a MapIter after
> merge - realistically, people are going to copy/paste the dummy backend all
> over the place, and iterating a MultiMap in this style has pessimal
> performance. Iterating a SmallMultiMap like this is particularly bad.

Fixed. Good catch.

> @@ +1093,3 @@
> +    {
> +      /* Make sure it includes our local ID. */
> +      local_ids.add (this.iid);
> 
> It seems pretty strange that this alters its parameter. Since this is only test
> code, I think it'd be OK to just document it.

I dropped it instead — it doesn’t make sense anyway, since local-ids is for linking to other personas, so including the current persona’s IID in there creates a pointless reflexive link.

> ::: backends/dummy/lib/dummy-persona-store.vala
> @@ +837,3 @@
> +   * Negative delays result in the call completing synchronously, zero delays
> +   * result in completion in an idle callback, and positive delays result in
> +   * completion after that many milliseconds.
> 
> I assume this is necessary for historical reasons, because Folks doesn't
> specify whether prepare can be synchronous? With hindsight, it'd be good for
> prepare to be GAsyncResult-based.

prepare() _is_ GAsyncResult-based, so it should never complete synchronously, I think (although I haven’t actually checked what code Vala generates). A negative delay results in a single idle callback, and a zero delay results in two then, I suppose.

> I would be unhappy to see real regression tests that need to delay for a
> positive time.

True, but I think it’s necessary. The use case is testing fallback timeouts in folks.

> I'd be tempted to have an API more like this (pseudocode):

Not quite sure what you mean by this.

> I'd say "use GTask", but GTask always returns async, which it seems is exactly
> what you're trying to avoid here.

Yes, and it would break API. :-)

> ::: tests/Makefile.am
> @@ +32,3 @@
>      tools \
>      folks \
> +    dummy \
> 
> Indentation is weird here

Fixed.
Comment 31 Travis Reitter 2013-11-27 00:32:13 UTC
Does this need further review before committing?
Comment 32 Philip Withnall 2013-11-27 09:55:46 UTC
(In reply to comment #31)
> Does this need further review before committing?

Please. I’d appreciate one final round of API sanity checking and high-level thought before it goes in.
Comment 33 Philip Withnall 2013-11-27 16:48:25 UTC
Created attachment 262960 [details] [review]
dummy: Add a dummy backend

This is a new backend targeted at making libfolks more testable. It is
designed to be used in internal libfolks unit tests, allowing the test
driver code to manipulate the backing store state to test how that
affects front-end state in libfolks. For example, it will be useful in
more thoroughly testing the IndividualAggregator.

It includes work by Renato Araujo Oliveira Filho <renatox@gmail.com>.

The backend may also be useful for testing libfolks clients,
such as contacts UIs, by providing an easy way to create well-known
personas to appear in the the UI. Hence, it is an installed backend, and
is loaded by default (although creates no Backend or PersonaStore instances
unless API calls are made).

It is designed to allow delay and error injection into all major
PersonaStore operations, and to allow any kind of Persona implementation
to be returned from the store.

It includes a few small test cases to sanity-check that the backend
works, but no thorough self-test-coverage.

Full API documentation is included and installed by default. The API is
not currently stable, so while external projects may start to consume
it, they should be prepared for breakage in the future as the API
stabilises. No timescale is given for such stabilisation.

This commit does not include any changes to the core libfolks unit
tests, but future changes could be made to port them to use the dummy
backend.

New API:
 • libfolks-dummy.la mocking library and all its symbols
Comment 34 Philip Withnall 2013-11-27 16:48:29 UTC
Created attachment 262961 [details] [review]
tests: Add a standalone-individuals test program

This contains a few test cases which check folks’ behaviour when
manually creating Individuals *outside* an IndividualAggregator. These
should catch the problems found in the following two bugs:
 • https://bugzilla.redhat.com/show_bug.cgi?id=1031252https://bugzilla.gnome.org/show_bug.cgi?id=712839
and hopefully fixed by commits:
 • f00534294d7d52ac7e37dfaa075e3465b7755483
 • 1ec050efc4f7135e9958c74da2028daf669077a0
Comment 35 Philip Withnall 2013-11-27 16:48:33 UTC
Created attachment 262962 [details] [review]
individual: Add default values for PresenceDetails properties

If an Individual is created with no Personas (as in the
standalone-individuals test cases), the PresenceDetails properties
should be initialised to empty strings. They were previously defaulting
to null.
Comment 36 Philip Withnall 2013-11-27 16:48:37 UTC
Created attachment 262963 [details] [review]
individual: Allow Individual.id to be an empty string with no personas

If an Individual has no Personas (as can happen when it’s just been
constructed), document the ID as being the empty string. This is a
special case.

Previously, the ID defaulted to being null, which violated its specified
type.
Comment 37 Travis Reitter 2013-11-28 02:09:07 UTC
Review of attachment 262960 [details] [review]:

General
-------
First, thanks for all the work on this. It's a giant effort and it will really
be useful to have in place.

* could we set a different version number for the dummy backend/library (eg, 0.1
  for the time being) and use clear messaging in releases to indicate that any
  API stability announcements do not apply to it? Though, I would really like to
  even get the dummy API stable by 1.0, so maybe it's OK as long as we've got
  separate soname numbering for it until 1.0 (at which point I think it'd be
  obnoxious /not/ to have them all unified, as that would lead to really ugly
  package numbering for at least Debian and derivatives)?

* update the NEWS changes to be in the 0.9.7 section

* as far as the broken persona-store test, you can merge this code then fix
  that. It must be fixed before the next release though. And we should do that
  relatively soon after since this is a big change worth getting out.

* in general, we don't have a common convention on the new symbols to say "these
  are special for the Dummy backend", eg, for changing the state of the Personas
  in the fake backing store. Maybe it's not necessary, but I know that it would
  even take me a little while to pick out exactly which of the new members are
  specifically for unique Dummy Backend functionality. We are certainly the
  primary audience for it, but it seems like it would be extra-difficult for
  anyone not already very familiar with the Folks API to use the dummy backend.
  I don't think every symbol needs a common prefix, but maybe a handful that we
  use consistently so any tutorial or we helping out other people could just say
  "you're looking for the symbols that start with "foo_", "bar_", or "baz_".

* please file a bug for "rebase tests/folks/* on dummy backend to remove EDS and
  key-file dependencies" and one to test a number of delays for properties and
  errors with persona adds/removes (using the mock functions) to make sure we
  don't break anything in the core with those types of issues. Having some tests
  with very long delays would also be a good time to split out long-running
  tests as a config option (to at least make sure they work before releases but
  not usually run during regular development).

* longer-term, we might want to remove the key-file backend before 1.0 since
  it's not terribly useful at this point

dummy/lib/dummy-backend.vala
----------------------------
set_persona_stores(), prepare(), unprepare():
* you use {freeze, thaw}_notify() to avoid extra notifications here. Is there
  any reason we shouldn't do this in all the other backends? If not, please open
  a bug for that

register_persona_stores():
* the docs claim that all stores must be a FolksDummy.PersonaStore (or subclass)
  but we don't actually enforce it. At the least, we should warn if this isn't
  met, maybe throw an Error

dummy/lib/dummy-fat-persona.vala
--------------------------------
* I think it would make more sense to call this something like SuperPersona,
  MaxPersona, or FullPersona to suggest it implements all interfaces. "Fat"
  makes me think it just implements "many" or always has a lot of preloaded
  attributes or something.

* would it make sense to use a different verb for the update_*() functions? It
  wasn't immediately obvious based on name that they were intended to make
  changes as if they happened in the backing store. What if we prepend
  "backend_" or "store_" to these functions to make it clear that they're
  simulating changes which would normally happen outside of our control? I
  wonder if it'd be cleaner to make them functions on the parent PersonaStore,
  but I don't have a strong opinion either way

dummy/lib/dummy-persona-store.vala
----------------------------------
* all the MaybeBool properties seem to default to FALSE. Would it make sense for
  them to default to UNSET, leaving it up to the caller to set up the details as
  it cares about them? I guess FALSE is a reasonable default for most cases
  though.

* It would be a little nice to wrap operations on _personas_changed_frozen in
  functions, so it can assert if we ever try to decrease it while it's <= 0
  (particularly since we mostly check whether it exactly equals 0)

+              else if (k == Folks.PersonaStore.detail_key (
... // repeat 30 times or more
There's so much repetition in this block. It's probably not worth changing but I
guess there isn't a great way to factor that pattern.

* as far as I can tell, we don't actually call the *_mock() functions from any
  tests. The code all looks right but I'd be a lot more confident if we
  exercised that code (at least one of each ranges of timeouts and with/without
  throwing an Error for a mock function)

add_persona_from_details_mock()
* the docs say that a negative return value in the delegate will have it return
  "synchronously". Is that actually true? It seems to just return immediately,
  and it's from an async function. I guess that's technically true but it makes
  it sound like it's somehow blocking for some amount of time.

* for all the other *_mock() functions, just have their docs refer to the first
  one's because otherwise we've got a lot of aliased text. Same for their
  delegates.

set_capabilities():
* I think we should probably have this accept a Map of well-known keys and their
  new values. Otherwise we could paint ourselves into a corner.

freeze_personas_changed():
* this functionality seems fairly useful for testing purposes. Is there any
  reason we don't have an equivalent for Persona details themselves (other than
  it being a lot hairier to implement)?

reach_quiescence():
* the docs should emphasize that it can only achieve quiescence after this
  function has been called, since that's normally something that clients can
  just expect to happen

update_is_user_set_default()
* Jonny would have a field day with this name but I think it's fine (other than
  the note above about update_*() functions)

dummy/lib/folks-dummy-uninstalled.pc.in
---------------------------------------
* this depends upon libebook and libedataserver — should it?
Comment 38 Travis Reitter 2013-11-28 02:14:02 UTC
Review of attachment 262961 [details] [review]:

This mostly looks good except for a trivial issue:

+      /* FIXME: assert (individual.display_name == "");*/

Just resolve that and push after the dummy backend is merged.
Comment 39 Travis Reitter 2013-11-28 02:15:16 UTC
Review of attachment 262962 [details] [review]:

Looks good. No need to wait to merge.
Comment 40 Travis Reitter 2013-11-28 02:15:55 UTC
Review of attachment 262963 [details] [review]:

Looks good. No need to wait to merge.
Comment 41 Philip Withnall 2013-11-28 10:11:15 UTC
Attachment 262962 [details] pushed as 1cff44a - individual: Add default values for PresenceDetails properties
Attachment 262963 [details] pushed as c3ace8c - individual: Allow Individual.id to be an empty string with no personas
Comment 42 Philip Withnall 2013-11-28 18:32:03 UTC
Created attachment 263048 [details] [review]
dummy: Add a dummy backend

This is a new backend targeted at making libfolks more testable. It is
designed to be used in internal libfolks unit tests, allowing the test
driver code to manipulate the backing store state to test how that
affects front-end state in libfolks. For example, it will be useful in
more thoroughly testing the IndividualAggregator.

It includes work by Renato Araujo Oliveira Filho <renatox@gmail.com>.

The backend may also be useful for testing libfolks clients,
such as contacts UIs, by providing an easy way to create well-known
personas to appear in the the UI. Hence, it is an installed backend, and
is loaded by default (although creates no Backend or PersonaStore instances
unless API calls are made).

It is designed to allow delay and error injection into all major
PersonaStore operations, and to allow any kind of Persona implementation
to be returned from the store.

It includes a few small test cases to sanity-check that the backend
works, but no thorough self-test-coverage.

Full API documentation is included and installed by default. The API is
not currently stable, so while external projects may start to consume
it, they should be prepared for breakage in the future as the API
stabilises. No timescale is given for such stabilisation.

This commit does not include any changes to the core libfolks unit
tests, but future changes could be made to port them to use the dummy
backend.

New API:
 • libfolks-dummy.la mocking library and all its symbols
Comment 43 Philip Withnall 2013-11-28 18:32:24 UTC
Created attachment 263050 [details] [review]
tests: Add a standalone-individuals test program

This contains a few test cases which check folks’ behaviour when
manually creating Individuals *outside* an IndividualAggregator. These
should catch the problems found in the following two bugs:
 • https://bugzilla.redhat.com/show_bug.cgi?id=1031252https://bugzilla.gnome.org/show_bug.cgi?id=712839
and hopefully fixed by commits:
 • f00534294d7d52ac7e37dfaa075e3465b7755483
 • 1ec050efc4f7135e9958c74da2028daf669077a0
Comment 44 Philip Withnall 2013-11-28 18:32:28 UTC
Created attachment 263051 [details] [review]
backends: Add [freeze|thaw]_notify() calls to [un]prepare() in backends

Reduce signal duplication. Inspired by the dummy backend.
Comment 45 Philip Withnall 2013-11-28 18:32:51 UTC
Updated branch here with fixup commits: http://cgit.collabora.com/git/user/pwith/folks.git/log/?h=648811-dummy-backend-final

Note it’s now based on the branch for bug #711544 (http://cgit.collabora.com/git/user/pwith/folks.git/log/?h=backend-lt-versioning).

I can’t upload any updated patches at the moment because Bugzilla doesn’t seem to be behaving properly.

(In reply to comment #37)
> * could we set a different version number for the dummy backend/library (eg,
> 0.1
>   for the time being) and use clear messaging in releases to indicate that any
>   API stability announcements do not apply to it? Though, I would really like
> to
>   even get the dummy API stable by 1.0, so maybe it's OK as long as we've got
>   separate soname numbering for it until 1.0 (at which point I think it'd be
>   obnoxious /not/ to have them all unified, as that would lead to really ugly
>   package numbering for at least Debian and derivatives)?

That’s bug #711544. I agree it’s definitely necessary to have different soname versioning, but I think the release versioning should  be kept uniform across the backends, or chaos will ensue. They’re all tied together by being the same tarball anyway.

I’ve updated that bug and made it a prerequisite of this one. The dummy backend branch is now rebased on it.

> * update the NEWS changes to be in the 0.9.7 section

Doesn’t seem to be necessary? May have fixed itself in the rebase.

> * as far as the broken persona-store test, you can merge this code then fix
>   that. It must be fixed before the next release though. And we should do that
>   relatively soon after since this is a big change worth getting out.

Agreed.

> * in general, we don't have a common convention on the new symbols to say
> "these
>   are special for the Dummy backend", *snip*

Actually, we do: ‘update’, ‘[un]register’ or ‘mock’ are used in almost all the backing store API. I’ve tweaked the documentation to better state this.

> * please file a bug for "rebase tests/folks/* on dummy backend to remove EDS
> and
>   key-file dependencies" *snip*

Bug #719502 and bug #719503.

> * longer-term, we might want to remove the key-file backend before 1.0 since
>   it's not terribly useful at this point

It’s useful as a fallback primary store if the user doesn’t have EDS. I would be opposed to removing it.

> dummy/lib/dummy-backend.vala
> ----------------------------
> set_persona_stores(), prepare(), unprepare():
> * you use {freeze, thaw}_notify() to avoid extra notifications here. Is there
>   any reason we shouldn't do this in all the other backends? If not, please
> open
>   a bug for that

Done as a new patch on this bug.

> register_persona_stores():
> * the docs claim that all stores must be a FolksDummy.PersonaStore (or
> subclass)
>   but we don't actually enforce it. At the least, we should warn if this isn't
>   met, maybe throw an Error

Added an assertion.

> dummy/lib/dummy-fat-persona.vala
> --------------------------------
> * I think it would make more sense to call this something like SuperPersona,
>   MaxPersona, or FullPersona to suggest it implements all interfaces. "Fat"
>   makes me think it just implements "many" or always has a lot of preloaded
>   attributes or something.

OK. Changed to FullPersona.

> * would it make sense to use a different verb for the update_*() functions? It
>   wasn't immediately obvious based on name that they were intended to make
>   changes as if they happened in the backing store. What if we prepend
>   "backend_" or "store_" to these functions to make it clear that they're
>   simulating changes which would normally happen outside of our control? I
>   wonder if it'd be cleaner to make them functions on the parent PersonaStore,
>   but I don't have a strong opinion either way

The method names are already pretty long and I don’t want to make them longer. I can’t think of anything better than ‘update’, so I’ll leave them as-is.

> dummy/lib/dummy-persona-store.vala
> ----------------------------------
> * all the MaybeBool properties seem to default to FALSE. Would it make sense
> for
>   them to default to UNSET, leaving it up to the caller to set up the details
> as
>   it cares about them? I guess FALSE is a reasonable default for most cases
>   though.

I think FALSE is a reasonable default and will leave them as-is.

> * It would be a little nice to wrap operations on _personas_changed_frozen in
>   functions, so it can assert if we ever try to decrease it while it's <= 0
>   (particularly since we mostly check whether it exactly equals 0)

The only way _personas_changed_frozen can be decremented is in thaw_personas_changed(), and that asserts it’s > 0 beforehand.

> +              else if (k == Folks.PersonaStore.detail_key (
> ... // repeat 30 times or more
> There's so much repetition in this block. It's probably not worth changing but
> I
> guess there isn't a great way to factor that pattern.

Not worth changing.

> * as far as I can tell, we don't actually call the *_mock() functions from any
>   tests. The code all looks right but I'd be a lot more confident if we
>   exercised that code (at least one of each ranges of timeouts and with/without
>   throwing an Error for a mock function)

I was planning on doing that as part of bug #719502.

> add_persona_from_details_mock()
> * the docs say that a negative return value in the delegate will have it return
>   "synchronously". Is that actually true? It seems to just return immediately,
>   and it's from an async function. I guess that's technically true but it makes
>   it sound like it's somehow blocking for some amount of time.

Whoops, looks like Vala does generate code which completes in an idle callback, rather than completely synchronously. Updated the documentation.

> * for all the other *_mock() functions, just have their docs refer to the first
>   one's because otherwise we've got a lot of aliased text. Same for their
>   delegates.

Fixed.

> set_capabilities():
> * I think we should probably have this accept a Map of well-known keys and
> their
>   new values. Otherwise we could paint ourselves into a corner.

I disagree. Those three capabilities have been fairly stable and sufficient for quite a while; I don’t foresee new ones being added. I dislike maps of well-known keys because they’re a faff to construct and call with, and not at all type-safe.

> freeze_personas_changed():
> * this functionality seems fairly useful for testing purposes. Is there any
>   reason we don't have an equivalent for Persona details themselves (other than
>   it being a lot hairier to implement)?

An equivalent for what? In the core libfolks or in the dummy backend? Sounds like bug #652659.

> reach_quiescence():
> * the docs should emphasize that it can only achieve quiescence after this
>   function has been called, since that's normally something that clients can
>   just expect to happen

Done.

> update_is_user_set_default()
> * Jonny would have a field day with this name but I think it's fine (other than
>   the note above about update_*() functions)

Hehe. Agreed.

> dummy/lib/folks-dummy-uninstalled.pc.in
> ---------------------------------------
> * this depends upon libebook and libedataserver — should it?

Good catch. Fixed.
Comment 46 Travis Reitter 2013-12-06 19:15:51 UTC
Review of attachment 263048 [details] [review]:

This mostly looks fine - but I'm now hitting a crasher with the dummy/add-persona test. And it's somehow missing debug symbols (and I can't tell why with just some quick examination):

Reading symbols from /home/treitter/collabora/folks/tests/dummy/.libs/lt-add-persona...(no debugging symbols found)...done.
(gdb) r
Starting program: /home/treitter/checkout/gnome/folks/tests/dummy/.libs/lt-add-persona 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Detaching after fork from child process 25240.
Detaching after fork from child process 25242.
/AddPersonaTests/adding a persona: [New Thread 0x7ffff0179700 (LWP 25253)]

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b2eac2 in folks_dummy_persona_store_real_add_persona_from_details_co ()
   from /home/treitter/checkout/gnome/folks/backends/dummy/lib/.libs/libfolks-dummy.so.25
Missing separate debuginfos, use: debuginfo-install gmp-5.1.1-2.fc19.x86_64 libmodman-2.0.1-6.fc19.x86_64 nettle-2.6-2.fc19.x86_64 systemd-libs-204-17.fc19.x86_64
(gdb) bt
  • #0 folks_dummy_persona_store_real_add_persona_from_details_co
    from /home/treitter/checkout/gnome/folks/backends/dummy/lib/.libs/libfolks-dummy.so.25
  • #1 folks_dummy_persona_store_add_persona_from_details_ready
    from /home/treitter/checkout/gnome/folks/backends/dummy/lib/.libs/libfolks-dummy.so.25
  • #2 g_simple_async_result_complete
    at gsimpleasyncresult.c line 777
  • #3 folks_dummy_full_persona_real_change_notes_co
    from /home/treitter/checkout/gnome/folks/backends/dummy/lib/.libs/libfolks-dummy.so.25
  • #4 folks_dummy_full_persona_change_notes_ready
    from /home/treitter/checkout/gnome/folks/backends/dummy/lib/.libs/libfolks-dummy.so.25
  • #5 g_simple_async_result_complete
    at gsimpleasyncresult.c line 777
  • #6 folks_dummy_persona_change_property_co
    from /home/treitter/checkout/gnome/folks/backends/dummy/lib/.libs/libfolks-dummy.so.25
  • #7 ____lambda2_
    from /home/treitter/checkout/gnome/folks/backends/dummy/lib/.libs/libfolks-dummy.so.25
  • #8 _____lambda2__gsource_func
    from /home/treitter/checkout/gnome/folks/backends/dummy/lib/.libs/libfolks-dummy.so.25
  • #9 g_main_dispatch
    at gmain.c line 3065
  • #10 g_main_context_dispatch
    at gmain.c line 3639
  • #11 g_main_context_iterate
    at gmain.c line 3710
  • #12 g_main_loop_run
    at gmain.c line 3904
  • #13 folks_test_utils_loop_run_with_timeout
  • #14 add_persona_tests_test_add_persona
  • #15 _add_persona_tests_test_add_persona_folks_test_case_test_method
  • #16 folks_test_case_weak_method_test
  • #17 test_case_run
    at gtestutils.c line 2067
  • #18 g_test_run_suite_internal
    at gtestutils.c line 2127
  • #19 g_test_run_suite_internal
    at gtestutils.c line 2138
  • #20 g_test_run_suite
    at gtestutils.c line 2189
  • #21 _vala_main
  • #22 main


So, please see if you can reproduce or figure out what might be going wrong. The implementation of the notes functionality doesn't seem obviously wrong, but I haven't tried debugging in detail.

Other than that, I think this patch is ready.
Comment 47 Travis Reitter 2013-12-06 19:16:40 UTC
Review of attachment 263050 [details] [review]:

Looks good. Merge after deps.
Comment 48 Travis Reitter 2013-12-06 19:17:01 UTC
Review of attachment 263051 [details] [review]:

Looks good.
Comment 49 Philip Withnall 2013-12-09 11:14:49 UTC
Fixed the crasher in comment #46 (was a missing NULL check). Everything pushed to master! Yay!

Attachment 263048 [details] pushed as 3a63de9 - dummy: Add a dummy backend
Attachment 263050 [details] pushed as e0e7675 - tests: Add a standalone-individuals test program
Attachment 263051 [details] pushed as 3eb474f - backends: Add [freeze|thaw]_notify() calls to [un]prepare() in backends