public void test_volatility_sensitivity() {
   double eps = 1.0e-6;
   int nData = TIME.size();
   for (int i = 0; i < NB_TEST; i++) {
     SwaptionSensitivity point =
         SwaptionSensitivity.of(
             CONVENTION,
             TEST_OPTION_EXPIRY[i],
             TENOR.get(i),
             TEST_STRIKE,
             TEST_FORWARD,
             GBP,
             TEST_SENSITIVITY[i]);
     SurfaceCurrencyParameterSensitivity sensi =
         PROVIDER_WITH_PARAM.surfaceCurrencyParameterSensitivity(point);
     Map<DoublesPair, Double> map = new HashMap<DoublesPair, Double>();
     for (int j = 0; j < nData; ++j) {
       DoubleArray volDataUp = VOL.subArray(0, nData).with(j, VOL.get(j) + eps);
       DoubleArray volDataDw = VOL.subArray(0, nData).with(j, VOL.get(j) - eps);
       InterpolatedNodalSurface paramUp =
           InterpolatedNodalSurface.of(
               METADATA_WITH_PARAM, TIME, TENOR, volDataUp, INTERPOLATOR_2D);
       InterpolatedNodalSurface paramDw =
           InterpolatedNodalSurface.of(
               METADATA_WITH_PARAM, TIME, TENOR, volDataDw, INTERPOLATOR_2D);
       BlackVolatilityExpiryTenorSwaptionProvider provUp =
           BlackVolatilityExpiryTenorSwaptionProvider.of(
               paramUp, CONVENTION, ACT_365F, VALUATION_DATE_TIME);
       BlackVolatilityExpiryTenorSwaptionProvider provDw =
           BlackVolatilityExpiryTenorSwaptionProvider.of(
               paramDw, CONVENTION, ACT_365F, VALUATION_DATE_TIME);
       double volUp =
           provUp.getVolatility(TEST_OPTION_EXPIRY[i], TEST_TENOR[i], TEST_STRIKE, TEST_FORWARD);
       double volDw =
           provDw.getVolatility(TEST_OPTION_EXPIRY[i], TEST_TENOR[i], TEST_STRIKE, TEST_FORWARD);
       double fd = 0.5 * (volUp - volDw) / eps;
       map.put(DoublesPair.of(TIME.get(j), TENOR.get(j)), fd);
     }
     SurfaceCurrencyParameterSensitivity sensiFromNoMetadata =
         PROVIDER.surfaceCurrencyParameterSensitivity(point);
     List<SurfaceParameterMetadata> list = sensi.getMetadata().getParameterMetadata().get();
     DoubleArray computed = sensi.getSensitivity();
     assertEquals(computed.size(), nData);
     for (int j = 0; j < list.size(); ++j) {
       SwaptionSurfaceExpiryTenorNodeMetadata metadata =
           (SwaptionSurfaceExpiryTenorNodeMetadata) list.get(i);
       double expected = map.get(DoublesPair.of(metadata.getYearFraction(), metadata.getTenor()));
       assertEquals(computed.get(i), expected, eps);
       assertTrue(
           sensiFromNoMetadata.getMetadata().getParameterMetadata().get().contains(metadata));
     }
   }
 }
 static {
   List<SwaptionSurfaceExpiryTenorNodeMetadata> list =
       new ArrayList<SwaptionSurfaceExpiryTenorNodeMetadata>();
   int nData = TIME.size();
   for (int i = 0; i < nData; ++i) {
     SwaptionSurfaceExpiryTenorNodeMetadata parameterMetadata =
         SwaptionSurfaceExpiryTenorNodeMetadata.of(TIME.get(i), TENOR.get(i));
     list.add(parameterMetadata);
   }
   METADATA_WITH_PARAM =
       DefaultSurfaceMetadata.builder()
           .dayCount(ACT_365F)
           .parameterMetadata(list)
           .surfaceName(SurfaceName.of("GOVT1-SWAPTION-VOL"))
           .xValueType(ValueType.YEAR_FRACTION)
           .yValueType(ValueType.YEAR_FRACTION)
           .build();
   METADATA =
       DefaultSurfaceMetadata.builder()
           .dayCount(ACT_365F)
           .surfaceName(SurfaceName.of("GOVT1-SWAPTION-VOL"))
           .xValueType(ValueType.YEAR_FRACTION)
           .yValueType(ValueType.YEAR_FRACTION)
           .build();
 }