コード例 #1
0
ファイル: manager_pubsub_test.go プロジェクト: levcom/csfw
func TestPubSubBubbling(t *testing.T) {
	defer errLogBuf.Reset()
	testPath := "a/b/c"

	m := config.NewManager()

	_, err := m.Subscribe("", nil)
	assert.EqualError(t, err, config.ErrPathEmpty.Error())

	subID, err := m.Subscribe(testPath, &testSubscriber{
		f: func(path string, sg scope.Scope, id int64) error {
			assert.Equal(t, testPath, path)
			if sg == scope.DefaultID {
				assert.Equal(t, int64(0), id)
			} else {
				assert.Equal(t, int64(123), id)
			}
			return nil
		},
	})
	assert.NoError(t, err)
	assert.Equal(t, 1, subID, "The very first subscription ID should be 1")

	assert.NoError(t, m.Write(config.Value(1), config.Path(testPath), config.Scope(scope.WebsiteID, 123)))

	assert.NoError(t, m.Close())
	time.Sleep(time.Millisecond * 10) // wait for goroutine to close

	// send on closed channel
	assert.NoError(t, m.Write(config.Value(1), config.Path(testPath+"Doh"), config.Scope(scope.WebsiteID, 3)))
	assert.EqualError(t, m.Close(), config.ErrPublisherClosed.Error())
}
コード例 #2
0
ファイル: http.go プロジェクト: levcom/csfw
func (t *HTTPRateLimit) quota() throttled.RateQuota {
	var burst, request int
	var duration string

	if burst, _ = t.Config.GetInt(config.Path(PathRateLimitBurst)); burst < 0 {
		burst = DefaultBurst
	}
	if request, _ = t.Config.GetInt(config.Path(PathRateLimitRequests)); request == 0 {
		request = DefaultRequests
	}
	if duration, _ = t.Config.GetString(config.Path(PathRateLimitDuration)); duration == "" {
		duration = DefaultDuration
	}

	var r throttled.Rate
	switch duration {
	case "s": // second
		r = throttled.PerSec(request)
	case "i": // minute
		r = throttled.PerMin(request)
	case "h": // hour
		r = throttled.PerHour(request)
	case "d": // day
		r = throttled.PerDay(request)
	default:
		r = throttled.PerHour(request)
	}

	return throttled.RateQuota{r, burst}
}
コード例 #3
0
ファイル: website.go プロジェクト: hafeez3000/csfw
// ConfigString tries to get a value from the scopeStore if empty
// falls back to default global scope.
// If using etcd or consul maybe this can lead to round trip times because of network access.
func (w *Website) ConfigString(path ...string) string {
	val := w.cr.GetString(config.ScopeWebsite(w.WebsiteID()), config.Path(path...))
	if val == "" {
		val = w.cr.GetString(config.Path(path...))
	}
	return val
}
コード例 #4
0
ファイル: store.go プロジェクト: hafeez3000/csfw
// ConfigString tries to get a value from the scopeStore if empty
// falls back to default global scope.
// If using etcd or consul maybe this can lead to round trip times because of network access.
func (s *Store) ConfigString(path ...string) string {
	val := s.cr.GetString(config.ScopeStore(s.StoreID()), config.Path(path...)) // TODO(cs) check for not bubbeling
	if val == "" {
		val = s.cr.GetString(config.Path(path...))
	}
	return val
}
コード例 #5
0
ファイル: store.go プロジェクト: bom-d-van/csfw
// ConfigString tries to get a value from the scopeStore if empty
// falls back to default global scope.
// If using etcd or consul maybe this can lead to round trip times because of network access.
func (s *Store) ConfigString(path ...string) string {
	val := s.cr.GetString(config.ScopeStore(s), config.Path(path...))
	if val == "" {
		val = s.cr.GetString(config.Path(path...))
	}
	return val
}
コード例 #6
0
ファイル: service_test.go プロジェクト: joao-parana/csfw
// TestApplyCoreConfigData reads from the MySQL core_config_data table and applies
// these value to the underlying storage. tries to get back the values from the
// underlying storage
func TestApplyCoreConfigData(t *testing.T) {
	defer debugLogBuf.Reset()
	defer infoLogBuf.Reset()

	dbc := csdb.MustConnectTest()
	defer func() { assert.NoError(t, dbc.Close()) }()
	sess := dbc.NewSession(nil) // nil tricks the NewSession ;-)

	s := config.NewService()
	defer func() { assert.NoError(t, s.Close()) }()

	loadedRows, writtenRows, err := s.ApplyCoreConfigData(sess)
	if err != nil {
		t.Fatal(err)
	}
	assert.True(t, loadedRows > 9, "loadedRows %d", loadedRows)
	assert.True(t, writtenRows > 9, "writtenRows %d", writtenRows)

	//	println("\n", debugLogBuf.String(), "\n")
	//	println("\n", infoLogBuf.String(), "\n")

	assert.NoError(t, s.Write(config.Path("web/secure/offloader_header"), config.ScopeDefault(), config.Value("SSL_OFFLOADED")))

	h, err := s.String(config.Path("web/secure/offloader_header"), config.ScopeDefault())
	assert.NoError(t, err)
	assert.Exactly(t, "SSL_OFFLOADED", h)

	assert.Len(t, s.Storage.AllKeys(), writtenRows)
}
コード例 #7
0
func TestPubSubBubbling(t *testing.T) {
	defer debugLogBuf.Reset()
	testPath := "a/b/c"

	s := config.NewService()

	_, err := s.Subscribe("", nil)
	assert.EqualError(t, err, config.ErrPathEmpty.Error())

	subID, err := s.Subscribe(testPath, &testSubscriber{
		f: func(path string, sg scope.Scope, id int64) error {
			assert.Equal(t, testPath, path)
			if sg == scope.DefaultID {
				assert.Equal(t, int64(0), id)
			} else {
				assert.Equal(t, int64(123), id)
			}
			return nil
		},
	})
	assert.NoError(t, err)
	assert.Equal(t, 1, subID, "The very first subscription ID should be 1")

	assert.NoError(t, s.Write(config.Value(1), config.Path(testPath), config.Scope(scope.WebsiteID, 123)))
	assert.NoError(t, s.Close())

	// send on closed channel
	assert.NoError(t, s.Write(config.Value(1), config.Path(testPath+"Doh"), config.Scope(scope.WebsiteID, 3)))
	assert.EqualError(t, s.Close(), config.ErrPublisherClosed.Error())
}
コード例 #8
0
ファイル: middleware.go プロジェクト: levcom/csfw
// WithValidateBaseURL is a middleware which checks if the request base URL
// is equal to the one store in the configuration, if not
// i.e. redirect from http://example.com/store/ to http://www.example.com/store/
// @see app/code/Magento/Store/App/FrontController/Plugin/RequestPreprocessor.php
func WithValidateBaseURL(cr config.ReaderPubSuber) ctxhttp.Middleware {

	// Having the GetBool command here, means you must restart the app to take
	// changes in effect. @todo refactor and use pub/sub to automatically change
	// the isRedirectToBase value.
	checkBaseURL, err := cr.GetBool(config.Path(PathRedirectToBase)) // scope default
	if config.NotKeyNotFoundError(err) && PkgLog.IsDebug() {
		PkgLog.Debug("ctxhttp.WithValidateBaseUrl.GetBool", "err", err, "path", PathRedirectToBase)
	}

	redirectCode := http.StatusMovedPermanently
	if rc, err := cr.GetInt(config.Path(PathRedirectToBase)); rc != redirectCode && false == config.NotKeyNotFoundError(err) {
		redirectCode = http.StatusFound
	}

	return func(h ctxhttp.Handler) ctxhttp.Handler {
		return ctxhttp.HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {

			if checkBaseURL && r.Method != "POST" {

				_, requestedStore, err := FromContextReader(ctx)
				if err != nil {
					if PkgLog.IsDebug() {
						PkgLog.Debug("ctxhttp.WithValidateBaseUrl.FromContextServiceReader", "err", err, "ctx", ctx)
					}
					return errgo.Mask(err)
				}

				baseURL, err := requestedStore.BaseURL(config.URLTypeWeb, requestedStore.IsCurrentlySecure(r))
				if err != nil {
					if PkgLog.IsDebug() {
						PkgLog.Debug("ctxhttp.WithValidateBaseUrl.requestedStore.BaseURL", "err", err, "ctx", ctx)
					}
					return errgo.Mask(err)
				}

				if err := httputils.IsBaseURLCorrect(r, &baseURL); err != nil {
					if PkgLog.IsDebug() {
						PkgLog.Debug("store.WithValidateBaseUrl.IsBaseUrlCorrect.error", "err", err, "baseURL", baseURL, "request", r)
					}

					baseURL.Path = r.URL.Path
					baseURL.RawPath = r.URL.RawPath
					baseURL.RawQuery = r.URL.RawQuery
					baseURL.Fragment = r.URL.Fragment
					http.Redirect(w, r, (&baseURL).String(), redirectCode)
					return nil
				}
			}
			return h.ServeHTTPContext(ctx, w, r)
		})
	}
}
コード例 #9
0
ファイル: daemon_unique_id.go プロジェクト: hafeez3000/csfw
func (u *uniqueID) getPort() int {
	p := u.config.GetInt(config.Path(PathSmtpPort), config.ScopeStore(u.scopeID))
	if p < 1 {
		p = defaultPort
	}
	return p
}
コード例 #10
0
ファイル: options.go プロジェクト: joao-parana/csfw
// WithPasswordFromConfig retrieves the password from the configuration with path
// as defined in constant PathJWTPassword
func WithPasswordFromConfig(cr config.Getter) Option {
	pw, err := cr.String(config.Path(PathJWTPassword))
	if config.NotKeyNotFoundError(err) {
		pw = string(uuid.NewRandom())
	}
	return WithPassword([]byte(pw))
}
コード例 #11
0
ファイル: daemon_dialer.go プロジェクト: hafeez3000/csfw
func (c *emailConfig) getPort(s config.ScopeIDer) int {
	p := c.Config.GetInt(config.Path(PathSmtpPort), config.ScopeStore(s))
	if p < 1 {
		p = defaultPort
	}
	return p
}
コード例 #12
0
ファイル: daemon_dialer.go プロジェクト: hafeez3000/csfw
func (c *emailConfig) getHost(s config.ScopeIDer) string {
	h := c.Config.GetString(config.Path(PathSmtpHost), config.ScopeStore(s))
	if h == "" {
		h = defaultHost
	}
	return h
}
コード例 #13
0
ファイル: currency.go プロジェクト: levcom/csfw
// BaseCurrencyCode retrieves application base currency code
func BaseCurrencyCode(cr config.Reader) (language.Currency, error) {
	base, err := cr.GetString(config.Path(PathCurrencyBase))
	if config.NotKeyNotFoundError(err) {
		return language.Currency{}, err
	}
	return language.ParseCurrency(base)
}
コード例 #14
0
ファイル: daemon.go プロジェクト: optimuse/csfw
func (dm *Daemon) getPort() int {
	p := dm.config.GetInt(config.Path(PathSmtpPort), config.ScopeStore(dm.scopeID))
	if p < 1 {
		p = defaultPort
	}
	return p
}
コード例 #15
0
ファイル: daemon.go プロジェクト: optimuse/csfw
func (dm *Daemon) getHost() string {
	h := dm.config.GetString(config.Path(PathSmtpHost), config.ScopeStore(dm.scopeID))
	if h == "" {
		h = defaultHost
	}
	return h
}
コード例 #16
0
ファイル: daemon_mandrill.go プロジェクト: hafeez3000/csfw
// SetMandrill sets the Mandrill API for sending emails. This function is not
// recursive and returns nil. @todo
func SetMandrill(opts ...MandrillOptions) DaemonOption {
	return func(da *Daemon) DaemonOption {
		// this whole func is just a quick write down. no idea if it's working
		// and refactor ... 8-)
		apiKey := da.Config.GetString(config.ScopeStore(da.ScopeID), config.Path(PathSmtpMandrillAPIKey))

		if apiKey == "" {
			da.lastErrs = append(da.lastErrs, errors.New("Mandrill API Key is empty."))
			return nil
		}

		md, err := gochimp.NewMandrill(apiKey)
		if err != nil {
			da.lastErrs = append(da.lastErrs, err)
			return nil
		}
		for _, o := range opts {
			o(md)
		}

		da.sendFunc = func(from string, to []string, msg io.WriterTo) error {

			// @todo figure out if "to" contains To, CC and BCC addresses.

			addr, err := mail.ParseAddress(from)
			if err != nil {
				return log.Error("mail.daemon.Mandrill.ParseAddress", "err", err, "from", from, "to", to)
			}

			r := gochimp.Recipient{
				Name:  addr.Name,
				Email: addr.Address,
			}

			var buf bytes.Buffer
			if _, err := msg.WriteTo(&buf); err != nil {
				return log.Error("mail.daemon.Mandrill.MessageWriteTo", "err", err, "from", from, "to", to, "msg", buf.String())
			}

			resp, err := md.MessageSendRaw(buf.String(), to, r, false)
			if err != nil {
				return log.Error("mail.daemon.Mandrill.MessageSendRaw", "err", err, "from", from, "to", to, "msg", buf.String())
			}
			if log.IsDebug() {
				log.Debug("mail.daemon.Mandrill.MessageSendRaw", "resp", resp, "from", from, "to", to, "msg", buf.String())
			}
			// The last arg in MessageSendRaw means async in the Mandrill API:
			// Async: enable a background sending mode that is optimized for bulk sending.
			// In async mode, messages/send will immediately return a status of "queued"
			// for every recipient. To handle rejections when sending in async mode, set
			// up a webhook for the 'reject' event. Defaults to false for messages with
			// no more than 10 recipients; messages with more than 10 recipients are
			// always sent asynchronously, regardless of the value of async.
			return nil
		}
		da.dialer = nil

		return nil
	}
}
コード例 #17
0
ファイル: daemon_unique_id.go プロジェクト: hafeez3000/csfw
func (u *uniqueID) getHost() string {
	h := u.config.GetString(config.Path(PathSmtpHost), config.ScopeStore(u.scopeID))
	if h == "" {
		h = defaultHost
	}
	return h
}
コード例 #18
0
ファイル: service.go プロジェクト: levcom/csfw
// IsSingleStoreMode check if Single-Store mode is enabled in configuration and from Store count < 3.
// This flag only shows that admin does not want to show certain UI components at backend (like store switchers etc)
// if Magento has only one store view but it does not check the store view collection.
func (sm *Service) IsSingleStoreMode() bool {
	isEnabled, err := sm.cr.GetBool(config.Path(PathSingleStoreModeEnabled)) // default scope
	if config.NotKeyNotFoundError(err) {
		// TODO maybe log error here
		return false
	}
	return sm.HasSingleStore() && isEnabled
}
コード例 #19
0
func TestPubSubEvict(t *testing.T) {
	defer debugLogBuf.Reset()

	levelCall := new(levelCalls)

	var pErr = errors.New("WTF Eviction? Panic!")
	s := config.NewService()
	subID, err := s.Subscribe("x/y", &testSubscriber{
		f: func(path string, sg scope.Scope, id int64) error {
			assert.Contains(t, path, "x/y")
			// this function gets called 3 times
			levelCall.Lock()
			levelCall.level2Calls++
			levelCall.Unlock()
			return nil
		},
	})
	assert.NoError(t, err)
	assert.Equal(t, 1, subID)

	subID, err = s.Subscribe("x/y/z", &testSubscriber{
		f: func(path string, sg scope.Scope, id int64) error {
			levelCall.Lock()
			levelCall.level3Calls++
			levelCall.Unlock()
			// this function gets called 1 times and then gets removed
			panic(pErr)
		},
	})
	assert.NoError(t, err)
	assert.Equal(t, 2, subID)

	assert.NoError(t, s.Write(config.Value(321), config.Path("x/y/z"), config.ScopeStore(123)))
	assert.NoError(t, s.Write(config.Value(321), config.Path("x/y/a"), config.ScopeStore(123)))
	assert.NoError(t, s.Write(config.Value(321), config.Path("x/y/z"), config.ScopeStore(123)))

	assert.NoError(t, s.Close())

	assert.Contains(t, debugLogBuf.String(), "config.pubSub.publish.recover.err err: WTF Eviction? Panic!")

	levelCall.Lock()
	assert.Equal(t, 3, levelCall.level2Calls)
	assert.Equal(t, 1, levelCall.level3Calls)
	levelCall.Unlock()
	assert.EqualError(t, s.Close(), config.ErrPublisherClosed.Error())
}
コード例 #20
0
ファイル: currency.go プロジェクト: levcom/csfw
// AllowedCurrencies returns all installed currencies from global scope.
func AllowedCurrencies(cr config.Reader) ([]string, error) {
	installedCur, err := cr.GetString(config.Path(PathSystemCurrencyInstalled))
	if config.NotKeyNotFoundError(err) {
		return nil, err
	}
	// TODO use internal model of PathSystemCurrencyInstalled defined in package directory
	return strings.Split(installedCur, ","), nil
}
コード例 #21
0
ファイル: website.go プロジェクト: hafeez3000/csfw
// @todo
func (w *Website) BaseCurrencyCode() (language.Currency, error) {
	var c string
	if w.ConfigString(PathPriceScope) == PriceScopeGlobal {
		c = w.cr.GetString(config.Path(directory.PathCurrencyBase))
	} else {
		c = w.ConfigString(directory.PathCurrencyBase)
	}
	return language.ParseCurrency(c)
}
コード例 #22
0
ファイル: user.go プロジェクト: hafeez3000/csfw
func (u *User) Authenticate(cr config.Reader, h crypto.Hasher, username, password string) error {
	isCaseSensitive := cr.GetBool(config.Path("admin/security/use_case_sensitive_login"))

	if !isCaseSensitive {
		// ... hmm
	}

	return nil
}
コード例 #23
0
ファイル: website.go プロジェクト: levcom/csfw
// BaseCurrencyCode returns the base currency code of a website TODO.
func (w *Website) BaseCurrencyCode() (currency.Currency, error) {
	var c string
	if w.Config.GetString(PathPriceScope) == PriceScopeGlobal {
		c, _ = w.cr.GetString(config.Path(directory.PathCurrencyBase)) // TODO check for error
	} else {
		c = w.Config.GetString(directory.PathCurrencyBase)
	}
	return currency.ParseISO(c)
}
コード例 #24
0
ファイル: source_models.go プロジェクト: bom-d-van/csfw
func (sca *SourceCurrencyAll) Options() config.ValueLabelSlice {
	// Magento\Framework\Locale\Resolver
	// grep locale from general/locale/code scope::store for the current store ID
	// the store locale greps the currencies from http://php.net/manual/en/class.resourcebundle.php
	// in the correct language
	storeLocale := sca.mc.ConfigReader.GetString(config.Path(PathDefaultLocale), config.ScopeStore(sca.mc.Scope))

	fmt.Printf("\nstoreLocale: %s\n", storeLocale)

	return nil
}
コード例 #25
0
func TestPubSubEvict(t *testing.T) {
	defer errLogBuf.Reset()

	var level2Calls int
	var level3Calls int

	var pErr = errors.New("WTF Eviction? Panic!")
	m := config.NewManager()
	subID, err := m.Subscribe("x/y", &testSubscriber{
		f: func(path string, sg scope.Scope, id int64) error {
			assert.Contains(t, path, "x/y")
			// this function gets called 3 times
			level2Calls++
			return nil
		},
	})
	assert.NoError(t, err)
	assert.Equal(t, 1, subID)

	subID, err = m.Subscribe("x/y/z", &testSubscriber{
		f: func(path string, sg scope.Scope, id int64) error {
			level3Calls++
			// this function gets called 1 times and then gets removed
			panic(pErr)
			return nil
		},
	})
	assert.NoError(t, err)
	assert.Equal(t, 2, subID)

	m.Write(config.Value(321), config.Path("x/y/z"), config.ScopeStore(123), config.NoBubble())
	m.Write(config.Value(321), config.Path("x/y/a"), config.ScopeStore(123), config.NoBubble())
	m.Write(config.Value(321), config.Path("x/y/z"), config.ScopeStore(123), config.NoBubble())

	time.Sleep(time.Millisecond * 20) // wait for goroutine ...

	assert.Contains(t, errLogBuf.String(), "testErr: stdLib.go:228: config.pubSub.publish.recover.err err: WTF Eviction? Panic!")

	assert.Equal(t, 3, level2Calls)
	assert.Equal(t, 1, level3Calls)
}
コード例 #26
0
ファイル: service_test.go プロジェクト: joao-parana/csfw
func TestScopeApplyDefaults(t *testing.T) {
	defer debugLogBuf.Reset()
	defer infoLogBuf.Reset()

	pkgCfg := element.MustNewConfiguration(
		&element.Section{
			ID: "contact",
			Groups: element.NewGroupSlice(
				&element.Group{
					ID: "contact",
					Fields: element.NewFieldSlice(
						&element.Field{
							// Path: `contact/contact/enabled`,
							ID:      "enabled",
							Default: true,
						},
					),
				},
				&element.Group{
					ID: "email",
					Fields: element.NewFieldSlice(
						&element.Field{
							// Path: `contact/email/recipient_email`,
							ID:      "recipient_email",
							Default: `[email protected]`,
						},
						&element.Field{
							// Path: `contact/email/sender_email_identity`,
							ID:      "sender_email_identity",
							Default: 2.7182818284590452353602874713527,
						},
						&element.Field{
							// Path: `contact/email/email_template`,
							ID:      "email_template",
							Default: 4711,
						},
					),
				},
			),
		},
	)
	s := config.NewService()
	s.ApplyDefaults(pkgCfg)
	cer, err := pkgCfg.FindFieldByPath("contact", "email", "recipient_email")
	if err != nil {
		t.Error(err)
		return
	}
	sval, err := s.String(config.Path("contact/email/recipient_email"))
	assert.NoError(t, err)
	assert.Exactly(t, cer.Default.(string), sval)
	assert.NoError(t, s.Close())
}
コード例 #27
0
ファイル: source_models.go プロジェクト: levcom/csfw
func (sca *SourceCurrencyAll) Options() valuelabel.Slice {
	// Magento\Framework\Locale\Resolver
	// 1. get all allowed currencies from the config
	// 2. get slice of currency code and currency name and filter out all not-allowed currencies
	// grep locale from general/locale/code scope::store for the current store ID
	// the store locale greps the currencies from http://php.net/manual/en/class.resourcebundle.php
	// in the correct language
	storeLocale, err := sca.mc.ConfigReader.GetString(config.Path(PathDefaultLocale), config.ScopeStore(sca.mc.ScopeStore.StoreID()))

	fmt.Printf("\nstoreLocale: %s\n Err %s\n", storeLocale, err)

	return nil
}
コード例 #28
0
ファイル: manager_test.go プロジェクト: levcom/csfw
func TestScopeApplyDefaults(t *testing.T) {
	pkgCfg := config.MustNewConfiguration(
		&config.Section{
			ID: "contact",
			Groups: config.GroupSlice{
				&config.Group{
					ID: "contact",
					Fields: config.FieldSlice{
						&config.Field{
							// Path: `contact/contact/enabled`,
							ID:      "enabled",
							Default: true,
						},
					},
				},
				&config.Group{
					ID: "email",
					Fields: config.FieldSlice{
						&config.Field{
							// Path: `contact/email/recipient_email`,
							ID:      "recipient_email",
							Default: `[email protected]`,
						},
						&config.Field{
							// Path: `contact/email/sender_email_identity`,
							ID:      "sender_email_identity",
							Default: 2.7182818284590452353602874713527,
						},
						&config.Field{
							// Path: `contact/email/email_template`,
							ID:      "email_template",
							Default: 4711,
						},
					},
				},
			},
		},
	)
	s := config.NewManager()
	s.ApplyDefaults(pkgCfg)
	cer, err := pkgCfg.FindFieldByPath("contact", "email", "recipient_email")
	if err != nil {
		t.Error(err)
		return
	}
	sval, err := s.GetString(config.Path("contact/email/recipient_email"))
	assert.NoError(t, err)
	assert.Exactly(t, cer.Default.(string), sval)
}
コード例 #29
0
func TestPubSubPanicSimple(t *testing.T) {
	defer debugLogBuf.Reset()
	testPath := "x/y/z"

	s := config.NewService()
	subID, err := s.Subscribe(testPath, &testSubscriber{
		f: func(path string, sg scope.Scope, id int64) error {
			panic("Don't panic!")
		},
	})
	assert.NoError(t, err)
	assert.Equal(t, 1, subID, "The very first subscription ID should be 1")
	assert.NoError(t, s.Write(config.Value(321), config.Path(testPath), config.ScopeStore(123)))
	assert.NoError(t, s.Close())
	assert.Contains(t, debugLogBuf.String(), `config.pubSub.publish.recover.r recover: "Don't panic!"`)
}
コード例 #30
0
ファイル: manager_pubsub_test.go プロジェクト: levcom/csfw
func TestPubSubPanic(t *testing.T) {
	defer errLogBuf.Reset()
	testPath := "x/y/z"

	m := config.NewManager()
	subID, err := m.Subscribe(testPath, &testSubscriber{
		f: func(path string, sg scope.Scope, id int64) error {
			panic("Don't panic!")
		},
	})
	assert.NoError(t, err)
	assert.Equal(t, 1, subID, "The very first subscription ID should be 1")
	assert.NoError(t, m.Write(config.Value(321), config.Path(testPath), config.ScopeStore(123)))
	assert.NoError(t, m.Close())
	time.Sleep(time.Millisecond * 10) // wait for goroutine to close
	assert.Contains(t, errLogBuf.String(), `config.pubSub.publish.recover.r recover: "Don't panic!"`)
}