text:
@interface DOSDataAPITests : XCTestCase

@end

@implementation DOSDataAPITests

- (void)setUp
{
    [super setUp];
    // Put setup code here. This method is called before the invocation of each test method in the class.
}

- (void)tearDown
{
    // Put teardown code here. This method is called after the invocation of each test method in the class.
    [super tearDown];
}

// Tests the parsing of the Secretary Travel Response
- (void)testSecretaryTravel
{
    DOSSecretaryTravelDataManager *dataMan = [[DOSSecretaryTravelDataManager alloc] init];
    [dataMan getSecretaryTravelWithOptions:nil success:^(NSArray *response) {

        XCTAssertNotNil(response[0], @"API Did not Return a Result: Secretary Travel Test");

        [self notify:XCTAsyncTestCaseStatusSucceeded];

    } failure:^(NSError *error) {
        XCTFail(@"Secretary Travel Error: %@", error);
    }];

    [self waitForStatus:XCTAsyncTestCaseStatusSucceeded timeout:5];
}

// Test empty search results
- (void)testSecretaryTravelTermSearchNullResults
{
    DOSSecretaryTravelDataManager *dataMan = [[DOSSecretaryTravelDataManager alloc] init];

    NSMutableDictionary *options = [[NSMutableDictionary alloc] init];
    [options setObject:@"id,title" forKey:DOSQueryArgFields];
    [options setObject:@"DOESNOTEXIST" forKey:DOSQueryArgTerms];

    [dataMan getSecretaryTravelWithOptions:options success:^(NSArray *response) {

        XCTAssertNotNil(response, @"SDK did not handle null search result correctly: Secretary Travel Term Search Test");

        [self notify:XCTAsyncTestCaseStatusSucceeded];

    } failure:^(NSError *error) {
        XCTFail(@"Secretary Travel Error: %@", error);
    }];

    [self waitForStatus:XCTAsyncTestCaseStatusSucceeded timeout:5];
}

// Tests the conversion of JSON response to Obj-C objects
- (void)testSecretaryTravelResponseConversion
{
    DOSSecretaryTravelDataManager *dataMan = [[DOSSecretaryTravelDataManager alloc] init];

    NSMutableDictionary *options = [[NSMutableDictionary alloc] init];
    [options setObject:@"id,title,site_url,content_url,content_html,full_url,full_html,mobile_url,date,date_start,date_end,terms" forKey:DOSQueryArgFields];
    [options setObject:[NSNumber numberWithInt:1] forKey:DOSQueryArgPerPage];

    [dataMan getSecretaryTravelWithOptions:options success:^(NSArray *response) {
        XCTAssertNotNil(response[0], @"API Did not Return a Result: Secretary Travel Full Field Test");

        // Test each field for data
        DOSSecretaryTravelItem *item = response[0];
        XCTAssertNotNil(item.itemId, @"Secretary Travel Response Parse Failed For: itemID");
        XCTAssertNotNil(item.title, @"Secretary Travel Response Parse Failed For: title");
        XCTAssertNotNil(item.siteUrl, @"Secretary Travel Response Parse Failed For: siteUrl");
        XCTAssertNotNil(item.contentUrl, @"Secretary Travel Response Parse Failed For: contentUrl");
        XCTAssertNotNil(item.contentHtml, @"Secretary Travel Response Parse Failed For: contentHtml");
        XCTAssertNotNil(item.fullUrl, @"Secretary Travel Response Parse Failed For: fullUrl");
        XCTAssertNotNil(item.fullHtml, @"Secretary Travel Response Parse Failed For: fullHtml");
        XCTAssertNotNil(item.mobileUrl, @"Secretary Travel Response Parse Failed For: mobileUrl");
        XCTAssertNotNil(item.date, @"Secretary Travel Response Parse Failed For: date");
        XCTAssertNotNil(item.dateStart, @"Secretary Travel Response Parse Failed For: dateStart");
        XCTAssertNotNil(item.dateEnd, @"Secretary Travel Response Parse Failed For: dateEnd");
        XCTAssertNotNil(item.terms, @"Secretary Travel Response Parse Failed For: terms");

        [self notify:XCTAsyncTestCaseStatusSucceeded];

    } failure:^(NSError *error) {
        XCTFail(@"Secretary Travel Error: %@", error);
    }];

    [self waitForStatus:XCTAsyncTestCaseStatusSucceeded timeout:10];
}

// Tests the Secretary Travel Detail interface
- (void)testSecretaryTravelDetail
{
    DOSSecretaryTravelDataManager *dataMan = [[DOSSecretaryTravelDataManager alloc] init];
    [dataMan getSecretaryTravelDetailForItem:@"10060804" withOptions:nil success:^(NSArray *response) {

        XCTAssertNotNil(response[0], @"API Did not Return a Result: Secretary Travel Detail Test");

        [self notify:XCTAsyncTestCaseStatusSucceeded];

    } failure:^(NSError *error) {
        XCTFail(@"Secretary Travel Detail Error: %@", error);
    }];

    [self waitForStatus:XCTAsyncTestCaseStatusSucceeded timeout:5];
}

// Tests the Secretary Travel Stats interface
-(void)testSecretaryTravelStatsResponse
{
    DOSSecretaryTravelDataManager *dataMan = [[DOSSecretaryTravelDataManager alloc] init];
    [dataMan getSecretaryTravelStatsWithSuccess:^(NSArray *response) {
        XCTAssertNotNil(response[0], @"API Did not Return a Result: Secretary Travel Stats Test");

        // Test each field for data
        DOSSecretaryTravelStatsItem *item = response[0];
        XCTAssertNotNil(item.flightTimeHours, @"Secretary Travel Stats Response Parse Failed For: flightTimeHours");
        XCTAssertNotNil(item.milage, @"Secretary Travel Stats Response Parse Failed For: milage");
        XCTAssertNotNil(item.countriesVisited, @"Secretary Travel Stats Response Parse Failed For: countriesVisited");
        XCTAssertNotNil(item.travelDays, @"Secretary Travel Stats Response Parse Failed For: travelDays");

        [self notify:XCTAsyncTestCaseStatusSucceeded];

    } failure:^(NSError *error) {
        XCTFail(@"Secretary Travel Stats Error: %@", error);
    }];

    [self waitForStatus:XCTAsyncTestCaseStatusSucceeded timeout:10];
}

// Tests the parsing of the Secretary Travel Schedule Response
- (void)testSecretaryAppointmentSchedule
{
    DOSSecretaryAppointmentManager *dataMan = [[DOSSecretaryAppointmentManager alloc] init];
    [dataMan getSecretaryAppointmentsWithOptions:nil success:^(NSArray *response) {

        XCTAssertNotNil(response[0], @"API Did not Return a Result: Secretary Appointment Test");

        [self notify:XCTAsyncTestCaseStatusSucceeded];

    } failure:^(NSError *error) {
        XCTFail(@"Secretary Appointment Schedule Error: %@", error);
    }];

    [self waitForStatus:XCTAsyncTestCaseStatusSucceeded timeout:5];
}

// Tests the conversion of JSON response to Obj-C objects
- (void)testSecretaryAppointmentResponseConversion
{
    DOSSecretaryAppointmentManager *dataMan = [[DOSSecretaryAppointmentManager alloc] init];

    NSMutableDictionary *options = [[NSMutableDictionary alloc] init];
    [options setObject:@"id,title,site_url,content_url,content_html,full_url,full_html,mobile_url,date,terms" forKey:DOSQueryArgFields];
    [options setObject:[NSNumber numberWithInt:1] forKey:DOSQueryArgPerPage];

    [dataMan getSecretaryAppointmentsWithOptions:options success:^(NSArray *response) {
        XCTAssertNotNil(response[0], @"API Did not Return a Result: Secretary Appointment Full Field Test");

        // Test each field for data
        DOSSecretaryAppointmentItem *item = response[0];
        XCTAssertNotNil(item.itemId, @"Secretary Appointment Response Parse Failed For: itemID");
        XCTAssertNotNil(item.title, @"Secretary Appointment Response Parse Failed For: title");
        XCTAssertNotNil(item.siteUrl, @"Secretary Appointment Response Parse Failed For: siteUrl");
        XCTAssertNotNil(item.contentUrl, @"Secretary Appointment Response Parse Failed For: contentUrl");
        XCTAssertNotNil(item.contentHtml, @"Secretary Appointment Response Parse Failed For: contentHtml");
        XCTAssertNotNil(item.fullUrl, @"Secretary Appointment Response Parse Failed For: fullUrl");
        XCTAssertNotNil(item.fullHtml, @"Secretary Appointment Response Parse Failed For: fullHtml");
        XCTAssertNotNil(item.mobileUrl, @"Secretary Appointment Response Parse Failed For: mobileUrl");
        XCTAssertNotNil(item.date, @"Secretary Appointment Response Parse Failed For: date");
        XCTAssertNotNil(item.terms, @"Secretary Appointment Response Parse Failed For: terms");

        [self notify:XCTAsyncTestCaseStatusSucceeded];

    } failure:^(NSError *error) {
        XCTFail(@"Secretary Appointment Error: %@", error);
    }];

    [self waitForStatus:XCTAsyncTestCaseStatusSucceeded timeout:10];
}

// Tests the parsing of the TIP Report Response
- (void)testTIPReportData
{
    DOSTIPReportManager *dataMan = [[DOSTIPReportManager alloc] init];
    [dataMan getTIPReportsWithOptions:nil success:^(NSArray *response) {

        XCTAssertNotNil(response[0], @"API Did not Return a Result: TIP Report Test");

        [self notify:XCTAsyncTestCaseStatusSucceeded];

    } failure:^(NSError *error) {
        XCTFail(@"TIP Report Error: %@", error);
    }];

    [self waitForStatus:XCTAsyncTestCaseStatusSucceeded timeout:5];
}

// Tests the conversion of JSON response to Obj-C objects
- (void)testTIPReportResponseConversion
{
    DOSTIPReportManager *dataMan = [[DOSTIPReportManager alloc] init];

    NSMutableDictionary *options = [[NSMutableDictionary alloc] init];
    [options setObject:@"id,title,site_url,content_url,content_html,full_url,full_html,mobile_url,year,terms" forKey:DOSQueryArgFields];
    [options setObject:[NSNumber numberWithInt:1] forKey:DOSQueryArgPerPage];

    [dataMan getTIPReportsWithOptions:options success:^(NSArray *response) {
        XCTAssertNotNil(response[0], @"API Did not Return a Result: TIP Report Full Field Test");

        // Test each field for data
        DOSTIPReportItem *item = response[0];
        XCTAssertNotNil(item.itemId, @"TIP Report Response Parse Failed For: itemID");
        XCTAssertNotNil(item.title, @"TIP Report Response Parse Failed For: title");
        XCTAssertNotNil(item.siteUrl, @"TIP Report Response Parse Failed For: siteUrl");
        XCTAssertNotNil(item.contentUrl, @"TIP Report Response Parse Failed For: contentUrl");
        XCTAssertNotNil(item.contentHtml, @"TIP Report Response Parse Failed For: contentHtml");
        XCTAssertNotNil(item.fullUrl, @"TIP Report Response Parse Failed For: fullUrl");
        XCTAssertNotNil(item.fullHtml, @"TIP Report Response Parse Failed For: fullHtml");
        XCTAssertNotNil(item.mobileUrl, @"TIP Report Response Parse Failed For: mobileUrl");
        XCTAssertNotNil(item.year, @"TIP Report Response Parse Failed For: date");
        XCTAssertNotNil(item.terms, @"TIP Report Response Parse Failed For: terms");

        [self notify:XCTAsyncTestCaseStatusSucceeded];

    } failure:^(NSError *error) {
        XCTFail(@"TIP Report Error: %@", error);
    }];

    [self waitForStatus:XCTAsyncTestCaseStatusSucceeded timeout:10];
}

