PipelineMetadataService implements ApiRoutable { @GET @TreeResponse public ExportedPipelineFunction[] doPipelineStepMetadata() { List<ExportedPipelineFunction> pd = new ArrayList<>(); for (StepDescriptor d : StepDescriptor.all()) { if (includeStep(d)) { ExportedPipelineStep step = getStepMetadata(d); if (step != null) { pd.add(step); } } } List<Descriptor<?>> metaStepDescriptors = new ArrayList<Descriptor<?>>(); populateMetaSteps(metaStepDescriptors, Builder.class); populateMetaSteps(metaStepDescriptors, Publisher.class); populateMetaSteps(metaStepDescriptors, BuildWrapper.class); for (Descriptor<?> d : metaStepDescriptors) { ExportedPipelineFunction metaStep = getStepMetadata(d); if (metaStep != null) { pd.add(metaStep); } } return pd.toArray(new ExportedPipelineFunction[pd.size()]); }  @Override String getUrlName(); @GET String doCrumbInfo(); @GET @TreeResponse ExportedDescribableModel[] doAgentMetadata(); @GET @TreeResponse ExportedToolDescriptor[] doToolMetadata(); @GET @TreeResponse ExportedBuildCondition[] doBuildConditions(); @GET @TreeResponse ExportedPipelineStep[] doWrapperMetadata(); @GET @TreeResponse ExportedPipelineFunction[] doPipelineStepMetadata();  }
@Test public void verifyFunctionNames() throws Exception { PipelineMetadataService svc = new PipelineMetadataService(); List<ExportedDescribableModel> steps = new ArrayList<>(); steps.addAll(Arrays.asList(svc.doPipelineStepMetadata())); assertFalse(steps.isEmpty()); assertThat(steps, hasItem(stepWithName("archiveArtifacts"))); assertThat(steps, not(hasItem(stepWithName("properties")))); assertThat(steps, not(hasItem(stepWithName("archive")))); assertThat(steps, hasItem(stepWithName("catchError"))); assertThat(steps, hasItem(stepWithName("withSonarQubeEnv"))); }