text:
require 'spec_helper'

describe 'API V2 Storefront Products Spec', type: :request do
  let!(:store)                 { create(:store, default: true) }
  let!(:products)              { create_list(:product, 5) }
  let(:taxon)                  { create(:taxon) }
  let(:product_with_taxon)     { create(:product, taxons: [taxon]) }
  let(:product_with_name)      { create(:product, name: 'Test Product') }
  let(:product_with_price)     { create(:product, price: 13.44) }
  let!(:option_type)           { create(:option_type) }
  let!(:option_value)          { create(:option_value, option_type: option_type) }
  let(:product_with_option)    { create(:product, option_types: [option_type]) }
  let!(:variant)               { create(:variant, product: product_with_option, option_values: [option_value]) }
  let(:product)                { create(:product) }
  let!(:deleted_product)       { create(:product, deleted_at: Time.current - 1.day) }
  let!(:discontinued_product)  { create(:product, discontinue_on: Time.current - 1.day) }
  let!(:not_available_product) { create(:product, available_on: nil) }

  before { Spree::Api::Config[:api_v2_per_page_limit] = 4 }

  describe 'products#index' do
    context 'with no params' do
      before { get '/api/v2/storefront/products' }

      it_behaves_like 'returns 200 HTTP status'

      it 'returns all products' do
        expect(json_response['data'].count).to eq Spree::Product.available.count
        expect(json_response['data'].first).to have_type('product')
      end
    end

    context 'with specified ids' do
      before { get "/api/v2/storefront/products?filter[ids]=#{products.first.id}" }

      it_behaves_like 'returns 200 HTTP status'

      it 'returns products with specified ids' do
        expect(json_response['data'].count).to eq 1
        expect(json_response['data'].first).to have_id(products.first.id.to_s)
      end
    end

    context 'with specified skus' do
      before { get "/api/v2/storefront/products?filter[skus]=#{products.first.default_variant.sku}" }

      it_behaves_like 'returns 200 HTTP status'

      it 'returns products with specified ids' do
        expect(json_response['data'].count).to eq 1
        expect(json_response['data'].first).to have_id(products.first.id.to_s)
      end
    end

    context 'with specified price range' do
      before { get "/api/v2/storefront/products?filter[price]=#{product_with_price.price.to_f},#{product_with_price.price.to_f + 0.04}" }

      it_behaves_like 'returns 200 HTTP status'

      it 'returns products with specified price' do
        expect(json_response['data'].first).to have_id(product_with_price.id.to_s)
        expect(json_response['data'].first).to have_attribute(:price).with_value(product_with_price.price.to_f.to_s)
      end
    end

    context 'with specified taxon_ids' do
      before { get "/api/v2/storefront/products?filter[taxons]=#{product_with_taxon.taxons.first.id}" }

      it_behaves_like 'returns 200 HTTP status'

      it 'returns products with specified taxons' do
        expect(json_response['data'].first).to have_id(product_with_taxon.id.to_s)
      end
    end

    context 'with specified name' do
      before { get "/api/v2/storefront/products?filter[name]=#{product_with_name.name}" }

      it_behaves_like 'returns 200 HTTP status'

      it 'returns products with specified name' do
        expect(json_response['data'].first).to have_id(product_with_name.id.to_s)
        expect(json_response['data'].first).to have_attribute(:name).with_value(product_with_name.name)
      end
    end

    context 'with specified options' do
      before { get "/api/v2/storefront/products?filter[options][#{option_type.name}]=#{option_value.name}&include=option_types,variants.option_values" }

      it_behaves_like 'returns 200 HTTP status'

      it 'returns products with specified options' do
        expect(json_response['data'].first).to have_id(product_with_option.id.to_s)
        expect(json_response['included']).to   include(have_type('option_type').and(have_attribute(:name).with_value(option_type.name)))
        expect(json_response['included']).to   include(have_type('option_value').and(have_attribute(:name).with_value(option_value.name)))
      end
    end

    context 'with specified multiple filters' do
      before { get "/api/v2/storefront/products?filter[name]=#{product_with_name.name}&filter[price]=#{product_with_name.price.to_f - 0.02},#{product_with_name.price.to_f + 0.02}" }

      it_behaves_like 'returns 200 HTTP status'

      it 'returns products with specified name and price' do
        expect(json_response['data'].count).to eq 1
        expect(json_response['data'].first).to have_id(product_with_name.id.to_s)
      end
    end

    context 'with included deleted' do
      before { get "/api/v2/storefront/products?filter[show_deleted]=#{true}" }

      it_behaves_like 'returns 200 HTTP status'

      it 'returns products with deleted products' do
        expect(json_response['data'].count).to eq 7
        expect(json_response['data'].pluck(:id)).to include(deleted_product.id.to_s)
      end
    end

    context 'with included discontinued' do
      before { get "/api/v2/storefront/products?filter[show_discontinued]=#{true}" }

      it_behaves_like 'returns 200 HTTP status'

      it 'returns products with discontinued products' do
        expect(json_response['data'].count).to eq 8
        expect(json_response['data'].pluck(:id)).to include(discontinued_product.id.to_s)
      end
    end

    context 'with included discontinued and deleted' do
      before do
        get "/api/v2/storefront/products?filter[show_deleted]=#{true}&filter[show_discontinued]=#{true}"
      end

      it_behaves_like 'returns 200 HTTP status'

      it 'returns available, deleted and discontinued products' do
        expect(json_response['data'].count).to eq 9
        expect(json_response['data'].pluck(:id)).to include(deleted_product.id.to_s, discontinued_product.id.to_s)
      end
    end

    context 'sort products' do
      context 'sorting by price' do
        context 'ascending order' do
          before { get '/api/v2/storefront/products?sort=price' }

          it_behaves_like 'returns 200 HTTP status'

          it 'returns products sorted by price' do
            expect(json_response['data'].count).to      eq Spree::Product.available.count
            expect(json_response['data'].pluck(:id)).to eq Spree::Product.available.joins(master: :prices).select("#{Spree::Product.table_name}.*, #{Spree::Price.table_name}.amount").distinct.order("#{Spree::Price.table_name}.amount").map(&:id).map(&:to_s)
          end
        end

        context 'descending order' do
          before { get '/api/v2/storefront/products?sort=-price' }

          it_behaves_like 'returns 200 HTTP status'

          it 'returns products sorted by price with descending order' do
            expect(json_response['data'].count).to      eq Spree::Product.available.count
            expect(json_response['data'].pluck(:id)).to eq Spree::Product.available.joins(master: :prices).select("#{Spree::Product.table_name}.*, #{Spree::Price.table_name}.amount").distinct.order("#{Spree::Price.table_name}.amount DESC").map(&:id).map(&:to_s)
          end
        end
      end

      context 'sorting by updated_at' do
        context 'ascending order' do
          before { get '/api/v2/storefront/products?sort=updated_at' }

          it_behaves_like 'returns 200 HTTP status'

          it 'returns products sorted by updated_at' do
            expect(json_response['data'].count).to      eq Spree::Product.available.count
            expect(json_response['data'].pluck(:id)).to eq Spree::Product.available.order(:updated_at).pluck(:id).map(&:to_s)
          end
        end

        context 'descending order' do
          before { get '/api/v2/storefront/products?sort=-updated_at' }

          it_behaves_like 'returns 200 HTTP status'

          it 'returns products sorted by updated_at with descending order' do
            expect(json_response['data'].count).to      eq Spree::Product.available.count
            expect(json_response['data'].pluck(:id)).to eq Spree::Product.available.order(updated_at: :desc).pluck(:id).map(&:to_s)
          end
        end
      end
    end

    context 'paginate products' do
      context 'with specified pagination params' do
        context 'when per_page is between 1 and default value' do
          before { get '/api/v2/storefront/products?page=1&per_page=2' }

          it_behaves_like 'returns 200 HTTP status'

          it 'returns the default number of products' do
            expect(json_response['data'].count).to eq 2
          end

          it 'returns proper meta data' do
            expect(json_response['meta']['count']).to       eq 2
            expect(json_response['meta']['total_count']).to eq Spree::Product.available.count
          end

          it 'returns proper links data' do
            expect(json_response['links']['self']).to include('/api/v2/storefront/products?page=1&per_page=2')
            expect(json_response['links']['next']).to include('/api/v2/storefront/products?page=2&per_page=2')
            expect(json_response['links']['prev']).to include('/api/v2/storefront/products?page=1&per_page=2')
          end
        end

        context 'when per_page is above the default value' do
          before { get '/api/v2/storefront/products?page=1&per_page=10' }

          it 'returns the default number of products' do
            expect(json_response['data'].count).to eq 6
          end
        end

        context 'when per_page is less than 0' do
          before { get '/api/v2/storefront/products?page=1&per_page=-1' }

          it 'returns the default number of products' do
            expect(json_response['data'].count).to eq 6
          end
        end

        context 'when per_page is equal 0' do
          before { get '/api/v2/storefront/products?page=1&per_page=0' }

          it 'returns the default number of products' do
            expect(json_response['data'].count).to eq 6
          end
        end
      end

      context 'without specified pagination params' do
        before { get '/api/v2/storefront/products' }

        it_behaves_like 'returns 200 HTTP status'

        it 'returns specified amount products' do
          expect(json_response['data'].count).to eq Spree::Product.available.count
        end

        it 'returns proper meta data' do
          expect(json_response['meta']['count']).to       eq json_response['data'].count
          expect(json_response['meta']['total_count']).to eq Spree::Product.available.count
        end

        it 'returns proper links data' do
          expect(json_response['links']['self']).to include('/api/v2/storefront/products')
          expect(json_response['links']['next']).to include('/api/v2/storefront/products?page=1')
          expect(json_response['links']['prev']).to include('/api/v2/storefront/products?page=1')
        end
      end
    end

    context 'fetch products by curency param' do
      let!(:store) { create(:store, default: true, supported_currencies: 'USD,EUR,GBP', default_currency: 'USD' ) }

      context 'with default currency' do
        before { get '/api/v2/storefront/products?currency=USD' }

        it 'returns products' do
          expect(json_response['data']).not_to be_empty
          expect(json_response['data'][0]['attributes']['currency']).to eq 'USD'
          expect(json_response['data'].count).to eq Spree::Product.available.count
        end
      end

      context 'with supported currency' do
        let(:product) { products.first }
        let(:currency) { 'EUR' }

        before do
          product.master.prices.create(currency: currency, amount: 99.90, compare_at_amount: 129.90)
          get "/api/v2/storefront/products?currency=#{currency}&include=default_variant"
        end

        it 'returns products with prices in that currency' do
          expect(json_response['data']).not_to be_empty
          expect(json_response['data'].count).to eq(1)
          expect(json_response['data'][0]['id']).to eq(product.id.to_s)
          expect(json_response['data'][0]['attributes']['currency']).to eq currency
          expect(json_response['data'][0]['attributes']['price']).to eq('99.90')
          expect(json_response['data'][0]['attributes']['display_price']).to eq('€99.90')
          expect(json_response['data'][0]['attributes']['compare_at_price']).to eq('129.90')
          expect(json_response['data'][0]['attributes']['display_compare_at_price']).to eq('€129.90')
          expect(json_response['included'][0]['id']).to eq(product.default_variant_id.to_s)
          expect(json_response['included'][0]['type']).to eq('variant')
          expect(json_response['included'][0]['attributes']['price']).to eq('99.90')
          expect(json_response['included'][0]['attributes']['display_price']).to eq('€99.90')
          expect(json_response['included'][0]['attributes']['compare_at_price']).to eq('129.90')
          expect(json_response['included'][0]['attributes']['display_compare_at_price']).to eq('€129.90')
        end
      end

      context 'without supported currency' do
        before { get '/api/v2/storefront/products?currency=PLN' }

        it 'returns results with default currency' do
          expect(json_response['data']).not_to be_empty
          expect(json_response['data'][0]['attributes']['currency']).to eq 'USD'
          expect(json_response['data'][0]['attributes']['display_price']).to match('$')
        end
      end
    end
  end

  describe 'products#show' do
    context 'with supported currency param' do
      before { get "/api/v2/storefront/products/#{product.slug}?currency=USD" }

      it_behaves_like 'returns 200 HTTP status'

      it 'return product with supported currency' do
        expect(json_response['data']).not_to be_empty
        expect(json_response['data']['id']).to eq(product.id.to_s)
        expect(json_response['data']['attributes']['currency']).to eq('USD')
      end
    end

    context 'with supported currency but without prices in that currency' do
      let!(:store) { create(:store, default: true, supported_currencies: 'USD,EUR,GBP', default_currency: 'USD') }

      before { get "/api/v2/storefront/products/#{product.slug}?currency=EUR&include=default_variant" }

      it_behaves_like 'returns 200 HTTP status'

      it 'returns empty prices' do
        expect(json_response['data']).not_to be_empty
        expect(json_response['data']['id']).to eq(product.id.to_s)
        expect(json_response['data']['attributes']['currency']).to eq('EUR')
        expect(json_response['data']['attributes']['price']).to be_nil
        expect(json_response['data']['attributes']['display_price']).to be_nil
        expect(json_response['data']['attributes']['compare_at_price']).to be_nil
        expect(json_response['data']['attributes']['display_compare_at_price']).to be_nil
        expect(json_response['included'][0]['id']).to eq(product.default_variant_id.to_s)
        expect(json_response['included'][0]['type']).to eq('variant')
        expect(json_response['included'][0]['attributes']['currency']).to eq('EUR')
        expect(json_response['included'][0]['attributes']['price']).to be_nil
        expect(json_response['included'][0]['attributes']['display_price']).to be_nil
        expect(json_response['included'][0]['attributes']['compare_at_price']).to be_nil
        expect(json_response['included'][0]['attributes']['display_compare_at_price']).to be_nil
      end
    end

    context 'without supported currency param' do
      before { get "/api/v2/storefront/products/#{product.slug}?currency=PLN" }

      it 'fallbacks to default currency' do
        expect(json_response['data']).not_to be_empty
        expect(json_response['data']['id']).to eq(product.id.to_s)
        expect(json_response['data']['attributes']['currency']).to eq('USD')
      end
    end

    context 'with non-existing product' do
      before { get '/api/v2/storefront/products/example' }

      it_behaves_like 'returns 404 HTTP status'
    end

    context 'with existing product' do
      before { get "/api/v2/storefront/products/#{product.slug}" }

      it_behaves_like 'returns 200 HTTP status'

      it 'returns a valid JSON response' do
        expect(json_response['data']).to have_id(product.id.to_s)

        expect(json_response['data']).to have_type('product')

        expect(json_response['data']).to have_attribute(:name).with_value(product.name)
        expect(json_response['data']).to have_attribute(:description).with_value(product.description)
        expect(json_response['data']).to have_attribute(:price).with_value(product.price.to_s)
        expect(json_response['data']).to have_attribute(:currency).with_value(product.currency)
        expect(json_response['data']).to have_attribute(:display_price).with_value(product.display_price.to_s)
        expect(json_response['data']).to have_attribute(:available_on).with_value(product.available_on.as_json)
        expect(json_response['data']).to have_attribute(:slug).with_value(product.slug)
        expect(json_response['data']).to have_attribute(:meta_description).with_value(product.meta_description)
        expect(json_response['data']).to have_attribute(:meta_keywords).with_value(product.meta_keywords)
        expect(json_response['data']).to have_attribute(:updated_at).with_value(product.updated_at.as_json)
        expect(json_response['data']).to have_attribute(:purchasable).with_value(product.purchasable?)
        expect(json_response['data']).to have_attribute(:in_stock).with_value(product.in_stock?)
        expect(json_response['data']).to have_attribute(:backorderable).with_value(product.backorderable?)

        expect(json_response['data']).to have_relationships(
          :variants, :option_types, :product_properties, :default_variant
        )
      end
    end
  end