// Tests the parsing of the Country Fact Sheet Response
- (void)testCountryFactSheetData
{
    DOSCountryFactSheetManager *dataMan = [[DOSCountryFactSheetManager alloc] init];
    [dataMan getCountryFactSheetsWithOptions:nil success:^(NSArray *response) {

        XCTAssertNotNil(response[0], @"API Did not Return a Result: Country Fact Sheet Test");

        [self notify:XCTAsyncTestCaseStatusSucceeded];

    } failure:^(NSError *error) {
        XCTFail(@"Country Fact Sheet Error: %@", error);
    }];

    [self waitForStatus:XCTAsyncTestCaseStatusSucceeded timeout:5];
}

// Tests the conversion of JSON response to Obj-C objects
- (void)testCountryFactSheetResponseConversion
{
    DOSCountryFactSheetManager *dataMan = [[DOSCountryFactSheetManager alloc] init];

    NSMutableDictionary *options = [[NSMutableDictionary alloc] init];
    [options setObject:@"id,title,site_url,content_url,content_html,full_url,full_html,mobile_url,date,terms,bureau,official_name" forKey:DOSQueryArgFields];
    [options setObject:[NSNumber numberWithInt:1] forKey:DOSQueryArgPerPage];

    [dataMan getCountryFactSheetsWithOptions:options success:^(NSArray *response) {
        XCTAssertNotNil(response[0], @"API Did not Return a Result: Country Fact Sheet Full Field Test");

        // Test each field for data
        DOSCountryFactSheetItem *item = response[0];
        XCTAssertNotNil(item.itemId, @"Country Fact Sheet Response Parse Failed For: itemID");
        XCTAssertNotNil(item.title, @"Country Fact Sheet Response Parse Failed For: title");
        XCTAssertNotNil(item.siteUrl, @"Country Fact Sheet Response Parse Failed For: siteUrl");
        XCTAssertNotNil(item.contentUrl, @"Country Fact Sheet Response Parse Failed For: contentUrl");
        XCTAssertNotNil(item.contentHtml, @"Country Fact Sheet Response Parse Failed For: contentHtml");
        XCTAssertNotNil(item.fullUrl, @"Country Fact Sheet Response Parse Failed For: fullUrl");
        XCTAssertNotNil(item.fullHtml, @"Country Fact Sheet Response Parse Failed For: fullHtml");
        XCTAssertNotNil(item.mobileUrl, @"Country Fact Sheet Response Parse Failed For: mobileUrl");
        XCTAssertNotNil(item.date, @"Country Fact Sheet Response Parse Failed For: date");
        XCTAssertNotNil(item.terms, @"Country Fact Sheet Response Parse Failed For: terms");
        XCTAssertNotNil(item.bureau, @"Country Fact Sheet Response Parse Failed For: bureau");
        XCTAssertNotNil(item.officialName, @"Country Fact Sheet Response Parse Failed For: officialName");

        [self notify:XCTAsyncTestCaseStatusSucceeded];

    } failure:^(NSError *error) {
        XCTFail(@"Country Fact Sheet Error: %@", error);
    }];

    [self waitForStatus:XCTAsyncTestCaseStatusSucceeded timeout:10];
}

// Tests the parsing of the Bureau list Response
- (void)testBureauData
{
    DOSBureauManager *dataMan = [[DOSBureauManager alloc] init];
    [dataMan getBureausWithOptions:nil success:^(NSArray *response) {

        XCTAssertNotNil(response[0], @"API Did not Return a Result: Bureau list Test");

        [self notify:XCTAsyncTestCaseStatusSucceeded];

    } failure:^(NSError *error) {
        XCTFail(@"Bureau List Error: %@", error);
    }];

    [self waitForStatus:XCTAsyncTestCaseStatusSucceeded timeout:5];
}

// Tests the conversion of JSON response to Obj-C objects
- (void)testBureauResponseConversion
{
    DOSBureauManager *dataMan = [[DOSBureauManager alloc] init];

    NSMutableDictionary *options = [[NSMutableDictionary alloc] init];
    [options setObject:[NSNumber numberWithInt:1] forKey:DOSQueryArgPerPage];

    [dataMan getBureausWithOptions:options success:^(NSArray *response) {
        XCTAssertNotNil(response[0], @"API Did not Return a Result: Bureau Full Field Test");

        // Test each field for data
        DOSBureauItem *item = response[0];
        XCTAssertNotNil(item.name, @"Bureau Response Parse Failed For: name");
        XCTAssertNotNil(item.description, @"Bureau Response Parse Failed For: description");

        [self notify:XCTAsyncTestCaseStatusSucceeded];

    } failure:^(NSError *error) {
        XCTFail(@"Bureau List Error: %@", error);
    }];

    [self waitForStatus:XCTAsyncTestCaseStatusSucceeded timeout:10];
}

// Tests the parsing of the Term list Response
- (void)testTermData
{
    DOSTermManager *dataMan = [[DOSTermManager alloc] init];
    [dataMan getTermsWithOptions:nil success:^(NSArray *response) {

        XCTAssertNotNil(response[0], @"API Did not Return a Result: Term list Test");

        [self notify:XCTAsyncTestCaseStatusSucceeded];

    } failure:^(NSError *error) {
        XCTFail(@"Term List Error: %@", error);
    }];

    [self waitForStatus:XCTAsyncTestCaseStatusSucceeded timeout:5];
}

// Tests the conversion of JSON response to Obj-C objects
- (void)testTermResponseConversion
{
    DOSTermManager *dataMan = [[DOSTermManager alloc] init];

    NSMutableDictionary *options = [[NSMutableDictionary alloc] init];
    [options setObject:[NSNumber numberWithInt:1] forKey:DOSQueryArgPerPage];

    [dataMan getTermsWithOptions:options success:^(NSArray *response) {
        XCTAssertNotNil(response[0], @"API Did not Return a Result: Terms Full Field Test");

        // Test each field for data
        DOSTermItem *item = response[0];
        XCTAssertNotNil(item.name, @"Term Response Parse Failed For: name");
        XCTAssertNotNil(item.description, @"Term Response Parse Failed For: description");

        [self notify:XCTAsyncTestCaseStatusSucceeded];

    } failure:^(NSError *error) {
        XCTFail(@"Term List Error: %@", error);
    }];

    [self waitForStatus:XCTAsyncTestCaseStatusSucceeded timeout:10];
}

@end


text:
layout: page
title: Farrell - Singleton Wedding
date: 2016-05-24
author: Marilyn Oneill
tags: weekly links, java
status: published
summary: Mauris maximus, sapien et sagittis efficitur, lacus enim pharetra libero.
banner: images/banner/people.jpg
booking:
  startDate: 08/10/2019
  endDate: 08/15/2019
  ctyhocn: TCLBMHX
  groupCode: FSW
published: true
---
Etiam imperdiet metus sapien, vitae pharetra est molestie non. Mauris blandit laoreet urna. Donec egestas augue neque, sed consectetur sapien porta at. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Quisque dictum blandit est, in iaculis elit dictum non. Nulla vel feugiat ex, suscipit ornare nibh. Donec convallis leo odio, et luctus velit facilisis sed. Duis enim lorem, dignissim eu nibh vel, consequat sodales dolor. Nam condimentum libero id dapibus blandit. Vestibulum eget sem vitae odio dapibus vehicula. Praesent cursus quam eu ante lacinia sodales. In tincidunt non erat quis iaculis.

* Donec placerat velit eu tortor porta pellentesque
* Curabitur vitae justo a nulla venenatis mollis
* Aliquam lacinia dolor bibendum tincidunt suscipit.

Suspendisse eleifend nec erat in laoreet. Nam tempor semper volutpat. Aenean vitae dapibus lorem, consectetur luctus orci. Aliquam eu tortor ac mi sagittis malesuada eget sit amet nunc. Nulla a mi augue. Nulla vel mauris accumsan, gravida nunc vitae, luctus metus. Pellentesque vitae eleifend felis. Vestibulum consectetur tortor vitae eros blandit convallis. Fusce pretium fermentum dictum. Vestibulum et iaculis nibh. Phasellus volutpat, orci vel consectetur elementum, nisi quam semper dolor, nec blandit nisl ipsum condimentum eros. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Etiam aliquet mauris a libero sodales, non maximus ligula fringilla. Curabitur et arcu et urna bibendum vestibulum.
Aenean lacus libero, vestibulum sed tortor eget, gravida finibus sem. Cras molestie enim ut efficitur pulvinar. Phasellus sit amet varius lacus. Cras condimentum mi nec risus pretium maximus. Ut bibendum eget dui id dictum. Cras finibus consequat elit, eu porttitor magna eleifend non. Curabitur quis mauris scelerisque, bibendum ligula eu, blandit sem. Vestibulum at imperdiet arcu.

redpajama_set_name: RedPajamaGithub


text:
package org.elasticsearch.test.rest.yaml.section;

