datafaker icon indicating copy to clipboard operation
datafaker copied to clipboard

java.lang.RuntimeException: Unable to resolve #{male_first_name} directive for FakerContext

Open bodiam opened this issue 1 year ago • 12 comments

Describe the bug

Running the following code shows the issue:

public class ExpressionBugTest {

    @Test
    void testExpressionEnglishFails() {
        Faker faker = new Faker(Locale.ENGLISH);
        String expression = faker.expression("#{name.first_name}");
        System.out.println(expression);
    }

    @Test
    void testExpressionFails() {
        Faker faker = new Faker();
        String expression = faker.expression("#{name.first_name}");
        System.out.println(expression);
    }

    @Test
    void testExpressionUsFails() {
        Faker faker = new Faker(new Locale("en", "US"));
        String expression = faker.expression("#{name.first_name}");
        System.out.println(expression);
    }

    @Test
    void testExpressionAUWorks() {
        Faker faker = new Faker(new Locale("en", "AU"));
        String expression = faker.expression("#{name.first_name}");
        System.out.println(expression);
    }

    @Test
    void testExpressionNLWorks() {
        Faker faker = new Faker(new Locale("nl", "nl"));
        String expression = faker.expression("#{name.first_name}");
        System.out.println(expression);
    }
}

Running this gives the following error:

java.lang.RuntimeException: Unable to resolve #{male_first_name} directive for FakerContext FakerContext{, locale=SingletonLocale{locale=en}, randomService=net.datafaker.service.RandomService@1}.

	at net.datafaker.service.FakeValuesService.resolveExpression(FakeValuesService.java:578)
	at net.datafaker.service.FakeValuesService.resolveExpression(FakeValuesService.java:580)
	at net.datafaker.service.FakeValuesService.expression(FakeValuesService.java:453)
	at net.datafaker.providers.base.BaseFaker.expression(BaseFaker.java:434)
	at net.datafaker.ExpressionBugTest.x(ExpressionBugTest.java:12)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at java.base/java.util.concurrent.RecursiveAction.exec(RecursiveAction.java:194)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)

To Reproduce See above

Expected behavior Generate a name

Versions:

  • Faker Version 2.2.2

Additional context Add any other context about the problem here.

bodiam avatar Apr 28 '24 10:04 bodiam

2.2.2 snapshot?

kingthorin avatar Apr 28 '24 10:04 kingthorin

Are you working on a fix or hoping someone will pick this up?

kingthorin avatar Apr 28 '24 10:04 kingthorin

No, not 2.2.2-snapshot, 2.2.2-non-snapshot. It probably affects other versions too.

And no, I'm not working on a fix at the moment. I had a look to see if I could find the issue, but so far I was a bit lost what's causing this. And yes, I would appreciate if a keen person for who it's not Sunday 9pm could have a look at this :-)

bodiam avatar Apr 28 '24 11:04 bodiam

Sorry, apparently I lost track of releases this week 😀

I'll try to have a look this week.

kingthorin avatar Apr 28 '24 12:04 kingthorin

Sorry, apparently I lost track of releases this week 😀

Well, that's excusable: I did 3 releases in 3 days ;-). I'll also try to have a look when I'm a bit more fresh, thanks!

bodiam avatar Apr 28 '24 12:04 bodiam

It has something to do with chained or nested expressions. In en-AU name.first_name is a litteral list. In en-US (or well default) name.first_name is:

      first_name:
      - "#{female_first_name}"
      - "#{male_first_name}"

If changed to:

      first_name:
      - "#{name.female_first_name}"
      - "#{name.male_first_name}"

The tests pass. I'll have to keep testing/playing but I thought I should mention it in-case one of you sees the fix quicker knowing the code better than me 👍

Conversely the following test fails (seemingly for the same reason as the other English/default tests):

    @Test
    void testExpressionNLWithMiddleWorks() {
        Faker faker = new Faker(new Locale("nl", "nl"));
        String expression = faker.expression("#{name.name_with_middle}");
        System.out.println(expression);
    }

kingthorin avatar Apr 28 '24 18:04 kingthorin

The issue seems to be "current" being passed as null: https://github.com/datafaker-net/datafaker/blob/70d2ef45ab6b34f41c597d6201d29c98a5a1a433/src/main/java/net/datafaker/service/FakeValuesService.java#L453

The following makes the tests pass (obviously not a fix, but a PoC):

diff --git a/src/main/java/net/datafaker/service/FakeValuesService.java b/src/main/java/net/datafaker/service/FakeValuesService.java
index daafc8dd..dd026bd3 100644
--- a/src/main/java/net/datafaker/service/FakeValuesService.java
+++ b/src/main/java/net/datafaker/service/FakeValuesService.java
@@ -1,5 +1,6 @@
 package net.datafaker.service;

+import net.datafaker.Faker;
 import net.datafaker.internal.helper.COWMap;
 import net.datafaker.internal.helper.SingletonLocale;
 import net.datafaker.providers.base.AbstractProvider;
@@ -547,6 +548,9 @@ protected String resolveExpression(String expression, Object current, ProviderRe
         if (!expression.contains("}")) {
             return expression;
         }
+        if (current == null) {
+            current = new BaseFaker().name();
+        }
         final int expressionLength = expression.length();
         final String[] expressions = splitExpressions(expression, expressionLength);
         final StringBuilder result = new StringBuilder(expressions.length * expressionLength);

kingthorin avatar Apr 28 '24 19:04 kingthorin

yep, the issue is with current object however not only name could be here

for instance for this test

Faker faker = new Faker(new Locale("nl", "nl"));
faker.expression("#{address.full_address}");

the PoC code will fail

snuyanzin avatar Apr 28 '24 20:04 snuyanzin

Yeah that's why I said it wasn't a fix, just a poc

kingthorin avatar Apr 28 '24 20:04 kingthorin

https://github.com/datafaker-net/datafaker/pull/1180 here i submitted a poc, however there is still one test which need to think how to handle it

snuyanzin avatar Apr 28 '24 22:04 snuyanzin

@snuyanzin I've done some more tests, but things like this also don't work, no matter the Locale:

        String expression = faker.expression("#{address.city}");

bodiam avatar May 01 '24 13:05 bodiam

I added this test as well to the PR

snuyanzin avatar May 01 '24 15:05 snuyanzin

@bodiam is there anything else which is not fixed here? it seems #1180 covers all the issues mentioned here

snuyanzin avatar Jun 01 '24 11:06 snuyanzin

Things seem to be stable again, aren't they? Let's close it.

bodiam avatar Jun 01 '24 14:06 bodiam