public ScalarFn loadScalarFunction(List<String> functionPath, String jarPath) {
    String functionFullName = String.join(".", functionPath);
    try {
      FunctionDefinitions functionDefinitions = loadJar(jarPath);
      if (!functionDefinitions.scalarFunctions().containsKey(functionPath)) {
        throw new IllegalArgumentException(
            String.format(
                "No implementation of scalar function %s found in %s.%n"
                    + " 1. Create a class implementing %s and annotate it with @AutoService(%s.class).%n"
                    + " 2. Add function %s to the class's userDefinedScalarFunctions implementation.",
                functionFullName,
                jarPath,
                UdfProvider.class.getSimpleName(),
                UdfProvider.class.getSimpleName(),
                functionFullName));
      }
      return functionDefinitions.scalarFunctions().get(functionPath);
    } catch (IOException e) {
      throw new RuntimeException(
          String.format(
              "Failed to load user-defined scalar function %s from %s", functionFullName, jarPath),
          e);
    }
  }
@Test
  public void testJarMissingUdfProviderThrowsProviderNotFoundException() {
    JavaUdfLoader udfLoader = new JavaUdfLoader();
    thrown.expect(ProviderNotFoundException.class);
    thrown.expectMessage(String.format("No UdfProvider implementation found in %s.", emptyJarPath));
    // Load from an inhabited jar first so we can make sure we load UdfProviders in isolation
    // from other jars.
    udfLoader.loadScalarFunction(Collections.singletonList("helloWorld"), jarPath);
    udfLoader.loadScalarFunction(Collections.singletonList("helloWorld"), emptyJarPath);
  }