import org.apache.http.HttpHost;
import org.elasticsearch.Version;
import org.elasticsearch.client.Node;
import org.elasticsearch.client.NodeSelector;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.logging.HeaderWarning;
import org.elasticsearch.common.xcontent.XContentLocation;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.yaml.YamlXContent;
import org.elasticsearch.test.rest.yaml.ClientYamlTestExecutionContext;
import org.elasticsearch.test.rest.yaml.ClientYamlTestResponse;
import org.hamcrest.MatcherAssert;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class DoSectionTests extends AbstractClientYamlTestFragmentParserTestCase {

    public void testWarningHeaders() {
        {
            final DoSection section = new DoSection(new XContentLocation(1, 1));

            // No warning headers doesn't throw an exception
            section.checkWarningHeaders(emptyList(), Version.CURRENT);
        }

        final String testHeader = HeaderWarning.formatWarning("test");
        final String anotherHeader = HeaderWarning.formatWarning("another");
        final String someMoreHeader = HeaderWarning.formatWarning("some more");
        final String catHeader = HeaderWarning.formatWarning("cat");
        // Any warning headers fail
        {
            final DoSection section = new DoSection(new XContentLocation(1, 1));

            final AssertionError one = expectThrows(AssertionError.class, () ->
                    section.checkWarningHeaders(singletonList(testHeader), Version.CURRENT));
            assertEquals("got unexpected warning header [\n\t" + testHeader + "\n]\n", one.getMessage());

            final AssertionError multiple = expectThrows(AssertionError.class, () ->
                    section.checkWarningHeaders(Arrays.asList(testHeader, anotherHeader, someMoreHeader), Version.CURRENT));
            assertEquals(
                    "got unexpected warning headers [\n\t" +
                            testHeader + "\n\t" +
                            anotherHeader + "\n\t" +
                            someMoreHeader + "\n]\n",
                    multiple.getMessage());
        }

        // But not when we expect them
        {
            final DoSection section = new DoSection(new XContentLocation(1, 1));
            section.setExpectedWarningHeaders(singletonList("test"));
            section.checkWarningHeaders(singletonList(testHeader), Version.CURRENT);
        }
        {
            final DoSection section = new DoSection(new XContentLocation(1, 1));
            section.setExpectedWarningHeaders(Arrays.asList("test", "another", "some more"));
            section.checkWarningHeaders(Arrays.asList(testHeader, anotherHeader, someMoreHeader), Version.CURRENT);
        }

        // But if you don't get some that you did expect, that is an error
        {
            final DoSection section = new DoSection(new XContentLocation(1, 1));
            section.setExpectedWarningHeaders(singletonList("test"));
            final AssertionError e = expectThrows(AssertionError.class, () -> section.checkWarningHeaders(emptyList(), Version.CURRENT));
            assertEquals("did not get expected warning header [\n\ttest\n]\n", e.getMessage());
        }
        {
            final DoSection section = new DoSection(new XContentLocation(1, 1));
            section.setExpectedWarningHeaders(Arrays.asList("test", "another", "some more"));

            final AssertionError multiple = expectThrows(AssertionError.class, () ->
                    section.checkWarningHeaders(emptyList(), Version.CURRENT));
            assertEquals("did not get expected warning headers [\n\ttest\n\tanother\n\tsome more\n]\n", multiple.getMessage());

            final AssertionError one = expectThrows(AssertionError.class, () ->
                    section.checkWarningHeaders(Arrays.asList(testHeader, someMoreHeader), Version.CURRENT));
            assertEquals("did not get expected warning header [\n\tanother\n]\n", one.getMessage());
        }

        // It is also an error if you get some warning you want and some you don't want
        {
            final DoSection section = new DoSection(new XContentLocation(1, 1));
            section.setExpectedWarningHeaders(Arrays.asList("test", "another", "some more"));
            final AssertionError e = expectThrows(AssertionError.class, () ->
                    section.checkWarningHeaders(Arrays.asList(testHeader, catHeader), Version.CURRENT));
            assertEquals("got unexpected warning header [\n\t" +
                            catHeader + "\n]\n" +
                            "did not get expected warning headers [\n\tanother\n\tsome more\n]\n",
                    e.getMessage());
        }

        // "allowed" warnings are fine
        {
            final DoSection section = new DoSection(new XContentLocation(1, 1));
            section.setAllowedWarningHeaders(singletonList("test"));
            section.checkWarningHeaders(singletonList(testHeader), Version.CURRENT);
            // and don't throw exceptions if we don't receive them
            section.checkWarningHeaders(emptyList(), Version.CURRENT);
        }
    }

    public void testParseDoSectionNoBody() throws Exception {
        parser = createParser(YamlXContent.yamlXContent,
                "get:\n" +
                "    index:    test_index\n" +
                "    type:    test_type\n" +
                "    id:        1"
        );

        DoSection doSection = DoSection.parse(parser);
        ApiCallSection apiCallSection = doSection.getApiCallSection();

        assertThat(apiCallSection, notNullValue());
        assertThat(apiCallSection.getApi(), equalTo("get"));
        assertThat(apiCallSection.getParams().size(), equalTo(3));
        assertThat(apiCallSection.getParams().get("index"), equalTo("test_index"));
        assertThat(apiCallSection.getParams().get("type"), equalTo("test_type"));
        assertThat(apiCallSection.getParams().get("id"), equalTo("1"));
        assertThat(apiCallSection.hasBody(), equalTo(false));
    }

    public void testParseDoSectionNoParamsNoBody() throws Exception {
        parser = createParser(YamlXContent.yamlXContent,
                "cluster.node_info: {}"
        );

        DoSection doSection = DoSection.parse(parser);
        ApiCallSection apiCallSection = doSection.getApiCallSection();

        assertThat(apiCallSection, notNullValue());
        assertThat(apiCallSection.getApi(), equalTo("cluster.node_info"));
        assertThat(apiCallSection.getParams().size(), equalTo(0));
        assertThat(apiCallSection.hasBody(), equalTo(false));
    }

    public void testParseDoSectionWithJsonBody() throws Exception {
        String body = "{ \"include\": { \"field1\": \"v1\", \"field2\": \"v2\" }, \"count\": 1 }";
        parser = createParser(YamlXContent.yamlXContent,
                "index:\n" +
                "    index:  test_1\n" +
                "    type:   test\n" +
                "    id:     1\n" +
                "    body:   " + body
        );

        DoSection doSection = DoSection.parse(parser);
        ApiCallSection apiCallSection = doSection.getApiCallSection();

        assertThat(apiCallSection, notNullValue());
        assertThat(apiCallSection.getApi(), equalTo("index"));
        assertThat(apiCallSection.getParams().size(), equalTo(3));
        assertThat(apiCallSection.getParams().get("index"), equalTo("test_1"));
        assertThat(apiCallSection.getParams().get("type"), equalTo("test"));
        assertThat(apiCallSection.getParams().get("id"), equalTo("1"));
        assertThat(apiCallSection.hasBody(), equalTo(true));

        assertJsonEquals(apiCallSection.getBodies().get(0), body);
    }

    public void testParseDoSectionWithJsonMultipleBodiesAsLongString() throws Exception {
        String bodies[] = new String[]{
                "{ \"index\": { \"_index\":\"test_index\", \"_type\":\"test_type\", \"_id\":\"test_id\" } }\n",
                "{ \"f1\":\"v1\", \"f2\":42 }\n",
                "{ \"index\": { \"_index\":\"test_index2\", \"_type\":\"test_type2\", \"_id\":\"test_id2\" } }\n",
                "{ \"f1\":\"v2\", \"f2\":47 }\n"
        };
        parser = createParser(YamlXContent.yamlXContent,
                "bulk:\n" +
                "    refresh: true\n" +
                "    body: |\n" +
                "        " + bodies[0] +
                "        " + bodies[1] +
                "        " + bodies[2] +
                "        " + bodies[3]
        );

        DoSection doSection = DoSection.parse(parser);
        ApiCallSection apiCallSection = doSection.getApiCallSection();

        assertThat(apiCallSection, notNullValue());
        assertThat(apiCallSection.getApi(), equalTo("bulk"));
        assertThat(apiCallSection.getParams().size(), equalTo(1));
        assertThat(apiCallSection.getParams().get("refresh"), equalTo("true"));
        assertThat(apiCallSection.hasBody(), equalTo(true));
        assertThat(apiCallSection.getBodies().size(), equalTo(4));
    }

    public void testParseDoSectionWithYamlBody() throws Exception {
        parser = createParser(YamlXContent.yamlXContent,
                "search:\n" +
                "    body:\n" +
                "        \"_source\": [ include.field1, include.field2 ]\n" +
                "        \"query\": { \"match_all\": {} }"
        );
        String body = "{ \"_source\": [ \"include.field1\", \"include.field2\" ], \"query\": { \"match_all\": {} }}";

        DoSection doSection = DoSection.parse(parser);
        ApiCallSection apiCallSection = doSection.getApiCallSection();

        assertThat(apiCallSection, notNullValue());
        assertThat(apiCallSection.getApi(), equalTo("search"));
        assertThat(apiCallSection.getParams().size(), equalTo(0));
        assertThat(apiCallSection.hasBody(), equalTo(true));
        assertThat(apiCallSection.getBodies().size(), equalTo(1));
        assertJsonEquals(apiCallSection.getBodies().get(0), body);
    }

    public void testParseDoSectionWithYamlMultipleBodies() throws Exception {
        parser = createParser(YamlXContent.yamlXContent,
                "bulk:\n" +
                "    refresh: true\n" +
                "    body:\n" +
                "        - index:\n" +
                "            _index: test_index\n" +
                "            _type:  test_type\n" +
                "            _id:    test_id\n" +
                "        - f1: v1\n" +
                "          f2: 42\n" +
                "        - index:\n" +
                "            _index: test_index2\n" +
                "            _type:  test_type2\n" +
                "            _id:    test_id2\n" +
                "        - f1: v2\n" +
                "          f2: 47"
        );
        String[] bodies = new String[4];
        bodies[0] = "{\"index\": {\"_index\": \"test_index\", \"_type\":  \"test_type\", \"_id\": \"test_id\"}}";
        bodies[1] = "{ \"f1\":\"v1\", \"f2\": 42 }";
        bodies[2] = "{\"index\": {\"_index\": \"test_index2\", \"_type\":  \"test_type2\", \"_id\": \"test_id2\"}}";
        bodies[3] = "{ \"f1\":\"v2\", \"f2\": 47 }";

        DoSection doSection = DoSection.parse(parser);
        ApiCallSection apiCallSection = doSection.getApiCallSection();

        assertThat(apiCallSection, notNullValue());
        assertThat(apiCallSection.getApi(), equalTo("bulk"));
        assertThat(apiCallSection.getParams().size(), equalTo(1));
        assertThat(apiCallSection.getParams().get("refresh"), equalTo("true"));
        assertThat(apiCallSection.hasBody(), equalTo(true));
        assertThat(apiCallSection.getBodies().size(), equalTo(bodies.length));

        for (int i = 0; i < bodies.length; i++) {
            assertJsonEquals(apiCallSection.getBodies().get(i), bodies[i]);
        }
    }

    public void testParseDoSectionWithYamlBodyMultiGet() throws Exception {
        parser = createParser(YamlXContent.yamlXContent,
                "mget:\n" +
                "    body:\n" +
                "        docs:\n" +
                "            - { _index: test_2, _type: test, _id: 1}\n" +
                "            - { _index: test_1, _type: none, _id: 1}"
        );
        String body = "{ \"docs\": [ " +
                "{\"_index\": \"test_2\", \"_type\":\"test\", \"_id\":1}, " +
                "{\"_index\": \"test_1\", \"_type\":\"none\", \"_id\":1} " +
                "]}";

        DoSection doSection = DoSection.parse(parser);
        ApiCallSection apiCallSection = doSection.getApiCallSection();

        assertThat(apiCallSection, notNullValue());
        assertThat(apiCallSection.getApi(), equalTo("mget"));
        assertThat(apiCallSection.getParams().size(), equalTo(0));
        assertThat(apiCallSection.hasBody(), equalTo(true));
        assertThat(apiCallSection.getBodies().size(), equalTo(1));
        assertJsonEquals(apiCallSection.getBodies().get(0), body);
    }

    public void testParseDoSectionWithBodyStringified() throws Exception {
        parser = createParser(YamlXContent.yamlXContent,
                "index:\n" +
                "    index:  test_1\n" +
                "    type:   test\n" +
                "    id:     1\n" +
                "    body:   \"{ \\\"_source\\\": true, \\\"query\\\": { \\\"match_all\\\": {} } }\""
        );

        DoSection doSection = DoSection.parse(parser);
        ApiCallSection apiCallSection = doSection.getApiCallSection();

        assertThat(apiCallSection, notNullValue());
        assertThat(apiCallSection.getApi(), equalTo("index"));
        assertThat(apiCallSection.getParams().size(), equalTo(3));
        assertThat(apiCallSection.getParams().get("index"), equalTo("test_1"));
        assertThat(apiCallSection.getParams().get("type"), equalTo("test"));
        assertThat(apiCallSection.getParams().get("id"), equalTo("1"));
        assertThat(apiCallSection.hasBody(), equalTo(true));
        assertThat(apiCallSection.getBodies().size(), equalTo(1));
        //stringified body is taken as is
        assertJsonEquals(apiCallSection.getBodies().get(0), "{ \"_source\": true, \"query\": { \"match_all\": {} } }");
    }

    public void testParseDoSectionWithBodiesStringifiedAndNot() throws Exception {
        parser = createParser(YamlXContent.yamlXContent,
                "index:\n" +
                "    body:\n" +
                "        - \"{ \\\"_source\\\": true, \\\"query\\\": { \\\"match_all\\\": {} } }\"\n" +
                "        - { size: 100, query: { match_all: {} } }"
        );

        String body = "{ \"size\": 100, \"query\": { \"match_all\": {} } }";

        DoSection doSection = DoSection.parse(parser);
        ApiCallSection apiCallSection = doSection.getApiCallSection();

        assertThat(apiCallSection.getApi(), equalTo("index"));
        assertThat(apiCallSection.getParams().size(), equalTo(0));
        assertThat(apiCallSection.hasBody(), equalTo(true));
        assertThat(apiCallSection.getBodies().size(), equalTo(2));
        //stringified body is taken as is
        assertJsonEquals(apiCallSection.getBodies().get(0), "{ \"_source\": true, \"query\": { \"match_all\": {} } }");
        assertJsonEquals(apiCallSection.getBodies().get(1), body);
    }

    public void testParseDoSectionWithCatch() throws Exception {
        parser = createParser(YamlXContent.yamlXContent,
                "catch: missing\n" +
                "indices.get_warmer:\n" +
                "    index: test_index\n" +
                "    name: test_warmer"
        );

        DoSection doSection = DoSection.parse(parser);
        assertThat(doSection.getCatch(), equalTo("missing"));
        assertThat(doSection.getApiCallSection(), notNullValue());
        assertThat(doSection.getApiCallSection().getApi(), equalTo("indices.get_warmer"));
        assertThat(doSection.getApiCallSection().getParams().size(), equalTo(2));
        assertThat(doSection.getApiCallSection().hasBody(), equalTo(false));
    }

    public void testUnsupportedTopLevelField() throws Exception {
        parser = createParser(YamlXContent.yamlXContent,
            "max_concurrent_shard_requests: 1"
        );

        ParsingException e = expectThrows(ParsingException.class, () -> DoSection.parse(parser));
        assertThat(e.getMessage(), is("unsupported field [max_concurrent_shard_requests]"));
        parser.nextToken();
        parser.nextToken();
    }

    public void testParseDoSectionWithHeaders() throws Exception {
        parser = createParser(YamlXContent.yamlXContent,
                "headers:\n" +
                "    Authorization: \"thing one\"\n" +
                "    Content-Type: \"application/json\"\n" +
                "indices.get_warmer:\n" +
                "    index: test_index\n" +
                "    name: test_warmer"
        );

        DoSection doSection = DoSection.parse(parser);
        assertThat(doSection.getApiCallSection(), notNullValue());
        assertThat(doSection.getApiCallSection().getApi(), equalTo("indices.get_warmer"));
        assertThat(doSection.getApiCallSection().getParams().size(), equalTo(2));
        assertThat(doSection.getApiCallSection().hasBody(), equalTo(false));
        assertThat(doSection.getApiCallSection().getHeaders(), notNullValue());
        assertThat(doSection.getApiCallSection().getHeaders().size(), equalTo(2));
        assertThat(doSection.getApiCallSection().getHeaders().get("Authorization"), equalTo("thing one"));
        assertThat(doSection.getApiCallSection().getHeaders().get("Content-Type"), equalTo("application/json"));
    }

    public void testParseDoSectionWithoutClientCallSection() throws Exception {
        parser = createParser(YamlXContent.yamlXContent,
                "catch: missing\n"
        );

        Exception e = expectThrows(IllegalArgumentException.class, () -> DoSection.parse(parser));
        assertThat(e.getMessage(), is("client call section is mandatory within a do section"));
    }

    public void testParseDoSectionMultivaluedField() throws Exception {
        parser = createParser(YamlXContent.yamlXContent,
                "indices.get_field_mapping:\n" +
                "        index: test_index\n" +
                "        type: test_type\n" +
                "        field: [ text , text1 ]"
        );

        DoSection doSection = DoSection.parse(parser);
        assertThat(doSection.getCatch(), nullValue());
        assertThat(doSection.getApiCallSection(), notNullValue());
        assertThat(doSection.getApiCallSection().getApi(), equalTo("indices.get_field_mapping"));
        assertThat(doSection.getApiCallSection().getParams().size(), equalTo(3));
        assertThat(doSection.getApiCallSection().getParams().get("index"), equalTo("test_index"));
        assertThat(doSection.getApiCallSection().getParams().get("type"), equalTo("test_type"));
        assertThat(doSection.getApiCallSection().getParams().get("field"), equalTo("text,text1"));
        assertThat(doSection.getApiCallSection().hasBody(), equalTo(false));
        assertThat(doSection.getApiCallSection().getBodies().size(), equalTo(0));
    }

    public void testParseDoSectionExpectedWarnings() throws Exception {
        parser = createParser(YamlXContent.yamlXContent,
                "indices.get_field_mapping:\n" +
                "        index: test_index\n" +
                "        type: test_type\n" +
                "warnings:\n" +
                "    - some test warning they are typically pretty long\n" +
                "    - some other test warning sometimes they have [in] them"
        );

        DoSection doSection = DoSection.parse(parser);
        assertThat(doSection.getCatch(), nullValue());
        assertThat(doSection.getApiCallSection(), notNullValue());
        assertThat(doSection.getApiCallSection().getApi(), equalTo("indices.get_field_mapping"));
        assertThat(doSection.getApiCallSection().getParams().size(), equalTo(2));
        assertThat(doSection.getApiCallSection().getParams().get("index"), equalTo("test_index"));
        assertThat(doSection.getApiCallSection().getParams().get("type"), equalTo("test_type"));
        assertThat(doSection.getApiCallSection().hasBody(), equalTo(false));
        assertThat(doSection.getApiCallSection().getBodies().size(), equalTo(0));
        assertThat(doSection.getExpectedWarningHeaders(), equalTo(Arrays.asList(
                "some test warning they are typically pretty long",
                "some other test warning sometimes they have [in] them")));

        parser = createParser(YamlXContent.yamlXContent,
                "indices.get_field_mapping:\n" +
                "        index: test_index\n" +
                "warnings:\n" +
                "    - just one entry this time"
        );

        doSection = DoSection.parse(parser);
        assertThat(doSection.getCatch(), nullValue());
        assertThat(doSection.getApiCallSection(), notNullValue());
        assertThat(doSection.getExpectedWarningHeaders(), equalTo(singletonList(
                "just one entry this time")));
    }

    public void testParseDoSectionAllowedWarnings() throws Exception {
        parser = createParser(YamlXContent.yamlXContent,
                "indices.get_field_mapping:\n" +
                "        index: test_index\n" +
                "        type: test_type\n" +
                "allowed_warnings:\n" +
                "    - some test warning they are typically pretty long\n" +
                "    - some other test warning sometimes they have [in] them"
        );

        DoSection doSection = DoSection.parse(parser);
        assertThat(doSection.getCatch(), nullValue());
        assertThat(doSection.getApiCallSection(), notNullValue());
        assertThat(doSection.getApiCallSection().getApi(), equalTo("indices.get_field_mapping"));
        assertThat(doSection.getApiCallSection().getParams().size(), equalTo(2));
        assertThat(doSection.getApiCallSection().getParams().get("index"), equalTo("test_index"));
        assertThat(doSection.getApiCallSection().getParams().get("type"), equalTo("test_type"));
        assertThat(doSection.getApiCallSection().hasBody(), equalTo(false));
        assertThat(doSection.getApiCallSection().getBodies().size(), equalTo(0));
        assertThat(doSection.getAllowedWarningHeaders(), equalTo(Arrays.asList(
                "some test warning they are typically pretty long",
                "some other test warning sometimes they have [in] them")));

        parser = createParser(YamlXContent.yamlXContent,
                "indices.get_field_mapping:\n" +
                "        index: test_index\n" +
                "allowed_warnings:\n" +
                "    - just one entry this time"
        );

        doSection = DoSection.parse(parser);
        assertThat(doSection.getCatch(), nullValue());
        assertThat(doSection.getApiCallSection(), notNullValue());
        assertThat(doSection.getAllowedWarningHeaders(), equalTo(singletonList(
                "just one entry this time")));

        parser = createParser(YamlXContent.yamlXContent,
                "indices.get_field_mapping:\n" +
                "        index: test_index\n" +
                "warnings:\n" +
                "    - foo\n" +
                "allowed_warnings:\n" +
                "    - foo"
        );
        Exception e = expectThrows(IllegalArgumentException.class, () -> DoSection.parse(parser));
        assertThat(e.getMessage(), equalTo("the warning [foo] was both allowed and expected"));
    }

    public void testNodeSelectorByVersion() throws IOException {
        parser = createParser(YamlXContent.yamlXContent,
                "node_selector:\n" +
                "    version: 5.2.0-6.0.0\n" +
                "indices.get_field_mapping:\n" +
                "    index: test_index"
        );

        DoSection doSection = DoSection.parse(parser);
        assertNotSame(NodeSelector.ANY, doSection.getApiCallSection().getNodeSelector());
        Node v170 = nodeWithVersion("1.7.0");
        Node v521 = nodeWithVersion("5.2.1");
        Node v550 = nodeWithVersion("5.5.0");
        Node v612 = nodeWithVersion("6.1.2");
        List<Node> nodes = new ArrayList<>();
        nodes.add(v170);
        nodes.add(v521);
        nodes.add(v550);
        nodes.add(v612);
        doSection.getApiCallSection().getNodeSelector().select(nodes);
        assertEquals(Arrays.asList(v521, v550), nodes);
        ClientYamlTestExecutionContext context = mock(ClientYamlTestExecutionContext.class);
        ClientYamlTestResponse mockResponse = mock(ClientYamlTestResponse.class);
        when(context.callApi("indices.get_field_mapping", singletonMap("index", "test_index"),
                emptyList(), emptyMap(), doSection.getApiCallSection().getNodeSelector())).thenReturn(mockResponse);
        doSection.execute(context);
        verify(context).callApi("indices.get_field_mapping", singletonMap("index", "test_index"),
                emptyList(), emptyMap(), doSection.getApiCallSection().getNodeSelector());

        {
            List<Node> badNodes = new ArrayList<>();
            badNodes.add(new Node(new HttpHost("dummy")));
            Exception e = expectThrows(IllegalStateException.class, () ->
                    doSection.getApiCallSection().getNodeSelector().select(badNodes));
            assertEquals("expected [version] metadata to be set but got [host=http://dummy]",
                    e.getMessage());
        }
    }

    private static Node nodeWithVersion(String version) {
        return new Node(new HttpHost("dummy"), null, null, version, null, null);
    }

    public void testNodeSelectorByAttribute() throws IOException {
        parser = createParser(YamlXContent.yamlXContent,
                "node_selector:\n" +
                "    attribute:\n" +
                "        attr: val\n" +
                "indices.get_field_mapping:\n" +
                "    index: test_index"
        );

        DoSection doSection = DoSection.parse(parser);
        assertNotSame(NodeSelector.ANY, doSection.getApiCallSection().getNodeSelector());
        Node hasAttr = nodeWithAttributes(singletonMap("attr", singletonList("val")));
        Node hasAttrWrongValue = nodeWithAttributes(singletonMap("attr", singletonList("notval")));
        Node notHasAttr = nodeWithAttributes(singletonMap("notattr", singletonList("val")));
        {
            List<Node> nodes = new ArrayList<>();
            nodes.add(hasAttr);
            nodes.add(hasAttrWrongValue);
            nodes.add(notHasAttr);
            doSection.getApiCallSection().getNodeSelector().select(nodes);
            assertEquals(Arrays.asList(hasAttr), nodes);
        }
        {
            List<Node> badNodes = new ArrayList<>();
            badNodes.add(new Node(new HttpHost("dummy")));
            Exception e = expectThrows(IllegalStateException.class, () ->
                    doSection.getApiCallSection().getNodeSelector().select(badNodes));
            assertEquals("expected [attributes] metadata to be set but got [host=http://dummy]",
                    e.getMessage());
        }

        parser = createParser(YamlXContent.yamlXContent,
                "node_selector:\n" +
                "    attribute:\n" +
                "        attr: val\n" +
                "        attr2: val2\n" +
                "indices.get_field_mapping:\n" +
                "    index: test_index"
        );

        DoSection doSectionWithTwoAttributes = DoSection.parse(parser);
        assertNotSame(NodeSelector.ANY, doSection.getApiCallSection().getNodeSelector());
        Node hasAttr2 = nodeWithAttributes(singletonMap("attr2", singletonList("val2")));
        Map<String, List<String>> bothAttributes = new HashMap<>();
        bothAttributes.put("attr", singletonList("val"));
        bothAttributes.put("attr2", singletonList("val2"));
        Node hasBoth = nodeWithAttributes(bothAttributes);
        {
            List<Node> nodes = new ArrayList<>();
            nodes.add(hasAttr);
            nodes.add(hasAttrWrongValue);
            nodes.add(notHasAttr);
            nodes.add(hasAttr2);
            nodes.add(hasBoth);
            doSectionWithTwoAttributes.getApiCallSection().getNodeSelector().select(nodes);
            assertEquals(Arrays.asList(hasBoth), nodes);
        }
    }

    private static Node nodeWithAttributes(Map<String, List<String>> attributes) {
        return new Node(new HttpHost("dummy"), null, null, null, null, attributes);
    }

    public void testNodeSelectorByTwoThings() throws IOException {
        parser = createParser(YamlXContent.yamlXContent,
                "node_selector:\n" +
                "    version: 5.2.0-6.0.0\n" +
                "    attribute:\n" +
                "        attr: val\n" +
                "indices.get_field_mapping:\n" +
                "    index: test_index"
        );

        DoSection doSection = DoSection.parse(parser);
        assertNotSame(NodeSelector.ANY, doSection.getApiCallSection().getNodeSelector());
        Node both = nodeWithVersionAndAttributes("5.2.1", singletonMap("attr", singletonList("val")));
        Node badVersion = nodeWithVersionAndAttributes("5.1.1", singletonMap("attr", singletonList("val")));
        Node badAttr = nodeWithVersionAndAttributes("5.2.1", singletonMap("notattr", singletonList("val")));
        List<Node> nodes = new ArrayList<>();
        nodes.add(both);
        nodes.add(badVersion);
        nodes.add(badAttr);
        doSection.getApiCallSection().getNodeSelector().select(nodes);
        assertEquals(Arrays.asList(both), nodes);
    }

    private static Node nodeWithVersionAndAttributes(String version, Map<String, List<String>> attributes) {
        return new Node(new HttpHost("dummy"), null, null, version, null, attributes);
    }

    private void assertJsonEquals(Map<String, Object> actual, String expected) throws IOException {
        Map<String,Object> expectedMap;
        try (XContentParser parser = createParser(YamlXContent.yamlXContent, expected)) {
            expectedMap = parser.mapOrdered();
        }
        MatcherAssert.assertThat(actual, equalTo(expectedMap));
    }
}