end


text:
using ::testing::_;
using ::testing::AnyNumber;
using ::testing::Return;

namespace media {

MATCHER(DirtyRegionIsNonEmptyRect, "") {
  const SkRegion& dirty_region = arg->dirty_region();
  const SkIRect& dirty_region_bounds = dirty_region.getBounds();
  if (dirty_region_bounds.isEmpty()) {
    return false;
  }
  return dirty_region == SkRegion(dirty_region_bounds);
}

class ScreenCapturerTest : public testing::Test {
 public:
  scoped_refptr<SharedBuffer> CreateSharedBuffer(uint32 size);

 protected:
  scoped_ptr<ScreenCapturer> capturer_;
  MockScreenCapturerDelegate delegate_;
};

scoped_refptr<SharedBuffer> ScreenCapturerTest::CreateSharedBuffer(
    uint32 size) {
  return scoped_refptr<SharedBuffer>(new SharedBuffer(size));
}

TEST_F(ScreenCapturerTest, StartCapturer) {
  capturer_ = ScreenCapturer::Create();
  capturer_->Start(&delegate_);
  capturer_->Stop();
}

TEST_F(ScreenCapturerTest, Capture) {
  // Assume that Start() treats the screen as invalid initially.
  EXPECT_CALL(delegate_,
              OnCaptureCompleted(DirtyRegionIsNonEmptyRect()));
  EXPECT_CALL(delegate_, OnCursorShapeChangedPtr(_))
      .Times(AnyNumber());

  EXPECT_CALL(delegate_, CreateSharedBuffer(_))
      .Times(AnyNumber())
      .WillRepeatedly(Return(scoped_refptr<SharedBuffer>()));

  capturer_ = ScreenCapturer::Create();
  capturer_->Start(&delegate_);
  capturer_->CaptureFrame();
  capturer_->Stop();
}

#if defined(OS_WIN)

TEST_F(ScreenCapturerTest, UseSharedBuffers) {
  EXPECT_CALL(delegate_,
              OnCaptureCompleted(DirtyRegionIsNonEmptyRect()));
  EXPECT_CALL(delegate_, OnCursorShapeChangedPtr(_))
      .Times(AnyNumber());

  EXPECT_CALL(delegate_, CreateSharedBuffer(_))
      .Times(AnyNumber())
      .WillRepeatedly(Invoke(this, &ScreenCapturerTest::CreateSharedBuffer));
  EXPECT_CALL(delegate_, ReleaseSharedBuffer(_))
      .Times(AnyNumber());

  capturer_ = ScreenCapturer::Create();
  capturer_->Start(&delegate_);
  capturer_->CaptureFrame();
  capturer_->Stop();
  capturer_.reset();
}

#endif  // defined(OS_WIN)

}  // namespace media

redpajama_set_name: RedPajamaGithub


text:
namespace blink {

HighlightPseudoMarker::HighlightPseudoMarker(unsigned start_offset,
                                             unsigned end_offset)
    : DocumentMarker(start_offset, end_offset) {}

}  // namespace blink


text:
import {ILang} from '../../core/index';

export class AppConfigService {

  public static SUPPORTED_LANGUAGES: Array<ILang> = [
    { code: 'en', title: 'English' },
    { code: 'es', title: 'Spanish' },
    { code: 'fr', title: 'French' },
    { code: 'ru', title: 'Russian' },
    { code: 'bg', title: 'Bulgarian' }
  ];

}


text:
package http_method_override_test

import (
	"fmt"
	"strings"
	"testing"

	"github.com/GoogleCloudPlatform/esp-v2/src/go/util"
	"github.com/GoogleCloudPlatform/esp-v2/tests/endpoints/echo/client"
	"github.com/GoogleCloudPlatform/esp-v2/tests/env"
	"github.com/GoogleCloudPlatform/esp-v2/tests/env/platform"
	"github.com/GoogleCloudPlatform/esp-v2/tests/utils"
)

func TestMethodOverrideBackendMethod(t *testing.T) {
	t.Parallel()

	s := env.NewTestEnv(platform.TestMethodOverrideBackendMethod, platform.EchoSidecar)

	defer s.TearDown(t)
	if err := s.Setup(utils.CommonArgs()); err != nil {
		t.Fatalf("fail to setup test env, %v", err)
	}

	testData := []struct {
		desc          string
		path          string
		method        string
		headers       map[string]string
		wantResp      string
		httpCallError error
	}{
		{
			desc:   "Overridden POST is received as GET",
			path:   "/echoMethod?key=api-key",
			method: "POST",
			headers: map[string]string{
				"X-HTTP-Method-Override": "GET",
			},
			wantResp: `{"RequestMethod":"GET"}`,
		},
		{
			desc:   "Overridden DELETE is received as POST",
			path:   "/echoMethod?key=api-key",
			method: "DELETE",
			headers: map[string]string{
				"X-HTTP-Method-Override": "POST",
			},
			wantResp: `{"RequestMethod":"POST"}`,
		},
		{
			desc:   "Overridden POST is rejected because DELETE is not defined in the service config",
			path:   "/echoMethod?key=api-key",
			method: "POST",
			headers: map[string]string{
				"X-HTTP-Method-Override": "DELETE",
			},
			httpCallError: fmt.Errorf("{\"code\":405,\"message\":\"The current request is matched to the defined url template \"/echoMethod\" but its http method is not allowed\"}"),
		},
	}
	for _, tc := range testData {
		url := fmt.Sprintf("http://%v:%v%v", platform.GetLoopbackAddress(), s.Ports().ListenerPort, tc.path)
		gotResp, err := client.DoWithHeaders(url, tc.method, "test-body", tc.headers)

		if tc.httpCallError == nil {
			if err != nil {
				t.Fatal(err)
			}
		} else {
			if err == nil || !strings.Contains(err.Error(), tc.httpCallError.Error()) {
				t.Errorf("expected Http call error: %v, got: %v", tc.httpCallError, err)
			}
			continue
		}
		gotRespStr := string(gotResp)
		if err := util.JsonEqual(tc.wantResp, gotRespStr); err != nil {
			t.Errorf("Test(%s) fails: \n %s", tc.desc, err)
		}
	}
}

func TestMethodOverrideBackendBody(t *testing.T) {
	t.Parallel()

	s := env.NewTestEnv(platform.TestMethodOverrideBackendBody, platform.EchoSidecar)
	defer s.TearDown(t)
	if err := s.Setup(utils.CommonArgs()); err != nil {
		t.Fatalf("fail to setup test env, %v", err)
	}

	testData := []struct {
		desc          string
		path          string
		method        string
		headers       map[string]string
		body          string
		wantResp      string
		httpCallError error
	}{
		{
			desc:   "Overridden PUT has body sent from client",
			path:   "/echo?key=api-key",
			method: "PUT",
			headers: map[string]string{
				"X-HTTP-Method-Override": "POST",
			},
			body:     `hello`,
			wantResp: `{"message":"hello"}`,
		},
		{
			desc:   "Overridden GET has no body for the backend to handle, as client did not send it",
			path:   "/echo?key=api-key",
			method: "GET",
			headers: map[string]string{
				"X-HTTP-Method-Override": "POST",
			},
			body:          "This body will not be sent in the request",
			httpCallError: fmt.Errorf(`{"code":500,"message":"Could not get body: EOF"}`),
		},
		{
			desc:   "Overridden POST has body sent from client",
			path:   "/echo?key=api-key",
			method: "POST",
			headers: map[string]string{
				"X-HTTP-Method-Override": "GET",
			},
			body:     "hello",
			wantResp: `{"message":"hello"}`,
		},
	}
	for _, tc := range testData {
		url := fmt.Sprintf("http://%v:%v%v", platform.GetLoopbackAddress(), s.Ports().ListenerPort, tc.path)
		gotResp, err := client.DoWithHeaders(url, tc.method, tc.body, tc.headers)

		if tc.httpCallError == nil {
			if err != nil {
				t.Fatal(err)
			}
		} else {
			if err == nil || !strings.Contains(err.Error(), tc.httpCallError.Error()) {
				t.Errorf("expected Http call error: %v, got: %v", tc.httpCallError, err)
			}
			continue
		}
		gotRespStr := string(gotResp)
		if err := util.JsonEqual(tc.wantResp, gotRespStr); err != nil {
			t.Errorf("Test(%s) fails: \n %s", tc.desc, err)
		}
	}
}