text:
// $Id$

package scala
package tools
package nsc
package settings

import java.util.zip.Deflater

import scala.annotation.{elidable, nowarn}
import scala.collection.mutable
import scala.language.existentials
import scala.reflect.internal.util.{ StatisticsStatics, StringContextStripMarginOps }
import scala.tools.nsc.util.DefaultJarFactory
import scala.tools.util.PathResolver.Defaults
import scala.util.chaining._

trait ScalaSettings extends StandardScalaSettings with Warnings { _: MutableSettings =>

  /** Set of settings */
  protected[scala] lazy val allSettings = mutable.LinkedHashMap[String, Setting]()

  /** The user class path, specified by `-classpath` or `-cp`,
   *  defaults to the value of CLASSPATH env var if it is set, as in Java,
   *  or else to `"."` for the current user directory.
   */
  protected def defaultClasspath = Option(System.getenv("CLASSPATH")).getOrElse(".")

  /** If any of these settings is enabled, the compiler should print a message and exit.  */
  def infoSettings = List[Setting](version, help, Vhelp, Whelp, Xhelp, Yhelp, showPlugins, showPhases, genPhaseGraph, printArgs)

  /** Is an info setting set? Any -option:help? */
  def isInfo = infoSettings.exists(_.isSetByUser) || allSettings.valuesIterator.exists(_.isHelping)

  /** Disable a setting */
  def disable(s: Setting) = allSettings -= s.name

  val jvmargs  = PrefixSetting("-J<flag>", "-J", "Pass <flag> directly to the runtime system.")
  val defines  = PrefixSetting("-Dproperty=value", "-D", "Pass -Dproperty=value directly to the runtime system.")
  /*val toolcp =*/ PathSetting("-toolcp", "Add to the runner classpath.", "") withAbbreviation "--tool-class-path"
  val nobootcp = BooleanSetting("-nobootcp", "Do not use the boot classpath for the scala jars.") withAbbreviation "--no-boot-class-path"

  /**
   *  Standard settings
   */
  // argfiles is only for the help message
  /*val argfiles = */ BooleanSetting("@<file>", "A text file containing compiler arguments (options and source files)")
  val classpath     = PathSetting   ("-classpath", "Specify where to find user class files.", defaultClasspath) withAbbreviation "-cp" withAbbreviation "--class-path"
  val outdir        = OutputSetting (".").withPostSetHook(s => try outputDirs.setSingleOutput(s.value) catch { case FatalError(msg) => errorFn(msg) }).tap(_.postSetHook())

  val nospecialization = BooleanSetting("-no-specialization", "Ignore @specialize annotations.") withAbbreviation "--no-specialization"

  // Would be nice to build this dynamically from scala.languageFeature.
  // The two requirements: delay error checking until you have symbols, and let compiler command build option-specific help.
  object languageFeatures extends MultiChoiceEnumeration {
    val dynamics            = Choice("dynamics",            "Allow direct or indirect subclasses of scala.Dynamic")
    val existentials        = Choice("existentials",        "Existential types (besides wildcard types) can be written and inferred")
    val higherKinds         = Choice("higherKinds",         "Allow higher-kinded types")
    val implicitConversions = Choice("implicitConversions", "Allow definition of implicit functions called views")
    val postfixOps          = Choice("postfixOps",          "Allow postfix operator notation, such as `1 to 10 toList` (not recommended)")
    val reflectiveCalls     = Choice("reflectiveCalls",     "Allow reflective access to members of structural types")
    val macros              = Choice("experimental.macros", "Allow macro definition (besides implementation and application)")
  }
  val language      = {
    val description = "Enable or disable language features"
    MultiChoiceSetting(
      name    = "-language",
      helpArg = "feature",
      descr   = description,
      domain  = languageFeatures
    ) withAbbreviation "--language"
  }

  /**
   * -X "Advanced" settings
   */
  val Xhelp              = BooleanSetting      ("-X", "Print a synopsis of advanced options.")
  val async              = BooleanSetting      ("-Xasync", "Enable the async phase for scala.async.Async.{async,await}.")
  val checkInit          = BooleanSetting      ("-Xcheckinit", "Wrap field accessors to throw an exception on uninitialized access.")
  val developer          = BooleanSetting      ("-Xdev", "Issue warnings about anything which seems amiss in compiler internals. Intended for compiler developers").withPostSetHook(s => if (s.value) StatisticsStatics.enableDeveloperAndDeoptimize())
  val noassertions       = BooleanSetting      ("-Xdisable-assertions", "Generate no assertions or assumptions.") andThen (flag =>
                                                if (flag) elidebelow.value = elidable.ASSERTION + 1)
  val elidebelow         = IntSetting          ("-Xelide-below", "Calls to @elidable methods are omitted if method priority is lower than argument",
                                                elidable.MINIMUM, None, elidable.byName get _)
  val noForwarders       = BooleanSetting      ("-Xno-forwarders", "Do not generate static forwarders in mirror classes.")
  val genPhaseGraph      = StringSetting       ("-Xgenerate-phase-graph", "file", "Generate the phase graphs (outputs .dot files) to fileX.dot.", "")
  val maxerrs            = IntSetting          ("-Xmaxerrs", "Maximum errors to print", 100, None, _ => None)
  val maxwarns           = IntSetting          ("-Xmaxwarns", "Maximum warnings to print", 100, None, _ => None)
  val Xmigration         = ScalaVersionSetting ("-Xmigration", "version", "Warn about constructs whose behavior may have changed since version.", initial = NoScalaVersion, default = Some(AnyScalaVersion))
  val Xnojline           = BooleanSetting      ("-Xnojline", "Do not use JLine for editing.")
    .withDeprecationMessage("Replaced by -Xjline:off")
    .withPostSetHook(_ => Xjline.value = "off")
  val Xjline             = ChoiceSetting       (
    name    = "-Xjline",
    helpArg = "mode",
    descr   = "Select JLine mode.",
    choices = List("emacs", "vi", "off"),
    default = "emacs",
    choicesHelp = List(
      "emacs key bindings.",
      "vi key bindings",
      "No JLine editing."))
  val Xverify            = BooleanSetting      ("-Xverify", "Verify generic signatures in generated bytecode.")
  val plugin             = MultiStringSetting  ("-Xplugin", "paths", "Load a plugin from each classpath.")
  val disable            = MultiStringSetting  ("-Xplugin-disable", "plugin", "Disable plugins by name.")
  val showPlugins        = BooleanSetting      ("-Xplugin-list", "Print a synopsis of loaded plugins.")
  val require            = MultiStringSetting  ("-Xplugin-require", "plugin", "Abort if a named plugin is not loaded.")
  val pluginsDir         = StringSetting       ("-Xpluginsdir", "path", "Path to search for plugin archives.", Defaults.scalaPluginPath)
  val prompt             = BooleanSetting      ("-Xprompt", "Display a prompt after each error (debugging option).")
  val resident           = BooleanSetting      ("-Xresident", "Compiler stays resident: read source filenames from standard input.")
  val script             = StringSetting       ("-Xscript", "object", "Treat the source file as a script and wrap it in a main method.", "Main")
  val mainClass          = StringSetting       ("-Xmain-class", "path", "Class for manifest's Main-Class entry (only useful with -d <jar>)", "")
  val sourceReader       = StringSetting       ("-Xsource-reader", "classname", "Specify a custom method for reading source files.", "")
  val reporter           = StringSetting       ("-Xreporter", "classname", "Specify a custom subclass of FilteringReporter for compiler messages.", "scala.tools.nsc.reporters.ConsoleReporter")
  @nowarn("cat=deprecation")
  val source             = ScalaVersionSetting ("-Xsource", "version", "Enable features that will be available in a future version of Scala, for purposes of early migration and alpha testing.", initial = ScalaVersion("2.13")).withPostSetHook { s =>
    if (s.value >= ScalaVersion("3"))
      isScala3.value = true
    else if (s.value >= ScalaVersion("2.14"))
      s.withDeprecationMessage("instead of -Xsource:2.14, use -Xsource:3").value = ScalaVersion("3")
    else if (s.value < ScalaVersion("2.13"))
      errorFn.apply(s"-Xsource must be at least the current major version (${ScalaVersion("2.13").versionString})")
  }
  @deprecated("Use currentRun.isScala3 instead", since="2.13.9")
  val isScala3           = BooleanSetting      ("isScala3", "Is -Xsource Scala 3?").internalOnly()
  // The previous "-Xsource" option is intended to be used mainly though ^ helper

  val XnoPatmatAnalysis = BooleanSetting ("-Xno-patmat-analysis", "Don't perform exhaustivity/unreachability analysis. Also, ignore @switch annotation.")

  val XmixinForceForwarders = ChoiceSetting(
    name    = "-Xmixin-force-forwarders",
    helpArg = "mode",
    descr   = "Generate forwarder methods in classes inhering concrete methods from traits.",
    choices = List("true", "junit", "false"),
    default = "true",
    choicesHelp = List(
      "Always generate mixin forwarders.",
      "Generate mixin forwarders for JUnit-annotated methods (JUnit 4 does not support default methods).",
      "Only generate mixin forwarders required for program correctness."))

  object mixinForwarderChoices {
    def isTruthy = XmixinForceForwarders.value == "true"
    def isAtLeastJunit = isTruthy || XmixinForceForwarders.value == "junit"
  }

  val nonStrictPatmatAnalysis = BooleanSetting("-Xnon-strict-patmat-analysis", "Disable strict exhaustivity analysis, which assumes guards are false and refutable extractors don't match")

  // XML parsing options
  object XxmlSettings extends MultiChoiceEnumeration {
    val coalescing   = Choice("coalescing", "Convert PCData to Text and coalesce sibling nodes")
    def isCoalescing = Xxml contains coalescing
  }
  val Xxml = MultiChoiceSetting(
    name    = "-Xxml",
    helpArg = "property",
    descr   = "Configure XML parsing.",
    domain  = XxmlSettings
  )

  /** Compatibility stubs for options whose value name did
   *  not previously match the option name.
   */
  def debuginfo = g
  def dependenciesFile = dependencyfile
  def nowarnings = nowarn
  @deprecated("Use outdir instead.", since="2.13.2")
  def d = outdir
  def printLate = print