func TestMethodOverrideScReport(t *testing.T) {
	t.Parallel()

	s := env.NewTestEnv(platform.TestMethodOverrideScReport, platform.EchoSidecar)
	defer s.TearDown(t)
	if err := s.Setup(utils.CommonArgs()); err != nil {
		t.Fatalf("fail to setup test env, %v", err)
	}

	testData := []struct {
		desc           string
		url            string
		method         string
		requestHeader  map[string]string
		message        string
		wantResp       string
		httpCallError  error
		wantScRequests []interface{}
	}{
		{
			desc:    "Overridden POST is displayed as GET in SC Report, success case",
			url:     fmt.Sprintf("http://%v:%v%v", platform.GetLoopbackAddress(), s.Ports().ListenerPort, "/echo?key=api-key"),
			message: "hello",
			method:  "POST",
			requestHeader: map[string]string{
				"X-HTTP-Method-Override": "GET",
			},
			wantResp: `{"message":"hello"}`,
			wantScRequests: []interface{}{
				&utils.ExpectedCheck{
					Version:         utils.ESPv2Version(),
					ServiceName:     "echo-api.endpoints.cloudesf-testing.cloud.goog",
					ServiceConfigID: "test-config-id",
					ConsumerID:      "api_key:api-key",
					OperationName:   "1.echo_api_endpoints_cloudesf_testing_cloud_goog.EchoGetWithBody",
					CallerIp:        platform.GetLoopbackAddress(),
				},
				&utils.ExpectedReport{
					Version:                      utils.ESPv2Version(),
					ServiceName:                  "echo-api.endpoints.cloudesf-testing.cloud.goog",
					ServiceConfigID:              "test-config-id",
					URL:                          "/echo?key=api-key",
					ApiKeyInOperationAndLogEntry: "api-key",
					ApiKeyState:                  "VERIFIED",
					ApiMethod:                    "1.echo_api_endpoints_cloudesf_testing_cloud_goog.EchoGetWithBody",
					ApiName:                      "1.echo_api_endpoints_cloudesf_testing_cloud_goog",
					ApiVersion:                   "1.0.0",
					ProducerProjectID:            "producer-project",
					ConsumerProjectID:            "123456",
					HttpMethod:                   "GET",
					FrontendProtocol:             "http",
					LogMessage:                   "1.echo_api_endpoints_cloudesf_testing_cloud_goog.EchoGetWithBody is called",
					StatusCode:                   "0",
					ResponseCode:                 200,
					Platform:                     util.GCE,
					Location:                     "test-zone",
				},
			},
		},
	}
	for _, tc := range testData {
		resp, err := client.DoWithHeaders(tc.url, tc.method, tc.message, tc.requestHeader)
		if tc.httpCallError == nil {
			if err != nil {
				t.Fatalf("Test (%s): failed, %v", tc.desc, err)
			}
			if !strings.Contains(string(resp), tc.wantResp) {
				t.Errorf("Test (%s): failed,  expected: %s, got: %s", tc.desc, tc.wantResp, string(resp))
			}
		} else {
			if err == nil || !strings.Contains(err.Error(), tc.httpCallError.Error()) {
				t.Errorf("Test (%s): failed,  expected Http call error: %v, got: %v", tc.desc, tc.httpCallError, err)
			}
		}

		scRequests, err1 := s.ServiceControlServer.GetRequests(len(tc.wantScRequests))
		if err1 != nil {
			t.Fatalf("Test (%s): failed, GetRequests returns error: %v", tc.desc, err1)
		}
		utils.CheckScRequest(t, scRequests, tc.wantScRequests, tc.desc)
	}
}


text:
/* Interface for NSNotificationQueue for GNUStep
   Copyright (C) 1996 Free Software Foundation, Inc.

   Modified by: Richard Frith-Macdonald <richard@brainstorm.co.uk>

   This file is part of the GNUstep Base Library.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the Free
   Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02111 USA.
*/

#ifndef __NSNotificationQueue_h_GNUSTEP_BASE_INCLUDE
#define __NSNotificationQueue_h_GNUSTEP_BASE_INCLUDE
#import	<GNUstepBase/GSVersionMacros.h>

#import	<Foundation/NSObject.h>

#if	defined(__cplusplus)
extern "C" {
#endif

@class NSArray;
@class NSNotification;
@class NSNotificationCenter;

/*
 * Posting styles into notification queue
 */

/**
 *  Enumeration of possible timings for distribution of notifications handed
 *  to an [NSNotificationQueue]:
 <example>
{
  NSPostWhenIdle,	// post when runloop is idle
  NSPostASAP,		// post soon
  NSPostNow		// post synchronously
}
 </example>
 */
enum {
  NSPostWhenIdle = 1,
  NSPostASAP = 2,
  NSPostNow = 3
};
typedef NSUInteger NSPostingStyle;

/**
 * Enumeration of possible ways to combine notifications when dealing with
 * [NSNotificationQueue]:
 <example>
{
  NSNotificationNoCoalescing,       // don't combine
  NSNotificationCoalescingOnName,   // combine all registered with same name
  NSNotificationCoalescingOnSender  // combine all registered with same object
}
 </example>
 */
enum {
  NSNotificationNoCoalescing = 0,
  NSNotificationCoalescingOnName = 1,
  NSNotificationCoalescingOnSender = 2
};
typedef NSUInteger NSNotificationCoalescing;

/*
 * NSNotificationQueue class
 */

/**
 *  Structure used internally by [NSNotificationQueue].
 */
struct _NSNotificationQueueList;

@interface NSNotificationQueue : NSObject
{
#if	GS_EXPOSE(NSNotificationQueue)
@public
  NSNotificationCenter			*_center;
  struct _NSNotificationQueueList	*_asapQueue;
  struct _NSNotificationQueueList	*_idleQueue;
  NSZone				*_zone;
#endif
}

/* Creating Notification Queues */

+ (NSNotificationQueue*) defaultQueue;
- (id) initWithNotificationCenter: (NSNotificationCenter*)notificationCenter;

/* Inserting and Removing Notifications From a Queue */

- (void) dequeueNotificationsMatching: (NSNotification*)notification
			 coalesceMask: (NSUInteger)coalesceMask;

- (void) enqueueNotification: (NSNotification*)notification
	        postingStyle: (NSPostingStyle)postingStyle;

- (void) enqueueNotification: (NSNotification*)notification
	        postingStyle: (NSPostingStyle)postingStyle
	        coalesceMask: (NSUInteger)coalesceMask
		    forModes: (NSArray*)modes;

@end

#if	defined(__cplusplus)
}
#endif

#endif /* __NSNotificationQueue_h_GNUSTEP_BASE_INCLUDE */


text:
// Code generated by MockGen. DO NOT EDIT.
// Source: types.go

// Package testing is a generated GoMock package.
package testing

import (
	reflect "reflect"

	gomock "github.com/golang/mock/gomock"
	v1 "k8s.io/api/core/v1"
	v10 "k8s.io/kubelet/pkg/apis/podresources/v1"
)

// MockDevicesProvider is a mock of DevicesProvider interface.
type MockDevicesProvider struct {
	ctrl     *gomock.Controller
	recorder *MockDevicesProviderMockRecorder
}

// MockDevicesProviderMockRecorder is the mock recorder for MockDevicesProvider.
type MockDevicesProviderMockRecorder struct {
	mock *MockDevicesProvider
}

// NewMockDevicesProvider creates a new mock instance.
func NewMockDevicesProvider(ctrl *gomock.Controller) *MockDevicesProvider {
	mock := &MockDevicesProvider{ctrl: ctrl}
	mock.recorder = &MockDevicesProviderMockRecorder{mock}
	return mock
}

// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockDevicesProvider) EXPECT() *MockDevicesProviderMockRecorder {
	return m.recorder
}

// GetAllocatableDevices mocks base method.
func (m *MockDevicesProvider) GetAllocatableDevices() []*v10.ContainerDevices {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "GetAllocatableDevices")
	ret0, _ := ret[0].([]*v10.ContainerDevices)
	return ret0
}

// GetAllocatableDevices indicates an expected call of GetAllocatableDevices.
func (mr *MockDevicesProviderMockRecorder) GetAllocatableDevices() *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllocatableDevices", reflect.TypeOf((*MockDevicesProvider)(nil).GetAllocatableDevices))
}

// GetDevices mocks base method.
func (m *MockDevicesProvider) GetDevices(podUID, containerName string) []*v10.ContainerDevices {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "GetDevices", podUID, containerName)
	ret0, _ := ret[0].([]*v10.ContainerDevices)
	return ret0
}

// GetDevices indicates an expected call of GetDevices.
func (mr *MockDevicesProviderMockRecorder) GetDevices(podUID, containerName interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDevices", reflect.TypeOf((*MockDevicesProvider)(nil).GetDevices), podUID, containerName)
}

// UpdateAllocatedDevices mocks base method.
func (m *MockDevicesProvider) UpdateAllocatedDevices() {
	m.ctrl.T.Helper()
	m.ctrl.Call(m, "UpdateAllocatedDevices")
}

// UpdateAllocatedDevices indicates an expected call of UpdateAllocatedDevices.
func (mr *MockDevicesProviderMockRecorder) UpdateAllocatedDevices() *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateAllocatedDevices", reflect.TypeOf((*MockDevicesProvider)(nil).UpdateAllocatedDevices))
}

// MockPodsProvider is a mock of PodsProvider interface.
type MockPodsProvider struct {
	ctrl     *gomock.Controller
	recorder *MockPodsProviderMockRecorder
}

// MockPodsProviderMockRecorder is the mock recorder for MockPodsProvider.
type MockPodsProviderMockRecorder struct {
	mock *MockPodsProvider
}

// NewMockPodsProvider creates a new mock instance.
func NewMockPodsProvider(ctrl *gomock.Controller) *MockPodsProvider {
	mock := &MockPodsProvider{ctrl: ctrl}
	mock.recorder = &MockPodsProviderMockRecorder{mock}
	return mock
}

// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockPodsProvider) EXPECT() *MockPodsProviderMockRecorder {
	return m.recorder
}

// GetPods mocks base method.
func (m *MockPodsProvider) GetPods() []*v1.Pod {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "GetPods")
	ret0, _ := ret[0].([]*v1.Pod)
	return ret0
}

// GetPods indicates an expected call of GetPods.
func (mr *MockPodsProviderMockRecorder) GetPods() *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPods", reflect.TypeOf((*MockPodsProvider)(nil).GetPods))
}

// MockCPUsProvider is a mock of CPUsProvider interface.
type MockCPUsProvider struct {
	ctrl     *gomock.Controller
	recorder *MockCPUsProviderMockRecorder
}

// MockCPUsProviderMockRecorder is the mock recorder for MockCPUsProvider.
type MockCPUsProviderMockRecorder struct {
	mock *MockCPUsProvider
}