  /**
   * -Y "Private" settings
   */
  val Yhelp           = BooleanSetting    ("-Y", "Print a synopsis of private options.")
  val breakCycles     = BooleanSetting    ("-Ybreak-cycles", "Attempt to break cycles encountered during typing")
  val check           = PhasesSetting     ("-Ycheck", "Check the tree at the end of")
  val Ycompacttrees   = BooleanSetting    ("-Ycompact-trees", "Use compact tree printer when displaying trees.")
  val noCompletion    = BooleanSetting    ("-Yno-completion", "Disable tab-completion in the REPL.")
  val termConflict    = ChoiceSetting     ("-Yresolve-term-conflict", "strategy", "Resolve term conflicts.", List("package", "object", "error"), "error")
  val Ynogenericsig   = BooleanSetting    ("-Yno-generic-signatures", "Suppress generation of generic signatures for Java.")
  val noimports       = BooleanSetting    ("-Yno-imports", "Compile without importing scala.*, java.lang.*, or Predef.")
                       .withPostSetHook(bs => if (bs.value) imports.value = Nil)
  val nopredef        = BooleanSetting    ("-Yno-predef", "Compile without importing Predef.")
                       .withPostSetHook(bs => if (bs.value && !noimports.value) imports.value = "java.lang" :: "scala" :: Nil)
  val imports         = MultiStringSetting(name="-Yimports", arg="import", descr="Custom root imports, default is `java.lang,scala,scala.Predef`.", helpText=Some(
  sm"""|Specify a list of packages and objects to import from as "root" imports.
       |Root imports form the root context in which all Scala source is evaluated.
       |The names supplied to `-Yimports` must be fully-qualified.
       |
       |For example, the default scala.Predef results in an `import scala.Predef._`.
       |Ordinary access and scoping rules apply. Root imports increase the scoping
       |depth, so that later root imports shadow earlier ones. In addition,
       |names bound by root imports have lowest binding precedence, so that they
       |cannot induce ambiguities in user code, where definitions and imports
       |always have a higher precedence. Root imports are imports of last resort.
       |
       |By convention, an explicit import from a root import object such as
       |Predef disables that root import for the current source file. The import
       |is disabled when the import expression is compiled, so, also by convention,
       |the import should be placed early in source code order. The textual name
       |in the import does not need to match the value of `-Yimports`; the import
       |works in the usual way, subject to renames and name binding precedence.
       |
    """
  ))
  val Yrecursion      = IntSetting        ("-Yrecursion", "Set recursion depth used when locking symbols.", 0, Some((0, Int.MaxValue)), (_: String) => None)

  val YprintTrees = ChoiceSetting(
      name = "-Yprint-trees",
      helpArg = "style",
      descr = "How to print trees when -Vprint is enabled.",
      choices = List("text", "compact", "format", "text+format", "diff"),
      default = "text"
    ).withPostSetHook(pt => pt.value match {
      case "compact"     => XshowtreesCompact.value = true
      case "format"      => Xshowtrees.value = true
      case "text+format" => XshowtreesStringified.value = true
      case _             =>
    })

  def showTreeDiff: Boolean = YprintTrees.value == "diff"
  val Xshowtrees      = BooleanSetting    ("-Yshow-trees", "(Requires -Vprint:) Print detailed ASTs in formatted form.").internalOnly()
  val XshowtreesCompact
                      = BooleanSetting    ("-Yshow-trees-compact", "(Requires -Vprint:) Print detailed ASTs in compact form.").internalOnly()
  val XshowtreesStringified
                      = BooleanSetting    ("-Yshow-trees-stringified", "(Requires -Vprint:) Print stringifications along with detailed ASTs.").internalOnly()

  val skip            = PhasesSetting     ("-Yskip", "Skip")
  val Ygenasmp        = StringSetting     ("-Ygen-asmp",  "dir", "Generate a parallel output directory of .asmp files (ie ASM Textifier output).", "")
  val Ydumpclasses    = StringSetting     ("-Ydump-classes", "dir", "Dump the generated bytecode to .class files (useful for reflective compilation that utilizes in-memory classloaders).", "")
  val stopAfter       = PhasesSetting     ("-Ystop-after", "Stop after") withAbbreviation ("-stop") // backward compat
  val stopBefore      = PhasesSetting     ("-Ystop-before", "Stop before")
  val Yrangepos       = BooleanSetting    ("-Yrangepos", "Use range positions for syntax trees.", true)
  val Yvalidatepos    = PhasesSetting     ("-Yvalidate-pos", s"Validate positions after the given phases (implies ${Yrangepos.name})") withPostSetHook (_ => Yrangepos.value = true)
  val Yreifycopypaste = BooleanSetting    ("-Yreify-copypaste", "Dump the reified trees in copypasteable representation.")
  val Ymacroexpand    = ChoiceSetting     ("-Ymacro-expand", "policy", "Control expansion of macros, useful for scaladoc and presentation compiler.", List(MacroExpand.Normal, MacroExpand.None, MacroExpand.Discard), MacroExpand.Normal)
  val YmacroFresh     = BooleanSetting    ("-Ymacro-global-fresh-names", "Should fresh names in macros be unique across all compilation units")
  val YmacroAnnotations = BooleanSetting  ("-Ymacro-annotations", "Enable support for macro annotations, formerly in macro paradise.")
  val YtastyNoAnnotations = BooleanSetting("-Ytasty-no-annotations", "Disable support for reading annotations from TASTy, this will prevent safety features such as pattern match exhaustivity and reachability analysis.")
  val YtastyReader        = BooleanSetting("-Ytasty-reader", "Enable support for reading Scala 3's TASTy files, allowing consumption of libraries compiled with Scala 3 (provided they don't use any Scala 3 only features).")
  val Yreplclassbased = BooleanSetting    ("-Yrepl-class-based", "Use classes to wrap REPL snippets instead of objects", default = true)
  val YreplMagicImport = BooleanSetting   ("-Yrepl-use-magic-imports", "In the code that wraps REPL snippets, use magic imports rather than nesting wrapper object/classes", default = true)
  val Yreploutdir     = StringSetting     ("-Yrepl-outdir", "path", "Write repl-generated classfiles to given output directory (use \"\" to generate a temporary dir)" , "")
  @deprecated("Unused setting will be removed", since="2.13")
  val Yreplsync       = new BooleanSetting    ("-Yrepl-sync", "Legacy setting for sbt compatibility, unused.", default = false).internalOnly()
  val Yscriptrunner   = StringSetting     ("-Yscriptrunner", "classname", "Specify a scala.tools.nsc.ScriptRunner (default, resident, shutdown, or a class name).", "default")
  val YdisableFlatCpCaching  = BooleanSetting    ("-Yno-flat-classpath-cache", "Do not cache flat classpath representation of classpath elements from jars across compiler instances.").withAbbreviation("-YdisableFlatCpCaching")
  // Zinc adds YdisableFlatCpCaching automatically for straight-to-JAR compilation, this is a way to override that choice.
  val YforceFlatCpCaching  = BooleanSetting    ("-Yforce-flat-cp-cache", "Force caching flat classpath representation of classpath elements from jars across compiler instances. Has precedence over: " + YdisableFlatCpCaching.name).internalOnly()
  val YcachePluginClassLoader  = CachePolicy.setting("plugin", "compiler plugins")
  val YcacheMacroClassLoader   = CachePolicy.setting("macro", "macros")
  val YmacroClasspath = PathSetting       ("-Ymacro-classpath", "The classpath used to reflectively load macro implementations, default is the compilation classpath.", "")

  val Youtline        = BooleanSetting    ("-Youtline", "Don't compile method bodies. Use together with `-Ystop-after:pickler` to generate the pickled signatures for all source files.").internalOnly()

  val exposeEmptyPackage = BooleanSetting ("-Yexpose-empty-package", "Internal only: expose the empty package.").internalOnly()
  val Ydelambdafy        = ChoiceSetting  ("-Ydelambdafy", "strategy", "Strategy used for translating lambdas into JVM code.", List("inline", "method"), "method")

  // Allows a specialised jar to be written. For instance one that provides stable hashing of content, or customisation of the file storage
  val YjarFactory = StringSetting   ("-YjarFactory", "classname", "factory for jar files", classOf[DefaultJarFactory].getName)
  val YaddBackendThreads = IntSetting   ("-Ybackend-parallelism", "maximum worker threads for backend", 1, Some((1,16)), (x: String) => None )
  val YmaxQueue = IntSetting   ("-Ybackend-worker-queue", "backend threads worker queue size", 0, Some((0,1000)), (x: String) => None )
  val YjarCompressionLevel = IntSetting("-Yjar-compression-level", "compression level to use when writing jar files",
    Deflater.DEFAULT_COMPRESSION, Some((Deflater.DEFAULT_COMPRESSION,Deflater.BEST_COMPRESSION)), (x: String) => None)
  val YpickleJava = BooleanSetting("-Ypickle-java", "Pickler phase should compute pickles for .java defined symbols for use by build tools").internalOnly()
  val YpickleWrite = StringSetting("-Ypickle-write", "directory|jar", "destination for generated .sig files containing type signatures.", "", None).internalOnly()
  val YpickleWriteApiOnly = BooleanSetting("-Ypickle-write-api-only", "Exclude private members (other than those material to subclass compilation, such as private trait vals) from generated .sig files containing type signatures.").internalOnly()
  val YtrackDependencies = BooleanSetting("-Ytrack-dependencies", "Record references to in unit.depends. Deprecated feature that supports SBT 0.13 with incOptions.withNameHashing(false) only.", default = true)
  val Yscala3ImplicitResolution = BooleanSetting("-Yscala3-implicit-resolution", "Use Scala-3-style downwards comparisons for implicit search and overloading resolution (see https://github.com/scala/bug/issues/12437).", default = false)

  sealed abstract class CachePolicy(val name: String, val help: String)
  object CachePolicy {
    def setting(style: String, styleLong: String) = ChoiceSetting(s"-Ycache-$style-class-loader", "policy", s"Policy for caching class loaders for $styleLong that are dynamically loaded.", values.map(_.name), None.name, values.map(_.help))
    object None extends CachePolicy("none", "Don't cache class loader")
    object LastModified extends CachePolicy("last-modified", "Cache class loader, using file last-modified time to invalidate")
    object Always extends CachePolicy("always", "Cache class loader with no invalidation")
    // TODO Jorge to add new policy. Think about whether there is a benefit to the user on offering this as a separate policy or unifying with the previous one.
    // object ZipMetadata extends CachePolicy("zip-metadata", "Cache classloader, using file last-modified time, then ZIP file metadata to invalidate")
    def values: List[CachePolicy] = List(None, LastModified, Always)
  }

  object optChoices extends MultiChoiceEnumeration {
    val unreachableCode         = Choice("unreachable-code",            "Eliminate unreachable code, exception handlers guarding no instructions, redundant metadata (debug information, line numbers).")
    val simplifyJumps           = Choice("simplify-jumps",              "Simplify branching instructions, eliminate unnecessary ones.")
    val compactLocals           = Choice("compact-locals",              "Eliminate empty slots in the sequence of local variables.")
    val copyPropagation         = Choice("copy-propagation",            "Eliminate redundant local variables and unused values (including closures). Enables unreachable-code.")
    val redundantCasts          = Choice("redundant-casts",             "Eliminate redundant casts using a type propagation analysis.")
    val boxUnbox                = Choice("box-unbox",                   "Eliminate box-unbox pairs within the same method (also tuples, xRefs, value class instances). Enables unreachable-code.")
    val nullnessTracking        = Choice("nullness-tracking",           "Track nullness / non-nullness of local variables and apply optimizations.")
    val closureInvocations      = Choice("closure-invocations" ,        "Rewrite closure invocations to the implementation method.")
    val allowSkipCoreModuleInit = Choice("allow-skip-core-module-init", "Allow eliminating unused module loads for core modules of the standard library (e.g., Predef, ClassTag).")
    val assumeModulesNonNull    = Choice("assume-modules-non-null",     "Assume loading a module never results in null (happens if the module is accessed in its super constructor).")
    val allowSkipClassLoading   = Choice("allow-skip-class-loading",    "Allow optimizations that can skip or delay class loading.")
    val ell                     = Choice("l",                           "Deprecated l:none, l:default, l:method, l:inline.")

    // none is not an expanding option. It is excluded from -opt:_ below.
    val lNone = Choice("none", "Disable all optimizations, including explicit options.")

    val defaultOptimizations = List(unreachableCode)
    val lDefault = Choice(
      "default",
      defaultOptimizations.mkString("Enable default optimizations: ", ",", "."),
      expandsTo = defaultOptimizations)

    val localOptimizations = List(simplifyJumps, compactLocals, copyPropagation, redundantCasts, boxUnbox, nullnessTracking, closureInvocations, allowSkipCoreModuleInit, assumeModulesNonNull, allowSkipClassLoading)
    val lMethod = Choice(
      "local",
      (defaultOptimizations ::: localOptimizations).mkString("Enable intra-method optimizations: ", ",", "."),
      expandsTo = defaultOptimizations ::: localOptimizations)

    val inlineFrom = Choice(
      "inline",
      s"Inline method invocations and enable all optimizations; specify where to inline from, as shown below. See also -Yopt-inline-heuristics.\n$inlineHelp",
      expandsTo = defaultOptimizations ::: localOptimizations,
      requiresSelections = true
    )

    // "none" is excluded from wildcard expansion so that -opt:_ does not disable all settings
    override def wildcardChoices = super.wildcardChoices.filter(_ ne lNone)
  }

  // We don't use the `default` parameter of `MultiChoiceSetting`: it specifies the default values
  // when `-opt` is passed without explicit choices. When `-opt` is not explicitly specified, the
  // set `opt.value` is empty.
  val opt = MultiChoiceSetting(
    name = "-opt",
    helpArg = "optimization",
    descr = "Enable optimizations: `-opt:local`, `-opt:inline:<pattern>`; `-opt:help` for details.",
    domain = optChoices,
  ).withPostSetHook { ss =>
    // kludge alert: will be invoked twice, with selections available 2nd time
    // for -opt:l:method reset the ell selections then enable local
    if (ss.contains(optChoices.ell) && optChoices.ell.selections.nonEmpty) {
      val todo = optChoices.ell.selections.map {
        case "none"    => "none"
        case "default" => "default"
        case "method"  => "local"
        case "inline"  => "local"   // enable all except inline, see -opt-inline-from
      }
      optChoices.ell.selections = Nil
      ss.tryToSetColon(todo)
    }
  }

  private def optEnabled(choice: optChoices.Choice) =
    !optNone && {
      opt.contains(choice) ||
      !opt.isSetByUser && optChoices.lDefault.expandsTo.contains(choice)
    }

  def optNone                    = opt.contains(optChoices.lNone)
  def optUnreachableCode         = optEnabled(optChoices.unreachableCode)
  def optSimplifyJumps           = optEnabled(optChoices.simplifyJumps)
  def optCompactLocals           = optEnabled(optChoices.compactLocals)
  def optCopyPropagation         = optEnabled(optChoices.copyPropagation)
  def optRedundantCasts          = optEnabled(optChoices.redundantCasts)
  def optBoxUnbox                = optEnabled(optChoices.boxUnbox)
  def optNullnessTracking        = optEnabled(optChoices.nullnessTracking)
  def optClosureInvocations      = optEnabled(optChoices.closureInvocations)
  def optAllowSkipCoreModuleInit = optEnabled(optChoices.allowSkipCoreModuleInit)
  def optAssumeModulesNonNull    = optEnabled(optChoices.assumeModulesNonNull)
  def optAllowSkipClassLoading   = optEnabled(optChoices.allowSkipClassLoading)
  def optInlinerEnabled          = !optInlineFrom.isEmpty && !optNone

  def optBuildCallGraph          = optInlinerEnabled || optClosureInvocations
  def optAddToBytecodeRepository = optBuildCallGraph || optInlinerEnabled || optClosureInvocations
  def optUseAnalyzerCache        = opt.isSetByUser && !optNone && (optBuildCallGraph || opt.value.size > 1)

  def optInlineFrom: List[String] = optChoices.inlineFrom.selections

  def inlineHelp =
      """
        |Inlining requires a list of patterns defining where code can be inlined from: `-opt:inline:p1,p2`.
        |
        |  *              Matches classes in the empty package
        |  **             All classes
        |  a.C            Class a.C
        |  a.*            Classes in package a
        |  a.**           Classes in a and in sub-packages of a
        |  **.Util        Classes named Util in any package (including the empty package)
        |  a.**.*Util*    Classes in a and sub-packages with Util in their name (including a.Util)
        |  a.C$D          The nested class D defined in class a.C
        |  scala.Predef$  The scala.Predef object
        |  <sources>      Classes defined in source files compiled in the current compilation, either
        |                 passed explicitly to the compiler or picked up from the `-sourcepath`
        |
        |`-opt:inline:p` may be specified multiple times to extend the list of patterns.
        |A leading `!` means exclude anything that matches the pattern. The last matching pattern wins.
        |For example, `a.**,!a.b.**` includes classes in `a` and sub-packages, but not in `a.b` and sub-packages.
        |
        |When patterns are supplied on a command line, it is usually necessary to quote special shell characters
        |such as `*`, `<`, `>`, and `$`: `'-opt:inline:p.*,!p.C$D' '-opt:inline:<sources>'`.
        |Quoting may not be needed in a build file.""".stripMargin

  @deprecated("Deprecated alias", since="2.13.8")
  val xoptInlineFrom = MultiStringSetting(
    "-opt-inline-from",
    "patterns",
    "Patterns for classfile names from which to allow inlining, `help` for details.",
    helpText = Some(inlineHelp))
      //.withDeprecationMessage("use -opt:inline:**")
      .withPostSetHook(from => opt.add("inline", from.value))

  val YoptInlineHeuristics = ChoiceSetting(
    name = "-Yopt-inline-heuristics",
    helpArg = "strategy",
    descr = "Set the heuristics for inlining decisions.",
    choices = List("at-inline-annotated", "everything", "default"),
    default = "default")

  object optWarningsChoices extends MultiChoiceEnumeration {
    val none                               = Choice("none"                       , "No optimizer warnings.")
    val atInlineFailedSummary              = Choice("at-inline-failed-summary"   , "One-line summary if there were @inline method calls that could not be inlined.")
    val atInlineFailed                     = Choice("at-inline-failed"           , "A detailed warning for each @inline method call that could not be inlined.")
    val anyInlineFailed                    = Choice("any-inline-failed"          , "A detailed warning for every callsite that was chosen for inlining by the heuristics, but could not be inlined.")
    val noInlineMixed                      = Choice("no-inline-mixed"            , "In mixed compilation, warn at callsites methods defined in java sources (the inlining decision cannot be made without bytecode).")
    val noInlineMissingBytecode            = Choice("no-inline-missing-bytecode" , "Warn if an inlining decision cannot be made because a the bytecode of a class or member cannot be found on the compilation classpath.")
    val noInlineMissingScalaInlineInfoAttr = Choice("no-inline-missing-attribute", "Warn if an inlining decision cannot be made because a Scala classfile does not have a ScalaInlineInfo attribute.")
  }

  val optWarnings = MultiChoiceSetting(
    name = "-Wopt",
    helpArg = "warning",
    descr = "Enable optimizer warnings, `help` for details.",
    domain = optWarningsChoices,
    default = Some(List(optWarningsChoices.atInlineFailed.name))
  ).withPostSetHook { _ =>
    // no need to set `Wconf` to `silent` if optWarnings is none, since no warnings are reported
    if (optWarningsSummaryOnly) Wconf.tryToSet(List(s"cat=optimizer:ws"))
    else Wconf.tryToSet(List(s"cat=optimizer:w"))
  }
  @deprecated("Deprecated alias", since="2.13.8")
  val xoptWarnings = MultiChoiceSetting(
    name = "-opt-warnings",
    helpArg = "warning",
    descr = "Enable optimizer warnings, `help` for details.",
    domain = optWarningsChoices,
    default = Some(List(optWarningsChoices.atInlineFailed.name))
  ).withPostSetHook { ow =>
    optWarnings.value = ow.value
  }//.withDeprecationMessage("Use -Wopt instead.")

  def optWarningsSummaryOnly: Boolean = optWarnings.value subsetOf Set(optWarningsChoices.none, optWarningsChoices.atInlineFailedSummary)

  def optWarningEmitAtInlineFailed =
    !optWarnings.isSetByUser ||
      optWarnings.contains(optWarningsChoices.atInlineFailedSummary) ||
      optWarnings.contains(optWarningsChoices.atInlineFailed) ||
      optWarnings.contains(optWarningsChoices.anyInlineFailed)

  def optWarningNoInlineMixed                      = optWarnings.contains(optWarningsChoices.noInlineMixed)
  def optWarningNoInlineMissingBytecode            = optWarnings.contains(optWarningsChoices.noInlineMissingBytecode)
  def optWarningNoInlineMissingScalaInlineInfoAttr = optWarnings.contains(optWarningsChoices.noInlineMissingScalaInlineInfoAttr)

  val YprofileEnabled = BooleanSetting("-Yprofile-enabled", "Enable profiling.")
  val YprofileDestination = StringSetting("-Yprofile-destination", "file", "Profiling output - specify a file or `-` for console.", "").
    withPostSetHook( _ => YprofileEnabled.value = true )
  val YprofileTrace = StringSetting("-Yprofile-trace", "file", "Capture trace of compilation in Chrome Trace format", "profile.trace").
    withPostSetHook( _ => YprofileEnabled.value = true )
  val YprofileExternalTool = PhasesSetting("-Yprofile-external-tool", "Enable profiling for a phase using an external tool hook. Generally only useful for a single phase", "typer").
    withPostSetHook( _ => YprofileEnabled.value = true )
  val YprofileRunGcBetweenPhases = PhasesSetting("-Yprofile-run-gc", "Run a GC between phases - this allows heap size to be accurate at the expense of more time. Specify a list of phases, or all", "_").
    withPostSetHook( _ => YprofileEnabled.value = true )

  val YpatmatExhaustdepth     = IntSetting("-Ypatmat-exhaust-depth", "off", 20, Some((10, Int.MaxValue)),
    str => Some(if(str.equalsIgnoreCase("off")) Int.MaxValue else str.toInt))