// NewMockCPUsProvider creates a new mock instance.
func NewMockCPUsProvider(ctrl *gomock.Controller) *MockCPUsProvider {
	mock := &MockCPUsProvider{ctrl: ctrl}
	mock.recorder = &MockCPUsProviderMockRecorder{mock}
	return mock
}

// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockCPUsProvider) EXPECT() *MockCPUsProviderMockRecorder {
	return m.recorder
}

// GetAllocatableCPUs mocks base method.
func (m *MockCPUsProvider) GetAllocatableCPUs() []int64 {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "GetAllocatableCPUs")
	ret0, _ := ret[0].([]int64)
	return ret0
}

// GetAllocatableCPUs indicates an expected call of GetAllocatableCPUs.
func (mr *MockCPUsProviderMockRecorder) GetAllocatableCPUs() *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllocatableCPUs", reflect.TypeOf((*MockCPUsProvider)(nil).GetAllocatableCPUs))
}

// GetCPUs mocks base method.
func (m *MockCPUsProvider) GetCPUs(podUID, containerName string) []int64 {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "GetCPUs", podUID, containerName)
	ret0, _ := ret[0].([]int64)
	return ret0
}

// GetCPUs indicates an expected call of GetCPUs.
func (mr *MockCPUsProviderMockRecorder) GetCPUs(podUID, containerName interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCPUs", reflect.TypeOf((*MockCPUsProvider)(nil).GetCPUs), podUID, containerName)
}

// MockMemoryProvider is a mock of MemoryProvider interface.
type MockMemoryProvider struct {
	ctrl     *gomock.Controller
	recorder *MockMemoryProviderMockRecorder
}

// MockMemoryProviderMockRecorder is the mock recorder for MockMemoryProvider.
type MockMemoryProviderMockRecorder struct {
	mock *MockMemoryProvider
}

// NewMockMemoryProvider creates a new mock instance.
func NewMockMemoryProvider(ctrl *gomock.Controller) *MockMemoryProvider {
	mock := &MockMemoryProvider{ctrl: ctrl}
	mock.recorder = &MockMemoryProviderMockRecorder{mock}
	return mock
}

// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockMemoryProvider) EXPECT() *MockMemoryProviderMockRecorder {
	return m.recorder
}

// GetAllocatableMemory mocks base method.
func (m *MockMemoryProvider) GetAllocatableMemory() []*v10.ContainerMemory {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "GetAllocatableMemory")
	ret0, _ := ret[0].([]*v10.ContainerMemory)
	return ret0
}

// GetAllocatableMemory indicates an expected call of GetAllocatableMemory.
func (mr *MockMemoryProviderMockRecorder) GetAllocatableMemory() *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllocatableMemory", reflect.TypeOf((*MockMemoryProvider)(nil).GetAllocatableMemory))
}

// GetMemory mocks base method.
func (m *MockMemoryProvider) GetMemory(podUID, containerName string) []*v10.ContainerMemory {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "GetMemory", podUID, containerName)
	ret0, _ := ret[0].([]*v10.ContainerMemory)
	return ret0
}

// GetMemory indicates an expected call of GetMemory.
func (mr *MockMemoryProviderMockRecorder) GetMemory(podUID, containerName interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMemory", reflect.TypeOf((*MockMemoryProvider)(nil).GetMemory), podUID, containerName)
}


text:
namespace RNNSharp
{
    public enum TFEATURE_WEIGHT_TYPE_ENUM
    {
        BINARY,
        FREQUENCY
    }

    public enum LayerType
    {
        Softmax,
        SampledSoftmax,
        LSTM,
        DropOut,
        Simple,
        None
    }

    public enum PRETRAIN_TYPE
    {
        AutoEncoder,
        Embedding,
        None
    }

    public enum NETWORKTYPE
    {
        Forward = 0,
        ForwardSeq2Seq,
        BiDirectional,
        BiDirectionalAverage
    }

    public enum LAYERTYPE
    {
        BPTT = 0,
        LSTM
    }

    public enum RunningMode
    {
        Training = 0,
        Validate = 1,
        Test = 2
    }
}


text:
package com.sanoma.cda.geo

/**
 * This object provides basic Geohash encoding and decoding.
 * Geohash web-site: http://geohash.org/
 * Geohash description on Wikipedia: https://en.wikipedia.org/wiki/Geohash
 *
 * This implementation is very simple and mostly modelled after
 * Python version at https://github.com/vinsci/geohash/blob/master/Geohash/geohash.py
 */
object GeoHash {
  type Geohash = String

  // geohash uses it's own base32 - from Wikipedia
  val base32 = "0123456789bcdefghjkmnpqrstuvwxyz".toList
  val decodeMap = base32.zipWithIndex.toMap
  val bitMask = Array(16, 8, 4, 2, 1)

  @inline def mid(interval: (Double, Double)) = (interval._1 + interval._2) / 2.0

  /**
   * This function decodes fully the given Geohash string
   * @param geohash - Geohash string
   * @return - Tuple with (latitude, longitude, latitude ±error, longitude ±error)
   */
  def decodeFully(geohash: Geohash): (Double, Double, Double, Double) = {
    // latitude and longitude (interval, error)
    var (latI, latE) = ((-90.0, 90.0), 90.0)
    var (lonI, lonE) = ((-180.0, 180.0), 180.0)
    var isEven = true

    for (c <- geohash.toCharArray) {
      val cd = decodeMap(c)
      for (mask <- bitMask) {
        if (isEven) { // longitude
          lonE = lonE / 2.0
          lonI = if ((cd & mask) > 0) (mid(lonI), lonI._2) else (lonI._1, mid(lonI))
        } else { // latitude
          latE = latE / 2.0
          latI = if ((cd & mask) > 0) (mid(latI), latI._2) else (latI._1, mid(latI))
        }
        isEven = !isEven
      }
    }
    (mid(latI), mid(lonI), latE, lonE)
  }

  def geoHash2Rectangle(geohash: Geohash): Rectangle = {
    val (latMid, lonMid, latE, lonE) = decodeFully(geohash)
    new Rectangle(latMid + latE, lonMid + lonE, latMid - latE, lonMid - lonE)
  }

  /**
   * This rounds the coordinates to desired precision. See wikipedia for rounding.
   * @param x Value to round
   * @param xError ±error for x
   * @return Rounded value
   */
  def getRounded(x: Double, xError: Double) = {
    import math._
    val xmin = x - xError
    val xmax = x + xError
    //println(s"x=$x => [$xmin, $xmax]")
    var xPrecision: Double = max(1, round(-log10(xError))) - 1
    var decimals: Double = pow(10, xPrecision)
    var rounded = round(x * decimals) / decimals
    //println(s"rounded = $rounded, decimals = $decimals")
    while ((rounded < xmin) | (rounded > xmax)) {
      xPrecision += 1.0
      decimals = pow(10, xPrecision)
      rounded = round(x * decimals) / decimals
      //println(s"rounded = $rounded, decimals = $decimals")
    }
    rounded
  }

  /**
   * Just decode and get the point. Rounds the precisions also
   * @param gh Geohash to decode
   * @return The point
   */
  def decode(gh: Geohash): Point = {
    val (lat, lon, latErr, lonErr) = decodeFully(gh)
    Point(getRounded(lat, latErr), getRounded(lon, lonErr))
  }

  /**
   * Encoding function
   * @param point Point
   * @param hashLength Desired length of the hash
   * @return The geohash string
   */
  def encode(point: Point, hashLength: Int = 12): Geohash = {
    var latI = (-90.0, 90.0)
    var lonI = (-180.0, 180.0)
    var isEven = true
    var geohash = new StringBuilder
    var bit = 0
    var ch = 0

    while (geohash.length < hashLength) {
      if (isEven) { // longitude
        val midPoint = mid(lonI)
        if (point.longitude > midPoint) {
          ch = ch | bitMask(bit)
          lonI = (midPoint, lonI._2)
        } else lonI = (lonI._1, midPoint)
      } else { // latitude
        val midPoint = mid(latI)
        if (point.latitude > midPoint) {
          ch = ch | bitMask(bit)
          latI = (midPoint, latI._2)
        } else latI = (latI._1, midPoint)
      }
      isEven = !isEven
      if (bit < 4) bit = bit + 1
      else {
        geohash += base32(ch)
        bit = 0
        ch = 0
      }
    }
    geohash.toString
  }

  /**
    * This function just returns the longest common prefix of the sequence of strings.
    * @param strs Sequence of the strings
    * @return The longest common prefix
    */
  def longestCommonPrefix(strs: Seq[String]): String = {
    val charA = strs.map(_.toCharArray)
    val maxLength = charA.map(_.length).min
    (0 until maxLength).view
      .map{i => charA.map(_(i)).toSet}
      .takeWhile(_.size == 1)
      .map(_.head).mkString
  }

  /**
    * This tries to find the smallest geohash that contains all the points.
    * It does it by encoding all points to highest precision and looks for the
    * longest common prefix of the geohash. However, due the way geohash is calculated
    * this may return very large areas. If this is long or "accurate", the points are all
    * in close proximity. However, this may be very large area even if the points are
    * all from very small region that happens to cross large geohash borders.
    * @param points List of points
    * @return The smalles common Geohash
    */
  def smallestCommonGeohash(points: Seq[Point]): Geohash =
    longestCommonPrefix(points.map(p => encode(p)))
}


text:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/app_white"
    android:orientation="vertical">

    <include layout="@layout/toolbar_actionbar"></include>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.ervin.litepal.ui.widget.DragCardsView
            android:id="@+id/dragCardsView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:layout_centerInParent="true"
            android:background="#00ffffff"
            app:cards_height="330dp"
            app:cards_shift="10"
            app:cards_width="300dp"
            app:max_visible="4"
            app:rotation_degrees="15">
        </com.ervin.litepal.ui.widget.DragCardsView>

    </RelativeLayout>

</LinearLayout>


text:
#  KunstmaanConfigBundle

## Installation