  /**
   * -V "Verbose" settings
   */
  val Vhelp              = BooleanSetting("-V", "Print a synopsis of verbose options.")
  val browse          = PhasesSetting("-Vbrowse", "Browse the abstract syntax tree after") withAbbreviation "-Ybrowse"
  val debug           = BooleanSetting("-Vdebug", "Increase the quantity of debugging output.") withAbbreviation "-Ydebug" withPostSetHook (s => if (s.value) StatisticsStatics.enableDebugAndDeoptimize())
  val YdebugTasty     = BooleanSetting("-Vdebug-tasty", "Increase the quantity of debugging output when unpickling tasty.") withAbbreviation "-Ydebug-tasty"
  val VdebugTypeError = BooleanSetting("-Vdebug-type-error", "Print the stack trace when any error is caught.") withAbbreviation "-Ydebug-type-error"
  val Ydocdebug       = BooleanSetting("-Vdoc", "Trace scaladoc activity.") withAbbreviation "-Ydoc-debug"
  val Yidedebug          = BooleanSetting("-Vide", "Generate, validate and output trees using the interactive compiler.") withAbbreviation "-Yide-debug"
//  val Yissuedebug        = BooleanSetting("-Vissue", "Print stack traces when a context issues an error.") withAbbreviation "-Yissue-debug"
  val log                = PhasesSetting("-Vlog", "Log operations during") withAbbreviation "-Ylog"
  val Ylogcp             = BooleanSetting("-Vclasspath", "Output information about what classpath is being applied.") withAbbreviation "-Ylog-classpath"
  val YmacrodebugLite    = BooleanSetting("-Vmacro-lite", "Trace macro activities with less output.") withAbbreviation "-Ymacro-debug-lite"
  val YmacrodebugVerbose = BooleanSetting("-Vmacro", "Trace macro activities: compilation, generation of synthetics, classloading, expansion, exceptions.") withAbbreviation "-Ymacro-debug-verbose"
  val YoptTrace = StringSetting("-Vopt", "package/Class.method", "Trace the optimizer progress for methods; `_` to print all, prefix match to select.", "")
    .withAbbreviation("-Yopt-trace")
  val YoptLogInline = StringSetting("-Vinline", "package/Class.method", "Print a summary of inliner activity; `_` to print all, prefix match to select.", "")
    .withAbbreviation("-Yopt-log-inline")
  val Ypatmatdebug       = BooleanSetting("-Vpatmat", "Trace pattern matching translation.") withAbbreviation "-Ypatmat-debug"
  val showPhases         = BooleanSetting("-Vphases", "Print a synopsis of compiler phases.")
    .withAbbreviation("-Xshow-phases")
  val Yposdebug          = BooleanSetting("-Vpos", "Trace position validation.") withAbbreviation "-Ypos-debug"
  val Xprint             = PhasesSetting("-Vprint", "Print out program after")
    .withAbbreviation("-Xprint")
  val Xprintpos          = BooleanSetting("-Vprint-pos", "Print tree positions, as offsets.")
    .withAbbreviation("-Xprint-pos")
  val printtypes         = BooleanSetting("-Vprint-types", "Print tree types (debugging option).")
    .withAbbreviation("-Xprint-types")
  val printArgs          = StringSetting("-Vprint-args", "file", "Print all compiler arguments to the specified location. Use - to echo to the reporter.", "-")
    .withAbbreviation("-Xprint-args")
  val Yquasiquotedebug   = BooleanSetting("-Vquasiquote", "Trace quasiquotations.") withAbbreviation "-Yquasiquote-debug"
  val Yreifydebug        = BooleanSetting("-Vreify", "Trace reification.") withAbbreviation "-Yreify-debug"
  val Yshow           = PhasesSetting     ("-Vshow", "(Requires -Xshow-class or -Xshow-object) Show after")
    .withAbbreviation("-Yshow")
  val Xshowcls           = StringSetting("-Vshow-class", "class", "Show internal representation of class.", "")
    .withAbbreviation("-Xshow-class")
  val Xshowobj           = StringSetting("-Vshow-object", "object", "Show internal representation of object.", "")
    .withAbbreviation("-Xshow-object")
  val Ymemberpos      = StringSetting("-Vshow-member-pos", "output style", s"Show start and end positions of members (implies ${Yrangepos.name})", "")
    .withPostSetHook(_ => Yrangepos.value = true)
    .withAbbreviation("-Yshow-member-pos")
  val Yshowsymkinds   = BooleanSetting    ("-Vshow-symkinds", "Print abbreviated symbol kinds next to symbol names.")
    .withAbbreviation("-Yshow-symkinds")
  val Yshowsymowners  = BooleanSetting    ("-Vshow-symowners", "Print owner identifiers next to symbol names.")
    .withAbbreviation("-Yshow-symowners")
  val Ystatistics = PhasesSetting("-Vstatistics", "Print compiler statistics for specific phases", "parser,typer,patmat,erasure,cleanup,jvm")
    .withPostSetHook(s => YstatisticsEnabled.value = s.value.nonEmpty)
    .withAbbreviation("-Ystatistics")
  val YstatisticsEnabled = BooleanSetting("-Ystatistics-enabled", "Internal setting, indicating that statistics are enabled for some phase.").internalOnly().withPostSetHook(s => if (s.value) StatisticsStatics.enableColdStatsAndDeoptimize())
  val YhotStatisticsEnabled = BooleanSetting("-Vhot-statistics", s"Enable `${Ystatistics.name}` to also print hot statistics.")
    .withAbbreviation("-Yhot-statistics").withPostSetHook(s => if (s.value && YstatisticsEnabled.value) StatisticsStatics.enableHotStatsAndDeoptimize())
  val Yshowsyms       = BooleanSetting("-Vsymbols", "Print the AST symbol hierarchy after each phase.") withAbbreviation "-Yshow-syms"
  val Ytyperdebug        = BooleanSetting("-Vtyper", "Trace type assignments.") withAbbreviation "-Ytyper-debug"
  val Vimplicits            = BooleanSetting("-Vimplicits", "Print dependent missing implicits.").withAbbreviation("-Xlog-implicits")
  val VimplicitsVerboseTree = BooleanSetting("-Vimplicits-verbose-tree", "Display all intermediate implicits in a chain.")
  val VimplicitsMaxRefined  = IntSetting("-Vimplicits-max-refined", "max chars for printing refined types, abbreviate to `F {...}`", Int.MaxValue, Some((0, Int.MaxValue)), _ => None)
  val VtypeDiffs            = BooleanSetting("-Vtype-diffs", "Print found/required error messages as colored diffs.")
  val logImplicitConv    = BooleanSetting("-Vimplicit-conversions", "Print a message whenever an implicit conversion is inserted.")
    .withAbbreviation("-Xlog-implicit-conversions")
  val logReflectiveCalls = BooleanSetting("-Vreflective-calls", "Print a message when a reflective method call is generated")
    .withAbbreviation("-Xlog-reflective-calls")
  val logFreeTerms       = BooleanSetting("-Vfree-terms", "Print a message when reification creates a free term.")
    .withAbbreviation("-Xlog-free-terms")
  val logFreeTypes       = BooleanSetting("-Vfree-types", "Print a message when reification resorts to generating a free type.")
    .withAbbreviation("-Xlog-free-types")

  /** Groups of Settings.
   */
  val future        = BooleanSetting("-Xfuture", "Replaced by -Xsource.").withDeprecationMessage("Not used since 2.13.")
  val optimise      = BooleanSetting("-optimize", "Enables optimizations.")
    .withAbbreviation("-optimise")
    .withDeprecationMessage("Since 2.12, enables -opt:inline:**. This can be dangerous.")
    .withPostSetHook(_ => opt.add("inline", List("**")))
  val Xexperimental = BooleanSetting("-Xexperimental", "Former graveyard for language-forking extensions.")
    .withDeprecationMessage("Not used since 2.13.")

  // Feature extensions
  val XmacroSettings          = MultiStringSetting("-Xmacro-settings", "option", "Custom settings for macros.")

  /**
   * IDE-specific settings
   */
  val YpresentationVerbose = BooleanSetting("-Ypresentation-verbose", "Print information about presentation compiler tasks.")
  val YpresentationDebug   = BooleanSetting("-Ypresentation-debug",  "Enable debugging output for the presentation compiler.")
  val YpresentationAnyThread  = BooleanSetting("-Ypresentation-any-thread", "Allow use of the presentation compiler from any thread")
  val YpresentationStrict     = BooleanSetting("-Ypresentation-strict", "Do not report type errors in sources with syntax errors.")
  val YpresentationLog     = StringSetting("-Ypresentation-log", "file", "Log presentation compiler events into file", "")
  val YpresentationReplay  = StringSetting("-Ypresentation-replay", "file", "Replay presentation compiler events from file", "")
  val YpresentationDelay   = IntSetting("-Ypresentation-delay", "Wait number of ms after typing before starting typechecking", 0, Some((0, 999)), str => Some(str.toInt))

  val YpresentationLocateSourceFile = BooleanSetting("-Ypresentation-locate-source-file", "Enables legacy code in the classfile parser to locate a .scala file in the output directories corresponding to the SourceFile attribute .class file.")

  /**
   * -P "Plugin" settings
   */
  val pluginOptions = MultiStringSetting("-P", "plugin:opt", "Pass an option to a plugin") .
                        withHelpSyntax("-P:<plugin>:<opt>")

  /** Test whether this is scaladoc we're looking at */
  def isScaladoc = false

  object MacroExpand {
    val None = "none"
    val Normal = "normal"
    val Discard = "discard"
  }

  def conflictWarning: Option[String] = {
    // See cd878232b5 for an example how to warn about conflicting settings

    /*
    def checkSomeConflict: Option[String] = ...

    List(/* checkSomeConflict, ... */).flatten match {
      case Nil => None
      case warnings => Some("Conflicting compiler settings were detected. Some settings will be ignored.\n" + warnings.mkString("\n"))
    }
    */
    None
  }
}


text:
// Copyright (c) 2012 Ecma International.  All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
es5id: 15.2.3.6-4-269
description: >
    Object.defineProperty - 'O' is an Array, 'name' is an array index
    named property, name is accessor property and 'desc' is accessor
    descriptor, test setting the [[Set]] attribute value of 'name' as
    undefined (15.4.5.1 step 4.c)
includes: [propertyHelper.js]
---*/

var arrObj = [];

Object.defineProperty(arrObj, "0", {
    set: function () { },
    configurable: true
});

Object.defineProperty(arrObj, "0", {
    set: undefined
});
verifyNotEnumerable(arrObj, "0");

verifyConfigurable(arrObj, "0");


text:
require 'rubygems'
require 'bud'

#simple wrapper class for easier clock/msg access
class LamportMsg
  attr_accessor :clock
  attr_accessor :msg

  def initialize(clock, msg)
    @clock = clock
    @msg = msg
  end

  def to_s
    [@clock, @msg].inspect
  end

  def ==(another_msg)
    self.clock == another_msg.clock && self.msg == another_msg.msg
  end
end

#implements handling of Lamport clocks for use in both send/recieve actions
#note that even though one can access LamportMessage msg fields without
#passing them to retrieve_msg, neglecting to register received messages with the
#LamportClockManager will potentially result in incorrect Lamport clock stamps
#getting applied to outgoing messages!

module LamportInterface
  state do
    interface input, :to_stamp, [] => [:msg]
    interface output, :get_stamped, [:msg] => [:lamportmsg]
    interface input, :retrieve_msg, [:lamportmsg] => []
    interface output, :msg_return, [:lamportmsg] => [:msg]
  end
end

module LamportClockManager
  include LamportInterface

  state do
    table :localclock, [] => [:clock]

    table :action_buf, [] => [:actiontype, :msg, :queuetime]

    scratch :next_stamp, to_stamp.schema
    scratch :next_retrieve, retrieve_msg.schema
  end

  bootstrap do
    localclock <= [[0]]
  end

  bloom do

    temp :relativestamp <= to_stamp.each_with_index.to_a

    get_stamped <= (relativestamp * localclock).pairs do |m, c|
      [m[0][0], LamportMsg.new(m[1]+c.clock, m[0][0])]
    end

    msg_return <= retrieve_msg { |r| [r.lamportmsg, r.lamportmsg.msg] }

    localclock <+- localclock { |c|
      if retrieve_msg.length > 0
        [c.clock+
          [to_stamp.length+retrieve_msg.length,
            (retrieve_msg { |m| m.lamportmsg.clock }).max+1].max]
      else
        [c.clock+to_stamp.length+retrieve_msg.length]
      end
    }
  end
end


text:
angular.module('chatty')
    .directive('post', function() {
        return {
            restrict: 'E',
            replace: true,
            templateUrl: 'post/post.html',
            controller: function($scope, actionService, tabService) {
                $scope.collapse = function(post) {
                    if (post.parentId) {
                        actionService.collapsePostReply(post)
                    } else {
                        actionService.collapseThread(post)
                    }
                }

                $scope.openReplyBox = function(post) {
                    actionService.openReplyBox(post)
                }

                $scope.addUserTab = function(user) {
                    tabService.addTab('user', user)
                }

                $scope.pinPost = function(post) {
                    actionService.togglePinThread(post)
                }
            }
        }
    })


text:
The cAdvisor integration tests are run per-pr using [Github Actions](https://help.github.com/en/actions). Workflow configuration can be found at [.github/workflows/test.yml](.github/workflows/test.yml). Tests are executed in Docker containers run on MS Azure virtual machines.

To run them locally Docker must be installed on your machine. Following command allows you to execute default suite of integration tests:

```
make docker-test-integration
```

Build scripts take care of building cAdvisor and integration tests, and executing them against running cAdvisor process.

In order to run non-default tests suites (e.g. such that rely on third-party C libraries) you must source one of the files available at [build/config](build/config), e.g.:

```
source build/config/libpfm4.sh && make docker-test-integration
```

All the necessary packages will be installed, build flags will be applied and additional parameters will be passed to cAdvisor automatically. Configuration is performed using shell environment variables.

## VM-base tests (legacy)

The cAdvisor integration tests are run per-pr using the [kubernetes node-e2e testing framework](https://github.com/kubernetes/community/blob/master/contributors/devel/e2e-node-tests.md) on GCE instances.  To make use of this framework, complete the setup of GCP described in the node-e2e testing framework, clone `k8s.io/kubernetes`, and from that repository run:
```
$ make test-e2e-node TEST_SUITE=cadvisor REMOTE=true
```
This will create a VM, build cadvisor, run integration tests on that VM, retrieve logs, and will clean up the test afterwards.  See the [node-e2e testing documentation](https://github.com/kubernetes/community/blob/master/contributors/devel/e2e-node-tests.md) for more running options.

To simply run the tests against an existing cAdvisor:

```
$ go test github.com/google/cadvisor/integration/tests/... -host=HOST -port=PORT
```

Note that `HOST` and `PORT` default to `localhost` and `8080` respectively.
Today We only support remote execution in Google Compute Engine since that is where we run our continuous builds.