This bundle is compatible with all Symfony 3.* releases. More information about installing can be found in this line by line walkthrough of installing Symfony and all our bundles, please refer to the [Getting Started guide](http://bundles.kunstmaan.be/getting-started) and enjoy the full blown experience.

## Usage

This bundle allows you to create a entity that extends the AbstractConfig class.
By doing this you can create a settings form with some custom configuration variables.

### Create entity

Create a new entity with the fields you would like to be configurable.
This can be for example a site emailaddress, the site logo, ...

Change the created entity and let it extend the AbstractConfig class instead of the default AbstractEntity class.

By extending this class you will have to implement some methods from the ConfigurationInterface.

```PHP
    /**
    * This function is optional. Implement it if you would like a other ROLE to access the configuration section.
    **/
    public function getAccessRoles()
    {
        return array('ROLE_ADMIN_');
    }

    /**
     * Returns the form type to use for this configuratble entity.
     *
     * @return string
     */
    public function getDefaultAdminType()
    {
        return new SiteConfigType();
    }

   /**
    * The internal name will be used as unique id for the route etc.
    *
    * Use a name with no spaces but with underscores.
    *
    * @return string
    */
    public function getInternalName()
    {
        return 'siteconfig';
    }

     /**
     * Returns the label for the menu item that will be created.
     *
     * @return string
     */
    public function getLabel()
    {
        return 'Configuration';
    }
```

### Create the form

You can let symfony autogenerate your form for your custom entity. This formtype needs to be returned by the getDefaultAdminType() function.

### Add the created entity to your config.yml file.

```YAML
kunstmaan_config:
    entities:
        - path\toBundle\Entity\CustomEntity
```

### Add the kunstmaan_config routing to your routing.yml

```YAML
kunstmaan_config:
    resource: "@KunstmaanConfigBundle/Resources/config/routing.yml"
    prefix:   /{_locale}/
```

### Result

When you browse to "Settings" in the main menu, you will see that there is a new menu item available with the label you have chosen.

### Twig

There is a custom ConfigTwigExtension with the function get_config_by_internal_name.

The function needs the internal name of your entity as parameter.

You can use this function in your twig template to get your configuration variables.


text:
layout: post
title: "Push推送对比研究分析"
description: 针对市场各个推送SDK做一些简要的说明,方便SDK的设计与开发
category: tech
---

# Push推送对比研究分析
[TOC]
## 个推
### 一.主要功能及特点

 1. 个推不仅能提供云端到客户端的推送服务,也可以提供从客户端上传至云端的服务,即推送消息链路支持上下行双向通道,开发者与客户端之间互动更便利。
 2. 多个APP合并一条长连接,共享链路,省电省流量。
 3. SDK接口丰富,可定制推送模式和通知栏提示样式,也支持增量更新。
 4. 通过根据用户属性的分析建立不同标签,也可以进行A/B分组测试,从而进行精细化运营。
 5. 保持与服务器的长连接,以便消息能够即时推送到达客户端

### 二.Android SDK推送框架
   个推 Android SDK 是作为 Android Serivice 长期运行在后台的,从而创建并保持长连接,保持永远在线的能力。当开发者想要及时地推送消息到达 App 时,只需要调用个推 API推送,即可轻松与用户交流。

如下图所示,为个推推送服务框架图:

![enter image description here](http://docs.igetui.com/download/attachments/1214581/image2015-4-21+17:27:28.png?version=1&modificationDate=1429609417000)
### 三.集成说明

   集成主要包括【资源集成】,【AndroidManifest.xm配置】,【项目代码初始化】

####3.1 资源集成
  此部分集成主要是将第三方提供的SDK中的jar以及so库文件集成到自己项目中,此处可以参见
     [个推资源集成说明](http://docs.igetui.com/pages/viewpage.action?pageId=589991#AndroidSDK%E9%9B%86%E6%88%90%E6%AD%A5%E9%AA%A4-1%E5%AF%BC%E5%85%A5%E4%B8%AA%E6%8E%A8SDKLIB)

#### 3.2 AndroidManifest.xm配置
##### 3.2.1 权限声明

	<uses-permissionandroid:name="android.permission.INTERNET"/>
	<uses-permissionandroid:name="android.permission.READ_PHONE_STATE"/>
	<uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"/>
	<uses-permissionandroid:name="android.permission.CHANGE_WIFI_STATE"/>
	<uses-permissionandroid:name="android.permission.WAKE_LOCK"/>
	<uses-permissionandroid:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
	<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
	<uses-permissionandroid:name="android.permission.VIBRATE"/>
	<uses-permissionandroid:name="android.permission.ACCESS_WIFI_STATE"/>
	<uses-permissionandroid:name="getui.permission.GetuiService.第三方包名"/>
	<uses-permissionandroid:name="android.permission.GET_TASKS"/>
	<!--自定义权限-->
	<permission
	    android:name="getui.permission.GetuiService.第三方包名"
	    android:protectionLevel="normal">
	</permission>

##### 3.2.2 服务项配置

	<!--个推SDK配置开始-->
	<!--配置第三方应用参数属性-->
	<meta-data
	    android:name="PUSH_APPID"
	    android:value="你的APPID"/><!--替换为第三方应用的APPID-->
	<meta-data
	    android:name="PUSH_APPKEY"
	    android:value="你的APPKEY"/><!--替换为第三方应用的APPKEY-->
	<meta-data
	    android:name="PUSH_APPSECRET"
	    android:value="你的APPSECRET"/><!--替换为第三方应用的APPSECRET-->
	<meta-data
	    android:name="PUSH_GROUPID"
	    android:value=""/>
	<!--配置SDK核心服务-->
	<service
	    android:name="com.igexin.sdk.PushService"
	    android:exported="true"
	    android:label="NotificationCenter"
	    android:process=":pushservice">
	</service>
	<receiver
	    android:name="com.igexin.sdk.PushReceiver">
	    <intent-filter>
		<action android:name="android.intent.action.BOOT_COMPLETED"/>
		<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
		<action android:name="android.intent.action.USER_PRESENT"/>
		<action android:name="com.igexin.sdk.action.refreshls"/>
	    </intent-filter>
	</receiver>
	<receiver
		android:name="com.igexin.sdk.PushManagerReceiver"
		android:exported="false" >
		<intent-filter>
		    <action android:name="com.igexin.sdk.action.pushmanager" />
		</intent-filter>
	</receiver>
	<activity
	    android:name="com.igexin.sdk.PushActivity"
	    android:excludeFromRecents="true"
	    android:exported="false"
	    android:process=":pushservice"
	    android:taskAffinity="com.igexin.sdk.PushActivityTask"
	    android:theme="@android:style/Theme.Translucent.NoTitleBar">
	</activity>
	<!--配置弹框activity-->
	<activity
	    android:name="com.igexin.getuiext.activity.GetuiExtActivity"
	    android:configChanges="orientation|keyboard|keyboardHidden"
	    android:excludeFromRecents="true"
	    android:process=":pushservice"
	    android:taskAffinity="android.task.myServicetask"
	    android:theme="@android:style/Theme.Translucent.NoTitleBar"
	    android:exported="false"/>
	<receiver
	    android:name="com.igexin.getuiext.service.PayloadReceiver"
	    android:exported="false">
	    <intent-filter>
		<!--这个com.igexin.sdk.action.7fjUl2Z3LH6xYy7NQK4ni4固定,不能修改-->
		<action android:name="com.igexin.sdk.action.7fjUl2Z3LH6xYy7NQK4ni4"/>
		<!--替换为android:name="com.igexin.sdk.action.第三方的appId"-->
		<action android:name="com.igexin.sdk.action.你的APPID"/>
	    </intent-filter>
	</receiver>
	<service
	    android:name="com.igexin.getuiext.service.GetuiExtService"
	    android:process=":pushservice"/>
	<!--个推download模块配置-->
	<service
	    android:name="com.igexin.download.DownloadService"
	    android:process=":pushservice"/>
	<receiver
		android:name="com.igexin.download.DownloadReceiver">
		<intent-filter>
		    <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
		</intent-filter>
	</receiver>
	<provider
		 android:name="com.igexin.download.DownloadProvider"
		 android:process=":pushservice"
		 android:authorities="downloads.你的包名"/><!--替换为downloads.第三方包名-->

#### 3.3 项目代码初始化
在您应用程序启动初始化阶段,初始化SDK

	PushManager.getInstance().initialize(this.getApplicationContext());

> **Note:**
> 该方法必须在Activity或Service类内调用。一般情况下,可以在Activity的onCreate()方法中调用。由于应用每启动一个新的进程,就会调用一次Application的oncreat方法,而个推SDK是一个独立的进程,会导致在一个应用中至少调用2次Application的onCreate(),这样会影响应用的处理逻辑,所以不建议在Application继承类中调用。
为保证意外情况导致初始化失败,建议应用程序每次启动时都调用一次该初始化接口。

## 百度云推送
### 一.主要功能及特点

 1. 推送通知
 2. 推送消息
 3. 推送富媒体
 4. 基于地理位置的推送(或"LBS推送")

### 二.Android SDK推送框架
 云推送的Android SDK,是通过后台service和socket长连接机制来实现的。从消息时效性、耗电量、网络流量等因素考虑,这是目前最好的实现方式。
在同一台设备安装了多个使用推送的应用的情况下,如果每个应用都执行独立的后台service,且各自建立独立的长连接,这无疑是系统资源的巨大浪费。内存使用、耗电量、网络流量等关键因素都将以接近与应用数正比的倍数增长。
在这个背景下,云推送实现了单服务单通道的机制。同一台设备上,云推送服务的资源消耗不受集成该服务的应用数量影响。任何时刻,只会运行一个后台service和维持一个socket长连接。
应用的初始化、tag等接口调用,将通过intent方式发送到后台运行的service处理。service接收到推送消息时,将根据消息中指定的发送对象,通过intent,以指定目标应用包名的方式,发送私有消息给应用。应用无法接收到不属于自己的消息,也无法通过冒充截获。
 如下图所示:

 ![enter image description here](http://developer.baidu.com/wiki/static/channel/image/scene-info.png)

### 三.集成说明
#### 3.1资源集成

> **Note:** [具体详见百度云推送SDK开发文档](http://push.baidu.com/doc/android/api)

#### 3.2 AndroidManifest.xm配置
##### 3.2.1 权限声明

	<!-- Push service 运行需要的权限 -->
	<uses-permission android:name="android.permission.INTERNET"/>
	<uses-permission android:name="android.permission.READ_PHONE_STATE" />
	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
	<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
	<uses-permission android:name="android.permission.WRITE_SETTINGS" />
	<uses-permission android:name="android.permission.VIBRATE" />
	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
	<uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER"/>
	<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
	<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
	<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
	<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

##### 3.2.2 服务项配置

	<!-- push service start -->
	<!-- 用于接收系统消息以保证PushService正常运行 -->
	<receiver android:name="com.baidu.android.pushservice.PushServiceReceiver"
	    android:process=":bdservice_v1">
	    <intent-filter>
		<action android:name="android.intent.action.BOOT_COMPLETED" />
		<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
		<action android:name="com.baidu.android.pushservice.action.notification.SHOW" />
		<action android:name="com.baidu.android.pushservice.action.media.CLICK" />
		<!-- 以下四项为可选的action声明,可大大提高service存活率和消息到达速度 -->
		<action android:name="android.intent.action.MEDIA_MOUNTED" />
		<action android:name="android.intent.action.USER_PRESENT" />
		<action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
		<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
	    </intent-filter>
	</receiver>
	<!-- Push服务接收客户端发送的各种请求-->
	<receiver android:name="com.baidu.android.pushservice.RegistrationReceiver"
	    android:process=":bdservice_v1">
	    <intent-filter>
		<action android:name="com.baidu.android.pushservice.action.METHOD" />
		<action android:name="com.baidu.android.pushservice.action.BIND_SYNC" />
	    </intent-filter>
	    <intent-filter>
		<action android:name="android.intent.action.PACKAGE_REMOVED"/>
		<data android:scheme="package" />
	    </intent-filter>
	</receiver>
	<service android:name="com.baidu.android.pushservice.PushService" android:exported="true"
	    android:process=":bdservice_v1" >
	    <intent-filter >
		    <action android:name="com.baidu.android.pushservice.action.PUSH_SERVICE"/>
	    </intent-filter>
	</service>
	<!-- 4.4版本新增的CommandService声明,提升小米和魅族手机上的实际推送到达率 -->
	<service android:name="com.baidu.android.pushservice.CommandService"
	    android:exported="true" />

#### 3.3 项目代码初始化

 - 配置Application信息

	<application
	    android:name="com.baidu.frontia.FrontiaApplication"
	    android:icon="@drawable/ic_launcher"
	    android:label="@string/app_name">

 - 启动云推送

在当前工程的主Activity的onCreate函数中,添加以下代码:

	PushManager.startWork(getApplicationContext(),PushConstants.LOGIN_TYPE_API_KEY,"API KEY")

## 极光推送
### 一.主要功能及特点

 1. JPush Android SDK 是作为 Android Serivice 长期运行在后台的,从而创建并保持长连接,保持永远在线的能力。
 2. 多平台支持,JPush Android SDK 除了 jar 包,还有一个 .so 文件。.so 文件的存在 CPU 平台适配的问题。需要支持哪个平台的 CPU,就需要包含这个平台相应的 .so 编译文件。除支持默认的 ARM CPU 平台之外,JPush SDK 还提供 x86 与 MIPs 平台的 CPU 版本 SDK。请单独到 资源下载 页下载。
 3. 电量与流量,JPush Android SDK 由于使用自定义协议,协议体做得极致地小,流量消耗非常地小。电量方面,JPush Android SDK 经过持续地优化,尽可能减少不必要的代码执行;并且,长期的版本升级迭代,不断地调优,在保证一定的网络连接稳定性的要求小,减少电量消耗。

### 二.Android SDK推送框架
开发者集成 JPush Android SDK 到其应用里,JPush Android SDK 创建到 JPush Cloud 的长连接,为 App 提供永远在线的能力。
当开发者想要及时地推送消息到达 App 时,只需要调用 JPush API 推送,或者使用其他方便的智能推送工具,即可轻松与用户交流。
图中红色部分,是 JPush 与 App 开发者的接触点。手机客户端侧,App 需要集成 JPush SDK;服务器端部分,开发者调用 JPush REST API 来进行推送。
如下图:

![enter image description here](http://docs.jpush.io/client/image/jpush_android.png)
### 三.集成说明
#### 3.1资源集成

> **Note:**  [具体详见极光推送SDK包说明](http://docs.jpush.io/guideline/android_guide/)

#### 3.2 AndroidManifest.xm配置
##### 3.2.1 权限声明

    <!-- Required -->
    <permission android:name="Your Package.permission.JPUSH_MESSAGE" android:protectionLevel="signature" />

    <!-- Required -->
    <uses-permission android:name="You Package.permission.JPUSH_MESSAGE" />
    <uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <!--since 1.6.0 -->

    <!-- Optional. Required for location feature -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />

##### 3.2.2 服务项配置

        <!-- Required -->
        <service
            android:name="cn.jpush.android.service.PushService"
            android:enabled="true"
            android:exported="false" >
            <intent-filter>
                <action android:name="cn.jpush.android.intent.REGISTER" />
                <action android:name="cn.jpush.android.intent.REPORT" />
                <action android:name="cn.jpush.android.intent.PushService" />
                <action android:name="cn.jpush.android.intent.PUSH_TIME" />
            </intent-filter>
        </service>

        <!-- Required -->
        <receiver
            android:name="cn.jpush.android.service.PushReceiver"
            android:enabled="true" >
          <intent-filter android:priority="1000"> <!--since 1.3.5 -->
                <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED_PROXY" /> <!--since 1.3.5 -->
                <category android:name="Your Package" /> <!--since 1.3.5 -->
            </intent-filter> <!--since 1.3.5 -->
            <intent-filter>
                <action android:name="android.intent.action.USER_PRESENT" />
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.PACKAGE_ADDED" />
                <action android:name="android.intent.action.PACKAGE_REMOVED" />
                <data android:scheme="package" />
            </intent-filter>
        </receiver>
     <!-- Required SDK核心功能-->
        <activity
            android:name="cn.jpush.android.ui.PushActivity"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"
            android:configChanges="orientation|keyboardHidden" >
            <intent-filter>
                <action android:name="cn.jpush.android.ui.PushActivity" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="Your Package" />
            </intent-filter>
        </activity>
        <!-- Required SDK核心功能-->
        <service
            android:name="cn.jpush.android.service.DownloadService"
            android:enabled="true"
            android:exported="false" >
        </service>
        <!-- Required SDK核心功能-->
        <receiver android:name="cn.jpush.android.service.AlarmReceiver" />

        <!-- Required. For publish channel feature -->
        <!-- JPUSH_CHANNEL 是为了方便开发者统计APK分发渠道。-->
        <!-- 例如: -->
        <!-- 发到 Google Play 的APK可以设置为 google-play; -->
        <!-- 发到其他市场的 APK 可以设置为 xxx-market。 -->
        <!-- 目前这个渠道统计功能的报表还未开放。-->
        <meta-data android:name="JPUSH_CHANNEL" android:value="developer-default"/>
        <!-- Required. AppKey copied from Portal -->
        <meta-data android:name="JPUSH_APPKEY" android:value="Your AppKey"/>

#### 3.3 项目代码初始化
init 初始化SDK

	public static void init(Context context)

可以设置调试模式

	// You can enable debug mode in developing state. You should close debug mode when release.
	public static void setDebugMode(boolean debugEnalbed)

## Flyme云推送
### 一.主要功能及特点
  app为了及时获取到服务器端的消息更新,一般会采用轮寻或者推送的方式来获取消息更新,轮寻导致终端设备流量、电量、等系统资源严重浪费,所以目前采用的比较广泛的是推送的方式,目前 Meizu 的 Push SDK 不能脱离 Flyme OS 存在,当该 SDK 脱离 Flyme OS 之后由于没有长链接导致不能正常收到推送消息。本 SDK 首先要解决的时长链接由 SDK 自己维护,同时还要解决的就是多个 app 引用同一个 SDK 时长链接的复用问题。
### 二.Android SDK推送框架
该 SDK 以 Android Service 方式运行,独占一个进程,该 Service 自己维护与推送服务器的长链接。如果一款手机安装了多个集成了 SDK 的手机应用,则只有一个 service 实例运行,不会每个应用都会开启一个后台 service,而是采用多个应用共享一个Push通道的方式,这就解决了长链接复用的问题,节省了对流量、电量的浪费。使用该 SDK 只需要关心 MzPushManager 提供的API,与 MzPushMessageReceiver 提供的回调接口以及相应的配置即可。
### 三.集成说明
#### 3.1资源集成
集成前准备工作
  PushSDk 提供一个Jar包以及两个.so文件,目录结构如下

	--libs
	  --armeabi
	  ---libcrypto_framwork.so
	  ---libsnappy-jni.so
	  --pushsdk-all-V1.0.jar

#### 3.2 AndroidManifest.xm配置
##### 3.2.1 权限声明

    <!-- Push service 运行需要的权限 -->
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER"/>
    <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

##### 3.2.2 服务项配置
* (1)AndroidManifest.xml注册消息接收receiver

        <!-- push应用定义消息receiver声明 -->
        <receiver android:name="your.package.MyPushMsgReceiver">
            <intent-filter>
                <!-- 接收push消息 -->
                <action android:name="com.meizu.cloud.pushservice.action.ON_MESSAGE" />
            </intent-filter>
        </receiver>

* (2)客户端需要自己实现MyPushMessageReceiver,接收Push服务的消息,并实现对消息的处理MyPushMessageReceiver如下代码所示,继承com.meizu.cloud.pushsdk.MzPushMessageReceiver

		public class MyPushMsgReceiver extends MzPushMessageReceiver {
		    @Override
		    public void onRegister(Context context, String s) {

		    }
		    @Override
		    public void onMessage(Context context, String s) {
		    }
        }

* (3)AndroidManifest.xml增加pushservice配置

        <service
            android:name="com.meizu.cloud.pushsdk.pushservice.MzPushService"
            android:exported="true"
            android:process="com.meizu.cloud.pushservice" >
            <intent-filter >
                <action android:name="com.meizu.cloud.pushservice.action.PUSH_SERVICE"/>
            </intent-filter>
        </service>

        用于接收系统消息,保证pushservice正常运行
        <receiver android:name="com.meizu.cloud.pushsdk.PushServiceReceiver"
                  android:process="com.meizu.cloud.pushservice">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
                <!-- 以下四项为可选的action声明,可大大提高service存活率和消息到达速度 -->
                <action android:name="android.intent.action.MEDIA_MOUNTED" />
                <action android:name="android.intent.action.USER_PRESENT" />
                <action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
                <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
            </intent-filter>
        </receiver>

        <service
            android:name="com.meizu.cloud.pushsdk.pushservice.PushBroadcastProcessorService"
            android:exported="true"/>

#### 3.3 项目代码初始化
* 在自定义Application的onCreate方法中调用Push绑定接口

		PushManager.register(Context context)


text:
namespace ispc {
#endif // __cplusplus

struct AmbientLight
{
  Light super; // inherited light fields
  vec3f radiance; // emitted RGB radiance

#ifdef __cplusplus
  AmbientLight() : radiance(1.f) {}
};
} // namespace ispc
#else
};
#endif // __cplusplus


text:
namespace download {

DownloadNavigationObserver::DownloadNavigationObserver(
    content::WebContents* web_contents,
    NavigationMonitor* navigation_monitor)
    : content::WebContentsObserver(web_contents),
      content::WebContentsUserData<DownloadNavigationObserver>(*web_contents),
      navigation_monitor_(navigation_monitor) {}

DownloadNavigationObserver::~DownloadNavigationObserver() = default;

void DownloadNavigationObserver::DidStartLoading() {
  NotifyNavigationEvent(NavigationEvent::START_NAVIGATION);
}

void DownloadNavigationObserver::DidStopLoading() {
  NotifyNavigationEvent(NavigationEvent::NAVIGATION_COMPLETE);
}

void DownloadNavigationObserver::NotifyNavigationEvent(
    NavigationEvent navigation_event) {
  DCHECK(navigation_monitor_);
  navigation_monitor_->OnNavigationEvent(navigation_event);
}

WEB_CONTENTS_USER_DATA_KEY_IMPL(DownloadNavigationObserver);

}  // namespace download


text:
require 'simplecov' and SimpleCov.start do
	add_filter "spec/"
	add_filter "lib/mojito/utils/rspec.rb"
end
require 'mojito'
require 'mojito/utils/rspec'

describe ::Rack::Request do

	subject do
		Mojito::C.runtime_controller Mojito::Rendering::Content do
			write request.GET[:hello]
			halt!
		end.mock_request
	end

	it { subject.get('/?hello=world').status.should == 200 }
	it { subject.get('/?hello=world').body.should == 'world' }

end


text:
#ifndef ORG_EEROS_CONTROL_SOCKETDATA_HPP_
#define ORG_EEROS_CONTROL_SOCKETDATA_HPP_

#include <eeros/control/Blockio.hpp>
#include <eeros/math/Matrix.hpp>
#include <array>
#include <eeros/core/System.hpp>
#include <eeros/sockets/SocketServer.hpp>
#include <eeros/sockets/SocketClient.hpp>

namespace eeros {
namespace control {

using namespace sockets;

template < typename SigInType, typename SigOutType, typename Enable = void >
class SocketData: public Blockio<1,1,SigInType, SigOutType> { };

/**
 * This class allows to deliver a signal over a socket connection. While one end of the connection
 * acts as a server the other side will connect as a client. Various signal types can be sent over
 * such a connection, notably basic types such as int and doubles and composite types as matrices.
 * The connection is established automatically as soon as a server is alive an a client is starting.
 * When one of the two partners stops, the connection is broken. It is automatically re-
 * establed as soon as both are running again.
 *
 * @tparam SigInType - type of the input signal (double - default type)
 * @tparam SigOutType - type of the output signal (double - default type)
 * @since v1.0
 */

template < typename SigInType, typename SigOutType>
class SocketData<SigInType, SigOutType,
  typename std::enable_if<std::is_compound<SigInType>::value && std::is_compound<SigOutType>::value>::type>
      : public Blockio<1,1,SigInType, SigOutType> {
 public:

  /**
   * Creates a SocketData block. This block can be configured either as server or client.
   *
   * @param serverIP - IP number of the server, if left empty, block acts as a client
   * @param port - port number, server and client must be opened on the same port number
   * @param period - period in s which the thread polls the connection
   * @param timeout - connection timeout time in s
   */
  SocketData(std::string serverIP, uint16_t port, double period = 0.01, double timeout = 1.0) {
    bufInLen = sizeof(SigInType) / sizeof(SigInValueType);
    bufOutLen = sizeof(SigOutType) / sizeof(SigOutValueType);
    isServer = serverIP.empty();
    if (isServer)
      server = new SocketServer<sizeof(SigInType) / sizeof(SigInValueType), SigInValueType, sizeof(SigOutType) / sizeof(SigOutValueType), SigOutValueType>(port, period, timeout);
    else
      client = new SocketClient<sizeof(SigInType) / sizeof(SigInValueType), SigInValueType, sizeof(SigOutType) / sizeof(SigOutValueType), SigOutValueType>(serverIP, port, period, timeout);;
  }

  /**
   * Disabling use of copy constructor because the block should never be copied unintentionally.
   */
  SocketData(const SocketData& s) = delete;

  /**
   * Destructs the block, stops the server or client.
   */
  virtual ~SocketData() {if (isServer) server->stop(); else client->stop();}

  /**
   * Runs the transceiving algorithm.
   *
   */
  virtual void run() {
    // receive
    SigOutType output;
    if (isServer) {
      std::array<SigOutValueType, sizeof(SigOutType) / sizeof(SigOutValueType)>& getData = server->getReceiveBuffer();
      for (uint32_t i = 0; i < bufOutLen; i++) output(i) = getData[i];
    } else {
      std::array<SigOutValueType, sizeof(SigOutType) / sizeof(SigOutValueType)>& getData = client->getReceiveBuffer();
      for (uint32_t i = 0; i < bufOutLen; i++) output(i) = getData[i];
    }
    // send
    if (this->in.isConnected()) {
      for(uint32_t i = 0; i < bufInLen; i++) sendData[i] = this->in.getSignal().getValue()(i);
      if (isServer) server->setSendBuffer(sendData);
      else client->setSendBuffer(sendData);
    }

    this->out.getSignal().setValue(output);
    timestamp_t time = System::getTimeNs();
    this->out.getSignal().setTimestamp(time);
  }

  /**
   * A socket data block continously tries to get data from the block it is
   * connected to. This other block might temporarily stop sending data.
   * With this function you can query if new data has arrived. It will
   * return true, if the block has received new data. In order to set the
   * flag to false, you have to use the \ref resetNew() function.
   * @see resetNew()
   *
   * return true, if new data has arrived
   */
  virtual bool isNew() {
    if (isServer) return server->newData; else return client->newData;
  }

  /**
   * Use this function to reset the new data flag back to false.
   */
  virtual void resetNew() {
    if (isServer) server->newData = false; else client->newData = false;
  }

  /**
   * A socket data block continously tries to establish a connection to
   * its associated socket data block. Use this function to query if such a
   * connection has been made.
   *
   * @return true, if connected
   */
  virtual bool isConnected() {
    if (isServer) return server->isConnected();
    else return client->isConnected();
  }

  /*
   * Friend operator overload to give the operator overload outside
   * the class access to the private fields.
   */
  template <typename X, typename Y>
  friend std::ostream& operator<<(std::ostream& os, SocketData<X,Y>& s);

 private:
  typedef typename SigInType::value_type SigInValueType;
  typedef typename SigOutType::value_type SigOutValueType;
  SocketServer<sizeof(SigInType) / sizeof(SigInValueType), SigInValueType, sizeof(SigOutType) / sizeof(SigOutValueType), SigOutValueType>* server;
  SocketClient<sizeof(SigInType) / sizeof(SigInValueType), SigInValueType, sizeof(SigOutType) / sizeof(SigOutValueType), SigOutValueType>* client;
  std::array<SigInValueType, sizeof(SigInType) / sizeof(SigInValueType)> sendData;
  uint32_t bufInLen, bufOutLen;
  bool isServer;
};

template < typename SigInType, typename SigOutType >
class SocketData<SigInType, SigOutType,
  typename std::enable_if<std::is_arithmetic<SigInType>::value && std::is_compound<SigOutType>::value>::type>
  : public Blockio<1,1,SigInType, SigOutType> {
public:
  SocketData(std::string serverIP, uint16_t port, double period = 0.01, double timeout = 1.0) {
    bufInLen = 1;
    bufOutLen = sizeof(SigOutType) / sizeof(SigOutValueType);
    isServer = serverIP.empty();
    if (isServer)
      server =  new SocketServer<1, SigInType, sizeof(SigOutType) / sizeof(SigOutValueType), SigOutValueType>(port, period, timeout);
    else
      client =  new SocketClient<1, SigInType, sizeof(SigOutType) / sizeof(SigOutValueType), SigOutValueType>(serverIP, port, period, timeout);
  }

  virtual ~SocketData() {if (isServer) server->stop(); else client->stop();}

  virtual void run() {
    // receive
    SigOutType output;
    if (isServer) {
      std::array<SigOutValueType, sizeof(SigOutType) / sizeof(SigOutValueType)>& getData = server->getReceiveBuffer();
      for (uint32_t i = 0; i < bufOutLen; i++) output(i) = getData[i];
    } else {
      std::array<SigOutValueType, sizeof(SigOutType) / sizeof(SigOutValueType)>& getData = client->getReceiveBuffer();
      for (uint32_t i = 0; i < bufOutLen; i++) output(i) = getData[i];
    }

    // send
    if (this->in.isConnected()) {
      sendData[0] = this->in.getSignal().getValue();
      if (isServer) server->setSendBuffer(sendData);
      else client->setSendBuffer(sendData);
    }

    this->out.getSignal().setValue(output);
    timestamp_t time = System::getTimeNs();
    this->out.getSignal().setTimestamp(time);
  }

  virtual bool isNew() {
    if (isServer) return server->newData; else return client->newData;
  }

  virtual void resetNew() {
    if (isServer) server->newData = false; else client->newData = false;
  }

  virtual bool isConnected() {
    if (isServer) return server->isConnected();
    else return client->isConnected();
  }

  template <typename X, typename Y>
  friend std::ostream& operator<<(std::ostream& os, SocketData<X,Y>& s);

 private:
  typedef typename SigOutType::value_type SigOutValueType;
  SocketServer<1, SigInType, sizeof(SigOutType) / sizeof(SigOutValueType), SigOutValueType>* server;
  SocketClient<1, SigInType, sizeof(SigOutType) / sizeof(SigOutValueType), SigOutValueType>* client;
  std::array<SigInType, 1> sendData;;
  uint32_t bufInLen, bufOutLen;
  bool isServer;
};

template < typename SigInType, typename SigOutType >
class SocketData<SigInType, SigOutType,
  typename std::enable_if<std::is_compound<SigInType>::value && std::is_arithmetic<SigOutType>::value>::type>
  : public Blockio<1,1,SigInType, SigOutType> {
public:
  SocketData(std::string serverIP, uint16_t port, double period = 0.01, double timeout = 1.0) {
    bufInLen = sizeof(SigInType) / sizeof(SigInValueType);
    bufOutLen = 1;
    isServer = serverIP.empty();
    if (isServer)
      server =  new SocketServer<sizeof(SigInType) / sizeof(SigInValueType), SigInValueType, 1, SigOutType>(port, period, timeout);
    else
      client =  new SocketClient<sizeof(SigInType) / sizeof(SigInValueType), SigInValueType, 1, SigOutType>(serverIP, port, period, timeout);
  }

  virtual ~SocketData() {if (isServer) server->stop(); else client->stop();}

  virtual void run() {
    // receive
    SigOutType output;
    if (isServer) {
      std::array<SigOutType, 1>& getData = server->getReceiveBuffer();
      output = getData[0];
    } else {
      std::array<SigOutType, 1>& getData = client->getReceiveBuffer();
      output = getData[0];
    }

    // send
    if (this->in.isConnected()) {
      for(uint32_t i = 0; i < bufInLen; i++) sendData[i] = this->in.getSignal().getValue()(i);
      if (isServer) server->setSendBuffer(sendData);
      else client->setSendBuffer(sendData);
    }

    this->out.getSignal().setValue(output);
    timestamp_t time = System::getTimeNs();
    this->out.getSignal().setTimestamp(time);
  }

  virtual bool isNew() {
    if (isServer) return server->newData; else return client->newData;
  }

  virtual void resetNew() {
    if (isServer) server->newData = false; else client->newData = false;
  }

  virtual bool isConnected() {
    if (isServer) return server->isConnected();
    else return client->isConnected();
  }

  template <typename X, typename Y>
  friend std::ostream& operator<<(std::ostream& os, SocketData<X,Y>& s);

 private:
  typedef typename SigInType::value_type SigInValueType;
  SocketServer<sizeof(SigInType) / sizeof(SigInValueType), SigInValueType, 1, SigOutType>* server;
  SocketClient<sizeof(SigInType) / sizeof(SigInValueType), SigInValueType, 1, SigOutType>* client;
  std::array<SigInValueType, sizeof(SigInType) / sizeof(SigInValueType)> sendData;
  uint32_t bufInLen, bufOutLen;
  bool isServer;
};

template < typename SigInType, typename SigOutType >
class SocketData<SigInType, SigOutType,
  typename std::enable_if<std::is_arithmetic<SigInType>::value && std::is_arithmetic<SigOutType>::value>::type>
  : public Blockio<1,1,SigInType, SigOutType> {
public:
  SocketData(std::string serverIP, uint16_t port, double period = 0.01, double timeout = 1.0) {
    bufInLen = 1;
    bufOutLen = 1;
    isServer = serverIP.empty();
    if (isServer)
      server =  new SocketServer<1, SigInType, 1, SigOutType>(port, period, timeout);
    else
      client =  new SocketClient<1, SigInType, 1, SigOutType>(serverIP, port, period, timeout);
  }

  virtual ~SocketData() {if (isServer) server->stop(); else client->stop();}

  virtual void run() {
    // receive
    SigOutType output;
    if (isServer) {
      std::array<SigOutType, 1>& getData = server->getReceiveBuffer();
      output = getData[0];
    } else {
      std::array<SigOutType, 1>& getData = client->getReceiveBuffer();
      output = getData[0];
    }

    // send
    if (this->in.isConnected()) {
      sendData[0] = this->in.getSignal().getValue();
      if (isServer) server->setSendBuffer(sendData);
      else client->setSendBuffer(sendData);
    }

    this->out.getSignal().setValue(output);
    timestamp_t time = System::getTimeNs();
    this->out.getSignal().setTimestamp(time);
  }

  virtual bool isNew() {
    if (isServer) return server->newData; else return client->newData;
  }

  virtual void resetNew() {
    if (isServer) server->newData = false; else client->newData = false;
  }

  virtual bool isConnected() {
    if (isServer) return server->isConnected();
    else return client->isConnected();
  }

  template <typename X, typename Y>
  friend std::ostream& operator<<(std::ostream& os, SocketData<X,Y>& s);

 private:
  SocketServer<1, SigInType, 1, SigOutType>* server;
  SocketClient<1, SigInType, 1, SigOutType>* client;
  std::array<SigInType, 1> sendData;
  uint32_t bufInLen, bufOutLen;
  bool isServer;
};

template < typename SigInType, typename SigOutType >
class SocketData<SigInType, SigOutType,
  typename std::enable_if<std::is_compound<SigInType>::value && std::is_same<SigOutType, std::nullptr_t>::value>::type>
  : public Blockio<1,1,SigInType> {
public:
  SocketData(std::string serverIP, uint16_t port, double period = 0.01, double timeout = 1.0) {
    bufInLen = sizeof(SigInType) / sizeof(SigInValueType);
    isServer = serverIP.empty();
    if (isServer)
      server =  new SocketServer<sizeof(SigInType) / sizeof(SigInValueType), SigInValueType, 0, std::nullptr_t>(port, period, timeout);
    else
      client =  new SocketClient<sizeof(SigInType) / sizeof(SigInValueType), SigInValueType, 0, std::nullptr_t>(serverIP, port, period, timeout);
  }

  virtual ~SocketData() {if (isServer) server->stop(); else client->stop();}

  virtual void run() {
    // send
    if (this->in.isConnected()) {
      for(uint32_t i = 0; i < bufInLen; i++) sendData[i] = this->in.getSignal().getValue()(i);
      if (isServer) server->setSendBuffer(sendData);
      else client->setSendBuffer(sendData);
    }
  }

  virtual bool isConnected() {
    if (isServer) return server->isConnected();
    else return client->isConnected();
  }

  template <typename X, typename Y>
  friend std::ostream& operator<<(std::ostream& os, SocketData<X,Y>& s);

 private:
  typedef typename SigInType::value_type SigInValueType;
  SocketServer<sizeof(SigInType) / sizeof(SigInValueType), SigInValueType, 0, std::nullptr_t>* server;
  SocketClient<sizeof(SigInType) / sizeof(SigInValueType), SigInValueType, 0, std::nullptr_t>* client;
  std::array<SigInValueType, sizeof(SigInType) / sizeof(SigInValueType)> sendData;
  uint32_t bufInLen;
  bool isServer;
};

template < typename SigInType, typename SigOutType >
class SocketData<SigInType, SigOutType,
  typename std::enable_if<std::is_same<SigInType, std::nullptr_t>::value && std::is_compound<SigOutType>::value>::type>
  : public Blockio<1,1,SigOutType> {
public:
  SocketData(std::string serverIP, uint16_t port, double period = 0.01, double timeout = 1.0) {
    bufOutLen = sizeof(SigOutType) / sizeof(SigOutValueType);
    isServer = serverIP.empty();
    if (isServer)
      server =  new SocketServer<0, std::nullptr_t, sizeof(SigOutType) / sizeof(SigOutValueType), SigOutValueType>(port, period, timeout);
    else
      client =  new SocketClient<0, std::nullptr_t, sizeof(SigOutType) / sizeof(SigOutValueType), SigOutValueType>(serverIP, port, period, timeout);
  }

  virtual ~SocketData() {if (isServer) server->stop(); else client->stop();}

  virtual void run() {
    // receive
    SigOutType output;
    if (isServer) {
      std::array<SigOutValueType, sizeof(SigOutType) / sizeof(SigOutValueType)>& getData = server->getReceiveBuffer();
      for (uint32_t i = 0; i < bufOutLen; i++) output(i) = getData[i];
    } else {
      std::array<SigOutValueType, sizeof(SigOutType) / sizeof(SigOutValueType)>& getData = client->getReceiveBuffer();
      for (uint32_t i = 0; i < bufOutLen; i++) output(i) = getData[i];
    }

    this->out.getSignal().setValue(output);
    timestamp_t time = System::getTimeNs();
    this->out.getSignal().setTimestamp(time);
  }

  virtual bool isNew() {
    if (isServer) return server->newData; else return client->newData;
  }

  virtual void resetNew() {
    if (isServer) server->newData = false; else client->newData = false;
  }

  virtual bool isConnected() {
    if (isServer) return server->isConnected();
    else return client->isConnected();
  }

  template <typename X, typename Y>
  friend std::ostream& operator<<(std::ostream& os, SocketData<X,Y>& s);

 private:
  typedef typename SigOutType::value_type SigOutValueType;
  SocketServer<0, std::nullptr_t, sizeof(SigOutType) / sizeof(SigOutValueType), SigOutValueType>* server;
  SocketClient<0, std::nullptr_t, sizeof(SigOutType) / sizeof(SigOutValueType), SigOutValueType>* client;
  uint32_t bufOutLen;
  bool isServer;
};

template < typename SigInType, typename SigOutType >
class SocketData<SigInType, SigOutType,
  typename std::enable_if<std::is_arithmetic<SigInType>::value && std::is_same<SigOutType, std::nullptr_t>::value>::type>
  : public Blockio<1,1,SigInType> {
public:
  SocketData(std::string serverIP, uint16_t port, double period = 0.01, double timeout = 1.0) {
    bufInLen = 1;
    isServer = serverIP.empty();
    if (isServer)
      server =  new SocketServer<1, SigInType, 0, std::nullptr_t>(port, period, timeout);
    else
      client =  new SocketClient<1, SigInType, 0, std::nullptr_t>(serverIP, port, period, timeout);
  }

  virtual ~SocketData() {if (isServer) server->stop(); else client->stop();}

  virtual void run() {
    // send
    if (this->in.isConnected()) {
      sendData[0] = this->in.getSignal().getValue();
      if (isServer) server->setSendBuffer(sendData);
      else client->setSendBuffer(sendData);
    }
  }

  virtual bool isConnected() {
    if (isServer) return server->isConnected();
    else return client->isConnected();
  }

  template <typename X, typename Y>
  friend std::ostream& operator<<(std::ostream& os, SocketData<X,Y>& s);

 private:
  SocketServer<1, SigInType, 0, std::nullptr_t>* server;
  SocketClient<1, SigInType, 0, std::nullptr_t>* client;
  std::array<SigInType, 1> sendData;
  uint32_t bufInLen;
  bool isServer;
};

template < typename SigInType, typename SigOutType >
class SocketData<SigInType, SigOutType,
  typename std::enable_if<std::is_same<SigInType, std::nullptr_t>::value && std::is_arithmetic<SigOutType>::value>::type>
  : public Blockio<1,1,SigOutType> {
public:
  SocketData(std::string serverIP, uint16_t port, double period = 0.01, double timeout = 1.0) {
    bufOutLen = 1;
    isServer = serverIP.empty();
    if (isServer)
      server =  new SocketServer<0, std::nullptr_t, 1, SigOutType>(port, period, timeout);
    else
      client =  new SocketClient<0, std::nullptr_t, 1, SigOutType>(serverIP, port, period, timeout);
  }

  virtual ~SocketData() {if (isServer) server->stop(); else client->stop();}

  virtual void run() {
    // receive
    SigOutType output;
    if (isServer) {
      std::array<SigOutType, 1>& getData = server->getReceiveBuffer();
      output = getData[0];
    } else {
      std::array<SigOutType, 1>& getData = client->getReceiveBuffer();
      output = getData[0];
    }

    this->out.getSignal().setValue(output);
    timestamp_t time = System::getTimeNs();
    this->out.getSignal().setTimestamp(time);
  }

  virtual bool isNew() {
    if (isServer) return server->newData; else return client->newData;
  }

  virtual void resetNew() {
    if (isServer) server->newData = false; else client->newData = false;
  }

  virtual bool isConnected() {
    if (isServer) return server->isConnected();
    else return client->isConnected();
  }

  template <typename X, typename Y>
  friend std::ostream& operator<<(std::ostream& os, SocketData<X,Y>& s);

 private:
  SocketServer<0, std::nullptr_t, 1, SigOutType>* server;
  SocketClient<0, std::nullptr_t, 1, SigOutType>* client;
  uint32_t bufOutLen;
  bool isServer;
};

/********** Print functions **********/
template <typename X, typename Y>
std::ostream& operator<<(std::ostream& os, SocketData<X,Y>& s) {
  os << "Block socket data: '" << s.getName() << "'";
  return os;
}

};
}

#endif /* ORG_EEROS_CONTROL_SOCKETDATA_HPP_ */


text:
git-force-clone(1) -- overwrite local repositories with clone
===

## SYNOPSIS

`force-clone --help`
`force-clone {remote_url} {destination_path}`
`force-clone --branch {branch_name} {remote_url} {destination_path}`

## DESCRIPTION

Provides the basic functionality of `git clone`, but if the destination git
repository already exists it will force-reset it to resemble a clone of the
remote.

Because it doesn't actually delete the directory, it is usually significantly
faster than the alternative of deleting the directory and cloning the
repository from scratch.

**CAUTION**: If the repository exists, this will destroy *all* local work:
changed files will be reset, local branches and other remotes will be removed.

## PROCESS

If `target-directory` doesn't exist or isn't a git repository then the
arguments will simply be passed through to `git clone`.

If `target-directory` exists and is a git repository then this will:

- Remove all remotes
- Set the origin remote to `{remote_url}` and fetch the remote
- Discover the default branch, if no branch was specified
- Check out the selected branch
- Delete all other local branches

## OPTIONS

`{remote_url}` - The URL for a git remote repository of which to make a clone.
`{destination_path}` - A path to the local git repository location to clone into.
`--branch {branch_name}` - After cloning, checkout this branch.

## EXAMPLES

`git-force-clone -b master git@github.com:me/repo.git ./repo_dir`

## AUTHOR

Written by Robin Winslow <robin@robinwinslow.co.uk>.

## REPORTING BUGS

<https://github.com/tj/git-extras/issues>

## SEE ALSO

<https://github.com/tj/git-extras>


text:
[![CI](https://github.com/JuliaCloud/AWS.jl/workflows/CI/badge.svg)](https://github.com/JuliaCloud/AWS.jl/actions?query=workflow%3ACI)
[![Bors: enabled](https://bors.tech/images/badge_small.svg)](https://app.bors.tech/repositories/6778)
[![Code Style: Blue](https://img.shields.io/badge/code%20style-blue-4495d1.svg)](https://github.com/invenia/BlueStyle)
[![ColPrac: Contributor's Guide on Collaborative Practices for Community Packages](https://img.shields.io/badge/ColPrac-Contributor's%20Guide-blueviolet)](https://github.com/SciML/ColPrac)

[AWS.jl](https://github.com/JuliaCloud/AWS.jl) is a Julia interface for [Amazon Web Services](https://aws.amazon.com).

This package replaces [AWSCore.jl](https://github.com/JuliaCloud/AWSCore.jl) and [AWSSDK.jl](https://github.com/JuliaCloud/AWSSDK.jl) which previously provided low-level and high-level APIs respectively.
It includes automated code generation to ensure all new AWS services are available, as well as keeping existing services up to date.

To see an overview of the architecture see the [design document](https://github.com/JuliaCloud/AWS.jl/wiki/v1-Design-Document).

## Installation
You will need some form of AWS credentials to use this package.
The most simple way is to set up [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html).

```julia
julia> Pkg.add("AWS")
```

## Usage
`AWS.jl` can be used with low-level and high-level API requests.
Please note when passing parameters for a request they must be a subtype of `AbstractDict{String, <:Any}`.

### Low-Level
To use the low-level API, you must know how to perform the request you are making.
If you do not know how to perform a request you can reference the [AWS Documentation](https://docs.aws.amazon.com/).
Alternatively you can look at `/src/services/{Service}.jl` to find a list of available requests, as well as their required and optional parameters.

For example, to list the objects in an S3 bucket you must pass in the request method (`"GET"`) and the endpoint (`"/${bucket}"`):

```julia
using AWS.AWSServices: s3

s3("GET", "/your-bucket")
```

### High-Level
To use the high-level API, you only need to know the name of the request you wish to make.
For example again, to list the objects in an S3 bucket:

```julia
using AWS: @service
@service S3

S3.list_objects("/your-bucket")
```

#### Documentation for High-Level APIs
```@contents
Pages = readdir("services"; join=true)
```


text:
// Copyright 2007-2011 The Apache Software Foundation.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
namespace Topshelf.Messages
{
	public class ServiceInfo
	{
		public ServiceInfo(string name, string currentState, string serviceType)
		{
			Name = name;
			CurrentState = currentState;
			ServiceType = serviceType;
		}

		protected ServiceInfo()
		{
		}

		public string Name { get; private set; }
		public string CurrentState { get; private set; }
		public string ServiceType { get; private set; }
	}
}